Repository: visualfc/liteide Branch: master Commit: 6c0660ac7d21 Files: 1673 Total size: 10.3 MB Directory structure: gitextract_mv_lcv3e/ ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── CONTRIBUTORS ├── ISSUE_TEMPLATE.md ├── LICENSE.LGPL ├── README.md ├── build/ │ ├── .gitignore │ ├── build_freebsd.sh │ ├── build_freebsd_g++.sh │ ├── build_linux.sh │ ├── build_linux_debian72_x64.sh │ ├── build_linux_fedora27_x64.sh │ ├── build_linux_qt4.sh │ ├── build_linux_qt4_webkit.sh │ ├── build_linux_qt5.sh │ ├── build_linux_webkit.sh │ ├── build_macos_qt4.sh │ ├── build_macos_qt5.sh │ ├── build_netbsd.sh │ ├── build_openbsd.sh │ ├── build_openbsd_g++.sh │ ├── build_windows_386_mingw32.cmd │ ├── build_windows_mingw32.cmd │ ├── build_windows_msvc.cmd │ ├── deploy_linux_bundle.sh │ ├── deploy_linux_debian72_x64_qt4.8_webkit.sh │ ├── deploy_linux_qt4.7_webkit.sh │ ├── deploy_linux_qt4.8_webkit.sh │ ├── deploy_linux_qt4.sh │ ├── deploy_linux_x32_appimage.sh │ ├── deploy_linux_x32_qt4.sh │ ├── deploy_linux_x32_qt5.5.sh │ ├── deploy_linux_x32_qt5.sh │ ├── deploy_linux_x64_appimage.sh │ ├── deploy_linux_x64_qt4.sh │ ├── deploy_linux_x64_qt4_webkit.sh │ ├── deploy_linux_x64_qt5.5.sh │ ├── deploy_linux_x64_qt5.sh │ ├── deploy_macos_qt4.sh │ ├── deploy_macos_qt5.sh │ ├── deploy_windows_qt4.8.cmd │ ├── deploy_windows_qt4.8_msvc.cmd │ ├── deploy_windows_qt5.15.2.cmd │ ├── deploy_windows_qt5.9.cmd │ ├── liteide.desktop │ ├── liteide_archlinux/ │ │ ├── PKGBUILD │ │ └── liteide.md │ ├── update_pkg.cmd │ ├── update_pkg.sh │ ├── update_tr.cmd │ ├── update_tr.sh │ ├── update_ts.cmd │ ├── update_ts.sh │ ├── vars4.8.5.cmd │ ├── vars5.15.2.cmd │ ├── vars5.15.2_msvc.cmd │ ├── vars5.15.2_x64.cmd │ └── vars5.9.6.cmd └── liteidex/ ├── LGPL_EXCEPTION.TXT ├── LICENSE.LGPL ├── bash.bat ├── deploy/ │ ├── liteapp/ │ │ ├── kms/ │ │ │ └── default.kms │ │ ├── mimetype/ │ │ │ ├── folderproject.xml │ │ │ ├── gopackage.xml │ │ │ ├── liteeditor.xml │ │ │ └── qsqleditor.xml │ │ ├── qss/ │ │ │ ├── black.qss │ │ │ ├── carbon.qss │ │ │ ├── coffee.qss │ │ │ ├── default.qss │ │ │ ├── default_macos.qss │ │ │ ├── detroit-future.qss │ │ │ ├── evilworks.qss │ │ │ ├── gray.qss │ │ │ ├── one-dark.qss │ │ │ ├── sublime.qss │ │ │ ├── vs-dark-hdpi.qss │ │ │ └── vs-dark.qss │ │ └── template/ │ │ ├── empty/ │ │ │ ├── root │ │ │ └── setup.inf │ │ ├── file.sub │ │ ├── goarticle/ │ │ │ ├── root.article │ │ │ └── setup.inf │ │ ├── gocmd/ │ │ │ ├── doc.go │ │ │ ├── main.go │ │ │ └── setup.inf │ │ ├── gocmdex/ │ │ │ ├── doc.go │ │ │ ├── main.go │ │ │ └── setup.inf │ │ ├── gopkg/ │ │ │ ├── doc.go │ │ │ ├── root.go │ │ │ └── setup.inf │ │ ├── gopkgex/ │ │ │ ├── doc.go │ │ │ ├── root.go │ │ │ └── setup.inf │ │ ├── goslide/ │ │ │ ├── root.slide │ │ │ └── setup.inf │ │ ├── gosrc/ │ │ │ ├── root.go │ │ │ └── setup.inf │ │ ├── luasrc/ │ │ │ ├── root.lua │ │ │ └── setup.inf │ │ ├── mdsrc/ │ │ │ ├── root.md │ │ │ └── setup.inf │ │ └── project.sub │ ├── litebuild/ │ │ ├── build.md │ │ ├── command/ │ │ │ └── go.api │ │ ├── gomod.xml │ │ ├── goplus.xml │ │ ├── gosrc.xml │ │ ├── lua.xml │ │ ├── python.xml │ │ ├── qlang.xml │ │ ├── rust.xml │ │ └── tcl.xml │ ├── liteeditor/ │ │ ├── color/ │ │ │ ├── carbon.xml │ │ │ ├── clearday.xml │ │ │ ├── cobalt black.xml │ │ │ ├── cobalt blue.xml │ │ │ ├── colorhelp.md │ │ │ ├── dark-blue.xml │ │ │ ├── dark-gray.xml │ │ │ ├── dark.xml │ │ │ ├── darktango.xml │ │ │ ├── darkvim.xml │ │ │ ├── default-func.xml │ │ │ ├── default.xml │ │ │ ├── detroit-future.xml │ │ │ ├── evilworks.xml │ │ │ ├── gist-github.xml │ │ │ ├── highcontrastdark.xml │ │ │ ├── one-dark.xml │ │ │ ├── railscast.xml │ │ │ ├── solarized-dark.xml │ │ │ ├── solarized-light.xml │ │ │ ├── solarsooty.xml │ │ │ ├── sublime-bold.xml │ │ │ ├── sublime.xml │ │ │ └── visualstudio.xml │ │ └── kate/ │ │ ├── alert.xml │ │ ├── alert_indent.xml │ │ ├── awk.xml │ │ ├── bash.xml │ │ ├── c.xml │ │ ├── cmake.xml │ │ ├── cpp.xml │ │ ├── css.xml │ │ ├── go.xml │ │ ├── gohtml.xml │ │ ├── gomod.xml │ │ ├── goplus.xml │ │ ├── gopresent.xml │ │ ├── gowork.xml │ │ ├── html.xml │ │ ├── java.xml │ │ ├── javadoc.xml │ │ ├── javascript.xml │ │ ├── json.xml │ │ ├── katehelp.md │ │ ├── language.dtd │ │ ├── less.xml │ │ ├── lua.xml │ │ ├── makefile.xml │ │ ├── markdown.xml │ │ ├── perl.xml │ │ ├── python.xml │ │ ├── qlang.xml │ │ ├── ruby.xml │ │ ├── rust.xml │ │ ├── tcl.xml │ │ ├── toml.xml │ │ ├── xml.xml │ │ ├── yacc.xml │ │ └── yaml.xml │ ├── packages/ │ │ ├── go/ │ │ │ ├── funcs.api │ │ │ ├── go.snippet.json │ │ │ ├── godoc/ │ │ │ │ ├── about.html │ │ │ │ ├── all.css │ │ │ │ ├── finddoc.html │ │ │ │ ├── godoc.html │ │ │ │ └── style.css │ │ │ ├── keyword.api │ │ │ ├── pkglist │ │ │ └── types.api │ │ ├── gopresent/ │ │ │ ├── js/ │ │ │ │ └── jquery-ui.js │ │ │ └── static/ │ │ │ ├── article.css │ │ │ ├── dir.css │ │ │ ├── dir.js │ │ │ ├── print.css │ │ │ ├── slides.js │ │ │ └── styles.css │ │ ├── lua/ │ │ │ ├── luabase.api │ │ │ ├── lualib.api │ │ │ └── lualib5_annot.api │ │ └── markdown/ │ │ ├── css/ │ │ │ ├── Clearness Dark.css │ │ │ ├── Clearness.css │ │ │ ├── Documents.css │ │ │ ├── GitHub.css │ │ │ ├── GitHub2.css │ │ │ ├── GitHub_Style.css │ │ │ └── GitHub_Word.css │ │ └── export.html │ ├── translations/ │ │ ├── liteide_de.qm │ │ ├── liteide_fr.qm │ │ ├── liteide_ja.qm │ │ ├── liteide_ru.qm │ │ ├── liteide_uk.qm │ │ ├── liteide_zh.qm │ │ └── liteide_zh_TW.qm │ └── welcome/ │ ├── css/ │ │ └── style.css │ ├── en/ │ │ ├── LGPL_EXCEPTION.TXT │ │ ├── LICENSE.LGPL │ │ ├── changes.md │ │ ├── forever.md │ │ ├── guide.md │ │ ├── install.md │ │ ├── liteide.html │ │ ├── readme.md │ │ ├── shortcuts.html │ │ ├── website.md │ │ └── welcome.html │ ├── images/ │ │ └── liteide128.xpm │ └── zh_CN/ │ ├── LGPL_EXCEPTION.TXT │ ├── LICENSE.LGPL │ ├── changes.md │ ├── forever.md │ ├── guide.md │ ├── install.md │ ├── liteide.html │ ├── readme.md │ ├── shortcuts.html │ ├── website.md │ └── welcome.html ├── export_qrc.cmd ├── export_qrc.sh ├── install-icon.sh ├── linux_deploy.sh ├── liteide.desktop ├── liteide_de.ts ├── liteide_fr.ts ├── liteide_ja.ts ├── liteide_ru.ts ├── liteide_tr.ts ├── liteide_uk.ts ├── liteide_zh.ts ├── liteide_zh_TW.ts ├── liteidex.pri ├── liteidex.pro ├── macosx_deploy.sh ├── make_tools.cmd ├── make_tools.sh ├── os_deploy/ │ ├── freebsd/ │ │ └── liteenv/ │ │ ├── cross-arm5.env │ │ ├── cross-arm6.env │ │ ├── cross-darwin32.env │ │ ├── cross-darwin64.env │ │ ├── cross-linux32.env │ │ ├── cross-linux64.env │ │ ├── cross-win32.env │ │ ├── cross-win64.env │ │ ├── freebsd32.env │ │ ├── freebsd64.env │ │ └── system.env │ ├── linux/ │ │ ├── liteenv/ │ │ │ ├── cross-arm5.env │ │ │ ├── cross-arm6.env │ │ │ ├── cross-darwin32.env │ │ │ ├── cross-darwin64.env │ │ │ ├── cross-freebsd32.env │ │ │ ├── cross-freebsd64.env │ │ │ ├── cross-win32.env │ │ │ ├── cross-win64.env │ │ │ ├── linux32-local.env │ │ │ ├── linux32.env │ │ │ ├── linux64-local.env │ │ │ ├── linux64.env │ │ │ └── system.env │ │ └── qt.conf │ ├── macosx/ │ │ └── liteenv/ │ │ ├── cross-arm5.env │ │ ├── cross-arm6.env │ │ ├── cross-freebsd32.env │ │ ├── cross-freebsd64.env │ │ ├── cross-linux32.env │ │ ├── cross-linux64.env │ │ ├── cross-win32.env │ │ ├── cross-win64.env │ │ ├── darwin32-home.env │ │ ├── darwin32-local.env │ │ ├── darwin64-home.env │ │ ├── darwin64-local.env │ │ └── system.env │ ├── openbsd/ │ │ └── liteenv/ │ │ ├── cross-arm5.env │ │ ├── cross-arm6.env │ │ ├── cross-darwin32.env │ │ ├── cross-darwin64.env │ │ ├── cross-freebsd32.env │ │ ├── cross-freebsd64.env │ │ ├── cross-linux32.env │ │ ├── cross-linux64.env │ │ ├── cross-win32.env │ │ ├── cross-win64.env │ │ ├── openbsd32.env │ │ ├── openbsd64.env │ │ └── system.env │ └── windows/ │ ├── liteenv/ │ │ ├── cross-arm5.env │ │ ├── cross-arm6.env │ │ ├── cross-darwin32.env │ │ ├── cross-darwin64.env │ │ ├── cross-freebsd32.env │ │ ├── cross-freebsd64.env │ │ ├── cross-linux32.env │ │ ├── cross-linux64.env │ │ ├── system.env │ │ ├── win32-user.env │ │ ├── win32.env │ │ ├── win64-user.env │ │ └── win64.env │ └── qt.conf ├── src/ │ ├── 3rdparty/ │ │ ├── 3rdparty.pro │ │ ├── cmark/ │ │ │ ├── COPYING │ │ │ ├── README.md │ │ │ ├── changelog.txt │ │ │ ├── cmark.pri │ │ │ ├── cmark.pro │ │ │ ├── cmark_export.h │ │ │ ├── cmark_version.h │ │ │ ├── config.h │ │ │ ├── libcmark.cpp │ │ │ ├── libcmark.h │ │ │ └── src/ │ │ │ ├── CMakeLists.txt │ │ │ ├── blocks.c │ │ │ ├── buffer.c │ │ │ ├── buffer.h │ │ │ ├── case_fold_switch.inc │ │ │ ├── chunk.h │ │ │ ├── cmark.c │ │ │ ├── cmark.h │ │ │ ├── cmark_ctype.c │ │ │ ├── cmark_ctype.h │ │ │ ├── cmark_version.h.in │ │ │ ├── commonmark.c │ │ │ ├── config.h.in │ │ │ ├── entities.inc │ │ │ ├── houdini.h │ │ │ ├── houdini_href_e.c │ │ │ ├── houdini_html_e.c │ │ │ ├── houdini_html_u.c │ │ │ ├── html.c │ │ │ ├── inlines.c │ │ │ ├── inlines.h │ │ │ ├── iterator.c │ │ │ ├── iterator.h │ │ │ ├── latex.c │ │ │ ├── libcmark.pc.in │ │ │ ├── main.c │ │ │ ├── man.c │ │ │ ├── node.c │ │ │ ├── node.h │ │ │ ├── parser.h │ │ │ ├── references.c │ │ │ ├── references.h │ │ │ ├── render.c │ │ │ ├── render.h │ │ │ ├── scanners.c │ │ │ ├── scanners.h │ │ │ ├── scanners.re │ │ │ ├── utf8.c │ │ │ ├── utf8.h │ │ │ └── xml.c │ │ ├── cplusplus/ │ │ │ ├── BackwardsScanner.cpp │ │ │ ├── BackwardsScanner.h │ │ │ ├── Keywords.cpp │ │ │ ├── Keywords.kwgen │ │ │ ├── Lexer.cpp │ │ │ ├── Lexer.h │ │ │ ├── SimpleLexer.cpp │ │ │ ├── SimpleLexer.h │ │ │ ├── Token.cpp │ │ │ ├── Token.h │ │ │ ├── cplusplus.pri │ │ │ ├── cplusplus.pro │ │ │ ├── cppassert.h │ │ │ ├── gobuiltin.cpp │ │ │ ├── gobuiltin.kwgen │ │ │ ├── gogen.bat │ │ │ ├── gokeyword.cpp │ │ │ ├── gokeyword.kwgen │ │ │ ├── gopredecl.cpp │ │ │ ├── gopredecl.kwgen │ │ │ ├── gotypes.cpp │ │ │ └── gotypes.kwgen │ │ ├── diff_match_patch/ │ │ │ ├── README.txt │ │ │ ├── diff_match_patch.cpp │ │ │ ├── diff_match_patch.h │ │ │ ├── diff_match_patch.pri │ │ │ ├── diff_match_patch.pro │ │ │ ├── diff_match_patch_test.cpp │ │ │ └── diff_match_patch_test.h │ │ ├── elidedlabel/ │ │ │ ├── elidedlabel.cpp │ │ │ ├── elidedlabel.h │ │ │ ├── elidedlabel.pri │ │ │ └── elidedlabel.pro │ │ ├── fakevim/ │ │ │ ├── .gitignore │ │ │ ├── LGPL_EXCEPTION.TXT │ │ │ ├── LICENSE.LGPL │ │ │ ├── README.md │ │ │ ├── fakevim/ │ │ │ │ ├── fakevim.pri │ │ │ │ ├── fakevim.pro │ │ │ │ ├── fakevimactions.cpp │ │ │ │ ├── fakevimactions.h │ │ │ │ ├── fakevimhandler.cpp │ │ │ │ ├── fakevimhandler.h │ │ │ │ └── utils/ │ │ │ │ ├── hostosinfo.h │ │ │ │ ├── qtcassert.cpp │ │ │ │ ├── qtcassert.h │ │ │ │ ├── utils.pri │ │ │ │ └── utils_global.h │ │ │ ├── fakevim.pro │ │ │ ├── python/ │ │ │ │ ├── README.md │ │ │ │ ├── build.sh │ │ │ │ ├── configure.py │ │ │ │ ├── fakevim.sip │ │ │ │ ├── fakevimproxy.cpp │ │ │ │ ├── fakevimproxy.h │ │ │ │ └── test.py │ │ │ ├── test/ │ │ │ │ ├── main.cpp │ │ │ │ └── test.pro │ │ │ └── tests/ │ │ │ ├── main.cpp │ │ │ └── vim-test.sh │ │ ├── libucd/ │ │ │ ├── AUTHORS │ │ │ ├── README.md │ │ │ ├── include/ │ │ │ │ └── libucd.h │ │ │ ├── libucd.pri │ │ │ ├── libucd.pro │ │ │ └── src/ │ │ │ ├── Big5Freq.tab │ │ │ ├── CharDistribution.cpp │ │ │ ├── CharDistribution.h │ │ │ ├── EUCKRFreq.tab │ │ │ ├── EUCTWFreq.tab │ │ │ ├── GB2312Freq.tab │ │ │ ├── JISFreq.tab │ │ │ ├── JpCntx.cpp │ │ │ ├── JpCntx.h │ │ │ ├── LangBulgarianModel.cpp │ │ │ ├── LangCyrillicModel.cpp │ │ │ ├── LangCzechModel.cpp │ │ │ ├── LangFinnishModel.cpp │ │ │ ├── LangFrenchModel.cpp │ │ │ ├── LangGermanModel.cpp │ │ │ ├── LangGreekModel.cpp │ │ │ ├── LangHebrewModel.cpp │ │ │ ├── LangHungarianModel.cpp │ │ │ ├── LangPolishModel.cpp │ │ │ ├── LangSpanishModel.cpp │ │ │ ├── LangSwedishModel.cpp │ │ │ ├── LangThaiModel.cpp │ │ │ ├── LangTurkishModel.cpp │ │ │ ├── Makefile.am │ │ │ ├── nsBig5Prober.cpp │ │ │ ├── nsBig5Prober.h │ │ │ ├── nsCharSetProber.cpp │ │ │ ├── nsCharSetProber.h │ │ │ ├── nsCodingStateMachine.h │ │ │ ├── nsDebug.h │ │ │ ├── nsEUCJPProber.cpp │ │ │ ├── nsEUCJPProber.h │ │ │ ├── nsEUCKRProber.cpp │ │ │ ├── nsEUCKRProber.h │ │ │ ├── nsEUCTWProber.cpp │ │ │ ├── nsEUCTWProber.h │ │ │ ├── nsEscCharsetProber.cpp │ │ │ ├── nsEscCharsetProber.h │ │ │ ├── nsEscSM.cpp │ │ │ ├── nsGB2312Prober.cpp │ │ │ ├── nsGB2312Prober.h │ │ │ ├── nsHebrewProber.cpp │ │ │ ├── nsHebrewProber.h │ │ │ ├── nsLatin1Prober.cpp │ │ │ ├── nsLatin1Prober.h │ │ │ ├── nsMBCSGroupProber.cpp │ │ │ ├── nsMBCSGroupProber.h │ │ │ ├── nsMBCSSM.cpp │ │ │ ├── nsPkgInt.h │ │ │ ├── nsSBCSGroupProber.cpp │ │ │ ├── nsSBCSGroupProber.h │ │ │ ├── nsSBCharSetProber.cpp │ │ │ ├── nsSBCharSetProber.h │ │ │ ├── nsSJISProber.cpp │ │ │ ├── nsSJISProber.h │ │ │ ├── nsUTF8Prober.cpp │ │ │ ├── nsUTF8Prober.h │ │ │ ├── nsUniversalDetector.cpp │ │ │ ├── nsUniversalDetector.h │ │ │ ├── nscore.h │ │ │ ├── prmem.h │ │ │ └── ucdapi.cpp │ │ ├── libvterm/ │ │ │ ├── CONTRIBUTING │ │ │ ├── LICENSE │ │ │ ├── bin/ │ │ │ │ ├── unterm.c │ │ │ │ ├── vterm-ctrl.c │ │ │ │ └── vterm-dump.c │ │ │ ├── doc/ │ │ │ │ ├── URLs │ │ │ │ └── seqs.txt │ │ │ ├── find-wide-chars.pl │ │ │ ├── include/ │ │ │ │ ├── vterm.h │ │ │ │ └── vterm_keycodes.h │ │ │ ├── libvterm.pri │ │ │ ├── libvterm.pro │ │ │ ├── src/ │ │ │ │ ├── encoding/ │ │ │ │ │ ├── DECdrawing.inc │ │ │ │ │ ├── DECdrawing.tbl │ │ │ │ │ ├── uk.inc │ │ │ │ │ └── uk.tbl │ │ │ │ ├── encoding.c │ │ │ │ ├── fullwidth.inc │ │ │ │ ├── keyboard.c │ │ │ │ ├── mouse.c │ │ │ │ ├── parser.c │ │ │ │ ├── pen.c │ │ │ │ ├── rect.h │ │ │ │ ├── screen.c │ │ │ │ ├── state.c │ │ │ │ ├── unicode.c │ │ │ │ ├── utf8.h │ │ │ │ ├── vterm.c │ │ │ │ └── vterm_internal.h │ │ │ ├── t/ │ │ │ │ ├── 02parser.test │ │ │ │ ├── 03encoding_utf8.test │ │ │ │ ├── 10state_putglyph.test │ │ │ │ ├── 11state_movecursor.test │ │ │ │ ├── 12state_scroll.test │ │ │ │ ├── 13state_edit.test │ │ │ │ ├── 14state_encoding.test │ │ │ │ ├── 15state_mode.test │ │ │ │ ├── 16state_resize.test │ │ │ │ ├── 17state_mouse.test │ │ │ │ ├── 18state_termprops.test │ │ │ │ ├── 20state_wrapping.test │ │ │ │ ├── 21state_tabstops.test │ │ │ │ ├── 22state_save.test │ │ │ │ ├── 25state_input.test │ │ │ │ ├── 26state_query.test │ │ │ │ ├── 27state_reset.test │ │ │ │ ├── 28state_dbl_wh.test │ │ │ │ ├── 29state_fallback.test │ │ │ │ ├── 30state_pen.test │ │ │ │ ├── 31state_rep.test │ │ │ │ ├── 60screen_ascii.test │ │ │ │ ├── 61screen_unicode.test │ │ │ │ ├── 62screen_damage.test │ │ │ │ ├── 63screen_resize.test │ │ │ │ ├── 64screen_pen.test │ │ │ │ ├── 65screen_protect.test │ │ │ │ ├── 66screen_extent.test │ │ │ │ ├── 67screen_dbl_wh.test │ │ │ │ ├── 68screen_termprops.test │ │ │ │ ├── 90vttest_01-movement-1.test │ │ │ │ ├── 90vttest_01-movement-2.test │ │ │ │ ├── 90vttest_01-movement-3.test │ │ │ │ ├── 90vttest_01-movement-4.test │ │ │ │ ├── 90vttest_02-screen-1.test │ │ │ │ ├── 90vttest_02-screen-2.test │ │ │ │ ├── 90vttest_02-screen-3.test │ │ │ │ ├── 90vttest_02-screen-4.test │ │ │ │ ├── 92lp1640917.test │ │ │ │ ├── harness.c │ │ │ │ └── run-test.pl │ │ │ ├── tbl2inc_c.pl │ │ │ └── vterm.pc.in │ │ ├── ptyqt/ │ │ │ ├── CMakeLists.txt │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── core/ │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── conptyprocess.cpp │ │ │ │ ├── conptyprocess.h │ │ │ │ ├── iptyprocess.h │ │ │ │ ├── ptyqt.cpp │ │ │ │ ├── ptyqt.h │ │ │ │ ├── unixptyprocess.cpp │ │ │ │ ├── unixptyprocess.h │ │ │ │ ├── winpty.h │ │ │ │ ├── winpty_constants.h │ │ │ │ ├── winptyprocess.cpp │ │ │ │ └── winptyprocess.h │ │ │ ├── examples/ │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── vt100terminal/ │ │ │ │ │ ├── CMakeLists.txt │ │ │ │ │ ├── ptydevice.h │ │ │ │ │ └── vt100terminal.cpp │ │ │ │ └── xtermjs/ │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── index.html │ │ │ │ ├── style.css │ │ │ │ └── xtermjs.cpp │ │ │ ├── ptyqt.pri │ │ │ ├── ptyqt.pro │ │ │ └── tests/ │ │ │ ├── CMakeLists.txt │ │ │ └── ptyqt_tests.cpp │ │ ├── qjson/ │ │ │ ├── .gitignore │ │ │ ├── CMakeLists.txt │ │ │ ├── COPYING.lib │ │ │ ├── ChangeLog │ │ │ ├── INSTALL │ │ │ ├── QJSONConfig.cmake.in │ │ │ ├── QJSONConfigVersion.cmake.in │ │ │ ├── QJson.pc.in │ │ │ ├── README │ │ │ ├── cmake_uninstall.cmake.in │ │ │ ├── doc/ │ │ │ │ ├── Doxyfile │ │ │ │ ├── footer.html │ │ │ │ ├── header.html │ │ │ │ └── qjson.dox │ │ │ ├── include/ │ │ │ │ └── QJson/ │ │ │ │ ├── Parser │ │ │ │ ├── QObjectHelper │ │ │ │ └── Serializer │ │ │ ├── qjson.pri │ │ │ ├── qjson.pro │ │ │ ├── src/ │ │ │ │ ├── .gitignore │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── json_parser.cc │ │ │ │ ├── json_parser.hh │ │ │ │ ├── json_parser.yy │ │ │ │ ├── json_scanner.cpp │ │ │ │ ├── json_scanner.h │ │ │ │ ├── location.hh │ │ │ │ ├── parser.cpp │ │ │ │ ├── parser.h │ │ │ │ ├── parser_p.h │ │ │ │ ├── parserrunnable.cpp │ │ │ │ ├── parserrunnable.h │ │ │ │ ├── position.hh │ │ │ │ ├── qjson_debug.h │ │ │ │ ├── qjson_export.h │ │ │ │ ├── qobjecthelper.cpp │ │ │ │ ├── qobjecthelper.h │ │ │ │ ├── serializer.cpp │ │ │ │ ├── serializer.h │ │ │ │ ├── serializerrunnable.cpp │ │ │ │ ├── serializerrunnable.h │ │ │ │ ├── src.pro │ │ │ │ └── stack.hh │ │ │ └── tests/ │ │ │ ├── .gitignore │ │ │ ├── CMakeLists.txt │ │ │ └── tests.pro │ │ ├── qjsonrpc/ │ │ │ ├── AUTHORS │ │ │ ├── CHANGES │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── TODO │ │ │ ├── debian/ │ │ │ │ ├── changelog │ │ │ │ ├── compat │ │ │ │ ├── control │ │ │ │ ├── copyright │ │ │ │ ├── libqjsonrpc-dev.install │ │ │ │ ├── libqjsonrpc.install │ │ │ │ ├── rules │ │ │ │ └── source/ │ │ │ │ └── format │ │ │ ├── qjsonrpc.pri │ │ │ ├── qjsonrpc.pro │ │ │ ├── src/ │ │ │ │ ├── http-parser/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── .mailmap │ │ │ │ │ ├── .travis.yml │ │ │ │ │ ├── AUTHORS │ │ │ │ │ ├── CONTRIBUTIONS │ │ │ │ │ ├── LICENSE-MIT │ │ │ │ │ ├── README.md │ │ │ │ │ ├── contrib/ │ │ │ │ │ │ ├── parsertrace.c │ │ │ │ │ │ └── url_parser.c │ │ │ │ │ ├── http-parser.pri │ │ │ │ │ ├── http_parser.c │ │ │ │ │ ├── http_parser.gyp │ │ │ │ │ ├── http_parser.h │ │ │ │ │ └── test.c │ │ │ │ ├── json/ │ │ │ │ │ ├── json.pri │ │ │ │ │ ├── qjson.cpp │ │ │ │ │ ├── qjson_export.h │ │ │ │ │ ├── qjson_p.h │ │ │ │ │ ├── qjsonarray.cpp │ │ │ │ │ ├── qjsonarray.h │ │ │ │ │ ├── qjsondocument.cpp │ │ │ │ │ ├── qjsondocument.h │ │ │ │ │ ├── qjsonobject.cpp │ │ │ │ │ ├── qjsonobject.h │ │ │ │ │ ├── qjsonparser.cpp │ │ │ │ │ ├── qjsonparser_p.h │ │ │ │ │ ├── qjsonvalue.cpp │ │ │ │ │ ├── qjsonvalue.h │ │ │ │ │ ├── qjsonwriter.cpp │ │ │ │ │ └── qjsonwriter_p.h │ │ │ │ ├── qjsonrpcabstractserver.cpp │ │ │ │ ├── qjsonrpcabstractserver.h │ │ │ │ ├── qjsonrpcabstractserver_p.h │ │ │ │ ├── qjsonrpcglobal.h │ │ │ │ ├── qjsonrpchttpclient.cpp │ │ │ │ ├── qjsonrpchttpclient.h │ │ │ │ ├── qjsonrpchttpserver.cpp │ │ │ │ ├── qjsonrpchttpserver.h │ │ │ │ ├── qjsonrpchttpserver_p.h │ │ │ │ ├── qjsonrpclocalserver.cpp │ │ │ │ ├── qjsonrpclocalserver.h │ │ │ │ ├── qjsonrpcmessage.cpp │ │ │ │ ├── qjsonrpcmessage.h │ │ │ │ ├── qjsonrpcmetatype.h │ │ │ │ ├── qjsonrpcservice.cpp │ │ │ │ ├── qjsonrpcservice.h │ │ │ │ ├── qjsonrpcservice_p.h │ │ │ │ ├── qjsonrpcserviceprovider.cpp │ │ │ │ ├── qjsonrpcserviceprovider.h │ │ │ │ ├── qjsonrpcservicereply.cpp │ │ │ │ ├── qjsonrpcservicereply.h │ │ │ │ ├── qjsonrpcservicereply_p.h │ │ │ │ ├── qjsonrpcsocket.cpp │ │ │ │ ├── qjsonrpcsocket.h │ │ │ │ ├── qjsonrpcsocket_p.h │ │ │ │ ├── qjsonrpctcpserver.cpp │ │ │ │ ├── qjsonrpctcpserver.h │ │ │ │ └── src.pro │ │ │ └── tests/ │ │ │ ├── auto/ │ │ │ │ ├── auto.pro │ │ │ │ ├── issue22/ │ │ │ │ │ ├── issue22.pro │ │ │ │ │ └── tst_issue22.cpp │ │ │ │ ├── json/ │ │ │ │ │ ├── bom.json │ │ │ │ │ ├── json.pro │ │ │ │ │ ├── test.bjson │ │ │ │ │ ├── test.json │ │ │ │ │ ├── test2.json │ │ │ │ │ ├── test3.json │ │ │ │ │ ├── tst_qtjson.cpp │ │ │ │ │ └── tst_qtjson.qrc │ │ │ │ ├── qjsonrpchttpclient/ │ │ │ │ │ ├── qjsonrpchttpclient.pro │ │ │ │ │ ├── testhttpserver.cpp │ │ │ │ │ ├── testhttpserver.h │ │ │ │ │ └── tst_qjsonrpchttpclient.cpp │ │ │ │ ├── qjsonrpchttpserver/ │ │ │ │ │ ├── certificates.qrc │ │ │ │ │ ├── certs/ │ │ │ │ │ │ ├── aspiriniks.ca.crt │ │ │ │ │ │ ├── fake-login.live.com.key │ │ │ │ │ │ ├── fake-login.live.com.pem │ │ │ │ │ │ ├── fluke.cert │ │ │ │ │ │ ├── fluke.key │ │ │ │ │ │ └── qt-test-server-cacert.pem │ │ │ │ │ ├── qjsonrpchttpserver.pro │ │ │ │ │ └── tst_qjsonrpchttpserver.cpp │ │ │ │ ├── qjsonrpcmessage/ │ │ │ │ │ ├── qjsonrpcmessage.pro │ │ │ │ │ └── tst_qjsonrpcmessage.cpp │ │ │ │ ├── qjsonrpcmetatype/ │ │ │ │ │ ├── qjsonrpcmetatype.pro │ │ │ │ │ └── tst_qjsonrpcmetatype.cpp │ │ │ │ ├── qjsonrpcserver/ │ │ │ │ │ ├── qjsonrpcserver.pro │ │ │ │ │ ├── testservices.cpp │ │ │ │ │ ├── testservices.h │ │ │ │ │ └── tst_qjsonrpcserver.cpp │ │ │ │ ├── qjsonrpcservice/ │ │ │ │ │ ├── qjsonrpcservice.pro │ │ │ │ │ └── tst_qjsonrpcservice.cpp │ │ │ │ └── qjsonrpcsocket/ │ │ │ │ ├── qjsonrpcsocket.pro │ │ │ │ ├── testwire.json │ │ │ │ ├── tst_qjsonrpcsocket.cpp │ │ │ │ └── tst_qjsonrpcsocket.qrc │ │ │ ├── common/ │ │ │ │ └── signalspy.h │ │ │ ├── gen-coverage.sh │ │ │ ├── manual/ │ │ │ │ ├── benchmark/ │ │ │ │ │ ├── benchmark.pro │ │ │ │ │ └── tst_benchmark.cpp │ │ │ │ ├── console/ │ │ │ │ │ ├── console.pro │ │ │ │ │ ├── interface.cpp │ │ │ │ │ ├── interface.h │ │ │ │ │ └── main.cpp │ │ │ │ ├── httpclient/ │ │ │ │ │ ├── httpclient.pro │ │ │ │ │ └── main.cpp │ │ │ │ ├── httpserver/ │ │ │ │ │ ├── httpserver.cpp │ │ │ │ │ ├── httpserver.pro │ │ │ │ │ ├── testservice.cpp │ │ │ │ │ └── testservice.h │ │ │ │ ├── localclient/ │ │ │ │ │ ├── localclient.cpp │ │ │ │ │ ├── localclient.h │ │ │ │ │ ├── localclient.pro │ │ │ │ │ ├── main.cpp │ │ │ │ │ └── runclientmac │ │ │ │ ├── localserver/ │ │ │ │ │ ├── localserver.cpp │ │ │ │ │ ├── localserver.pro │ │ │ │ │ ├── runservermac │ │ │ │ │ ├── testservice.cpp │ │ │ │ │ └── testservice.h │ │ │ │ ├── manual.pro │ │ │ │ ├── python/ │ │ │ │ │ ├── jsonrpc.py │ │ │ │ │ └── testqjsonrpc.py │ │ │ │ ├── qjsonrpc/ │ │ │ │ │ ├── qjsonrpc.cpp │ │ │ │ │ └── qjsonrpc.pro │ │ │ │ ├── tcpclient/ │ │ │ │ │ ├── main.cpp │ │ │ │ │ ├── runclientmac │ │ │ │ │ ├── tcpclient.cpp │ │ │ │ │ ├── tcpclient.h │ │ │ │ │ └── tcpclient.pro │ │ │ │ └── tcpserver/ │ │ │ │ ├── runservermac │ │ │ │ ├── tcpserver.cpp │ │ │ │ ├── tcpserver.pro │ │ │ │ ├── testservice.cpp │ │ │ │ └── testservice.h │ │ │ ├── tests.pri │ │ │ └── tests.pro │ │ ├── qt_browser/ │ │ │ ├── chasewidget.cpp │ │ │ ├── chasewidget.h │ │ │ ├── qt_browser.pri │ │ │ └── qt_browser.pro │ │ ├── qtc_editutil/ │ │ │ ├── fancylineedit.cpp │ │ │ ├── fancylineedit.h │ │ │ ├── filterlineedit.cpp │ │ │ ├── filterlineedit.h │ │ │ ├── qtc_editutil.pri │ │ │ ├── qtc_editutil.pro │ │ │ ├── uncommentselection.cpp │ │ │ ├── uncommentselection.h │ │ │ └── utils_global.h │ │ ├── qtc_gdbmi/ │ │ │ ├── gdbmi.cpp │ │ │ ├── gdbmi.h │ │ │ ├── qtc_gdbmi.pri │ │ │ └── qtc_gdbmi.pro │ │ ├── qtc_itemview/ │ │ │ ├── itemviews.cpp │ │ │ ├── itemviews.h │ │ │ ├── opendocumentstreeview.cpp │ │ │ ├── opendocumentstreeview.h │ │ │ ├── proxymodel.cpp │ │ │ ├── proxymodel.h │ │ │ ├── qtc_itemview.pri │ │ │ ├── qtc_itemview.pro │ │ │ └── qtc_itemview.qrc │ │ ├── qtc_searchresult/ │ │ │ ├── qtc_searchresult.pri │ │ │ ├── qtc_searchresult.pro │ │ │ ├── searchresultcolor.h │ │ │ ├── searchresultitem.h │ │ │ ├── searchresulttreeitemdelegate.cpp │ │ │ ├── searchresulttreeitemdelegate.h │ │ │ ├── searchresulttreeitemroles.h │ │ │ ├── searchresulttreeitems.cpp │ │ │ ├── searchresulttreeitems.h │ │ │ ├── searchresulttreemodel.cpp │ │ │ ├── searchresulttreemodel.h │ │ │ ├── searchresulttreeview.cpp │ │ │ ├── searchresulttreeview.h │ │ │ ├── searchresultwidget.cpp │ │ │ └── searchresultwidget.h │ │ ├── qtc_texteditor/ │ │ │ ├── autocompleter.cpp │ │ │ ├── autocompleter.h │ │ │ ├── basetextblockselection.cpp │ │ │ ├── basetextblockselection.h │ │ │ ├── basetextdocumentlayout.cpp │ │ │ ├── basetextdocumentlayout.h │ │ │ ├── colorscheme.cpp │ │ │ ├── colorscheme.h │ │ │ ├── generichighlighter/ │ │ │ │ ├── context.cpp │ │ │ │ ├── context.h │ │ │ │ ├── definitiondownloader.cpp │ │ │ │ ├── definitiondownloader.h │ │ │ │ ├── dynamicrule.cpp │ │ │ │ ├── dynamicrule.h │ │ │ │ ├── highlightdefinition.cpp │ │ │ │ ├── highlightdefinition.h │ │ │ │ ├── highlightdefinitionhandler.cpp │ │ │ │ ├── highlightdefinitionhandler.h │ │ │ │ ├── highlightdefinitionmetadata.cpp │ │ │ │ ├── highlightdefinitionmetadata.h │ │ │ │ ├── highlighter.cpp │ │ │ │ ├── highlighter.h │ │ │ │ ├── highlighterexception.h │ │ │ │ ├── highlightersettingspage.ui │ │ │ │ ├── includerulesinstruction.cpp │ │ │ │ ├── includerulesinstruction.h │ │ │ │ ├── itemdata.cpp │ │ │ │ ├── itemdata.h │ │ │ │ ├── keywordlist.cpp │ │ │ │ ├── keywordlist.h │ │ │ │ ├── managedefinitionsdialog.cpp │ │ │ │ ├── managedefinitionsdialog.h │ │ │ │ ├── managedefinitionsdialog.ui │ │ │ │ ├── manager.cpp │ │ │ │ ├── manager.h │ │ │ │ ├── manager2.cpp │ │ │ │ ├── manager2.h │ │ │ │ ├── progressdata.cpp │ │ │ │ ├── progressdata.h │ │ │ │ ├── reuse.h │ │ │ │ ├── rule.cpp │ │ │ │ ├── rule.h │ │ │ │ ├── specificrules.cpp │ │ │ │ └── specificrules.h │ │ │ ├── itexteditor.cpp │ │ │ ├── itexteditor.h │ │ │ ├── katehighlighter.cpp │ │ │ ├── katehighlighter.h │ │ │ ├── qtc_texteditor.pri │ │ │ ├── qtc_texteditor.pro │ │ │ ├── syntaxhighlighter.cpp │ │ │ ├── syntaxhighlighter.h │ │ │ ├── tabsettings.cpp │ │ │ ├── tabsettings.h │ │ │ ├── texteditor_global.h │ │ │ ├── texteditorconstants.h │ │ │ └── utils/ │ │ │ └── settingsutils.h │ │ └── treemodelcompleter/ │ │ ├── treemodelcompleter.cpp │ │ ├── treemodelcompleter.h │ │ ├── treemodelcompleter.pri │ │ └── treemodelcompleter.pro │ ├── api/ │ │ ├── api.pro │ │ ├── docbrowserapi/ │ │ │ ├── docbrowserapi.h │ │ │ ├── docbrowserapi.pri │ │ │ └── docbrowserapi.pro │ │ ├── golangastapi/ │ │ │ ├── golangastapi.h │ │ │ ├── golangastapi.pri │ │ │ └── golangastapi.pro │ │ ├── golangdocapi/ │ │ │ ├── golangdocapi.h │ │ │ ├── golangdocapi.pri │ │ │ └── golangdocapi.pro │ │ ├── liteapi/ │ │ │ ├── liteapi.h │ │ │ ├── liteapi.pri │ │ │ ├── liteapi.pro │ │ │ ├── litehtml.h │ │ │ ├── liteids.h │ │ │ ├── liteobj.h │ │ │ ├── liteqt.h │ │ │ └── liteutil.h │ │ ├── litebuildapi/ │ │ │ ├── litebuildapi.h │ │ │ ├── litebuildapi.pri │ │ │ └── litebuildapi.pro │ │ ├── litedebugapi/ │ │ │ ├── litedebugapi.h │ │ │ ├── litedebugapi.pri │ │ │ └── litedebugapi.pro │ │ ├── liteeditorapi/ │ │ │ ├── liteeditorapi.h │ │ │ ├── liteeditorapi.pri │ │ │ └── liteeditorapi.pro │ │ ├── liteenvapi/ │ │ │ ├── liteenvapi.h │ │ │ ├── liteenvapi.pri │ │ │ └── liteenvapi.pro │ │ ├── litefindapi/ │ │ │ ├── litefindapi.h │ │ │ ├── litefindapi.pri │ │ │ └── litefindapi.pro │ │ ├── litettyapi/ │ │ │ ├── litettyapi.h │ │ │ ├── litettyapi.pri │ │ │ └── litettyapi.pro │ │ ├── quickopenapi/ │ │ │ ├── quickopenapi.h │ │ │ ├── quickopenapi.pri │ │ │ └── quickopenapi.pro │ │ └── terminalapi/ │ │ ├── terminalapi.h │ │ ├── terminalapi.pri │ │ └── terminalapi.pro │ ├── libgopher/ │ │ └── libgopher.go │ ├── license_update.lua │ ├── liteapp/ │ │ ├── Info.plist │ │ ├── aboutdialog.cpp │ │ ├── aboutdialog.h │ │ ├── aboutdialog.ui │ │ ├── actionmanager.cpp │ │ ├── actionmanager.h │ │ ├── cdrv.h │ │ ├── editormanager.cpp │ │ ├── editormanager.h │ │ ├── filemanager.cpp │ │ ├── filemanager.h │ │ ├── folderproject.cpp │ │ ├── folderproject.h │ │ ├── folderprojectfactory.cpp │ │ ├── folderprojectfactory.h │ │ ├── goproxy.cpp │ │ ├── goproxy.h │ │ ├── htmlwidgetmanager.cpp │ │ ├── htmlwidgetmanager.h │ │ ├── idletimer.cpp │ │ ├── idletimer.h │ │ ├── images/ │ │ │ └── liteide.icns │ │ ├── liteapp.cpp │ │ ├── liteapp.h │ │ ├── liteapp.pri │ │ ├── liteapp.pro │ │ ├── liteapp.qrc │ │ ├── liteapp.rc │ │ ├── liteapp_global.h │ │ ├── liteappoption.cpp │ │ ├── liteappoption.h │ │ ├── liteappoption.ui │ │ ├── liteappoptionfactory.cpp │ │ ├── liteappoptionfactory.h │ │ ├── macsupport.h │ │ ├── macsupport.mm │ │ ├── main.cpp │ │ ├── mainwindow.cpp │ │ ├── mainwindow.h │ │ ├── mimetypemanager.cpp │ │ ├── mimetypemanager.h │ │ ├── multifolderwindow.cpp │ │ ├── multifolderwindow.h │ │ ├── newfiledialog.cpp │ │ ├── newfiledialog.h │ │ ├── newfiledialog.ui │ │ ├── openeditorswidget.cpp │ │ ├── openeditorswidget.h │ │ ├── optionmanager.cpp │ │ ├── optionmanager.h │ │ ├── optionsbrowser.cpp │ │ ├── optionsbrowser.h │ │ ├── optionswidget.ui │ │ ├── outputoption.cpp │ │ ├── outputoption.h │ │ ├── outputoption.ui │ │ ├── pluginmanager.cpp │ │ ├── pluginmanager.h │ │ ├── pluginsdialog.cpp │ │ ├── pluginsdialog.h │ │ ├── pluginsdialog.ui │ │ ├── projectmanager.cpp │ │ ├── projectmanager.h │ │ ├── recentmanager.cpp │ │ ├── recentmanager.h │ │ ├── rotationtoolbutton.cpp │ │ ├── rotationtoolbutton.h │ │ ├── sidewindowstyle.cpp │ │ ├── sidewindowstyle.h │ │ ├── splitfolderwindow.cpp │ │ ├── splitfolderwindow.h │ │ ├── splitwindowstyle.cpp │ │ ├── splitwindowstyle.h │ │ ├── textbrowserhtmlwidget.cpp │ │ ├── textbrowserhtmlwidget.h │ │ ├── tooldockwidget.cpp │ │ ├── tooldockwidget.h │ │ ├── toolmainwindow.cpp │ │ ├── toolmainwindow.h │ │ ├── toolwindowmanager.cpp │ │ ├── toolwindowmanager.h │ │ └── windowstyle.h │ ├── liteide/ │ │ ├── Info.plist │ │ ├── liteide.icns │ │ ├── liteide.pro │ │ ├── liteide.rc │ │ └── main.cpp │ ├── liteideapi.pri │ ├── liteideplugin.pri │ ├── liteideutils.pri │ ├── liteshell/ │ │ ├── ReadMe.txt │ │ ├── StdAfx.cpp │ │ ├── StdAfx.h │ │ ├── liteshell.cpp │ │ ├── liteshell.dsp │ │ └── liteshell.dsw │ ├── memleak_readme.txt │ ├── memleak_remove.lua │ ├── memleak_update.lua │ ├── pch/ │ │ ├── liteide_gui_pch.h │ │ └── liteide_pch.h │ ├── plugins/ │ │ ├── bookmarks/ │ │ │ ├── bookmarkmanager.cpp │ │ │ ├── bookmarkmanager.h │ │ │ ├── bookmarkmodel.cpp │ │ │ ├── bookmarkmodel.h │ │ │ ├── bookmarks.pro │ │ │ ├── bookmarks.qrc │ │ │ ├── bookmarks_global.h │ │ │ ├── bookmarksplugin.cpp │ │ │ └── bookmarksplugin.h │ │ ├── dlvdebugger/ │ │ │ ├── dlvdebugger.cpp │ │ │ ├── dlvdebugger.h │ │ │ ├── dlvdebugger.pro │ │ │ ├── dlvdebugger_global.h │ │ │ ├── dlvdebuggeroption.cpp │ │ │ ├── dlvdebuggeroption.h │ │ │ ├── dlvdebuggeroption.ui │ │ │ ├── dlvdebuggeroptionfactory.cpp │ │ │ ├── dlvdebuggeroptionfactory.h │ │ │ ├── dlvdebuggerplugin.cpp │ │ │ ├── dlvdebuggerplugin.h │ │ │ ├── dlvrpcdebugger.cpp │ │ │ └── dlvrpcdebugger.h │ │ ├── fakevimedit/ │ │ │ ├── fakevimedit.cpp │ │ │ ├── fakevimedit.h │ │ │ ├── fakevimedit.pro │ │ │ ├── fakevimedit_global.h │ │ │ ├── fakevimeditoption.cpp │ │ │ ├── fakevimeditoption.h │ │ │ ├── fakevimeditoption.ui │ │ │ ├── fakevimeditoptionfactory.cpp │ │ │ ├── fakevimeditoptionfactory.h │ │ │ ├── fakevimeditplugin.cpp │ │ │ └── fakevimeditplugin.h │ │ ├── filebrowser/ │ │ │ ├── filebrowser.cpp │ │ │ ├── filebrowser.h │ │ │ ├── filebrowser.pro │ │ │ ├── filebrowser.qrc │ │ │ ├── filebrowser_global.h │ │ │ ├── filebrowseroption.cpp │ │ │ ├── filebrowseroption.h │ │ │ ├── filebrowseroption.ui │ │ │ ├── filebrowseroptionfactory.cpp │ │ │ ├── filebrowseroptionfactory.h │ │ │ ├── filebrowserplugin.cpp │ │ │ └── filebrowserplugin.h │ │ ├── gdbdebugger/ │ │ │ ├── gdbdebugger.cpp │ │ │ ├── gdbdebugger.h │ │ │ ├── gdbdebugger.pro │ │ │ ├── gdbdebugger_global.h │ │ │ ├── gdbdebuggeroption.cpp │ │ │ ├── gdbdebuggeroption.h │ │ │ ├── gdbdebuggeroption.ui │ │ │ ├── gdbdebuggeroptionfactory.cpp │ │ │ ├── gdbdebuggeroptionfactory.h │ │ │ ├── gdbdebuggerplugin.cpp │ │ │ └── gdbdebuggerplugin.h │ │ ├── golangast/ │ │ │ ├── astwidget.cpp │ │ │ ├── astwidget.h │ │ │ ├── golangast.cpp │ │ │ ├── golangast.h │ │ │ ├── golangast.pro │ │ │ ├── golangast.qrc │ │ │ ├── golangast_global.h │ │ │ ├── golangasticon.cpp │ │ │ ├── golangasticon.h │ │ │ ├── golangastitem.h │ │ │ ├── golangastoption.cpp │ │ │ ├── golangastoption.h │ │ │ ├── golangastoption.ui │ │ │ ├── golangastoptionfactory.cpp │ │ │ ├── golangastoptionfactory.h │ │ │ ├── golangastplugin.cpp │ │ │ ├── golangastplugin.h │ │ │ ├── golangsymbol.cpp │ │ │ └── golangsymbol.h │ │ ├── golangcode/ │ │ │ ├── golangcode.cpp │ │ │ ├── golangcode.h │ │ │ ├── golangcode.pro │ │ │ ├── golangcode_global.h │ │ │ ├── golangcodeoption.cpp │ │ │ ├── golangcodeoption.h │ │ │ ├── golangcodeoption.ui │ │ │ ├── golangcodeoptionfactory.cpp │ │ │ ├── golangcodeoptionfactory.h │ │ │ ├── golangcodeplugin.cpp │ │ │ └── golangcodeplugin.h │ │ ├── golangdoc/ │ │ │ ├── findapiwidget.cpp │ │ │ ├── findapiwidget.h │ │ │ ├── finddocwidget.cpp │ │ │ ├── finddocwidget.h │ │ │ ├── golangdoc.cpp │ │ │ ├── golangdoc.h │ │ │ ├── golangdoc.pro │ │ │ ├── golangdoc_global.h │ │ │ ├── golangdocoption.cpp │ │ │ ├── golangdocoption.h │ │ │ ├── golangdocoption.ui │ │ │ ├── golangdocoptionfactory.cpp │ │ │ ├── golangdocoptionfactory.h │ │ │ ├── golangdocplugin.cpp │ │ │ └── golangdocplugin.h │ │ ├── golangedit/ │ │ │ ├── goaddtagsdialog.cpp │ │ │ ├── goaddtagsdialog.h │ │ │ ├── goaddtagsdialog.ui │ │ │ ├── golangedit.cpp │ │ │ ├── golangedit.h │ │ │ ├── golangedit.pro │ │ │ ├── golangedit_global.h │ │ │ ├── golangeditoption.cpp │ │ │ ├── golangeditoption.h │ │ │ ├── golangeditoption.ui │ │ │ ├── golangeditoptionfactory.cpp │ │ │ ├── golangeditoptionfactory.h │ │ │ ├── golangeditplugin.cpp │ │ │ ├── golangeditplugin.h │ │ │ ├── golangfilesearch.cpp │ │ │ ├── golangfilesearch.h │ │ │ ├── golanghighlighter.cpp │ │ │ ├── golanghighlighter.h │ │ │ ├── golanghighlighterfactory.cpp │ │ │ ├── golanghighlighterfactory.h │ │ │ ├── golangtextlexer.cpp │ │ │ ├── golangtextlexer.h │ │ │ ├── goplsfilesearch.cpp │ │ │ ├── goplsfilesearch.h │ │ │ ├── goremovetagsdialog.cpp │ │ │ ├── goremovetagsdialog.h │ │ │ └── goremovetagsdialog.ui │ │ ├── golangfmt/ │ │ │ ├── golangfmt.cpp │ │ │ ├── golangfmt.h │ │ │ ├── golangfmt.pro │ │ │ ├── golangfmt.qrc │ │ │ ├── golangfmt_global.h │ │ │ ├── golangfmtoption.cpp │ │ │ ├── golangfmtoption.h │ │ │ ├── golangfmtoption.ui │ │ │ ├── golangfmtoptionfactory.cpp │ │ │ ├── golangfmtoptionfactory.h │ │ │ ├── golangfmtplugin.cpp │ │ │ └── golangfmtplugin.h │ │ ├── golanglint/ │ │ │ ├── golanglint.cpp │ │ │ ├── golanglint.h │ │ │ ├── golanglint.pro │ │ │ ├── golanglint.qrc │ │ │ ├── golanglint_global.h │ │ │ ├── golanglintoption.cpp │ │ │ ├── golanglintoption.h │ │ │ ├── golanglintoption.ui │ │ │ ├── golanglintoptionfactory.cpp │ │ │ ├── golanglintoptionfactory.h │ │ │ ├── golanglintplugin.cpp │ │ │ └── golanglintplugin.h │ │ ├── golangpackage/ │ │ │ ├── filepathmodel.cpp │ │ │ ├── filepathmodel.h │ │ │ ├── golangpackage.pro │ │ │ ├── golangpackage_global.h │ │ │ ├── golangpackageoption.cpp │ │ │ ├── golangpackageoption.h │ │ │ ├── golangpackageoption.ui │ │ │ ├── golangpackageoptionfactory.cpp │ │ │ ├── golangpackageoptionfactory.h │ │ │ ├── golangpackageplugin.cpp │ │ │ ├── golangpackageplugin.h │ │ │ ├── gotool.cpp │ │ │ ├── gotool.h │ │ │ ├── packagebrowser.cpp │ │ │ ├── packagebrowser.h │ │ │ ├── packageproject.cpp │ │ │ ├── packageproject.h │ │ │ ├── packageprojectfactory.cpp │ │ │ ├── packageprojectfactory.h │ │ │ ├── packagetree.cpp │ │ │ └── packagetree.h │ │ ├── golangplay/ │ │ │ ├── golangplay.pro │ │ │ ├── golangplay_global.h │ │ │ ├── golangplayplugin.cpp │ │ │ ├── golangplayplugin.h │ │ │ ├── goplaybrowser.cpp │ │ │ └── goplaybrowser.h │ │ ├── golangpresent/ │ │ │ ├── exportdialog.cpp │ │ │ ├── exportdialog.h │ │ │ ├── exportdialog.ui │ │ │ ├── golangpresent.pro │ │ │ ├── golangpresent.qrc │ │ │ ├── golangpresent_global.h │ │ │ ├── golangpresentedit.cpp │ │ │ ├── golangpresentedit.h │ │ │ ├── golangpresentplugin.cpp │ │ │ └── golangpresentplugin.h │ │ ├── golangtool/ │ │ │ ├── golangtool.pro │ │ │ ├── golangtool.qrc │ │ │ ├── golangtool_global.h │ │ │ ├── golangtoolplugin.cpp │ │ │ ├── golangtoolplugin.h │ │ │ ├── gopathbrowser.cpp │ │ │ ├── gopathbrowser.h │ │ │ ├── gopathmodel.cpp │ │ │ ├── gopathmodel.h │ │ │ ├── gopathproject.cpp │ │ │ ├── gopathproject.h │ │ │ ├── gopathprojectfactor.cpp │ │ │ ├── gopathprojectfactor.h │ │ │ ├── importgopathdialog.cpp │ │ │ ├── importgopathdialog.h │ │ │ └── importgopathdialog.ui │ │ ├── imageeditor/ │ │ │ ├── imageeditor.cpp │ │ │ ├── imageeditor.h │ │ │ ├── imageeditor.pro │ │ │ ├── imageeditor.qrc │ │ │ ├── imageeditor_global.h │ │ │ ├── imageeditorfactory.cpp │ │ │ ├── imageeditorfactory.h │ │ │ ├── imageeditorfile.cpp │ │ │ ├── imageeditorfile.h │ │ │ ├── imageeditorplugin.cpp │ │ │ ├── imageeditorplugin.h │ │ │ ├── imageeditorwidget.cpp │ │ │ └── imageeditorwidget.h │ │ ├── jsonedit/ │ │ │ ├── jsonedit.cpp │ │ │ ├── jsonedit.h │ │ │ ├── jsonedit.pro │ │ │ ├── jsonedit_global.h │ │ │ ├── jsoneditplugin.cpp │ │ │ └── jsoneditplugin.h │ │ ├── litebuild/ │ │ │ ├── build.cpp │ │ │ ├── build.h │ │ │ ├── buildconfigdialog.cpp │ │ │ ├── buildconfigdialog.h │ │ │ ├── buildconfigdialog.ui │ │ │ ├── buildmanager.cpp │ │ │ ├── buildmanager.h │ │ │ ├── images/ │ │ │ │ └── image.pdn │ │ │ ├── litebuild.cpp │ │ │ ├── litebuild.h │ │ │ ├── litebuild.pro │ │ │ ├── litebuild.qrc │ │ │ ├── litebuild_global.h │ │ │ ├── litebuildoption.cpp │ │ │ ├── litebuildoption.h │ │ │ ├── litebuildoption.ui │ │ │ ├── litebuildoptionfactory.cpp │ │ │ ├── litebuildoptionfactory.h │ │ │ ├── litebuildplugin.cpp │ │ │ └── litebuildplugin.h │ │ ├── litedebug/ │ │ │ ├── debugmanager.cpp │ │ │ ├── debugmanager.h │ │ │ ├── debugwidget.cpp │ │ │ ├── debugwidget.h │ │ │ ├── litedebug.cpp │ │ │ ├── litedebug.h │ │ │ ├── litedebug.pro │ │ │ ├── litedebug.qrc │ │ │ ├── litedebug_global.h │ │ │ ├── litedebugoption.cpp │ │ │ ├── litedebugoption.h │ │ │ ├── litedebugoption.ui │ │ │ ├── litedebugoptionfactory.cpp │ │ │ ├── litedebugoptionfactory.h │ │ │ ├── litedebugplugin.cpp │ │ │ ├── litedebugplugin.h │ │ │ ├── selectexternaldialog.cpp │ │ │ ├── selectexternaldialog.h │ │ │ └── selectexternaldialog.ui │ │ ├── liteeditor/ │ │ │ ├── codecompleter.cpp │ │ │ ├── codecompleter.h │ │ │ ├── editorapimanager.cpp │ │ │ ├── editorapimanager.h │ │ │ ├── faketooltip.cpp │ │ │ ├── faketooltip.h │ │ │ ├── functiontooltip.cpp │ │ │ ├── functiontooltip.h │ │ │ ├── highlightermanager.cpp │ │ │ ├── highlightermanager.h │ │ │ ├── katehighlighterfactory.cpp │ │ │ ├── katehighlighterfactory.h │ │ │ ├── katetextlexer.cpp │ │ │ ├── katetextlexer.h │ │ │ ├── litecompleter.cpp │ │ │ ├── litecompleter.h │ │ │ ├── liteeditor.cpp │ │ │ ├── liteeditor.h │ │ │ ├── liteeditor.pro │ │ │ ├── liteeditor.qrc │ │ │ ├── liteeditor.xml │ │ │ ├── liteeditor_global.h │ │ │ ├── liteeditorfile.cpp │ │ │ ├── liteeditorfile.h │ │ │ ├── liteeditorfilefactory.cpp │ │ │ ├── liteeditorfilefactory.h │ │ │ ├── liteeditormark.cpp │ │ │ ├── liteeditormark.h │ │ │ ├── liteeditoroption.cpp │ │ │ ├── liteeditoroption.h │ │ │ ├── liteeditoroption.ui │ │ │ ├── liteeditoroptionfactory.cpp │ │ │ ├── liteeditoroptionfactory.h │ │ │ ├── liteeditorplugin.cpp │ │ │ ├── liteeditorplugin.h │ │ │ ├── liteeditorwidget.cpp │ │ │ ├── liteeditorwidget.h │ │ │ ├── liteeditorwidgetbase.cpp │ │ │ ├── liteeditorwidgetbase.h │ │ │ ├── litewordcompleter.cpp │ │ │ ├── litewordcompleter.h │ │ │ ├── snippetapi.cpp │ │ │ ├── snippetapi.h │ │ │ ├── wordapi.cpp │ │ │ └── wordapi.h │ │ ├── liteenv/ │ │ │ ├── envmanager.cpp │ │ │ ├── envmanager.h │ │ │ ├── goenvmanager.cpp │ │ │ ├── goenvmanager.h │ │ │ ├── liteenv.pro │ │ │ ├── liteenv.qrc │ │ │ ├── liteenv_global.h │ │ │ ├── liteenvoption.cpp │ │ │ ├── liteenvoption.h │ │ │ ├── liteenvoption.ui │ │ │ ├── liteenvoptionfactory.cpp │ │ │ ├── liteenvoptionfactory.h │ │ │ ├── liteenvplugin.cpp │ │ │ └── liteenvplugin.h │ │ ├── litefind/ │ │ │ ├── filesearch.cpp │ │ │ ├── filesearch.h │ │ │ ├── filesearchmanager.cpp │ │ │ ├── filesearchmanager.h │ │ │ ├── findeditor.cpp │ │ │ ├── findeditor.h │ │ │ ├── litefind.pro │ │ │ ├── litefind_global.h │ │ │ ├── litefindplugin.cpp │ │ │ ├── litefindplugin.h │ │ │ ├── replacedocument.cpp │ │ │ └── replacedocument.h │ │ ├── liteshell/ │ │ │ ├── liteshell.pro │ │ │ ├── liteshell_global.h │ │ │ ├── liteshellplugin.cpp │ │ │ └── liteshellplugin.h │ │ ├── litetty/ │ │ │ ├── fifotty.cpp │ │ │ ├── fifotty.h │ │ │ ├── litetty.cpp │ │ │ ├── litetty.h │ │ │ ├── litetty.pro │ │ │ ├── litetty_global.h │ │ │ ├── litettyplugin.cpp │ │ │ ├── litettyplugin.h │ │ │ ├── sockettty.cpp │ │ │ └── sockettty.h │ │ ├── makefileproject/ │ │ │ ├── makefilefile.cpp │ │ │ ├── makefilefile.h │ │ │ ├── makefilefilefactory.cpp │ │ │ ├── makefilefilefactory.h │ │ │ ├── makefileproject.cpp │ │ │ ├── makefileproject.h │ │ │ ├── makefileproject.pro │ │ │ ├── makefileproject.xml │ │ │ ├── makefileproject_global.h │ │ │ ├── makefileprojectplugin.cpp │ │ │ └── makefileprojectplugin.h │ │ ├── markdown/ │ │ │ ├── css/ │ │ │ │ └── textbrowser.css │ │ │ ├── htmlpreview.cpp │ │ │ ├── htmlpreview.h │ │ │ ├── markdown.pro │ │ │ ├── markdown.qrc │ │ │ ├── markdown_global.h │ │ │ ├── markdownbatchbrowser.cpp │ │ │ ├── markdownbatchbrowser.h │ │ │ ├── markdownbatchwidget.ui │ │ │ ├── markdownedit.cpp │ │ │ ├── markdownedit.h │ │ │ ├── markdownplugin.cpp │ │ │ └── markdownplugin.h │ │ ├── plugins.pro │ │ ├── profileproject/ │ │ │ ├── profilefile.cpp │ │ │ ├── profilefile.h │ │ │ ├── profilefilefactory.cpp │ │ │ ├── profilefilefactory.h │ │ │ ├── profileproject.cpp │ │ │ ├── profileproject.h │ │ │ ├── profileproject.pro │ │ │ ├── profileproject.xml │ │ │ ├── profileproject_global.h │ │ │ ├── profileprojectplugin.cpp │ │ │ └── profileprojectplugin.h │ │ ├── qsqleditor/ │ │ │ ├── qsqldbfile.cpp │ │ │ ├── qsqldbfile.h │ │ │ ├── qsqleditor.cpp │ │ │ ├── qsqleditor.h │ │ │ ├── qsqleditor.pro │ │ │ ├── qsqleditor.ui │ │ │ ├── qsqleditor_global.h │ │ │ ├── qsqleditorplugin.cpp │ │ │ ├── qsqleditorplugin.h │ │ │ ├── qsqlfilefactory.cpp │ │ │ ├── qsqlfilefactory.h │ │ │ ├── sqlitefile.h │ │ │ ├── sqlitemdelegate.cpp │ │ │ ├── sqlitemdelegate.h │ │ │ ├── sqliterfile.cpp │ │ │ ├── sqltablemodel.cpp │ │ │ ├── sqltablemodel.h │ │ │ ├── tableviewwidget.cpp │ │ │ ├── tableviewwidget.h │ │ │ └── tableviewwidget.ui │ │ ├── quickopen/ │ │ │ ├── quickopen.pro │ │ │ ├── quickopen_global.h │ │ │ ├── quickopenaction.cpp │ │ │ ├── quickopenaction.h │ │ │ ├── quickopeneditor.cpp │ │ │ ├── quickopeneditor.h │ │ │ ├── quickopenfiles.cpp │ │ │ ├── quickopenfiles.h │ │ │ ├── quickopenfilesystem.cpp │ │ │ ├── quickopenfilesystem.h │ │ │ ├── quickopenfolder.cpp │ │ │ ├── quickopenfolder.h │ │ │ ├── quickopenhelp.cpp │ │ │ ├── quickopenhelp.h │ │ │ ├── quickopenlines.cpp │ │ │ ├── quickopenlines.h │ │ │ ├── quickopenmanager.cpp │ │ │ ├── quickopenmanager.h │ │ │ ├── quickopenmimetype.cpp │ │ │ ├── quickopenmimetype.h │ │ │ ├── quickopenoption.cpp │ │ │ ├── quickopenoption.h │ │ │ ├── quickopenoption.ui │ │ │ ├── quickopenoptionfactory.cpp │ │ │ ├── quickopenoptionfactory.h │ │ │ ├── quickopenplugin.cpp │ │ │ ├── quickopenplugin.h │ │ │ ├── quickopenwidget.cpp │ │ │ └── quickopenwidget.h │ │ ├── rustedit/ │ │ │ ├── rustedit.cpp │ │ │ ├── rustedit.h │ │ │ ├── rustedit.pro │ │ │ ├── rustedit_global.h │ │ │ ├── rusteditplugin.cpp │ │ │ └── rusteditplugin.h │ │ ├── syntaxeditor/ │ │ │ ├── golangcompleter.cpp │ │ │ ├── golangcompleter.h │ │ │ ├── golanghighlighter.cpp │ │ │ ├── golanghighlighter.h │ │ │ ├── projecthighlighter.cpp │ │ │ ├── projecthighlighter.h │ │ │ ├── syntaxcompleter.h │ │ │ ├── syntaxeditor.cpp │ │ │ ├── syntaxeditor.h │ │ │ ├── syntaxeditor.pro │ │ │ ├── syntaxeditor.xml │ │ │ ├── syntaxeditor_global.h │ │ │ ├── syntaxeditorplugin.cpp │ │ │ ├── syntaxeditorplugin.h │ │ │ ├── syntaxfilefactory.cpp │ │ │ ├── syntaxfilefactory.h │ │ │ ├── syntaxtexteditor.cpp │ │ │ └── syntaxtexteditor.h │ │ ├── terminal/ │ │ │ ├── terminal.cpp │ │ │ ├── terminal.h │ │ │ ├── terminal.pro │ │ │ ├── terminal_global.h │ │ │ ├── terminaloption.cpp │ │ │ ├── terminaloption.h │ │ │ ├── terminaloption.ui │ │ │ ├── terminaloptionfactory.cpp │ │ │ ├── terminaloptionfactory.h │ │ │ ├── terminalplugin.cpp │ │ │ └── terminalplugin.h │ │ ├── webkithtmlwidget/ │ │ │ ├── webkitbrowser.cpp │ │ │ ├── webkitbrowser.h │ │ │ ├── webkithtmlwidget.pro │ │ │ ├── webkithtmlwidget_global.h │ │ │ ├── webkithtmlwidgetplugin.cpp │ │ │ ├── webkithtmlwidgetplugin.h │ │ │ ├── webviewhtmlwidget.cpp │ │ │ └── webviewhtmlwidget.h │ │ └── welcome/ │ │ ├── litedoc.cpp │ │ ├── litedoc.h │ │ ├── welcome.pro │ │ ├── welcome.qrc │ │ ├── welcome_global.h │ │ ├── welcomebrowser.cpp │ │ ├── welcomebrowser.h │ │ ├── welcomeplugin.cpp │ │ └── welcomeplugin.h │ ├── rpath.pri │ ├── src.pro │ ├── tools/ │ │ ├── check_hpp/ │ │ │ └── main.go │ │ ├── check_png/ │ │ │ └── main.go │ │ ├── exportqrc/ │ │ │ ├── README.md │ │ │ └── main.go │ │ ├── liteide_ctrlc_stub/ │ │ │ ├── liteide_ctrlc_stub.cpp │ │ │ └── liteide_ctrlc_stub.pro │ │ ├── template/ │ │ │ ├── hello_option/ │ │ │ │ ├── hellooption.cpp │ │ │ │ ├── hellooption.h │ │ │ │ ├── hellooption.ui │ │ │ │ ├── hellooptionfactory.cpp │ │ │ │ └── hellooptionfactory.h │ │ │ ├── hello_plugin/ │ │ │ │ ├── hello.pro │ │ │ │ ├── hello_global.h │ │ │ │ ├── helloplugin.cpp │ │ │ │ └── helloplugin.h │ │ │ ├── hello_utillib/ │ │ │ │ ├── hello.cpp │ │ │ │ ├── hello.h │ │ │ │ ├── hello.pri │ │ │ │ └── hello.pro │ │ │ ├── make_option.lua │ │ │ ├── make_plugin.lua │ │ │ ├── make_utillib.lua │ │ │ └── makelib.lua │ │ └── tools.pro │ └── utils/ │ ├── colorstyle/ │ │ ├── colorstyle.cpp │ │ ├── colorstyle.h │ │ ├── colorstyle.pri │ │ └── colorstyle.pro │ ├── dlvclient/ │ │ ├── dlvclient.cpp │ │ ├── dlvclient.h │ │ ├── dlvclient.pri │ │ ├── dlvclient.pro │ │ ├── dlvtypes.h │ │ ├── varianthelper.cpp │ │ └── varianthelper.h │ ├── documentbrowser/ │ │ ├── documentbrowser.cpp │ │ ├── documentbrowser.h │ │ ├── documentbrowser.pri │ │ ├── documentbrowser.pro │ │ ├── documentbrowserfactory.cpp │ │ └── documentbrowserfactory.h │ ├── editorutil/ │ │ ├── checkdata.h │ │ ├── difflib.h │ │ ├── editorutil.cpp │ │ ├── editorutil.h │ │ ├── editorutil.pri │ │ ├── editorutil.pro │ │ └── libucd.h │ ├── extension/ │ │ ├── extension.cpp │ │ ├── extension.h │ │ ├── extension.pri │ │ └── extension.pro │ ├── filesystem/ │ │ ├── filesystem.pri │ │ ├── filesystem.pro │ │ ├── filesystemmodel.cpp │ │ ├── filesystemmodel.h │ │ ├── filesystemwidget.cpp │ │ └── filesystemwidget.h │ ├── fileutil/ │ │ ├── fileutil.cpp │ │ ├── fileutil.h │ │ ├── fileutil.pri │ │ ├── fileutil.pro │ │ ├── fileutil_mac.mm │ │ ├── findfilesthread.cpp │ │ └── findfilesthread.h │ ├── folderview/ │ │ ├── abstractmultiproxymodel.cpp │ │ ├── abstractmultiproxymodel.h │ │ ├── abstractmultiproxymodel_p.h │ │ ├── basefolderview.cpp │ │ ├── basefoldeview.h │ │ ├── dirsortfilterproxymodel.cpp │ │ ├── dirsortfilterproxymodel.h │ │ ├── filesystemmodelex.cpp │ │ ├── filesystemmodelex.h │ │ ├── folderdialog.cpp │ │ ├── folderdialog.h │ │ ├── folderlistmodel.cpp │ │ ├── folderlistmodel.h │ │ ├── folderlistview.cpp │ │ ├── folderlistview.h │ │ ├── folderview.cpp │ │ ├── folderview.h │ │ ├── folderview.pri │ │ ├── folderview.pro │ │ ├── multifoldermodel.cpp │ │ ├── multifoldermodel.h │ │ ├── multifolderview.cpp │ │ ├── multifolderview.h │ │ ├── multiindexmodel.cpp │ │ ├── multiindexmodel.h │ │ └── multiindexmodel_p.h │ ├── golangapi/ │ │ ├── golangapi.cpp │ │ ├── golangapi.h │ │ ├── golangapi.pri │ │ └── golangapi.pro │ ├── gotools/ │ │ ├── gotools.cpp │ │ ├── gotools.h │ │ ├── gotools.pri │ │ ├── gotools.pro │ │ └── libgopher.h │ ├── htmlutil/ │ │ ├── htmlutil.cpp │ │ ├── htmlutil.h │ │ ├── htmlutil.pri │ │ └── htmlutil.pro │ ├── iconutil/ │ │ ├── iconutil.cpp │ │ ├── iconutil.h │ │ ├── iconutil.pri │ │ └── iconutil.pro │ ├── mimetype/ │ │ ├── mimetype.cpp │ │ ├── mimetype.h │ │ ├── mimetype.pri │ │ └── mimetype.pro │ ├── modelproject/ │ │ ├── modelfileimpl.cpp │ │ ├── modelfileimpl.h │ │ ├── modelproject.pri │ │ ├── modelproject.pro │ │ ├── modelprojectimpl.cpp │ │ └── modelprojectimpl.h │ ├── navigate/ │ │ ├── navigate.cpp │ │ ├── navigate.h │ │ ├── navigate.pri │ │ └── navigate.pro │ ├── processex/ │ │ ├── processex.cpp │ │ ├── processex.h │ │ ├── processex.pri │ │ └── processex.pro │ ├── symboltreeview/ │ │ ├── symboltreeview.cpp │ │ ├── symboltreeview.h │ │ ├── symboltreeview.pri │ │ └── symboltreeview.pro │ ├── tabwidget/ │ │ ├── litetabwidget.cpp │ │ ├── litetabwidget.h │ │ ├── tabwidget.pri │ │ └── tabwidget.pro │ ├── textoutput/ │ │ ├── terminaledit.cpp │ │ ├── terminaledit.h │ │ ├── textoutput.cpp │ │ ├── textoutput.h │ │ ├── textoutput.pri │ │ └── textoutput.pro │ ├── utils.pro │ └── vterm/ │ ├── vterm.pri │ ├── vterm.pro │ ├── vtermcolor.h │ ├── vtermwidget.cpp │ ├── vtermwidget.h │ ├── vtermwidgetbase.cpp │ └── vtermwidgetbase.h └── windows_deploy.cmd ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry custom: https://visualfc.github.io/support/ ================================================ FILE: .gitignore ================================================ /build-liteidex-Desktop* # C++ objects and libs *.slo *.lo *.o *.a *.la *.lai *.so *.dll *.dylib *.7z #Emacs *~ # Qt-es *.pro.user *.pro.user.* moc_*.cpp qrc_*.cpp Makefile *-build-* # hg .hg* #liteide *.exe liteidex/bin liteidex/liteide liteidex/src/github.com liteidex/src/golang.org/ #macosx .DS_Store ================================================ FILE: CONTRIBUTORS ================================================ # LiteIDE Contributor List: # This is the official list of people who can contribute # (and typically have contributed) code to the LiteIDE repository. # # Names should be added to this file like so: # Individual's name # Individual's name # # Please keep the list sorted. appajee Addxtoy Ahmed (OneOfOne) W Alexander Rødseth Александр Павлов bombless b-s-a devshell custa cl0ne Daniel Theophanes kardianos Dobrosław Żybort Dumitru Ungureanu Dvir Volk elfgoh eugoss Elgs Qian Chen Fan Yang FeelGo Fred Foonly GoEddie Guolei Georges Varouchas hopehook Hai Thanh Nguyen Harald Leinders Helge Plaschke Henson Lu idsol jsuppe Jeremy Harris Jon Suppe Jon Suppe lixiaolong Luther Goh Lee Forest Laurent Saint-Félix Lockals Lauri Ojansivu Lucio M. Tato mattn mars Marc Abramowitz Marius Karnauskas max Maxim Perenesenko Michael Käufl Mr Tom Nik U Philippe Lhoste Peter Gloor Roman Shmelev Roland Illig Sergey Belyashov Shauvik Roy Choudhary Santiago Corredoira Lascaray Slene stemd stemd tupunco Timothy Lin TomBoss Tylor Arndt vanackere Vincent Vanackere Vladimir Timofeev Vedran Vuk vahid Vahid pylover Vince Yuan Yuwen Shen Yılmaz Unknown William Kennedy Wanpat Anantapan zigal Zach Collier # All contributors that provided patches. # If they are missing, please let me know. ================================================ FILE: ISSUE_TEMPLATE.md ================================================ Please answer these questions before submitting your issue. Thanks! Please download LiteIDE latest version and test before submitting your issue. Thanks! ### What version of LiteIDE are you using (LiteIDE About - Version and Build Qt Version)? ### What version of Go are you using (`go version`)? ### What operating system and processor architecture are you using(`go env`)? ### What did you do? If possible, provide a recipe for reproducing the error. ### What did you expect to see? ### What did you see instead? ================================================ FILE: LICENSE.LGPL ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: README.md ================================================ LiteIDE X ========= ![liteide-logo](liteidex/liteide-logo/liteide.png) ### Introduction _LiteIDE is a simple, open source, cross-platform Go IDE._ * Version: X38.4 * Author: [visualfc](mailto:visualfc@gmail.com) ### Features * Core features * System environment management * MIME type management * Configurable build commands * Support files search replace and revert * Quick open file, symbol and commands * Plug-in system * Integrated terminal * Advanced code editor * Code editor supports Golang, Markdown and Golang Present * Rapid code navigation tools * Syntax highlighting and color scheme * Code completion * Code folding * Display save revision * Reload file by internal diff way * Golang support * Support Go1.18~Go1.21 generics * Support Go1.18 go.work * Support Go1.11 Go modules * Support Go1.5 Go vendor * Support Go1 GOPATH * Golang build environment management * Compile and test using standard Golang tools * Custom GOPATH support system, IDE and project * Custom project build configuration * Golang package browser * Golang class view and outline * Golang doc search and api index * Source code navigation and information tips * Source code find usages * Source code refactoring and revert * Integrated [gocode](https://github.com/visualfc/gocode) clone of [nsf/gocode](https://github.com/nsf/gocode) * Integrated [gomodifytags](https://github.com/fatih/gomodifytags) * Support source query tools guru * Debug with GDB and [Delve](https://github.com/derekparker/delve) ### Supported Systems * Windows x86 (32-bit or 64-bit) * Linux x86 (32-bit or 64-bit) * MacOS X10.6 or higher (64-bit) * FreeBSD 9.2 or higher (32-bit or 64-bit) * OpenBSD 5.6 or higher (64-bit) ### Latest Release Supported Platform Details * Windows * liteide-latest.windows-qt5.zip -> WindowsXP, Windows 7 8 10 * liteide-latest.windows-qt4.zip -> WindowsXP, Windows 7 * macOS * liteide-latest.macosx-qt5.zip -> macOS 10.8 or higher * Linux x64 * liteide-latest.linux-64-qt4.tar.bz2 -> Linux (64 bit) build on ubuntu 16.04 * liteide-latest.linux-64-qt5.tar.bz2 -> Linux (64 bit) build on ubuntu 16.04 * Linux x32 * liteide-latest.linux-32-qt4.tar.bz2 -> Linux (32 bit) build on ubuntu 16.04 * liteide-latest.linux-32-qt5.tar.bz2 -> Linux (32 bit) build on ubuntu 16.04 * ArchLinux * liteide-latest.archlinux-pkgbuild.zip -> ArchLinux (64 bit) PKGBUILD ### LiteIDE Command Line liteide [files|folder] [--select-env id] [--local-setting] [--user-setting] [--reset-setting] --select-env [system|win32|cross-linux64|...] select init environment id --local-setting force use local setting --user-setting force use user setting --reset-setting reset current setting ( clear setting file) ### Update liteide tools for support new Golang Version go install github.com/visualfc/gotools@latest go install github.com/visualfc/gocode@latest Windows/Linux: copy GOPATH/bin gotools and gocode to liteide/bin MacOS: copy GOPATH/bin gotools and gocode to LiteIDE.app/Contents/MacOS ### Documents * How to Install * FAQ * 安装 LiteIDE * FAQ 中文 ### Links * LiteIDE Source code * Gotools Source code * Gocode Source code * Release downloads * * * [百度网盘](https://pan.baidu.com/s/1wYHSEfG1TJRC2iOkE_saJg) 密码:jzrc * Google group * Changes ### Donate * https://visualfc.github.io/support ================================================ FILE: build/.gitignore ================================================ * !*/ !.gitignore !*.sh ================================================ FILE: build/build_freebsd.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . echo qmake-qt5 liteide ... echo . qmake-qt5 $LITEIDE_ROOT "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/freebsd/* liteide/share/liteide/ ================================================ FILE: build/build_freebsd_g++.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . echo qmake liteide ... echo . qmake $LITEIDE_ROOT -spec freebsd-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/freebsd/* liteide/share/liteide/ ================================================ FILE: build/build_linux.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . echo qmake liteide ... echo . qmake $LITEIDE_ROOT -spec linux-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide.desktop liteide cp -a -v $LITEIDE_ROOT/install_icon.sh liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: build/build_linux_debian72_x64.sh ================================================ #!/bin/sh export QTDIR=/usr/share/qt4 echo echo "Using QTDIR=$QTDIR here." echo export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo QTDIR=$QTDIR echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH echo qmake liteide ... echo . qmake $LITEIDE_ROOT -spec linux-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: build/build_linux_fedora27_x64.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . echo qmake-qt4 liteide ... echo . qmake-qt4 $LITEIDE_ROOT -spec linux-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide.desktop liteide cp -a -v $LITEIDE_ROOT/install_icon.sh liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: build/build_linux_qt4.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . export PATH=$QTDIR/bin:$PATH echo qmake liteide ... echo . qtchooser -qt=qt4 -run-tool=qmake $LITEIDE_ROOT -spec linux-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: build/build_linux_qt4_webkit.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . export PATH=$QTDIR/bin:$PATH echo qmake liteide ... echo . qtchooser -qt=qt4 -run-tool=qmake $LITEIDE_ROOT -spec linux-g++ "CONFIG+=release liteide_qtwebkit" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: build/build_linux_qt5.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . export PATH=$QTDIR/bin:$PATH echo qmake liteide ... echo . qtchooser -qt=qt5 -run-tool=qmake $LITEIDE_ROOT -spec linux-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: build/build_linux_webkit.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo QTDIR=$QTDIR echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH echo qmake liteide ... echo . qmake $LITEIDE_ROOT -spec linux-g++ "CONFIG+=release liteide_qtwebkit" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/bin mkdir -p liteide/share/liteide mkdir -p liteide/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: build/build_macos_qt4.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH echo qmake liteide ... echo . qmake $LITEIDE_ROOT -spec macx-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide cp -R -v $LITEIDE_ROOT/liteide/bin/LiteIDE.app liteide rm liteide/LiteIDE.app/Contents/PlugIns/*.a cp -R -v $LITEIDE_ROOT/src/liteide/Info.plist liteide/LiteIDE.app/Contents cp -R -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -R -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -R -v $LITEIDE_ROOT/../README.md liteide cp -R -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -R -v $LITEIDE_ROOT/bin/gotools liteide/LiteIDE.app/Contents/MacOS cp -R -v $LITEIDE_ROOT/bin/gocode liteide/LiteIDE.app/Contents/MacOS cp -R -v $LITEIDE_ROOT/bin/gomodifytags liteide/LiteIDE.app/Contents/MacOS cp -R -v $LITEIDE_ROOT/deploy/* liteide/LiteIDE.app/Contents/Resources cp -R -v $LITEIDE_ROOT/os_deploy/macosx/* liteide/LiteIDE.app/Contents/Resources ================================================ FILE: build/build_macos_qt5.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH echo qmake liteide ... echo . qmake $LITEIDE_ROOT -spec macx-clang CONFIG+=X86_64 if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide cp -R -v $LITEIDE_ROOT/liteide/bin/LiteIDE.app liteide rm liteide/LiteIDE.app/Contents/PlugIns/*.a cp -R -v $LITEIDE_ROOT/src/liteide/Info.plist liteide/LiteIDE.app/Contents cp -R -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -R -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -R -v $LITEIDE_ROOT/../README.md liteide cp -R -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -R -v $LITEIDE_ROOT/bin/gotools liteide/LiteIDE.app/Contents/MacOS cp -R -v $LITEIDE_ROOT/bin/gocode liteide/LiteIDE.app/Contents/MacOS cp -R -v $LITEIDE_ROOT/bin/gomodifytags liteide/LiteIDE.app/Contents/MacOS cp -R -v $LITEIDE_ROOT/deploy/* liteide/LiteIDE.app/Contents/Resources cp -R -v $LITEIDE_ROOT/os_deploy/macosx/* liteide/LiteIDE.app/Contents/Resources ================================================ FILE: build/build_netbsd.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi if [ -z $QTDIR ]; then export QTDIR=/usr/pkg/qt5 fi export PATH=$PATH:$QTDIR/bin echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . echo qmake-qt5 liteide ... echo . qmake $LITEIDE_ROOT "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/local/bin mkdir -p liteide/local/share/liteide mkdir -p liteide/local/share/pixmaps mkdir -p liteide/local/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/local/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/local/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/local/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/local/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/openbsd/* liteide/local/share/liteide/ cp -r -v $LITEIDE_ROOT/deploy/welcome/images/liteide-logo*.png liteide/local/share/pixmaps ================================================ FILE: build/build_openbsd.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . echo qmake-qt5 liteide ... echo . qmake-qt5 $LITEIDE_ROOT "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/local/bin mkdir -p liteide/local/share/liteide mkdir -p liteide/local/share/pixmaps mkdir -p liteide/local/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/local/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/local/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/local/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/local/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/openbsd/* liteide/local/share/liteide/ cp -r -v $LITEIDE_ROOT/deploy/welcome/images/liteide-logo*.png liteide/local/share/pixmaps ================================================ FILE: build/build_openbsd_g++.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . echo qmake liteide ... echo . qmake $LITEIDE_ROOT -spec openbsd-g++ "CONFIG+=release" if [ $? -ge 1 ]; then echo 'error, qmake fail' exit 1 fi echo make liteide ... echo . make if [ $? -ge 1 ]; then echo 'error, make fail' exit 1 fi go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo build liteide tools ... cd $LITEIDE_ROOT if [ -z $GOPATH ]; then export GOPATH=$PWD else export GOPATH=$PWD:$GOPATH fi #(cd "$PWD/src/github.com/visualfc/gotools" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/visualfc/gocode" && go install -ldflags "-s" -v) #(cd "$PWD/src/github.com/fatih/gomodifytags" && go install -ldflags "-s" -v) if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi echo export qrc images go run src/tools/exportqrc/main.go -root . if [ $? -ge 1 ]; then echo 'error, go run fail' exit 1 fi echo deploy ... cd $BUILD_ROOT rm -r liteide mkdir -p liteide mkdir -p liteide/local/bin mkdir -p liteide/local/share/liteide mkdir -p liteide/local/share/pixmaps mkdir -p liteide/local/lib/liteide/plugins cp -a -v $LITEIDE_ROOT/LICENSE.LGPL liteide cp -a -v $LITEIDE_ROOT/LGPL_EXCEPTION.TXT liteide cp -a -v $LITEIDE_ROOT/../README.md liteide cp -a -v $LITEIDE_ROOT/../CONTRIBUTORS liteide cp -a -v $LITEIDE_ROOT/liteide/bin/liteide liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gotools liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gocode liteide/local/bin cp -a -v $LITEIDE_ROOT/bin/gomodifytags liteide/local/bin cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/libliteapp.* liteide/local/lib/liteide cp -a -v $LITEIDE_ROOT/liteide/lib/liteide/plugins/*.so liteide/local/lib/liteide/plugins cp -r -v $LITEIDE_ROOT/deploy/* liteide/local/share/liteide/ cp -r -v $LITEIDE_ROOT/os_deploy/openbsd/* liteide/local/share/liteide/ cp -r -v $LITEIDE_ROOT/deploy/welcome/images/liteide-logo*.png liteide/local/share/pixmaps ================================================ FILE: build/build_windows_386_mingw32.cmd ================================================ set GOARCH=386 call build_windows_mingw32.cmd call update_pkg.cmd if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex xcopy %LITEIDE_ROOT%\bin\windows_386\gotools.exe liteide\bin /y xcopy %LITEIDE_ROOT%\bin\windows_386\gocode.exe liteide\bin /y xcopy %LITEIDE_ROOT%\bin\windows_386\gomodifytags.exe liteide\bin /y ================================================ FILE: build/build_windows_mingw32.cmd ================================================ @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo build liteide echo QTDIR=%QTDIR% echo GOROOT=%GOROOT% echo BUILD_ROOT=%BUILD_ROOT% echo LITEIDE_ROOT=%LITEIDE_ROOT% echo MINGWDIR=%MINGWDIR% echo . if x%QTDIR%==x goto qtdir_fail if x%MINGWDIR%==x goto mwdir_fail set PATH=%QTDIR%/bin;%MINGWDIR%/bin;%PATH% echo qmake liteide ... echo . qmake %LITEIDE_ROOT% -spec win32-g++ "CONFIG+=release" if ERRORLEVEL 1 goto qmake_fail echo make liteide ... echo . mingw32-make if ERRORLEVEL 1 goto make_fail go version if ERRORLEVEL 1 goto go_fail echo build liteide tools echo . cd %LITEIDE_ROOT% if defined %GOPATH ( set GOPATH=%CD%;%GOPATH% ) else ( set GOPATH=%CD% ) :: (cd "%CD%/src/github.com/visualfc/gotools" & go install -ldflags "-s" -v & cd %CD%) :: (cd "%CD%/src/github.com/visualfc/gocode" & go install -ldflags "-s" -v & cd %CD%) :: (cd "%CD%/src/github.com/fatih/gomodifytags" & go install -ldflags "-s" -v & cd %CD%) if ERRORLEVEL 1 goto go_fail echo export qrc images go run src/tools/exportqrc/main.go -root . if ERRORLEVEL 1 goto go_fail cd %BUILD_ROOT% echo deploy liteide ... echo . if exist liteide rmdir /q /s liteide if not exist liteide mkdir liteide if not exist liteide\bin mkdir liteide\bin if not exist liteide\lib mkdir liteide\lib if not exist liteide\lib\liteide mkdir liteide\lib\liteide if not exist liteide\lib\liteide\plugins mkdir liteide\lib\liteide\plugins xcopy %LITEIDE_ROOT%\LICENSE.LGPL liteide /y xcopy %LITEIDE_ROOT%\LGPL_EXCEPTION.TXT liteide /y xcopy %LITEIDE_ROOT%\..\README.MD liteide /y xcopy %LITEIDE_ROOT%\..\CONTRIBUTORS liteide /y xcopy %LITEIDE_ROOT%\liteide\bin\* liteide\bin /y xcopy %LITEIDE_ROOT%\bin\gotools.exe liteide\bin /y xcopy %LITEIDE_ROOT%\bin\gocode.exe liteide\bin /y xcopy %LITEIDE_ROOT%\bin\gomodifytags.exe liteide\bin /y xcopy %LITEIDE_ROOT%\liteide\lib\liteide\plugins\*.dll liteide\lib\liteide\plugins /y xcopy %LITEIDE_ROOT%\deploy liteide\share\liteide /e /y /i xcopy %LITEIDE_ROOT%\os_deploy\windows liteide\share\liteide /e /y /i goto end :qtdir_fail echo error, QTDIR is null goto end :mwdir_fail echo error, MINGWDIR is null goto end :qmake_fail echo error, qmake fail goto end :make_fail echo error, make fail goto end :go_fail echo error, go fail goto end :end ================================================ FILE: build/build_windows_msvc.cmd ================================================ @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo build liteide echo QTDIR=%QTDIR% echo GOROOT=%GOROOT% echo BUILD_ROOT=%BUILD_ROOT% echo LITEIDE_ROOT=%LITEIDE_ROOT% echo . if x%QTDIR%==x goto qtdir_fail set PATH=%QTDIR%/bin;%PATH% echo qmake liteide ... echo . qmake %LITEIDE_ROOT% "CONFIG+=release" if ERRORLEVEL 1 goto qmake_fail echo make liteide ... echo . nmake if ERRORLEVEL 1 goto make_fail go version if ERRORLEVEL 1 goto go_fail echo build liteide tools echo . cd %LITEIDE_ROOT% if defined %GOPATH ( set GOPATH=%CD%;%GOPATH% ) else ( set GOPATH=%CD% ) :: (cd "%CD%/src/github.com/visualfc/gotools" & go install -ldflags "-s" -v & cd %CD%) :: (cd "%CD%/src/github.com/visualfc/gocode" & go install -ldflags "-s" -v & cd %CD%) :: (cd "%CD%/src/github.com/fatih/gomodifytags" & go install -ldflags "-s" -v & cd %CD%) if ERRORLEVEL 1 goto go_fail echo export qrc images go run src/tools/exportqrc/main.go -root . if ERRORLEVEL 1 goto go_fail cd %BUILD_ROOT% echo deploy liteide ... echo . if exist liteide rmdir /q /s liteide if not exist liteide mkdir liteide if not exist liteide\bin mkdir liteide\bin if not exist liteide\lib mkdir liteide\lib if not exist liteide\lib\liteide mkdir liteide\lib\liteide if not exist liteide\lib\liteide\plugins mkdir liteide\lib\liteide\plugins xcopy %LITEIDE_ROOT%\LICENSE.LGPL liteide /y xcopy %LITEIDE_ROOT%\LGPL_EXCEPTION.TXT liteide /y xcopy %LITEIDE_ROOT%\..\README.MD liteide /y xcopy %LITEIDE_ROOT%\..\CONTRIBUTORS liteide /y xcopy %LITEIDE_ROOT%\liteide\bin\* liteide\bin /y xcopy %LITEIDE_ROOT%\bin\gotools.exe liteide\bin /y xcopy %LITEIDE_ROOT%\bin\gocode.exe liteide\bin /y xcopy %LITEIDE_ROOT%\bin\gomodifytags.exe liteide\bin /y xcopy %LITEIDE_ROOT%\liteide\lib\liteide\plugins\*.dll liteide\lib\liteide\plugins /y xcopy %LITEIDE_ROOT%\deploy liteide\share\liteide /e /y /i xcopy %LITEIDE_ROOT%\os_deploy\windows liteide\share\liteide /e /y /i goto end :qtdir_fail echo error, QTDIR is null goto end :qmake_fail echo error, qmake fail goto end :make_fail echo error, make fail goto end :go_fail echo error, go fail goto end :end ================================================ FILE: build/deploy_linux_bundle.sh ================================================ #!/bin/sh linuxdeployqt liteide/bin/liteide -bundle-non-qt-libs ================================================ FILE: build/deploy_linux_debian72_x64_qt4.8_webkit.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi DEBIANQTLIBS=/usr/lib/x86_64-linux-gnu echo "Setting DEBIANQTLIBS=$DEBIANQTLIBS" echo build liteide echo DEBIANQTLIBS=$DEBIANQTLIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $DEBIANQTLIBS ]; then echo 'error, DEBIANQTLIBS is null' exit 1 fi cp -a -v $DEBIANQTLIBS/libQtCore.so* liteide/lib/liteide cp -a -v $DEBIANQTLIBS/libQtGui.so* liteide/lib/liteide cp -a -v $DEBIANQTLIBS/libQtXml.so* liteide/lib/liteide cp -a -v $DEBIANQTLIBS/libQtNetwork.so* liteide/lib/liteide cp -a -v $DEBIANQTLIBS/libQtWebKit.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_qt4.7_webkit.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo QTDIR=$QTDIR echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi cp -a -v $QTDIR/lib/libQtCore.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtGui.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtXml.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libphonon.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtNetwork.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtWebKit.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtDBus.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_qt4.8_webkit.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo QTDIR=$QTDIR echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi cp -a -v $QTDIR/lib/libQtCore.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtGui.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtXml.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtNetwork.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtWebKit.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_qt4.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo build liteide echo QTDIR=$QTDIR echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi cp -a -v $QTDIR/lib/libQtCore.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtGui.so* liteide/lib/liteide cp -a -v $QTDIR/lib/libQtXml.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_x32_appimage.sh ================================================ #!/bin/sh mkdir liteide.AppDir mkdir liteide.AppDir/usr cp -r liteide/* liteide.AppDir/usr linuxdeployqt liteide.AppDir/usr/bin/liteide -bundle-non-qt-libs cp liteide.desktop liteide.AppDir cp liteide.png liteide.AppDir cd liteide.AppDir ln -s -f usr/bin/liteide AppRun cd .. appimagetool-i686.AppImage liteide.AppDir rm -r liteide.AppDir ================================================ FILE: build/deploy_linux_x32_qt4.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi QT4LIBS=/usr/lib/i386-linux-gnu echo "Setting QT4LIBS=$QT4LIBS" echo build liteide echo QT4LIBS=$QT4LIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QT4LIBS ]; then echo 'error, QT4LIBS is null' exit 1 fi cp -a -v $QT4LIBS/libQtCore.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtGui.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtXml.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_x32_qt5.5.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi QT5LIBS=/usr/lib/i386-linux-gnu echo "Setting QT5LIBS=$QT5LIBS" echo build liteide echo QT5LIBS=$QT5LIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QT5LIBS ]; then echo 'error, QT5LIBS is null' exit 1 fi cp -a -v $QT5LIBS/libQt5Core.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Gui.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Widgets.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Xml.so* liteide/lib/liteide cp -a -v $QT5LIBS/libicudata.so* liteide/lib/liteide cp -a -v $QT5LIBS/libicui18n.so* liteide/lib/liteide cp -a -v $QT5LIBS/libicuuc.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_x32_qt5.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi QT5LIBS=/usr/lib/i386-linux-gnu echo "Setting QT5LIBS=$QT5LIBS" echo build liteide echo QT5LIBS=$QT5LIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QT5LIBS ]; then echo 'error, QT5LIBS is null' exit 1 fi cp -a -v $QT5LIBS/libQt5Core.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Gui.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Widgets.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Xml.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_x64_appimage.sh ================================================ #!/bin/sh mkdir liteide.AppDir mkdir liteide.AppDir/usr cp -r liteide/* liteide.AppDir/usr linuxdeployqt liteide.AppDir/usr/bin/liteide -bundle-non-qt-libs cp liteide.desktop liteide.AppDir cp liteide.png liteide.AppDir cd liteide.AppDir ln -s -f usr/bin/liteide AppRun cd .. appimagetool-x86_64.AppImage liteide.AppDir rm -r liteide.AppDir ================================================ FILE: build/deploy_linux_x64_qt4.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi QT4LIBS=/usr/lib/x86_64-linux-gnu echo "Setting QT4LIBS=$QT4LIBS" echo build liteide echo QT4LIBS=$QT4LIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QT4LIBS ]; then echo 'error, QT4LIBS is null' exit 1 fi cp -a -v $QT4LIBS/libQtCore.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtGui.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtXml.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_x64_qt4_webkit.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi QT4LIBS=/usr/lib/x86_64-linux-gnu echo "Setting QT4LIBS=$QT4LIBS" echo build liteide echo QT4LIBS=$QT4LIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QT4LIBS ]; then echo 'error, QT4LIBS is null' exit 1 fi cp -a -v $QT4LIBS/libQtCore.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtGui.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtXml.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtNetwork.so* liteide/lib/liteide cp -a -v $QT4LIBS/libQtWebKit.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_x64_qt5.5.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi QT5LIBS=/usr/lib/x86_64-linux-gnu echo "Setting QT5LIBS=$QT5LIBS" echo build liteide echo QT5LIBS=$QT5LIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QT5LIBS ]; then echo 'error, QT5LIBS is null' exit 1 fi cp -a -v $QT5LIBS/libQt5Core.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Gui.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Widgets.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Xml.so* liteide/lib/liteide cp -a -v $QT5LIBS/libicudata.so* liteide/lib/liteide cp -a -v $QT5LIBS/libicui18n.so* liteide/lib/liteide cp -a -v $QT5LIBS/libicuuc.so* liteide/lib/liteide ================================================ FILE: build/deploy_linux_x64_qt5.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi QT5LIBS=/usr/lib/x86_64-linux-gnu echo "Setting QT5LIBS=$QT5LIBS" echo build liteide echo QT5LIBS=$QT5LIBS echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QT5LIBS ]; then echo 'error, QT5LIBS is null' exit 1 fi cp -a -v $QT5LIBS/libQt5Core.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Gui.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Widgets.so* liteide/lib/liteide cp -a -v $QT5LIBS/libQt5Xml.so* liteide/lib/liteide ================================================ FILE: build/deploy_macos_qt4.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo deploy liteide/LiteIDE.app echo QTDIR=$QTDIR echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH macdeployqt liteide/LiteIDE.app ================================================ FILE: build/deploy_macos_qt5.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo deploy liteide/LiteIDE.app echo QTDIR=$QTDIR echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH rm liteide/LiteIDE.app/Contents/Resources/qt.conf macdeployqt liteide/LiteIDE.app ================================================ FILE: build/deploy_windows_qt4.8.cmd ================================================ @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo build liteide echo QTDIR=%QTDIR% echo . if x%QTDIR%==x goto qtdir_fail xcopy %QTDIR%\bin\QtCore4.dll liteide\bin /y xcopy %QTDIR%\bin\QtGui4.dll liteide\bin /y xcopy %QTDIR%\bin\QtXml4.dll liteide\bin /y xcopy %QTDIR%\bin\mingwm10.dll liteide\bin /y xcopy %QTDIR%\bin\libgcc_s_dw2-1.dll liteide\bin /y xcopy %QTDIR%\bin\QtNetwork4.dll liteide\bin /y xcopy %QTDIR%\bin\QtWebkit4.dll liteide\bin /y goto end :qtdir_fail echo error, QTDIR is null goto end :end ================================================ FILE: build/deploy_windows_qt4.8_msvc.cmd ================================================ @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo build liteide echo QTDIR=%QTDIR% echo . if x%QTDIR%==x goto qtdir_fail xcopy %QTDIR%\bin\QtCore4.dll liteide\bin /y xcopy %QTDIR%\bin\QtGui4.dll liteide\bin /y xcopy %QTDIR%\bin\QtXml4.dll liteide\bin /y xcopy %QTDIR%\bin\QtNetwork4.dll liteide\bin /y xcopy %QTDIR%\bin\QtWebkit4.dll liteide\bin /y goto end :qtdir_fail echo error, QTDIR is null goto end :end ================================================ FILE: build/deploy_windows_qt5.15.2.cmd ================================================ @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo build liteide echo QTDIR=%QTDIR% echo . if x%QTDIR%==x goto qtdir_fail windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/liteeditor.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/welcome.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/litebuild.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/dlvdebugger.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/bin/liteapp.dll goto end :qtdir_fail echo error, QTDIR is null goto end :end ================================================ FILE: build/deploy_windows_qt5.9.cmd ================================================ @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo build liteide echo QTDIR=%QTDIR% echo . if x%QTDIR%==x goto qtdir_fail windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/liteeditor.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/welcome.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/litebuild.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/lib/liteide/plugins/dlvdebugger.dll windeployqt --no-angle --no-opengl-sw --dir liteide/bin liteide/bin/liteapp.dll goto end :qtdir_fail echo error, QTDIR is null goto end :end ================================================ FILE: build/liteide.desktop ================================================ [Desktop Entry] Type=Application Name=liteide Exec=liteide Icon=liteide Comment=LiteIDE is a simple, open source, cross-platform Go IDE. Terminal=false Categories=Development; Name[zh_CN]=liteide ================================================ FILE: build/liteide_archlinux/PKGBUILD ================================================ # $Id$ # Maintainer: Alexander F Rødseth # Contributor: spambanane # Contributor: Matteo # Contributor: Matthew Zimmerman pkgname=liteide pkgver=38.3 pkgrel=1 pkgdesc='IDE for editing and building projects written in the Go programming language' license=('LGPL') arch=('x86_64') url='https://github.com/visualfc/liteide' makedepends=('go' 'gendesk' 'git') depends=('go-tools' 'qt5-base') optdepends=('go: go compiler' 'gcc-go: go compiler') options=('!strip' '!emptydirs') source=("$pkgname-x$pkgver::git+https://github.com/visualfc/liteide.git#tag=x$pkgver") md5sums=('SKIP') prepare() { gendesk -f -n --name LiteIDE --pkgname "$pkgname" --pkgdesc "$pkgdesc" chmod +x "liteide-x$pkgver/build/"*_*.sh # Fix for FS#4662 until fixed by upstream cd "liteide-x$pkgver/liteidex/os_deploy/linux/liteenv" sed -i 's|^GOROOT|#GOROOT|g' linux32.env sed -i 's|^GOROOT|#GOROOT|g' linux64.env # Fix the libpng warning: iCCP: known incorrect sRGB profile find "$srcdir" -type f -iname "*.png" -exec mogrify -strip '{}' \; } build() { cd "liteide-x$pkgver/build" mkdir -p go export GOPATH="$(pwd)/go" export QTDIR=/usr ./update_pkg.sh ./build_linux.sh } package() { cd "liteide-x$pkgver/build/liteide" msg2 'Creating directories...' mkdir -p \ "$pkgdir/usr/lib/liteide" \ "$pkgdir/usr/share/liteide" \ "$pkgdir/usr/share/doc/$pkgname" msg2 'Packaging executables...' for binary in gomodifytags gotools gocode liteide; do # goimports install -Dm755 "bin/$binary" "$pkgdir/usr/bin/$binary" done ln -s /usr/bin/liteide "$pkgdir/usr/bin/golangide" cd "$srcdir/liteide-x$pkgver/liteidex" msg2 'Packaging resources...' cp -r deploy/* os_deploy/* "$pkgdir/usr/share/liteide" msg2 'Packaging libraries and plugins...' cp -r liteide/lib/liteide/* "$pkgdir/usr/lib/liteide" chmod -x "$pkgdir/usr/lib/liteide/plugins/"* msg2 'Packaging license and license exception...' install -Dm644 LICENSE.LGPL \ "$pkgdir/usr/share/licenses/$pkgname/LICENSE" install -Dm644 LGPL_EXCEPTION.TXT \ "$pkgdir/usr/share/licenses/$pkgname/LGPL_EXCEPTION" cd "$srcdir" msg2 'Packaging desktop shortcut...' install -Dm644 "$pkgname.desktop" \ "$pkgdir/usr/share/applications/$pkgname.desktop" install -d "$pkgdir/usr/share/pixmaps" ln -s /usr/share/liteide/welcome/images/liteide400.png \ "$pkgdir/usr/share/pixmaps/$pkgname.png" msg2 'Cleaning up...' rm -rf "$pkgdir/usr/share/$pkgname/doc" # Fix for FS#38781 mv "$pkgdir/usr/share/liteide/linux/liteenv" \ "$pkgdir/usr/share/liteide/liteenv" } # vim: ts=2 sw=2 et: ================================================ FILE: build/liteide_archlinux/liteide.md ================================================ LiteIDE ======= ### Introduction _LiteIDE is a simple, open source, cross-platform Go IDE._ https://github.com/visualfc/liteide ### Install LiteIDE for ArchLinux $ makepkg -sri ================================================ FILE: build/update_pkg.cmd ================================================ @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo GOROOT=%GOROOT% echo BUILD_ROOT=%BUILD_ROOT% echo LITEIDE_ROOT=%LITEIDE_ROOT% echo . go version if ERRORLEVEL 1 goto go_fail echo update liteide tools ... cd %LITEIDE_ROOT% set GOBIN=%CD%\bin echo install gocode ... go install -v github.com/visualfc/gocode@latest echo install gotools ... go install -v github.com/visualfc/gotools@latest echo install gomodifytags ... go install -v github.com/fatih/gomodifytags@latest cd %BUILD_ROOT% goto end :go_fail echo error, go fail goto end :end ================================================ FILE: build/update_pkg.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo GOROOT=$GOROOT echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . go version if [ $? -ge 1 ]; then echo 'error, not find go in PATH' exit 1 fi echo update liteide tools ... cd $LITEIDE_ROOT export GOBIN=$PWD/bin echo install gocode ... go install -v github.com/visualfc/gocode@latest echo install gotools ... go install -v github.com/visualfc/gotools@latest echo install gomodifytags ... go install -v github.com/fatih/gomodifytags@latest if [ $? -ge 1 ]; then echo 'error, go install fail' exit 1 fi cd $BUILD_ROOT ================================================ FILE: build/update_tr.cmd ================================================ @echo off @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo QTDIR=%QTDIR% echo GOROOT=%GOROOT% echo BUILD_ROOT=%BUILD_ROOT% echo LITEIDE_ROOT=%LITEIDE_ROOT% echo . if x%QTDIR%==x goto qtdir_fail set PATH=%QTDIR%/bin;%PATH% echo compress translator files lrelease -compress %LITEIDE_ROOT%\liteide_zh.ts -qm %LITEIDE_ROOT%\deploy\translations\liteide_zh.qm lrelease -compress %LITEIDE_ROOT%\liteide_zh_TW.ts -qm %LITEIDE_ROOT%\deploy\translations\liteide_zh_TW.qm lrelease -compress %LITEIDE_ROOT%\liteide_de.ts -qm %LITEIDE_ROOT%\deploy\translations\liteide_de.qm lrelease -compress %LITEIDE_ROOT%\liteide_fr.ts -qm %LITEIDE_ROOT%\deploy\translations\liteide_fr.qm lrelease -compress %LITEIDE_ROOT%\liteide_ja.ts -qm %LITEIDE_ROOT%\deploy\translations\liteide_ja.qm lrelease -compress %LITEIDE_ROOT%\liteide_ru.ts -qm %LITEIDE_ROOT%\deploy\translations\liteide_ru.qm lrelease -compress %LITEIDE_ROOT%\liteide_uk.ts -qm %LITEIDE_ROOT%\deploy\translations\liteide_uk.qm goto end :go_fail echo error, go fail goto end :end ================================================ FILE: build/update_tr.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo GOROOT=$GOROOT echo QTDIR=$QTDIR echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH echo compress translator files lrelease -compress $LITEIDE_ROOT/liteide_zh.ts -qm $LITEIDE_ROOT/deploy/translations/liteide_zh.qm lrelease -compress $LITEIDE_ROOT/liteide_zh_TW.ts -qm $LITEIDE_ROOT/deploy/translations/liteide_zh_TW.qm lrelease -compress $LITEIDE_ROOT/liteide_de.ts -qm $LITEIDE_ROOT/deploy/translations/liteide_de.qm lrelease -compress $LITEIDE_ROOT/liteide_fr.ts -qm $LITEIDE_ROOT/deploy/translations/liteide_fr.qm lrelease -compress $LITEIDE_ROOT/liteide_ja.ts -qm $LITEIDE_ROOT/deploy/translations/liteide_ja.qm lrelease -compress $LITEIDE_ROOT/liteide_ru.ts -qm $LITEIDE_ROOT/deploy/translations/liteide_ru.qm ================================================ FILE: build/update_ts.cmd ================================================ @echo off @echo off setlocal set BUILD_ROOT=%CD% if x%LITEIDE_ROOT%==x set LITEIDE_ROOT=%CD%\..\liteidex echo QTDIR=%QTDIR% echo GOROOT=%GOROOT% echo BUILD_ROOT=%BUILD_ROOT% echo LITEIDE_ROOT=%LITEIDE_ROOT% echo . if x%QTDIR%==x goto qtdir_fail set PATH=%QTDIR%/bin;%PATH% echo update translator files lupdate %LITEIDE_ROOT%\liteidex.pro goto end :go_fail echo error, go fail goto end :end ================================================ FILE: build/update_ts.sh ================================================ #!/bin/sh export BUILD_ROOT=$PWD if [ -z $LITEIDE_ROOT ]; then export LITEIDE_ROOT=$PWD/../liteidex fi echo GOROOT=$GOROOT echo QTDIR=$QTDIR echo BUILD_ROOT=$BUILD_ROOT echo LITEIDE_ROOT=$LITEIDE_ROOT echo . if [ -z $QTDIR ]; then echo 'error, QTDIR is null' exit 1 fi export PATH=$QTDIR/bin:$PATH echo update translator files lupdate -no-obsolete $LITEIDE_ROOT/liteidex.pro ================================================ FILE: build/vars4.8.5.cmd ================================================ @echo off set QTDIR=C:\Qt\4.8.5 set MINGWDIR=C:\Qt\mingw set PATH=%MINGWDIR%\bin;%QTDIR%\bin;%PATH%;c:\go\bin; ================================================ FILE: build/vars5.15.2.cmd ================================================ @echo off set QTDIR=C:\Qt\5.15.2\msvc2019_64 set PATH=%QTDIR%\bin;%PATH% ================================================ FILE: build/vars5.15.2_msvc.cmd ================================================ @echo off set QTDIR=C:\Qt\5.15.2\msvc2019_64 set PATH=%QTDIR%\bin;%PATH% ================================================ FILE: build/vars5.15.2_x64.cmd ================================================ @echo off set QTDIR=C:\Qt\5.15.2\mingw81_64 set MINGWDIR=C:\Qt\Tools\mingw810_64 set PATH=%QTDIR%\bin;%MINGWDIR%\bin;%PATH% ================================================ FILE: build/vars5.9.6.cmd ================================================ @echo off set QTDIR=C:\Qt\Qt5.9.6\5.9.6\mingw53_32 set MINGWDIR=C:\Qt\Qt5.9.6\Tools\mingw530_32 set PATH=%QTDIR%\bin;%MINGWDIR%\bin;%PATH% ================================================ FILE: liteidex/LGPL_EXCEPTION.TXT ================================================ LiteIDE is distributed under the terms of the LGPLv2.1 license with an exception: License exception: In addition, as a special exception, that plugins developed for LiteIDE, are allowed to remain closed sourced and can be distributed under any license . ================================================ FILE: liteidex/LICENSE.LGPL ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: liteidex/bash.bat ================================================ cmd.exe /c c:\mingw\msys\1.0\bin\sh --login -c "cd '%cd%';exec bash --rcfile ~/.bashrc" ================================================ FILE: liteidex/deploy/liteapp/kms/default.kms ================================================ [liteidex] version=1 [Find] FileSearch=Ctrl+Shift+F [Build] Bench= Build="Ctrl+B; F7" BuildAndRun="Ctrl+R; Ctrl+F7" Clean= CleanAll= ClearOutput= Config= FileRun=Alt+F6 Fmt= Get= Install=Ctrl+F8 Run="Alt+F5; Ctrl+R" RunTerm=Alt+Shift+F5 Stop= Test=Ctrl+T Vet= ExecuteFile="Ctrl+," BuildTests= Cover= CoverFunc= Get%20Force= Gopm%20Build= Gopm%20Gen= Gopm%20Help= TestCover= [Editor] DecreaseFontSize=Ctrl+- DeleteLine=Ctrl+Shift+K Duplicate=Ctrl+D Fold=Ctrl+< FoldAll= GotoLine=Ctrl+L GotoMatchBrace=Ctrl+E GotoNextBlock=Ctrl+] GotoPreviousBlock=Ctrl+[ IncreaseFontSize="Ctrl++; Ctrl+=" Paste="Shift+Insert; Ctrl+V" Redo="Ctrl+Shift+Z; Ctrl+Y" ResetFontSize=Ctrl+0 SelectBlock=Ctrl+U Unfold=Ctrl+> UnfoldAll= CleanWhitespace= InsertLineAfter=Ctrl+Return InsertLineBefore=Ctrl+Shift+Return WordWrap= [Document] DecreaseFontSize=Ctrl+- IncreaseFontSize="Ctrl++; Ctrl+=" ResizeFontSize=Ctrl+0 [App] About= AboutPlugins= Backward=Alt+Left CloseAllFiles= CloseFile=Ctrl+W Forward=Alt+Right FullScreen=Ctrl+Shift+F11 OpenFolder= SaveAllFiles= AddFolder= CloseAllFolders= CloseProject= CloseWindow=Ctrl+Shift+W Escape=Esc NewWindow=Ctrl+Shift+N OpenFolderNewWindow= ToolWindow_HtmlPreview=Alt+6 ToolWindow_WebKitBrowser=Alt+5 ToolWindow_buildoutput=Alt+2 ToolWindow_classview=Alt+3 ToolWindow_debugoutput=Alt+7 ToolWindow_eventlog=Alt+1 ToolWindow_folders=Alt+0 ToolWindow_godocfind=Alt+9 ToolWindow_gopackbrowser=Alt+8 ToolWindow_outline=Alt+4 [GoPkg] SetupGOPATH= [GoDoc] JumpToDeclaration=F2 [Debug] Breakpoint=F9 Continue=F5 LiteDebug.StepOver=F10 RemoveAllBreakPoints= RunToLine=Ctrl+F10 ShowLine= StartDebug=F5 StartDebugExternal= StepInfo=F11 StepOut=Shift+F11 StopDebug=Shift+F5 StartDebugTests=F6 [GoFmt] Gofmt=Shift+F7 Goplayfmt=Shift+F7 [Markdown] Blockquote=Ctrl+Shift+Q Header1=Ctrl+1 Header2=Ctrl+2 Header3=Ctrl+3 Header4=Ctrl+4 Header5=Ctrl+5 Header6=Ctrl+6 HorizontalRule=Ctrl+Shift+H Image=Ctrl+Shift+I InlineCode=Ctrl+K Link=Ctrl+Shift+L OrderedList=Ctrl+Shift+O UnorderedList=Ctrl+Shift+U ================================================ FILE: liteidex/deploy/liteapp/mimetype/folderproject.xml ================================================ Folder Project ================================================ FILE: liteidex/deploy/liteapp/mimetype/gopackage.xml ================================================ Golang Package Project ================================================ FILE: liteidex/deploy/liteapp/mimetype/liteeditor.xml ================================================ Golang Source File Qlang Source File Golang module Rust Source File Lua Source File Python Source File HTML Source File Go HTML Template File XML Source File C Source File YAML Source File ================================================ FILE: liteidex/deploy/liteapp/mimetype/qsqleditor.xml ================================================ SQLite Database File ================================================ FILE: liteidex/deploy/liteapp/qss/black.qss ================================================ /* === Shared === */ QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QComboBox, QDialog { background-color: #222222; color: #BBBBBB; font-family: "Segoe UI"; } /* === QWidget === */ QWidget:window { background: #222222; color: #BBBBBB; font-family: "Segoe UI"; } /* === WebView === */ QTextBrowser, QWebView { background-color: #BBBBBB; selection-color: #0a214c; selection-background-color: #C19A6B; } /* === QToolTip === */ QToolTip { background-color: #000000; border: 2px solid #333333; color: yellow; } /* === QPushButton === */ QPushButton { border: 1px solid #333333; padding: 4px; min-width: 65px; min-height: 12px; } QPushButton:hover { background-color: #333333; border-color: #444444; } QPushButton:pressed { background-color: #111111; border-color: #333333; color: yellow; } QPushButton:disabled { color: #333333; } /* === Checkable items === */ QCheckBox::indicator, QRadioButton::indicator, QTreeView::indicator { width: 16px; height: 16px; background-color: #111111; border: 1px solid #333333; } QRadioButton::indicator { border-radius: 8px; } QCheckBox::indicator::checked, QRadioButton::indicator::checked, QTreeView::indicator::checked { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.25, fy:0.15, radius:0.3, stop:0 #BBBBBB, stop:1 #111111); } QCheckBox::indicator:disabled, QRadioButton::indicator:disabled, QTreeView::indicator:disabled { background-color: #444444; } QCheckBox::indicator::checked:disabled, QRadioButton::indicator::checked:disabled, QTreeView::indicator::checked:disabled { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.25, fy:0.15, radius:0.3, stop:0 #BBBBBB, stop:1 #444444); } /* === QComboBox === */ QComboBox { background-color: black; border: 1px solid #333333; color: white; padding:1px 2em 1px 3px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #333333; } QComboBox::down-arrow { border: 2px solid #333333; width: 6px; height: 6px; background: #5f5f5f; } /* === QGroupBox === */ QGroupBox { border: 2px solid #333333; margin-top: 2ex; } QGroupBox::title { color: yellow; subcontrol-origin: margin; subcontrol-position: top left; margin-left: 5px; } /* === QTabWidget === */ QTabWidget::pane { background: #222222; border: 2px solid #333333; } /* === QTabBar === */ QTabBar::tab { background: transparent; border: 1px solid #333333; border-bottom: none; color: #BBBBBB; padding-left: 5px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; } QTabBar::tab:hover { background-color: #333333; border: 1px solid #444444; border-bottom: none; } QTabBar::tab:selected { background-color: #111111; border: solid #fff; border-width: 1px 1px 0px; color: yellow } /* === QToolBar === */ QToolBar { background-color: #222222; border: none; padding: 1px; } QToolBar:handle { background: #222222; border-left: 1px dotted yellow; color: #BBBBBB; } QToolBar::separator { width: 6px; background-color: #222222; } /* === QToolButton === */ QToolButton { border: 1px solid #333333; margin: 1px; } QToolButton:hover { background-color: #333333; border: 1px solid #444444; } QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ padding-right: 20px; /* make way for the popup button */ } QToolButton::menu-button { border-left: 1px solid #333333; background: transparent; width: 16px; } QToolButton::menu-button:hover { border-left: 1px solid #444444; background: transparent; width: 16px; } QToolButton:checked, QToolButton:pressed { background-color: #111111; color: yellow; } /* === QMenu === */ QMenu { background-color: black; border: 1px solid gray; color: white; padding: 1px; } QMenu::item { padding: 2px 25px 2px 20px; border: 1px solid transparent; } QMenu::item:disabled { color: #666666; } QMenu::item:selected { border-color: gray; background: #222222; } QMenu::icon:checked { } QMenu::separator { height: 1px; background: #222222; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: black; color: white; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: gray; } QMenuBar::item:selected { background: #222222; } QMenuBar::item:pressed { background: #444444; } /* === QScrollBar:vertical === */ QScrollBar:vertical { background: #111111; width: 16px; margin: 16px 0 16px 0; } QScrollBar::handle:vertical { background: #555555; min-height: 16px; } QScrollBar::add-line:vertical { background: #444444; height: 16px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { background: #444444; height: 16px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 2px solid #333333; width: 6px; height: 6px; background: #5f5f5f; } /* === QScrollBar:horizontal === */ QScrollBar:horizontal { background: #111111; height: 16px; margin: 0 16px 0 16px; } QScrollBar::handle:horizontal { background: #555555; min-width: 16px; } QScrollBar::add-line:horizontal { background: #444444; width: 16px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { background: #444444; width: 16px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 2px solid #333333; width: 6px; height: 6px; background: #5f5f5f; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: black; color: #BBBBBB; border: 1px solid #333333; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox, QComboBox { border-color: #333333; border: 1px solid #333333; } /* === QHeaderView === */ QHeaderView::section { background: #222222; border: 0; color: #BBBBBB; padding: 3px 0 3px 4px; } /* === QListView === */ QListView::item:hover { background: #333333; } QListView::item:selected { background: #111111; color: yellow; } /* === QTableView === */ QTableView::item:hover { background: #333333; } QTableView::item:hover { background: #111111; color: yellow; } /* === QTreeView === */ QTreeView::item { background: black; } QTreeView::item:hover { background: #333333; } QTreeView::item:selected { background: #111111; color: yellow; } QTreeView::branch { } QTreeView::branch:has-siblings:adjoins-item { } QTreeView::branch:has-siblings:!adjoins-item { } QTreeView::branch:closed:has-children:has-siblings { } QTreeView::branch:has-children:!has-siblings:closed { } QTreeView::branch:!has-children:!has-siblings:adjoins-item { } QTreeView::branch:open:has-children:has-siblings { } QTreeView::branch:open:has-children:!has-siblings { } /* === Customizations === */ QFrame#infoLabel { border: 1px inset #333333; } ================================================ FILE: liteidex/deploy/liteapp/qss/carbon.qss ================================================ /* === Shared === */ QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QComboBox, QDialog { background-color: #303030; color: #BBBBBB; } /* === QWidget === */ QWidget:window { background: #303030; color: #BBBBBB; } /* === WebView === */ QTextBrowser, QWebView { background-color: #BBBBBB; selection-color: #0a214c; selection-background-color: #C19A6B; } /* === QPushButton === */ QPushButton { border: 0.5px solid #303030; padding: 4px; min-width: 65px; min-height: 12px; } QPushButton:hover { background-color: #303030; border-color: #444444; } QPushButton:pressed { background-color: #222222; border-color: #303030; color: white; } QPushButton:disabled { color: #303030; } /* === QComboBox === */ QComboBox { background-color: #282828; border: 1px solid #303030; color: white; padding:1px 2em 1px 3px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #303030; } QComboBox::down-arrow { border: 2px solid #303030; width: 6px; height: 6px; background: #5f5f5f; } /* === QTabBar === */ QTabBar::tab { background: transparent; border: 1px solid #303030; border-bottom: none; color: #BBBBBB; padding-left: 5px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; } QTabBar::tab:hover { background-color: #303030; border: 1px solid #444444; border-bottom: none; } QTabBar::tab:selected { background-color: #282828; border: 1px solid #303030; border-top: 1px solid white; border-bottom: none; color: white } /* === QToolBar === */ QToolBar { background-color: #303030; border: none; padding: 1px; } QToolBar::separator { width: 6px; background-color: #303030; } /* === QToolButton === */ QToolButton { border: 1px solid #303030; margin: 1px; } QToolButton:hover { background-color: #303030; border: 1px solid #444444; } QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ padding-right: 20px; /* make way for the popup button */ } QToolButton::menu-button { border-left: 1px solid #303030; background: transparent; width: 16px; } QToolButton::menu-button:hover { border-left: 1px solid #444444; background: transparent; width: 16px; } QToolButton:checked, QToolButton:pressed { background-color: #222222; color: white; } /* === QMenu === */ QMenu { background-color: #282828; border: 1px solid gray; color: white; padding: 1px; } QMenu::item { padding: 2px 25px 2px 20px; border: 1px solid transparent; } QMenu::item:disabled { color: #666666; } QMenu::item:selected { border-color: gray; background: #303030; } QMenu::icon:checked { } QMenu::separator { height: 1px; background: #303030; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: #282828; color: white; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: gray; } QMenuBar::item:selected { background: #303030; } QMenuBar::item:pressed { background: #444444; } /* === QScrollBar:vertical === */ QScrollBar:vertical { background: #282828; width: 16px; margin: 16px 0 16px 0; } QScrollBar::handle:vertical { background: #303030; min-height: 16px; } QScrollBar::add-line:vertical { background: #444444; height: 16px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { background: #444444; height: 16px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 2px solid #303030; width: 6px; height: 6px; background: #5f5f5f; } /* === QScrollBar:horizontal === */ QScrollBar:horizontal { background: #282828; height: 16px; margin: 0 16px 0 16px; } QScrollBar::handle:horizontal { background: #303030; min-width: 16px; } QScrollBar::add-line:horizontal { background: #444444; width: 16px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { background: #444444; width: 16px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 2px solid #303030; width: 6px; height: 6px; background: #5f5f5f; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #282828; color: #BBBBBB; border: 1px solid #303030; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox, QComboBox { border-color: #303030; border: 1px solid #303030; } /* === QHeaderView === */ QHeaderView { background: #303030; } QHeaderView::section { background: #303030; border: 0; color: #BBBBBB; padding: 3px 0 3px 4px; } /* === Customizations === */ QFrame#infoLabel { border: 1px inset #303030; } ================================================ FILE: liteidex/deploy/liteapp/qss/coffee.qss ================================================ .QWidget { background-color: beige; } QToolBar { background-color: beige; } QDialog, QFileDialog { background-color: beige; } QTabWidget::pane { /* The tab widget frame */ border-top: 2px solid #C2C7CB; } QTabWidget::tab-bar { left: 5px; /* move to the right by 5px */ } QTabBar, QTabWidget { background-color: beige; } QTabBar::tab { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); border: 1px solid darkkhaki; border-bottom-color: #C2C7CB; /* same as the pane color */ border-top-left-radius: 4px; border-top-right-radius: 4px; min-width: 8ex; padding: 2px; } QTabBar::tab:selected, QTabBar::tab:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fafafa, stop: 0.4 #f4f4f4, stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); } QTabBar::tab:selected { border-color: #9B9B9B; border-bottom-color: #C2C7CB; /* same as pane color */ } QTabBar::tab:!selected { margin-top: 2px; /* make non-selected tabs look smaller */ } /* Nice Windows-XP-style password character. */ QLineEdit[echoMode="2"] { lineedit-password-character: 9679; } QHeaderView::section { background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #616161, stop: 0.5 #505050, stop: 0.6 #434343, stop:1 #656565); color: white; padding-left: 4px; border: 1px solid #6c6c6c; } QHeaderView::section:checked { background-color: red; } /* We provide a min-width and min-height for push buttons so that they look elegant regardless of the width of the text. */ QPushButton { background-color: palegoldenrod; border-width: 2px; border-color: darkkhaki; border-style: solid; border-radius: 5; padding: 3px; min-width: 9ex; min-height: 2.5ex; } QPushButton:hover { background-color: khaki; } /* Increase the padding, so the text is shifted when the button is pressed. */ QPushButton:pressed { padding-left: 5px; padding-top: 5px; background-color: #d0d67c; } QLabel, QAbstractButton { font: bold; } /* Mark mandatory fields with a brownish color. */ .mandatory { color: brown; } /* Bold text on status bar looks awful. */ QStatusBar QLabel { font: normal; } QStatusBar::item { border-width: 1; border-color: darkkhaki; border-style: solid; border-radius: 2; } QStackedWidget, QComboBox, QLineEdit, QSpinBox, QTextEdit, QListView, QWebView, QTreeView, QHeaderView { background-color: cornsilk; selection-color: #0a214c; selection-background-color: #C19A6B; } QListView { show-decoration-selected: 1; } QListView::item:hover { background-color: wheat; } /* We reserve 1 pixel space in padding. When we get the focus, we kill the padding and enlarge the border. This makes the items glow. */ QLineEdit, QFrame { border-width: 1px; padding: 1px; border-style: solid; border-color: darkkhaki; border-radius: 5px; } /* As mentioned above, eliminate the padding and increase the border. */ QLineEdit:focus, QFrame:focus { border-width: 3px; padding: 0px; } /* A QLabel is a QFrame ... */ QLabel { border: none; padding: 0; background: none; } /* A QToolTip is a QLabel ... */ QToolTip { border: 2px solid darkkhaki; padding: 5px; border-radius: 3px; opacity: 200; } /* Nice to have the background color change when hovered. */ QRadioButton:hover, QCheckBox:hover { background-color: wheat; } /* Force the dialog's buttons to follow the Windows guidelines. */ QDialogButtonBox { button-layout: 0; } ================================================ FILE: liteidex/deploy/liteapp/qss/default.qss ================================================ /* empty stylesheet */ ================================================ FILE: liteidex/deploy/liteapp/qss/default_macos.qss ================================================ /* Tab bar style copied from https://github.com/visualfc/liteide/blob/master/liteidex/deploy/liteapp/qss/coffee.qss */ QTabBar::tab { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); border: 1px solid darkkhaki; border-bottom-color: #C2C7CB; /* same as the pane color */ min-width: 8ex; padding: 4px 2px 4px 2px; } QTabBar::tab:selected, QTabBar::tab:hover { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #fafafa, stop: 0.4 #f4f4f4, stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); } QTabBar::tab:selected { border-color: #9B9B9B; border-bottom-color: #C2C7CB; /* same as pane color */ } QTabBar::tab:!selected { margin-top: 2px; /* make non-selected tabs look smaller */ } ================================================ FILE: liteidex/deploy/liteapp/qss/detroit-future.qss ================================================ /* Detroit Future github.com/donuts-are-good (MIT License) */ /* === Shared === */ QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QComboBox, QDialog { background-color: #000000; color: #DCCBF6; font-family: "Monospace"; } /* === QWidget === */ QWidget:window { background: #000000; color: #DCCBF6; font-family: "Monospace"; } /* === WebView === */ QTextBrowser, QWebView { background-color: #000000; selection-color: #ffee52; selection-background-color: #2A0F52; } /* === QToolTip === */ QToolTip { background-color: #000000; border: 2px solid #000000; color: #23F4AE; } /* === QPushButton === */ QPushButton { border: 1px solid #000000; padding: 4px; min-width: 65px; min-height: 12px; } QPushButton:hover { background-color: #03041A; border-color: #03041A; color: #23F4AE; } QPushButton:pressed { background-color: #03041A; border-color: #03041A; color: #5B20B1; } QPushButton:disabled { color: #2A0F52; } /* === Checkable items === */ QCheckBox::indicator, QRadioButton::indicator, QTreeView::indicator { width: 10px; height: 10px; background-color: #000000; border: 1px solid #000000; } QRadioButton::indicator { border-radius: 8px; } QCheckBox::indicator::checked, QRadioButton::indicator::checked, QTreeView::indicator::checked { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.25, fy:0.15, radius:0.3, stop:0 #DCCBF6, stop:1 #111111); } QCheckBox::indicator:disabled, QRadioButton::indicator:disabled, QTreeView::indicator:disabled { background-color: #000000; } QCheckBox::indicator::checked:disabled, QRadioButton::indicator::checked:disabled, QTreeView::indicator::checked:disabled { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.25, fy:0.15, radius:0.3, stop:0 #DCCBF6, stop:1 #444444); } /* === QComboBox === */ QComboBox { background-color: #000000; border: 1px solid #000000; color: #719ef7; padding:1px 2em 1px 3px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #000000; } QComboBox::down-arrow { border: 2px solid #000000; width: 6px; height: 6px; background: #23F4AE; } /* === QGroupBox === */ QGroupBox { border: 2px solid #000000; margin-top: 2em; } QGroupBox::title { color: #23F4AE; subcontrol-origin: margin; subcontrol-position: top left; margin-left: 5px; } /* === QTabWidget === */ QTabWidget::pane { background: #000000; border: 2px solid #000000; } /* === QTabBar === */ QTabBar::tab { background-color: #000000; background: transparent; border: 1px solid #000000; border-bottom: none; color: #DCCBF6; padding-left: 5px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; } QTabBar::tab:hover { background-color: #03041A; border: 1px solid #03041A; border-bottom: none; } QTabBar::tab:selected { background-color: #000000; border: solid #000000; border-width: 1px 1px 0px; color: #23F4AE; } /* === QToolBar === */ QToolBar { background-color: #000000; border: none; padding: 1px; } QToolBar:handle { background: #000000; border-left: 1px dotted #23F4AE; color: #DCCBF6; } QToolBar::separator { width: 6px; background-color: #000000; } /* === QToolButton === */ QToolButton { border: 1px solid #000000; margin: 1px; } QToolButton:hover { background-color: #03041A; border: 1px solid #03041A; } QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ padding-right: 20px; /* make way for the popup button */ } QToolButton::menu-button { border-left: 1px solid #000000; background: transparent; width: 10px; } QToolButton::menu-button:hover { border-left: 1px solid #03041A; color: #23F4AE; background: transparent; width: 10px; } QToolButton:checked, QToolButton:pressed { background-color: #000000; color: #5B20B1; } /* === QMenu === */ QMenu { background-color: #000000; border: 1px solid #000000; color: #8888ff; padding: 1px; } QMenu::item { padding: 2px 25px 2px 20px; border: 1px solid transparent; } QMenu::item:disabled { color: #2A0F52; } QMenu::item:selected { border-color: #2A0F52; background: #2A0F52; color: #ffee52; } QMenu::icon:checked { } QMenu::separator { height: 1px; background: #000000; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: #000000; color: #666699; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: #03041A; } QMenuBar::item:selected { background: #000000; } QMenuBar::item:pressed { background: #000000; color: #5B20B1; } /* === QScrollBar:vertical === */ QScrollBar:vertical { background: #03041A; width: 10px; margin: 10px 0 10px 0; border-radius: 8px; } QScrollBar::handle:vertical { background: #5B20B1; min-height: 10px; border-radius: 8px; } QScrollBar::add-line:vertical { background: #03041A; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; border-radius: 8px; } QScrollBar::sub-line:vertical { background: #03041A; height: 10px; subcontrol-position: top; subcontrol-origin: margin; border-radius: 8px; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 2px solid #03041A; width: 6px; height: 6px; background: #23F4AE; border-radius: 8px; } /* === QScrollBar:horizontal === */ QScrollBar:horizontal { background: #03041A; height: 10px; margin: 0 10px 0 10px; border-radius: 8px; } QScrollBar::handle:horizontal { background: #03041A; min-width: 10px; border-radius: 8px; } QScrollBar::add-line:horizontal { background: #03041A; width: 10px; subcontrol-position: right; subcontrol-origin: margin; border-radius: 8px; } QScrollBar::sub-line:horizontal { background: #03041A; width: 10px; subcontrol-position: left; subcontrol-origin: margin; border-radius: 8px; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; border-radius: 8px; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 2px solid #000000; width: 6px; height: 6px; background: #23F4AE; border-radius: 8px; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #000000; color: #DCCBF6; border: 1px solid #000000; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox, QComboBox { border-color: #000000; border: 1px solid #000000; } /* === QHeaderView === */ QHeaderView::section { background: #000000; border: 0; color: #DCCBF6; padding: 3px 0 3px 4px; } /* === QListView === */ QListView::item:hover { background: #03041A; color: #23F4AE; } QListView::item:selected { background: #000000; color: #23F4AE; } /* === QTableView === */ QTableView::item:hover { background: #03041A; } QTableView::item:hover { background: #03041A; color: #23F4AE; } /* === QTreeView === */ QTreeView::item { background: #000000; } QTreeView::item:hover { background: #03041A; } QTreeView::item:selected { background: #000000; color: #23F4AE; } QTreeView::branch { } QTreeView::branch:has-siblings:adjoins-item { } QTreeView::branch:has-siblings:!adjoins-item { } QTreeView::branch:closed:has-children:has-siblings { } QTreeView::branch:has-children:!has-siblings:closed { } QTreeView::branch:!has-children:!has-siblings:adjoins-item { } QTreeView::branch:open:has-children:has-siblings { } QTreeView::branch:open:has-children:!has-siblings { } /* === Customizations === */ QFrame#infoLabel { border: 1px inset #000000; } ================================================ FILE: liteidex/deploy/liteapp/qss/evilworks.qss ================================================ /* Style by evilworks, 2012-2013. pollux@lavabit.com This file is Public Domain. */ /* === Shared === */ QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QComboBox, QDialog, QTabBar { font-family: "Segoe UI"; background-color: #888; color: #000; } /* === QWidget === */ QWidget:window { font-family: 'Segoe UI'; background-color: #888; } /* === WebView === */ QTextBrowser, QWebView { background-color: #BBBBBB; selection-color: #0a214c; selection-background-color: #C19A6B; } /* === QPushButton === */ QPushButton { border: 1px solid #555; padding: 4px; min-width: 65px; min-height: 12px; } QPushButton:hover { background-color: #999; } QPushButton:pressed { background-color: #333; border-color: #555; color: #AAA; } QPushButton:disabled { color: #333333; } /* === QComboBox === QComboBox { background-color: #AAA; border: 1px solid #555; color: black; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #333333; } */ /* === QGroupBox === */ QGroupBox { border: 1px solid #555; margin-top: 2ex; } QGroupBox::title { color: black; subcontrol-origin: margin; subcontrol-position: top left; border: 1px solid #555; } /* === QTabBar === */ QTabBar::tab { border-bottom: none; color: #000; padding: 4px; background-color: #888; border: 1px solid #555; } QTabBar::tab:hover { background-color: #AAA; } QTabBar::tab:selected { background-color: #000; border: solid #fff; border-width: 1px 1px 0px; color: white; } /* === QTabWidget === */ QTabWidget::pane { background: #888; border: 1px solid #555; } /* === QToolBar === */ QToolBar { background: #949494; border: none; padding-left: 0px; padding-right: 0px; margin: 2px; } QToolBar::separator { width: 1px; margin-left: 3px; margin-right: 3px; background-color: #555; } /* === QToolButton === */ QToolButton { border: 1px solid #666; margin: 1px; } QToolButton:hover { background-color: #AAA; } QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ padding-right: 20px; /* make way for the popup button */ } QToolButton::menu-button { border-left: 1px solid #666; background: transparent; width: 16px; } QToolButton::menu-button:hover { border-left: 1px solid #666; background: transparent; width: 16px; } QToolButton:checked, QToolButton:pressed { background-color: #000; border: 1px solid #555; color: white; } /* === QScrollBar:vertical === */ QScrollBar:vertical { width: 16px; margin: 16px 0 16px 0; background: #333; } QScrollBar::handle:vertical { background: #888; min-height: 16px; border-top: 1px solid #666; border-bottom: 1px solid #666; } QScrollBar::add-line:vertical { background: #888; height: 16px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { background: #888; height: 16px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } /* === QScrollBar:horizontal === */ QScrollBar:horizontal { height: 16px; margin: 0 16px 0 16px; background: #333; } QScrollBar::handle:horizontal { background: #888; min-width: 16px; border-left: 1px solid #666; border-right: 1px solid #666; } QScrollBar::add-line:horizontal { background: #888; width: 16px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { background: #888; width: 16px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } /* === QMenu === */ QMenu { background-color: black; border: 1px solid gray; color: white; padding: 1px; } QMenu::item { padding: 2px 25px 2px 20px; border: 1px solid transparent; } QMenu::item:disabled { color: #666666; } QMenu::item:selected { border-color: gray; background: #222222; } QMenu::icon:checked { } QMenu::separator { height: 1px; background: #222222; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: black; color: white; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: gray; } QMenuBar::item:selected { background: #222222; } QMenuBar::item:pressed { background: #444444; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #AAA; color: #000; border: 1px solid #555; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox, QComboBox { border: 1px solid #555; } /* === QHeaderView === */ QHeaderView { background: #666; } QHeaderView::section { height: 20px; } QHeaderView::section { background: #666; border: 0; color: #000; padding-left: 4px; } /* === QListView === */ QListView::item:hover { background: #AAA; } QListView::item:selected { background: #333; color: #AAA; } /* === QTableView === */ QTableView::item:hover { background: #333333; } QTableView::item:hover { background: #111111; color: white; } /* === QTreeView === */ QTreeView::item { } QTreeView::item:hover { } QTreeView::item:selected { } QTreeView::branch { } QTreeView::branch:has-siblings:adjoins-item { } QTreeView::branch:has-siblings:!adjoins-item { } QTreeView::branch:closed:has-children:has-siblings { } QTreeView::branch:has-children:!has-siblings:closed { } QTreeView::branch:!has-children:!has-siblings:adjoins-item { } QTreeView::branch:open:has-children:has-siblings { } QTreeView::branch:open:has-children:!has-siblings { } ================================================ FILE: liteidex/deploy/liteapp/qss/gray.qss ================================================ /* === Shared === */ QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QDialog { background-color: #232323; color: #BBBBBB; } /* === QWidget === */ QWidget:window { background: #232323; color: #BBBBBB; } /* === WebView === */ QTextBrowser, QWebView { background-color: #BBBBBB; selection-color: #0a214c; selection-background-color: #C19A6B; } /* === QPushButton === */ QPushButton { border: 0.5px solid #232323; padding: 4px; min-width: 65px; min-height: 12px; } QPushButton:hover { background-color: #232323; border-color: #444444; } QPushButton:pressed { background-color: #111111; border-color: #444444; color: white; } QPushButton:disabled { color: #232323; } /* === QComboBox === */ QComboBox { background-color: #282828; border: 1px solid #232323; color: white; padding:1px 2em 1px 3px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #232323; } QComboBox::down-arrow { border: 2px solid #232323; width: 6px; height: 6px; background: #5f5f5f; } /* === QTabBar === */ QTabBar::tab { background: transparent; border: 1px solid #232323; border-bottom: none; color: #BBBBBB; padding-left: 5px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; } QTabBar::tab:hover { background-color: #232323; border: 1px solid #444444; border-bottom: none; } QTabBar::tab:selected { background-color: #111111; border: 1px solid #232323; border-top: 0px; border-bottom: none; color: white } /* === QToolBar === */ QToolBar { background-color: #232323; border: none; padding: 1px; } QToolBar::separator { width: 6px; background-color: #232323; } /* === QToolButton === */ QToolButton { border: 1px solid #232323; margin: 1px; } QToolButton:hover { background-color: #232323; border: 1px solid #444444; } QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ padding-right: 20px; /* make way for the popup button */ } QToolButton::menu-button { border-left: 1px solid #232323; background: transparent; width: 16px; } QToolButton::menu-button:hover { border-left: 1px solid #444444; background: transparent; width: 16px; } QToolButton:checked, QToolButton:pressed { background-color: #111111; color: white; } /* === QMenu === */ QMenu { background-color: #282828; border: 1px solid gray; color: white; padding: 1px; } QMenu::item { padding: 2px 25px 2px 20px; border: 1px solid transparent; } QMenu::item:disabled { color: #666666; } QMenu::item:selected { border-color: gray; background: #232323; } QMenu::icon:checked { } QMenu::separator { height: 1px; background: #232323; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: #282828; color: white; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: gray; } QMenuBar::item:selected { background: #232323; } QMenuBar::item:pressed { background: #444444; } /* === QScrollBar:vertical === */ QScrollBar:vertical { background: #303030; width: 16px; margin: 16px 0 16px 0; } QScrollBar::handle:vertical { background: #232323; min-height: 16px; } QScrollBar::add-line:vertical { background: #444444; height: 16px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { background: #444444; height: 16px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 2px solid #232323; width: 6px; height: 6px; background: #5f5f5f; } /* === QScrollBar:horizontal === */ QScrollBar:horizontal { background: #303030; height: 16px; margin: 0 16px 0 16px; } QScrollBar::handle:horizontal { background: #232323; min-width: 16px; } QScrollBar::add-line:horizontal { background: #444444; width: 16px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { background: #444444; width: 16px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 2px solid #232323; width: 6px; height: 6px; background: #5f5f5f; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #282828; color: #BBBBBB; border: 1px solid #232323; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox { border-color: #232323; border: 1px solid #232323; } /* === QHeaderView === */ QHeaderView { background: #232323; } QHeaderView::section { background: #232323; border: 0; color: #BBBBBB; padding: 3px 0 3px 4px; } /* === Customizations === */ QFrame#infoLabel { border: 1px inset #232323; } ================================================ FILE: liteidex/deploy/liteapp/qss/one-dark.qss ================================================ /* One Dark - https://github.com/atom/one-dark-ui */ /* Author: Lofanmi - https://github.com/Lofanmi */ /* MIT License */ QWidget, QToolBar, QFileDialog, QStackedWidget, QTextBrowser, QLabel, QPushButton, QRadioButton, QCheckBox, QStatusBar, QToolButton, QComboBox, QTabBar, QTabWidget, QLineEdit, QFrame, QSpinBox, QTextEdit, QListView, QWebView, QTreeView, QHeaderView, QDialog { background-color: #282c34; border-color: #464c55; border-radius: 6px; color: #b9b9b9; } QWidget:window { background: #282c34; border-color: #464c55; color: #b9b9b9; } QTabWidget::pane { background: #282c34; border: 1px solid #464c55; border-radius: 6px; } QPushButton { border: 1px solid #464c55; border-radius: 6px; padding: 4px; min-width: 65px; min-height: 12px; } QPushButton:hover { background-color: #282c34; } QPushButton:pressed { background-color: #282c34; color: white; } QPushButton:disabled { color: #282c34; } QComboBox { background-color: #282c34; border: 1px solid #464c55; border-radius: 6px; color: #b9b9b9; padding: 1px 2em 1px 3px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #464c55; } QComboBox::down-arrow { border: 1px solid #464c55; border-radius: 6px; width: 6px; height: 6px; background: #495162; } QTabBar::tab { background: #282C34; border: 1px solid #464c55; border-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; border-bottom-left-radius: 0; border-bottom-right-radius: 0; border-bottom: none; color: #b9b9b9; padding-left: 5px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; } QTabBar::tab:hover { background-color: #282c34; border: 1px solid #464c55; border-bottom: none; } QTabBar::tab:selected { background-color: #22252C; border: 1px solid #464c55; border-bottom: none; color: white; } QToolBar { background-color: #282c34; border: none; padding: 1px; } QToolBar::separator { width: 6px; background-color: #282c34; } QToolButton { border: 1px solid #464c55; border-radius: 6px; margin: 1px; } QToolButton:hover { background-color: #282c34; border: 1px solid #464c55; } QToolButton::menu-button { border-left: 1px solid #282c34; border-radius: 6px; background: #282C34; width: 16px; } QToolButton::menu-button:hover { border-left: 1px solid #464c55; background: #282C34; width: 16px; } QToolButton:checked, QToolButton:pressed { background-color: #282c34; color: white; } QMenu { background-color: #282c34; border: 1px solid #404859; border-radius: 6px; color: white; padding: 1px; } QMenu::item { padding: 2px 25px 2px 20px; border: 1px solid #282C34; border-radius: 6px; } QMenu::item:disabled { color: #666666; } QMenu::item:selected { border-color: #404859; background: #282c34; } QMenu::separator { height: 1px; background: #282c34; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } QMenuBar { background-color: #282c34; color: white; } QMenuBar::item { background: #282C34; } QMenuBar::item:disabled { color: #404859; } QMenuBar::item:selected { background: #282c34; } QMenuBar::item:pressed { background: #464c55; } QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #282c34; color: #b9b9b9; border: 1px solid #464c55; border-radius: 6px; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox, QComboBox { border: 1px solid #464c55; border-radius: 6px; } QScrollBar:vertical { background-color: #282c34; border: 1px solid #464c55; border-radius: 6px; width: 18px; margin: 18px 0 18px 0px; } QScrollBar::handle:vertical { background-color: #464c55; min-height: 20px; } QScrollBar::add-line:vertical { border: none; height: 18px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { border: none; height: 18px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 1px solid #464c55; border-radius: 6px; width: 14px; height: 14px; background-color: #282c34; } QScrollBar:horizontal { background-color: #282c34; border: 1px solid #464c55; border-radius: 6px; height: 18px; margin: 0px 18px 0 18px; } QScrollBar::handle:horizontal { background-color: #282c34; min-width: 20px; } QScrollBar::add-line:horizontal { border: none; width: 18px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { border: none; width: 18px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 1px solid #464c55; border-radius: 6px; width: 14px; height: 14px; background-color: #282c34; } QHeaderView { background: #282c34; } QHeaderView::section { background: #282c34; border: 0; color: #b9b9b9; padding: 3px 0 3px 4px; } QFrame#infoLabel { border: 1px inset #464c55; border-radius: 6px; } QGroupBox { margin-top: 1ex; border: 1px solid #464c55; border-radius: 6px; } QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; margin-bottom: 6px; } ================================================ FILE: liteidex/deploy/liteapp/qss/sublime.qss ================================================ /* === Shared === */ QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QComboBox, QDialog { background-color: #333333; color: #BBBBBB; } /* === QWidget === */ QWidget:window { background: #333333; color: #BBBBBB; } /* === WebView === */ QTextBrowser, QWebView { background-color: #BBBBBB; selection-color: #0a214c; selection-background-color: #C19A6B; } /* === QPushButton === */ QPushButton { border: 0.5px solid #333333; padding: 4px; min-width: 65px; min-height: 12px; } QPushButton:hover { background-color: #333333; border-color: #444444; } QPushButton:pressed { background-color: #222222; border-color: #333333; color: white; } QPushButton:disabled { color: #333333; } /* === QComboBox === */ QComboBox { background-color: #272822; border: 1px solid #333333; color: #BBBBBB; padding:1px 2em 1px 3px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #333333; } QComboBox::down-arrow { border: 2px solid #333333; width: 6px; height: 6px; background: #5f5f5f; } /* === QTabBar === */ QTabBar::tab { background: transparent; border: 1px solid #333333; border-bottom: none; color: #BBBBBB; padding-left: 5px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; } QTabBar::tab:hover { background-color: #333333; border: 1px solid #444444; border-bottom: none; } QTabBar::tab:selected { background-color: #272822; border: 1px solid #333333; border-bottom: none; color: white } /* === QToolBar === */ QToolBar { background-color: #333333; border: none; padding: 1px; } QToolBar::separator { width: 6px; background-color: #333333; } /* === QToolButton === */ QToolButton { border: 1px solid #333333; margin: 1px; } QToolButton:hover { background-color: #333333; border: 1px solid #444444; } QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ padding-right: 20px; /* make way for the popup button */ } QToolButton::menu-button { border-left: 1px solid #333333; background: transparent; width: 16px; } QToolButton::menu-button:hover { border-left: 1px solid #444444; background: transparent; width: 16px; } QToolButton:checked, QToolButton:pressed { background-color: #222222; color: white; } /* === QMenu === */ QMenu { background-color: #272822; border: 1px solid gray; color: white; padding: 1px; } QMenu::item { padding: 2px 25px 2px 20px; border: 1px solid transparent; } QMenu::item:disabled { color: #666666; } QMenu::item:selected { border-color: gray; background: #333333; } QMenu::icon:checked { } QMenu::separator { height: 1px; background: #333333; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: #272822; color: white; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: gray; } QMenuBar::item:selected { background: #333333; } QMenuBar::item:pressed { background: #444444; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #272822; color: #BBBBBB; border: 1px solid #333333; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox, QComboBox { border-color: #333333; border: 1px solid #333333; } /* === QScrollBar - Vertical === */ QScrollBar:vertical { background-color: #272822; border: 2px solid #272822; width: 18px; margin: 18px 0 18px 0px; } QScrollBar::handle:vertical { background-color: #333333; min-height: 20px; } QScrollBar::add-line:vertical { border: none; height: 18px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { border: none; height: 18px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: none; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 2px solid #272822; width: 14px; height: 14px; background-color: #333333; } /* === QScrollBar - Horizontal === */ QScrollBar:horizontal { background-color: #272822; border: 2px solid #272822; height: 18px; margin: 0px 18px 0 18px; } QScrollBar::handle:horizontal { background-color: #333333; min-width: 20px; } QScrollBar::add-line:horizontal { border: none; width: 18px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { border: none; width: 18px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: none; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 2px solid #272822; width: 14px; height: 14px; background-color: #333333; } /* === QHeaderView === */ QHeaderView { background: #333333; } QHeaderView::section { background: #333333; border: 0; color: #BBBBBB; padding: 3px 0 3px 4px; } /* === Customizations === */ QFrame#infoLabel { border: 1px inset #333333; } ================================================ FILE: liteidex/deploy/liteapp/qss/vs-dark-hdpi.qss ================================================ /* ===add file: \liteide\share\liteide\liteapp\qss\vs-dark.qss ===*/ /* ===FROM: https://gist.github.com/tupunco/fdb713ec9c6189a877e5eb003bd0457d ===*/ /* === Shared === */ QMainWindow{ background-color: #252526; color: #BBBBBB; } QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QComboBox, QDialog, QListView, QTabBar, QMenu, QMenuBar, QWidget::window { background-color: #252526; color: #BBBBBB; } /* === QWidget === */ QWidget:window { } /* === WebView === */ QTextBrowser, QWebView { background-color: #BBBBBB; selection-color: #0a214c; selection-background-color: #C19A6B; } /* === QToolTip === */ QToolTip { background-color: #EAEBF3; border: 1px solid #767676; color: #575757; } /* === QPushButton === */ QPushButton { border: 1px solid #333333; padding: 1ex 4ex; min-width: 12ex; min-height: 4ex; background-color: #333333; margin: 0 2px; } QPushButton:hover { background-color: #333333; border-color: #444444; } QPushButton:pressed { background-color: #2D2D30; border-color: #333333; color: #BBBBBB; } QPushButton:disabled { color: #333333; } /* === Checkable items === */ QCheckBox::indicator, QRadioButton::indicator, QTreeView::indicator { width: 4ex; height: 4ex; background-color: #2D2D30; border: 1px solid #434346; } QRadioButton::indicator { border-radius: 2px; } QCheckBox::indicator::checked, QRadioButton::indicator::checked, QTreeView::indicator::checked { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.5, fy:0.5, radius:1.0, stop:0.25 #BBBBBB, stop:0.3 #444444); } QCheckBox::indicator:disabled, QRadioButton::indicator:disabled, QTreeView::indicator:disabled { background-color: #333333; } QCheckBox::indicator::checked:disabled, QRadioButton::indicator::checked:disabled, QTreeView::indicator::checked:disabled { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.25, fy:0.15, radius:0.3, stop:0 #BBBBBB, stop:1 #444444); } /* === QComboBox === */ QComboBox { background-color: #333337; border: 1px solid #434346; color: #BBBBBB; padding:0.8ex 3ex; } QComboBox:hover { background-color: #3F3F46; } QComboBox::drop-down { background-color: #333337; subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #333333; } QComboBox::drop-down:hover { background-color: #1F1F20; border-left: 1px solid #007ACC; } QComboBox::down-arrow { border: 2px solid #999999; width: 1ex; height: 1ex; background: #999999; } QComboBox::down-arrow:hover { border: 2px solid #007ACC; background: #007ACC; } /* === QGroupBox === */ QGroupBox { border: 2px solid #333333; margin-top: 2ex; } QGroupBox::title { color: #FFFFFF; subcontrol-origin: margin; subcontrol-position: top left; margin-left: 5px; } /* === QTabWidget === */ QTabWidget::pane { background: #222222; border: 2px solid #333333; color: #BBBBBB; } /* === QTabBar === */ QTabBar::tab { background: transparent; border: 1px solid transparent; /*border-bottom: 2px solid #007ACC;*/ color: #BBBBBB; min-width: 10ex; padding: 1ex 4ex; } QTabBar::tab:hover { background-color: #1C97EA; /*border-bottom: 2px solid #007ACC;*/ border-bottom: none; } QTabBar::tab:selected { background-color: #2D2D30; border: 2px solid #3D3D3D; border-top: none; border-top: 1px solid #3D3D3D; border-bottom: 0px solid #3D3D3D; color: #AAAAAA; } /* === QToolBar === */ QToolBar { background-color: #2D2D30; border: none; padding: 1px; min-height: 6ex; } QToolBar:handle { background: transparent; border-left: 1px solid #3D3D3D; } QToolBar::separator { width: 6px; background-color: transparent; } /* === QToolButton === */ QToolButton { background-color: #2D2D30; border: none; margin: 1px; padding: 3px; min-width: 4ex; min-height: 4ex; } QToolButton:hover { background-color: #3E3E40; border: 1px solid #3E3E40; } QToolButton[popupMode="1"] { padding-right: 20px; } QToolButton[popupMode="2"] { padding-right: 10px; background-color: #3E3E40; } QToolButton[popupMode="2"]:hover { background-color: #333337; } QToolButton::menu-button { border-left: 1px solid #333333; background: #333337; } QToolButton::menu-button:hover { border-left: 1px solid #444444; background: #3F3F46; } QToolButton:pressed { background-color: #2D2D30; color: #FFFFFF; } QToolButton:checked { border: 1px solid transparent; background-color: transparent; color: #FFFFFF; } RotationToolButton, RotationToolButton:pressed, RotationToolButton:hover, RotationToolButton:checked { border-top-width: 1ex; border-top-style: solid; border-top-color: transparent; background-color: transparent; color: #AAAAAA; } RotationToolButton:pressed { color: #BBBBBB; } RotationToolButton:hover,RotationToolButton:checked:hover { border-top-color: #007ACC; color: #007ACC; } RotationToolButton:checked { border: 1px solid #444444; border-bottom: 0px solid #000000; color: #BBBBBB; } /* === QMenu === */ QMenu { background-color: #1B1B1C; border: 1px solid #1B1B1C; color: #BBBBBB; padding: 2px; } QMenu::item { padding: 2px 7ex 4px 7ex; border: 1px solid transparent; } QMenu::item:disabled { color: #656565; } QMenu::item:selected { border-color: #3D3D3D; background: #3D3D3D; } QMenu::item:checked { } QMenu::icon:checked { background: #FFFFFF; } QMenu::separator { height: 1px; background: #222222; margin: 1px 10px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: #2D2D30; color: #BBBBBB; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: gray; } QMenuBar::item:selected { background: #444444; } QMenuBar::item:pressed { background: #1B1B1C; } /* === QScrollBar:vertical === */ QScrollBar:vertical { background: #3E3E42; width: 4ex; margin: 16px 0 16px 0; } QScrollBar::handle:vertical { background: #686868; min-height: 4ex; border: 2px solid #3E3E42; } QScrollBar::add-line:vertical { background: #3E3E42; height: 4ex; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { background: #3E3E42; height: 4ex; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: #3E3E42; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 2px solid #686868; width: 6px; height: 6px; background: #686868; } /* === QScrollBar:horizontal === */ QScrollBar:horizontal { background: #3E3E42; height: 4ex; margin: 0 16px 0 16px; } QScrollBar::handle:horizontal { background: #686868; min-width: 4ex; border: 2px solid #3E3E42; } QScrollBar::add-line:horizontal { background: #3E3E42; width: 4ex; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { background: #3E3E42; width: 4ex; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: #3E3E42; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 2px solid #686868; width: 6px; height: 6px; background: #686868; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #2D2D30; color: #BBBBBB; border: 1px solid #333333; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox { border-color: #333333; border: 1px solid #333333; } /* === QHeaderView ===*/ QHeaderView { background: #222222; } QHeaderView::section { background: #222222; border: 0; color: #BBBBBB; padding: 3px 0 3px 4px; } /* === QListView === */ QListView::item:hover { background: #333333; } QListView::item:selected { background: #2D2D30; color: #FFFFFF; } /* === QTableView === */ QTableView::item:hover { background: #333333; } QTableView::item:hover { background: #2D2D30; color: #FFFFFF; } /* === QTreeView === */ QTreeView::item { background: #2D2D30; } QTreeView::item:hover { background: #333333; } QTreeView::item:selected { background: #2D2D30; color: #FFFFFF; } QTreeView::branch { } QTreeView::branch:has-siblings:adjoins-item { } QTreeView::branch:has-siblings:!adjoins-item { } QTreeView::branch:closed:has-children:has-siblings { } QTreeView::branch:has-children:!has-siblings:closed { } QTreeView::branch:!has-children:!has-siblings:adjoins-item { } QTreeView::branch:open:has-children:has-siblings { } QTreeView::branch:open:has-children:!has-siblings { } /* === Customizations === */ QFrame#infoLabel { border: 1px inset #333333; } ================================================ FILE: liteidex/deploy/liteapp/qss/vs-dark.qss ================================================ /* ===add file: \liteide\share\liteide\liteapp\qss\vs-dark.qss ===*/ /* ===FROM: https://gist.github.com/tupunco/fdb713ec9c6189a877e5eb003bd0457d ===*/ /* === Shared === */ QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatusBar, QToolButton, QComboBox, QDialog, QListView, QTabBar, QMenu, QMenuBar, QWidget::window { background-color: #252526; color: #F1F1F1; font-size: 14px; font-family: "微软雅黑;Segoe UI"; } /* === QWidget === */ QWidget:window { } /* === WebView === */ QTextBrowser, QWebView { background-color: #BBBBBB; selection-color: #0a214c; selection-background-color: #C19A6B; } /* === QToolTip === */ QToolTip { background-color: #EAEBF3; border: 1px solid #767676; color: #575757; } /* === QPushButton === */ QPushButton { border: 1px solid #333333; padding: 4px; min-width: 65px; min-height: 12px; background-color: #333333; } QPushButton:hover { background-color: #333333; border-color: #444444; } QPushButton:pressed { background-color: #2D2D30; border-color: #333333; color: #FFFFFF; } QPushButton:disabled { color: #333333; } /* === Checkable items === QCheckBox::indicator, QRadioButton::indicator, QTreeView::indicator { width: 16px; height: 16px; background-color: #2D2D30; border: 1px solid #434346; } QRadioButton::indicator { border-radius: 2px; } QCheckBox::indicator::checked, QRadioButton::indicator::checked, QTreeView::indicator::checked { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.25, fy:0.15, radius:0.3, stop:0 #CFCFCF, stop:1 #2D2D30); } QCheckBox::indicator:disabled, QRadioButton::indicator:disabled, QTreeView::indicator:disabled { background-color: #333333; } QCheckBox::indicator::checked:disabled, QRadioButton::indicator::checked:disabled, QTreeView::indicator::checked:disabled { background-color: qradialgradient(cx:0.5, cy:0.5, fx:0.25, fy:0.15, radius:0.3, stop:0 #BBBBBB, stop:1 #444444); } */ /* === QComboBox === */ QComboBox { background-color: #333337; border: 1px solid #434346; color: white; padding:1px 2em 1px 3px; } QComboBox:hover { background-color: #3F3F46; } QComboBox::drop-down { background-color: #333337; subcontrol-origin: padding; subcontrol-position: top right; border-left: 1px solid #333333; } QComboBox::drop-down:hover { background-color: #1F1F20; border-left: 1px solid #007ACC; } QComboBox::down-arrow { border: 2px solid #999999; width: 4px; height: 4px; background: #999999; } QComboBox::down-arrow:hover { border: 2px solid #007ACC; background: #007ACC; } /* === QGroupBox === */ QGroupBox { border: 2px solid #333333; margin-top: 2ex; } QGroupBox::title { color: #FFFFFF; subcontrol-origin: margin; subcontrol-position: top left; margin-left: 5px; } /* === QTabWidget === */ QTabWidget::pane { background: #222222; border: 2px solid #333333; } /* === QTabBar === */ QTabBar::tab { background: transparent; border: 1px solid transparent; border-bottom: 2px solid #007ACC; color: #FFFFFF; padding-left: 6px; padding-right: 6px; padding-top: 4px; padding-bottom: 4px; } QTabBar::tab:hover { background-color: #1C97EA; border-bottom: 2px solid #007ACC; border-bottom: none; } QTabBar::tab:selected { background-color: #007ACC; border: 2px solid #007ACC; border-top: none; border-bottom: 1px solid #007ACC; color: #FFFFFF; } /* === QToolBar === */ QToolBar { background-color: #2D2D30; border: none; padding: 1px; } QToolBar:handle { background: transparent; border-left: 1px solid #3D3D3D; } QToolBar::separator { width: 6px; background-color: transparent; } /* === QToolButton === */ QToolButton { background-color: #2D2D30; border: none; margin: 1px; padding: 3px; } QToolButton:hover { background-color: #3E3E40; border: 1px solid #3E3E40; } QToolButton[popupMode="1"] { /* only for MenuButtonPopup */ padding-right: 20px; /* make way for the popup button */ } QToolButton[popupMode="2"] { /* only for InstantPopup */ padding-right: 10px; /* make way for the InstantPopup button */ } QToolButton::menu-button { border-left: 1px solid #333333; background: #333337; width: 16px; } QToolButton::menu-button:hover { border-left: 1px solid #444444; background: #3F3F46; width: 16px; } QToolButton:pressed { background-color: #2D2D30; color: #FFFFFF; } QToolButton:checked { border: 1px solid #434346; background-color: #444444; color: #FFFFFF; } /* === QMenu === */ QMenu { background-color: #1B1B1C; border: 1px solid #1B1B1C; color: #F1F1F1; padding: 2px; } QMenu::item { padding: 2px 25px 4px 20px; border: 1px solid transparent; } QMenu::item:disabled { color: #656565; } QMenu::item:selected { border-color: #3D3D3D; background: #3D3D3D; } QMenu::item:checked { } QMenu::icon:checked { background: #FFFFFF; } QMenu::separator { height: 1px; background: #222222; margin-left: 10px; margin-right: 10px; margin-top: 1px; margin-bottom: 1px; } QMenu::indicator { width: 13px; height: 13px; } /* === QMenuBar === */ QMenuBar { background-color: #2D2D30; color: white; } QMenuBar::item { background: transparent; } QMenuBar::item:disabled { color: gray; } QMenuBar::item:selected { background: #222222; } QMenuBar::item:pressed { background: #444444; } /* === QScrollBar:vertical === */ QScrollBar:vertical { background: #3E3E42; width: 16px; margin: 16px 0 16px 0; } QScrollBar::handle:vertical { background: #686868; min-height: 16px; border: 2px solid #3E3E42; } QScrollBar::add-line:vertical { background: #3E3E42; height: 16px; subcontrol-position: bottom; subcontrol-origin: margin; } QScrollBar::sub-line:vertical { background: #3E3E42; height: 16px; subcontrol-position: top; subcontrol-origin: margin; } QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { background: #3E3E42; } QScrollBar:up-arrow:vertical, QScrollBar:down-arrow:vertical { border: 2px solid #686868; width: 6px; height: 6px; background: #686868; } /* === QScrollBar:horizontal === */ QScrollBar:horizontal { background: #3E3E42; height: 16px; margin: 0 16px 0 16px; } QScrollBar::handle:horizontal { background: #686868; min-width: 16px; border: 2px solid #3E3E42; } QScrollBar::add-line:horizontal { background: #3E3E42; width: 16px; subcontrol-position: right; subcontrol-origin: margin; } QScrollBar::sub-line:horizontal { background: #3E3E42; width: 16px; subcontrol-position: left; subcontrol-origin: margin; } QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: #3E3E42; } QScrollBar:left-arrow:horizontal, QScrollBar:right-arrow:horizontal { border: 2px solid #686868; width: 6px; height: 6px; background: #686868; } /* =================== */ QLineEdit, QListView, QTreeView, QTableView, QAbstractSpinBox { background-color: #2D2D30; color: #BBBBBB; border: 1px solid #333333; } QAbstractScrollArea, QLineEdit, QTextEdit, QAbstractSpinBox { border-color: #333333; border: 1px solid #333333; } /* === QHeaderView === */ QHeaderView { background: #222222; } QHeaderView::section { background: #222222; border: 0; color: #BBBBBB; padding: 3px 0 3px 4px; } /* === QListView === */ QListView::item:hover { background: #333333; } QListView::item:selected { background: #2D2D30; color: #FFFFFF; } /* === QTableView === */ QTableView::item:hover { background: #333333; } QTableView::item:hover { background: #2D2D30; color: #FFFFFF; } /* === QTreeView === */ QTreeView::item { } QTreeView::item:hover { } QTreeView::item:selected { } QTreeView::branch { } QTreeView::branch:has-siblings:adjoins-item { } QTreeView::branch:has-siblings:!adjoins-item { } QTreeView::branch:closed:has-children:has-siblings { } QTreeView::branch:has-children:!has-siblings:closed { } QTreeView::branch:!has-children:!has-siblings:adjoins-item { } QTreeView::branch:open:has-children:has-siblings { } QTreeView::branch:open:has-children:!has-siblings { } /* === Customizations === */ QFrame#infoLabel { border: 1px inset #333333; } ================================================ FILE: liteidex/deploy/liteapp/template/empty/root ================================================ ================================================ FILE: liteidex/deploy/liteapp/template/empty/setup.inf ================================================ [SETUP] NAME = "Empty File" AUTHOR = visualfc INFO = create a new empty file TYPE = file FILES = root OPEN = root ================================================ FILE: liteidex/deploy/liteapp/template/file.sub ================================================ empty gosrc luasrc mdsrc goslide goarticle ================================================ FILE: liteidex/deploy/liteapp/template/goarticle/root.article ================================================ # http://godoc.org/golang.org/x/tools/present # Present files have the following format. # The first non-blank non-comment line is the title. # The subtitle, date, and tags lines are optional. Title of document Subtitle of document $DATETIME$ Tags: foo, bar, baz Author Name Job title, Company joe@example.com http://url/ @twitter_name * Section1 * Section2 ================================================ FILE: liteidex/deploy/liteapp/template/goarticle/setup.inf ================================================ [SETUP] NAME = "Go Present Article File" AUTHOR = visualfc INFO = go article file(*.article) TYPE = file FILES = root.article OPEN = root.article ================================================ FILE: liteidex/deploy/liteapp/template/gocmd/doc.go ================================================ // $ROOT$ project doc.go /* $ROOT$ document */ package main ================================================ FILE: liteidex/deploy/liteapp/template/gocmd/main.go ================================================ // $ROOT$ project main.go package main import ( "fmt" ) func main() { fmt.Println("Hello World!") } ================================================ FILE: liteidex/deploy/liteapp/template/gocmd/setup.inf ================================================ [SETUP] NAME = "Go1 Command Project" AUTHOR = visualfc INFO = create Go command project GOPATH/src TYPE = gopath FILES = main.go doc.go OPEN = main.go SCHEME=folder ================================================ FILE: liteidex/deploy/liteapp/template/gocmdex/doc.go ================================================ // $ROOT$ project doc.go /* $ROOT$ document */ package main ================================================ FILE: liteidex/deploy/liteapp/template/gocmdex/main.go ================================================ // $ROOT$ project main.go package main import ( "fmt" ) func main() { fmt.Println("Hello World!") } ================================================ FILE: liteidex/deploy/liteapp/template/gocmdex/setup.inf ================================================ [SETUP] NAME = "Go1 Command Project (Anywhere)" AUTHOR = visualfc INFO = create Go command project anywhere TYPE = project FILES = main.go doc.go OPEN = main.go SCHEME=folderex ================================================ FILE: liteidex/deploy/liteapp/template/gopkg/doc.go ================================================ // $ROOT$ project doc.go /* $ROOT$ document */ package $ROOT$ ================================================ FILE: liteidex/deploy/liteapp/template/gopkg/root.go ================================================ // $ROOT$ project $ROOT$.go package $ROOT$ ================================================ FILE: liteidex/deploy/liteapp/template/gopkg/setup.inf ================================================ [SETUP] NAME = "Go1 Package Project" AUTHOR = visualfc INFO = create Go package project GOPATH/src TYPE = gopath FILES = root.go doc.go OPEN = root.go SCHEME=folder ================================================ FILE: liteidex/deploy/liteapp/template/gopkgex/doc.go ================================================ // $ROOT$ project doc.go /* $ROOT$ document */ package $ROOT$ ================================================ FILE: liteidex/deploy/liteapp/template/gopkgex/root.go ================================================ // $ROOT$ project $ROOT$.go package $ROOT$ ================================================ FILE: liteidex/deploy/liteapp/template/gopkgex/setup.inf ================================================ [SETUP] NAME = "Go1 Package Project (Anywhere)" AUTHOR = visualfc INFO = create Go package project anywhere TYPE = project FILES = root.go doc.go OPEN = root.go SCHEME=folderex ================================================ FILE: liteidex/deploy/liteapp/template/goslide/root.slide ================================================ # http://godoc.org/golang.org/x/tools/present # Present files have the following format. # The first non-blank non-comment line is the title. # The subtitle, date, and tags lines are optional. Title of document Subtitle of document $DATETIME$ Tags: foo, bar, baz Author Name Job title, Company joe@example.com http://url/ @twitter_name * Section1 * Section2 ================================================ FILE: liteidex/deploy/liteapp/template/goslide/setup.inf ================================================ [SETUP] NAME = "Go Present Slide File" AUTHOR = visualfc INFO = go slide file(*.slide) TYPE = file FILES = root.slide OPEN = root.slide ================================================ FILE: liteidex/deploy/liteapp/template/gosrc/root.go ================================================ // $ROOT$ package main import ( "fmt" ) func main() { fmt.Println("Hello World!") } ================================================ FILE: liteidex/deploy/liteapp/template/gosrc/setup.inf ================================================ [SETUP] NAME = "Go Source File" AUTHOR = visualfc INFO = make new golang source(*.go) TYPE = file FILES = root.go OPEN = root.go ================================================ FILE: liteidex/deploy/liteapp/template/luasrc/root.lua ================================================ ================================================ FILE: liteidex/deploy/liteapp/template/luasrc/setup.inf ================================================ [SETUP] NAME = "LUA Source File" AUTHOR = visualfc INFO = new lua source(*.lua) TYPE = file FILES = root.lua OPEN = root.lua ================================================ FILE: liteidex/deploy/liteapp/template/mdsrc/root.md ================================================ $ROOT$ ======== ================================================ FILE: liteidex/deploy/liteapp/template/mdsrc/setup.inf ================================================ [SETUP] NAME = "Markdown File" AUTHOR = visualfc INFO = new markdown file(*.md) TYPE = file FILES = root.md OPEN = root.md ================================================ FILE: liteidex/deploy/liteapp/template/project.sub ================================================ gocmd gocmdex gopkg gopkgex ================================================ FILE: liteidex/deploy/litebuild/build.md ================================================ ### LiteEdit Build Environment *** ### liteide app info LITEIDE_BIN_DIR LITEIDE_RES_DIR ### build dir info BUILD_DIR_PATH BUILD_DIR_NAME BUILD_DIR_BASENAME ### editor file info EDITOR_FILE_PATH EDITOR_FILE_NAME EDITOR_FILE_BASENAME EDITOR_FILE_SUFFIX ### editor dir info EDITOR_DIR_PATH EDITOR_DIR_NAME EDITOR_DIR_BASENAME ================================================ FILE: liteidex/deploy/litebuild/command/go.api ================================================ go go test go test -test.bench=.* go test -test.bench=.* -test.benchmem go test -cover go install go get go clean go env go version go build go build -ldflags " go build -ldflags "-r ." go build -ldflags "-H windowsgui" go build -ldflags "-H windowsgui -r ." go build -ldflags "-w -s" go build -gcflags " go mod init go mod tidy go mod download go mod verify go mod graph go mod why ================================================ FILE: liteidex/deploy/litebuild/gomod.xml ================================================ ================================================ FILE: liteidex/deploy/litebuild/goplus.xml ================================================ ================================================ FILE: liteidex/deploy/litebuild/gosrc.xml ================================================ ================================================ FILE: liteidex/deploy/litebuild/lua.xml ================================================ ================================================ FILE: liteidex/deploy/litebuild/python.xml ================================================ ================================================ FILE: liteidex/deploy/litebuild/qlang.xml ================================================ ================================================ FILE: liteidex/deploy/litebuild/rust.xml ================================================ ================================================ FILE: liteidex/deploy/litebuild/tcl.xml ================================================ ================================================ FILE: liteidex/deploy/liteeditor/color/carbon.xml ================================================ __MARKDOWN_TITLE__ __MARKDOWN_CONTENT__ ================================================ FILE: liteidex/deploy/welcome/css/style.css ================================================ body { text-align: left; margin: 0; font-family: Helvetica, Arial, sans-serif; } pre, code { font-family: Menlo, monospace; } pre .comment { color: #375EAB; } pre .ln { color: #999; } body { color: #222; } a { color: #375EAB; text-decoration: none; } p, pre, ul, ol { margin: 20px; } pre { background: #e9e9e9; padding: 10px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } h1, h2, h3, h4, .rootHeading { margin: 20px 0; padding: 0; color: #375EAB; font-weight: bold; } h2 { background: #E0EBF5; padding: 2px 5px; } .rootHeading { margin: 0; } h1 a, h2 a, h3 a, h4 a { text-decoration: underline; } dl { margin: 20px; } dd { margin: 2px 20px; } #nav table td { vertical-align: top; } table.dir th { text-align: left; } table.dir td { word-wrap: break-word; vertical-align: top; } #heading { float: left; margin: 0 0 10px 0; padding: 16px 0; font-weight: normal; } #heading a { color: #222; text-decoration: none; } #topbar { background: #E0EBF5; } body { text-align: center; } #page, #topbar .container { clear: both; text-align: left; margin-left: auto; margin-right: auto; width: 900px; } #plusone { float: right; } #plusoneRoot { float: right; } #copyright { color: #666; margin: 40px 0; } #menu > a, #menu > input, #learn .buttons a, #blog .read a { padding: 10px; text-decoration: none; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } #menu > a, #menu > input { border: 1px solid #375EAB; } #menu > a { color: white; background: #375EAB; } #start, #learn .buttons a, #blog .read a { color: #222; border: 1px solid #375EAB; background: #E0EBF5; } #menu { padding: 10px 0; text-align: right; } #menu > a { margin-right: 5px; margin-bottom: 10px; padding: 10px; } #menu > input { position: relative; top: 1px; width: 100px; background: white; color: #222; } #menu > input.inactive { color: #999; } #left { float: left; } #right { float: right; } #left, #right { width: 415px; } #learn, #about { padding-top: 20px; } #learn h2, #about { margin: 0; } #about { height: 96px; } #gopher { background: url(/doc/gopher/frontpage.png) no-repeat; background-position: center top; height: 155px; } #start { display: block; padding: 10px; text-align: center; text-decoration: none; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } #start .big { font-weight: bold; } #start .desc { font-weight: normal; margin-top: 5px; } #learn pre, #learn textarea { padding: 0; margin: 0; font-family: Menlo, monospace; } #learn .input { padding: 10px; margin-top: 10px; height: 150px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } #learn .input textarea { width: 100%; height: 100%; border: none; outline: none; resize: none; } #learn .output { border-top: none !important; padding: 10px; height: 59px; overflow: auto; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -moz-border-radius-bottomleft: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; } #learn .output pre { padding: 0; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } #learn .input, #learn .input textarea, #learn .output, #learn .output pre { background: #FFFFD8; } #learn .input, #learn .output { border: 1px solid #375EAB; } #learn .buttons { padding: 20px 0 10px 0; text-align: right; } #learn .buttons a { height: 16px; margin-left: 5px; padding: 10px; } #learn .buttons .tour { float: right; } #learn .buttons .tour a { margin-right: 0; font-weight: bold; } #blog, #video { margin-top: 40px; } #blog > div, #blog > a, #video > div, #video > a, #blog > h2, #video > h2 { margin-bottom: 10px; } #blog .title, #video .title { color: #222; text-decoration: none; display: block; } #blog .when { color: #666; } #blog .read { text-align: right; } .exampleHeading { cursor: pointer; } .example .collapsed { display: block; } .example .expanded { display: none; } .exampleVisible .collapsed { display: none; } .exampleVisible .expanded { display: block; } table.codetable { margin-left: auto; margin-right: auto; border-style: none; } hr { border-style: none; border-top: 1px solid black; } ================================================ FILE: liteidex/deploy/welcome/en/LGPL_EXCEPTION.TXT ================================================ LiteIDE is distributed under the terms of the LGPLv2.1 license with an exception: License exception: In addition, as a special exception, that plugins developed for LiteIDE, are allowed to remain closed sourced and can be distributed under any license . ================================================ FILE: liteidex/deploy/welcome/en/LICENSE.LGPL ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: liteidex/deploy/welcome/en/changes.md ================================================ ## LiteIDE X Version LiteIDE is a simple, open source, cross-platform Go IDE. ### 2025.5.20 Ver X38.4 * LiteIDE * support Go1.24 * LiteFind * fix FindFilesThread stop ### 2023.08.14 Ver X38.3 * LiteIDE * support Go1.21 * LiteEnv * support Go1.21 `go env` * LiteFind * support enter on directory searches * Terminal * fix source for not bash ### 2023.02.14 Ver X38.2 * LiteIDE * fix and update gotools & gocode * refactor astview outline * update dlv debugger plugin * GolangAst * new outline view by pos * support typeparams * LiteDebug * add disassemble view * DlvDebugger * fix generics func sync * fix dlv process exit on windows * refactor gorountines model * support disassemble model * LiteBuild * gosrc.xml TARGETNAME use BUILD_DIR_PATH * GolangEdit * support any and comparable * GolangCode * support any and comparable * gotools * types fix find obj field * types fix object string * gotest fix run test file use -run mode * astview add new -outline for outline * astview add new -tp for typeparams * astview fix interface embedded type * gocode * fix identifier comparable * update lookup object ### 2023.01.22 Ver X38.1 * LiteIDE * gotools & gocode support Go1.18 generics * support build for windows vs2019 * support build for freebsd/openbsd * fix memory leak * GolangCode * support Go1.18 generics * remove options and default set * uncheck GOPATH for set-lib * LiteEnv * fix memory leak * filter go env * LiteBuild * fix memory leak * fix buildconfigdialog twice accept * LiteEditor * fix selection navigation saved * check backspace empty completion unpopup * GolangEdit * update actions for GO111MODULE * GolangPlay * load depends * Bookmarks * fix memory leak * Terminal * libterm fix build for vs2019 * add option for set font * ptyqt use conptyprocess for vs2019 * ptyqt fix unixptyprocess for freebsd/openbsd * gotools * types support generics method lookup * gocode * support generics type autocomplete * support incomplete dep autocomplete ### 2022.05.22 Ver X38.0 * LiteIDE * support Go1.18 go.work * support Go1.18 format/types/gocode * LiteApp & LiteEditor * add 'Detroit Future' theme (thanks donuts-are-good) * LiteEditor * add go.work syntax * add color/dart-blue.xml (thanks qAison) * LiteBuild * only check first run action and output * update GoPlus config * LiteEnv * windows env use %PROGRAMFILES%\Go * Terminal * fix copy text containing tab in terminal * add context menu copy/paste/selectall * gotools * support Go1.18 format * support Go1.18 types * support go.work * gocode * support Go1.18 code completer * support go.work * update unsafe pkg * fix gomod imports completer ### 2021.03.02 Ver X37.4 * LiteIDE * move to trash use api on macos * fix find&replace repaint * update terminal action * add copy fullpath action * LiteApp * editor context menu add integrated terminal action * folder view update integrated terminal action * folder view add copy full path action * move to trash use api on macos * LiteFind * fix find&replace editor repaint * fix file search replace repaint * windows fileserach shortcuts add ctrl+atl+f * LiteEditor: * gomod.xml add retract * Terminal: * move to core plugin * DlvDebugger: * add pass flags options ### 2020.10.10 Ver X37.3 * LiteIDE * fix dlv debug exit crash on window * support mingw-64 build for window * LiteApp * update icon for hight-dpi * LiteBuild: * gosrc.xml add tool cover html command * gosrc.xml add make command * LiteEditor: * add dark-gray.xml color scheme, thanks for qAison * fix showlink tooltip bug for Qt5.12 * GolangEdit: * add find usages skip tests action * Terminal: * fix winpty load for Q_OS_WIN64 * add closeall action * DlvDebugger * fix exit crash on window * fix handle response regexp * gotools & gocode * update fastmod for go1.14 GOMOD * gotools * types add skip tests flag ### 2020.04.24 Ver X37.1 * LiteIDE * add new integrated terminal plugin * change LiteApi, IToolWindowManager and IFileManager api * Terminal: * new terminal plugin * export open in integrated terminal action * support open multiple shells (/etc/shells) on unix * support open cmd/powershell/git bash on window * support dark mode * support login mode --login (unix) * load enviroment from LiteIDE action (unix) * tab style multiple terminal * auto save / restore terminal info * ctrl+c key interrupt support * mouse to select, enter key copy to clipboard (ctrl+c/command+c) * ctrl+v / command+v to paste from clipboard * LiteApp * folder add open integrated terminal action * update hide tool window action icon. * folder view enable create folder in files * fix SideWindowStyle::moveToolWindow crash * fix #1106, options widget add ScrollArea, enable resize, init check screen size * LiteEditor * change copy/paste/cut/selectall/undo/redo unregister shortcut for macos * FileBorwser: * add open integrated terminal action * enable create folder in files * simple, remove litefind/terminal depends * LiteFind * SearchResultWidget add expandAll and collapseAll button * GolangEdit * fix fold by GO_ELSE * gotools & gocode * fix & update for Go 1.14 ### 2020.01.15 Ver X36.3 * LiteIDE * fix and update gotools&gocode for support Go Module. * refactor option, update all plugin option page * LiteApp * refactor option page, load/save and keep option page. * LiteEditor * fix code complete escape for Qt5.12 * Markdown * add CommonMark/cmark for markdown to html, replace sundown * GolangPackage * add GOPRIVATE,GONOPROXY,GONOSUMDB option * add goproxy.cn for GOPROXY list * merge GOPATH/GoModule setup to global options. * LiteBuild * add `go mod vendor` action * DlvDebugger * update stack frame to RPC api * gotools & gocode * fix fastmod match full version, example `github.com/mypkg/v2` * types check add basic type ### 2019.10.30 Ver X36.2 * LiteIDE * add new image viewer plugin * folder view support multi copy & paste * folder view support move to trash * fix gocode crash * update uk (Ukrainian) translation, thanks for cl0ne * LiteApp * fix floating dock widet style * add dock widget floating toolbar * folder view support multi copy and paste * folder view support move to trash action * ImageEditor * add new image viewer plugin * support image viewer and gif video play * GolangEdit * support go1.13 number literal syntax highlight * gotools & gocode * fix bad parser crash ### 2019.08.28 Ver X36.1 * LiteIDE * folder view support copy and paste * fix find usages and declinfo for _ start symbol * LiteApp * multi folder view support copy and parse * tool window support floating window action * LiteEditor * cached text layout, optimization long line paint * check and disable document too long line (4096) syntax. * GolangEdit * fix findusage and declinfo for _ start symbol * GolangPackage * add custom GOPROXY setup * update GO111MODULE env reload check * GolangDoc * remove godoc command, use gotools godoc * FileBorwser * folder view support copy and paste * Others * linux env add x-terminal-emulator * update Russian translation, thanks Sergey Belyashov * gotools & gocode * fix mod priority vendor check * gotools * godoc add go doc -all flags ### 2019.03.15 Ver X36 * LiteIDE * add new editor path navigation toolbar * QuickOpen * quickopenfile filter text length less than 3 use editor files, otherwise search in folder files. * add new quickfilesystem filter * GolangEdit * use new quickfilesystem for import jump * LiteEditor * add new path navigation toolbar (use quickfilesystem) * GolangCode * fix number+dot issues completer * FileUtil * show in Finder fast on macOS ### 2019.02.05 Ver X35.5 * LiteIDE * bug fix version * GolangEdit * fix cursor selections usages lookup * add byteOffsetToColumn to fix gotools/guru output byte offset to editor offset * LiteEditor * add allow vertical scrolling to the last line option * check file writed size != data.size and show error message * LiteFind * update search result item text for all same linenumber ### 2019.01.30 Ver X35.4 * LiteIDE * source code navigation can be used in wrong source code * imports completer support gomod depends and local imports for gomod project * imports completer support lookup all imports by source for GOPATH project * LiteApp * fix vs-dark.qss menu icon bug for windows10 * LiteEditor * fuzzy golang imports completer * fix complter imports offset * fix enter auto insert tab or space check by previous line * GolangCode * fix receive imports line process * GolangEdit * support lookup types info wrong source code * add jump to declaration toolbar * fix jump to declaration save history * gotools & gocode * source code navigation can be used in wrong source code * lookup gomod depends and local imports for gomod project * lookup all imports from source for GOPATH project ### 2018.12.22 Ver X35.3 * LiteIDE * optimization gotools & gocode, update editor and find plugin. * LiteApp * fix liteoutput antialias setup invalid * LiteEditor * enable vertical scrollbar move last block to top viewport * add the cut current line operator for cut action if not selected * add convert tab/spaces action * add tabtospace/tabwidth set by litapp/mimetype/liteeditor.xml or options * update line wrap mode for mimetype * update tabtospace mode for mimetype * LiteFind * file search check and skip binary file * add folders/filesystem context menu file search action * GolangEdit, GolangCode, LiteBuild * fix process start with cmd contains space on macOS * GolangDoc * support check go1.12 godoc remove -html, use text mode * gotools & gocode * fix lookup named method embedded * optimization, check save/load pkgconfig * add godoc command for check go1.12 use text mode * gocode * fixed global var completion ### 2018.11.12 Ver X35.2 * LiteIDE * fixed types info jump position * optimization types info lookup cache * LiteEditor * single line comment set after white spaces and add space * go.mod editor support comment action * color scheme support MatchBrackets background, default gray #808080 * Bookmarks * sort bookmark model by name/line, add context menu goto/remove/removeThisFile/removeAllFiles action * GolangDoc * fix mod package godoc import path view * GolangEdit * fix lookup types info by gocode cache * gotools & gocode * fixed types jump info position * optimization types info lookup cache ### 2018.10.24 Ver X35.1 * LiteIDE * BUG fixed, gocode code jump and import line jump * GolangEdit * fix jump def for import line * gotools & gocode * fix types jump ### 2018.10.24 Ver X35 * LiteIDE * all support Go1.11 Go modules * fast lookup types info by cache * fix delve debug recurse set blocking * LiteApp * side window style enable move tool window to any left/right/bottom side. * side window style output bar shortcut change to command+meta+number (macos) or ctrl+shift+number * GolangEdit * fast lookup types info by gocode cache * find all usages support Go modules work dir * refactor symbol support Go module work dir * GolangAst * support import path gopath/vendor/modules doc view * LiteDebug * add automatically add breakpoint main.main when debugging option (default disable) * DlvDebugger * fix dlv list variables blocking, change LoadConfig recurse to 3 * LiteBuild * update gosrc.xml for support custom target workdir * gotools & gocode * import https://github/visualfc/fastmod for fast parse go.mod depends * fast parse Go modules and fix issues https://github.com/visualfc/liteide/issues/986 * gotools * find all usages support Go module work dir * gotools * fast completer for Go module project * provide types info for liteide by cache ### 2018.10.05 Ver X34.3 * LiteIDE * fix support go1.11 modules * GolangEdit * fix jump import line * fix find usages for import line * LiteEditor * fix gocode completer item kind update * GolangCode * enviroment changed to reset gocode * gotools & gocode * types: fix module-based project with several subpackages https://github.com/visualfc/liteide/issues/977 * types: fix redeclared file parser cursor first * types: fix source file update check in stdin * types: fix x test files check * gomod: fix lookup module for go list * gocode * fix gocode crash https://github.com/visualfc/liteide/issues/978 ### 2018.09.15 Ver X34.2 * LiteIDE * fix gotools & gocode support go1.11 modules sub folder * support custom GO111MODULE setup * LiteApp * fix #939 display right margin at column wrong * change mime type check fullname first * GolangCode * fix #970 goplay editor cgo crash * GolangEdit * find usages / rename symbol add skip GOROOT actions * GolangPackage * add custom GO111MODULE setup * LiteEditor * add extra mouse navagite go back and forward * add gomod.xml for go.mod syntax * LiteBuild * add gomod.xml for go.mod build command * gotools & gocode * fix go1.11 modules sub folder ### 2018.08.12 Ver X34.1 * LiteIDE * update gotools support go1.11 modules * update gocode support go1.11 modules and vendor * LiteEditor * enable open binary file for editor * change widget readonly by binary file (ignore text file) * gocode * change parser by source use gotools/types * fix parser vendor & modules ### 2018.07.26 Ver X34 * LiteIDE * update gotools support go1.11 modules * update gocode for https://github.com/visualfc/gocode support go1.11 modules * LiteApp * refactor folder model code, remove depends * fix dock widget for Qt5.9.6 bug * move view godoc from folderview to litebuild * LiteBuild * update BUILDARGS, remove -i for go1.11 build * GolangCode * change to github.com/visualfc/gocode for support go1.11 modules * GolangDoc * pdoc support real ImportPath display for Go modules or vendor * fix docs.html $.GoogleCN code * GolangEdit * support go1.11 modules, view info / jump / find usages * support parser import path for Go modules or vendor for godoc view * GolangPackage * add pkg/mod tree for Go modules * QuickOpen * fix view pos for editor manager * support open file with fullpath on editor input * DlvDebugger * fix continue * gotools * types support go1.11 modules * add pkgcheck support modules or vendor check * gocode * clone https://github.com/nsf/gocode support go1.11 modules ### 2018.07.04 Ver X33.4 * LiteIDE * update gocode for mdempsky/gocode support go1.11 * update DlvDebugger plugin for Delve detail information * LiteDebug * add threads/goroutines/registers view * watch view support double clicked change and update * DlvDebugger * add dlv rcp-mode for get more info * variable and watch support detail information * watch support local/package variable * support threads/gorountines/registers model * GolangCode * support * QuickOpen * add dly filter editor for optimize many files search * fix quick open symbol action ### 2018.04.23 Ver X33.3 * LiteIDE * support import jump to package source file * support import hints for all package on code completer * add build & debug action to build menu * fix build debug gcflags for go version * LiteApp * fix tab style sheet for Qt5.9 on macOS * project wizard add gocmdex/gopkgex for anywhere * LiteBuild * build config file add debug support * golang build add debug/debugtest action * fix golang build debug gcflags depends for go version * LiteDebug * filesystem add debug file action * remove internal golang build function * LiteEditor * reimplemented backspace quotes audo insert/remove action * GolangCode * parser import package for GOPATH * fix vendor import for code completer * add import hints for all package option (default) * add parser cgo completer list on editor * GolangEdit * fix import line navigate show link source * add import line jump to package file list * QuickOpen * add quickopenfolder implement * gotools * add new debugflag action for print debug gcflags for go version * types find import dir check vendor * types add import info and doc * fix astview pkg nil check ### 2018.02.14 Ver X33.2 * LiteIDE * add folder tool window split mode swith * add archlinux makepkg * add tcl syntax and build * LiteEditor * support function color, thanks [discoverfly](https://github.com/discoverfly) * add default-func color theme * add style for scroll bars in sublime.qss, thanks [hauke96](https://github.com/hauke96) * add marks for selections and findings, thanks [jinq0123](https://github.com/jinq0123) * LiteFind * fix editor regexp replace * LiteBuild * add context menu go tool action ### 2017.12.12 Ver X33.1 * LiteIDE * support quick open command * support gomodifytags * fix libpng warning on qt5 build * LiteApp * add tools menu for quick open actions * standard and rename tool window title * enable edit menu anytime, fix edit menu disable on editor lost focus. * fix editor load large file bad_alloc recover * LiteEnv * add select env to tools menu * LiteEditor * check and not open large file * fix edit hide edit sub menu 'setup' on macos * LiteFind * fix find editor replace all wrap around* GolangEdit * Integrated [gomodifytags](https://github.com/fatih/gomodifytags) and gui tools support gomodifytags all options * QuickOpen * add quick open command action (ctrl+shift+p/command+shift+p) * quickopenfiles use thread for fast and cancel * fix quickopenfile cancel loading for esc or liteapp quit ### 2017.11.2 Ver X33 * LiteIDE * optimization editor plugin, load file check codec, reload file by diff * add astview TodoList * add new bookmarks plugin * fix liteapp clean plugin order * LiteApp * filemanager auto reload file default YesToAll * fix liteapp clean plugins reverse order * fix #832, sidebar change action by combox * fix folder sync editor same prefix error * LiteEditor * reload file use diff to keep state and mark * load file check is binary and report * load file check codec use libucd if utf8 decode failed. * load file check decode error and report * load file is readonly set editor widget readonly * load and save file support utf8 bom * add codec and lineend info on statusbar * add copied text into the clipboard as HTML option * add Solarized Dark color theme, thanks xgdgsc * reimplemented editor mark api * fix copy to clipboard tab escape * GolangAst * add TodoList for classview and outline * fix #848, astwidget double clicked index check. * GolangCode * update pkglist to go1.9 * GolangEdit * add stop source query action * add source query action implement_GOPATH for GOPATH scope * fix golang lexer parser folding end * fix GolangHighlighter fold indent error set * fix findUsage wordUnderCursor offset * fix find usages findStart signal late * GolangFmt * load diff check modify current block text * GolangCode * fix update gopath process stop and wait * LiteDebug * fix cmd to native separator * build target add -a build flag * change debug targget name to target.debug (custom by LiteBuild) * LiteBuild * add custom debug name in build config * LiteFind * fix memory leak by GolangEdit GolangFileSearch * fix findInFiles berore saveAllEditor * fix FindEditor replace all * Bookmarks * new plugin for show open editors bookmarks and jump * gotools * update stdlib for go1.9.1 * astview add TodoList support ### 2017.7.18 Ver X32.2 * LiteApp * fix editor file watcher is invalid for many change * GolangEdit * fix TODO/BUG/FIXME comment syntax * DlvDebugger * fix dlv headless process workdir * LiteDebug * fix debug tests action * fix load and save breakpoint for editor ### 2017.7.7 Ver X32.1 * LiteIDE * build config custom gopath support inherit parent path's gopath setup * GolangCode * update gocode lib-path by build config custom gopath * LiteEnv * optimization check go enviroment * LiteBuild * build config custom gopath inherit parent path * fix BuildAndRun kill old on window * fix build config custom gopath action * GolangPackage * fix load package treeview error * DlvDebugger * dlv use headless mode * fix dlv kill process ### 2017.6.12 Ver X32 * LiteIDE * support folder build config custom GOPATH * support folder build config BUILDFLAGS -tags setup * support folder build config TARGETBASENAME setup * support session switching for folder/editor * support load custom icon library from liteapp/qrc folder (default and folder) * reimplemented multifolder model, it took me a long time :) * add macOS session menu for native dock menu * recent menu sync for multi windows * gotools support +build source navigate (single file or -tags setup) * LiteApp * add the session switching function * add autosavedocument emit message option * add max editor tab count option * add option action to standard toolbar * add tool window use shortcuts option for unstandard keyboard option * add exit liteide ctrl+q on windows * add themes (carbon.qss gray.qss sublime.qss) for liteide & beautify old themes, thanks for hope hook * editor tab context add open terminal here action * folders context menu add open in new windows action (new folder session) * folder view add show showdetails action * fix folder sync editor incorrect on macOS * fix webview and debug console qss * fix folders tool window enter key to jump * fix exit error save session by ctrl+q on macos * fix newfile dialog space name * update folder tool window showInExporer showInShell action text * LiteFind * find files add auto swith current folder checkbox * find in editor add show replace mode checkbox * filesearch enable replace whitespace or empty * editor replace all in one edit block for ctrl+z once undo * LiteBuild * add custom GOPATH in build config for build/debug/GolangEdit * add custom share-value BUILDFLAGS in build config for build/debug/GolangEdit * add custom TARGETBASENAME in build config for build/debug * support BUILDFLAGS -tags for build/debug/GolangEdit * update gosrc.xml to export custom value and share-value * folders tool window context menu add Go build configuration action * folders tool window context go tool use Go build configuration setup * fix stop action for kill process * LiteDebug * console use editor color scheme * support LiteBuild folder build config BUILDFLAGS/BUILDARGS -tags flag setup * DlvDebugger * fix process identify for auto exit * LiteEnv * default env /usr/local/go on macosx * update macosx cross env GOROOT for system * LiteEditor * context menu add convert case menu * go.snippet add iferr * update sublime.xml / sublime-bold.xml, thanks for hopehook * alt+backspace delete serial whitespaces * option font QComboBox to QFontComboBox, add restore DefaultFont action * option add show monospace font check * option file types sort mimetype, show custom extsition first * GolangPackage * gopath setup add use sysgopath/litegopath check * GolangPlay * fix goplay use goenvironment * GolangDoc * change golang api index search for go/api folder * GolangEdit * add go root source readonly setup option * support folder go build config BUILDFLAGS/BUILDARGS -tags flag setup * fix interface type by gotools * fix find process stop and run * fix lookup guru for source query * GolangAst * fix astview enter key to jump * FileBorwser * fix file system enter key to jump * gotools * fix types interface method * types support +build for single source * types support -tags flag * tools * add new exportqrc tool for export liteide all build-in images ### 2017.3.9 Ver X31.1 * LiteApp * restore folder first on MacOS * GolangEdit * update pkglist ### 2017.3.2 Ver X31 * LiteIDE * add command line `liteide [files|folder] [--select-env id] [--local-setting] [--user-setting] [--reset-setting]` * LiteApp * add application idle timer automatic save documents option * folders are not sorted to resolve sync editing errors on MacOS * update new file wizard * GolangPackage * update GOPATH setup * GolangCode * update env load * GolangAst * classview and outline add sync editor action * DlvDebugger * fix dlv execution on MacOS * FakeVim * option add load default command list action * LiteEditor * fix editor restore vertical scrollbar postion * fix codecompleter prefix min setup * restore the editor toolbar * option add mimetype custom extsition setup * LiteBuild * build config xml file enable custom $() on cmd and args ### 2016.12.6 Ver X30.3 * LiteEnv * remove GO15VENDOREXPERIMENT env * LiteEditor * add fuzzy completion option, default setup * add clear completion cache when save files option * support drop file to open editor * add case convert actions * GolangEdit * add guru support (backup oracle) * GolangFmt * fmt try to keep the original location * DlvDebugger * use native stepout * filter term color * LiteBuild * filter term color * FileTest support TESTARGS * gotools * always use vendor * gotest support [build|test args] * update vendor for oracle ### 2016.7.12 Ver X30.2 * LiteApp * add new vs-dark css, thanks [tupunco](https://github.com/tupunco) * fix and re-implement editor list menu * QuickOpen * QuickOpenFile skip same folder and same files * QuickOpneFile add current editor local files ### 2016.7.5 Ver X30.1 * LiteIDE * add OpenEditor tool windows * add GolangSymbol for QuickOpen (CTRL+SHIFT+O) * fix gotools vendor error * LiteApp * add OpenEditor tool windows * update view menu * GolangAst * add GolangSymbol for QuickOpen * add GolangSymbol option * fix goto symbol * QuickOpen * optimization QuickOpenFile and QuickOpenEditor search * add QuickOpen option * gotools * fix vendor error ### 2016.7.2 Ver X30 * LiteIDE * add new QuickOpen plugin * add new FakeVim plugin, thanks for [jsuppe](https://github.com/jsuppe) * add custom env LITEIDE_TOOL_PATH/LITEIDE_PLUGIN_PATH/LITEIDE_RES_PATH * LiteApp * action tooltip shortcut show native text * option keyboard map show native text * QuickOpen * quick open files action CTRL+P * quick open editor action ATL+ALT+P * quick go to line action CTRL+L * quick open help * FakeVim * editor add vim style mode editing * LiteEditor * add goto line start/end action * add goto doc start/end action * add goto previous/next line action * add goto previous/next charater action * add goto previous/next word action * change '' braces only go source * fix codecompleter number first * MacOS fix move line up/down shortcut command+shift+up/down * GolangEdit * CTRL+mouse navigate preview source info * LiteFind * MacOS fix edit replace shortcut command+shift+F * Welcome * fix doc css style * gotools * types fix limit parser * types simple field info ### 2016.4.15 Ver X29 * LiteIDE * support for multiple debuggers * support Delve debugger * env GO15VENDOREXPERIMENT=1 default setup * LiteBuild * fix project folder id named go, error find go tool * fix project folder contains spaces run failed * fix output number of rows exceeds the maximum input fails * add output add automatic positioning cursor option * add single go file test action * add folder context menu more go tool action * LiteEnv * env GO15VENDOREXPERIMENT=1 default setup * LiteDebug * support for multiple debuggers * debug berore auto go build -gcflags "-N -l" * fix stack frame clicked to doubleClocked * DlvDebugger * support dlv debugger * simulation execution 'step-out' * GdbDebugger * fix show frame line locate * fix goto line action * LiteEditor * display limit tip line info * GolangEdit * fix folder contains spaces, gotools fails * gotools * add gotest action, test single go file * fix types info, display pkg real name ### 2015.12.10 Ver X28 * LiteIDE * gotools add go1.5 vendor support if env GO15VENDOREXPERIMENT=1 set * LiteApp * folder add sync edit action * fix close folder bug * LiteBuild * add folder context lock build path * add folder context gofmt * add output menu auto clear and line wrap action * LiteOutput * add set max line option * GolangFmt * add new gotools gofmt action * add sortimports option (default) * LiteEnv * add var GO15VENDOREXPERIMENT=1 (default comment) * GolangAst * support go1.5 vendor * LiteEditor * fix selection identifier regexp * GolangEdit * support go1.5 vendor * enable oracle enable referres action * GolangCode * use set lib-path action * gotools * types add go1.5 support if GO15VGOROOTXPERIMENT=1 set * types fix cycle import check * types fix pkg find bug * types add unsafe builtin info * astview add go1.5 support if GO15VGOROOTXPERIMENT=1 set * stdlib update to go1.5 * add new gofmt action * gofmt import godiff replace diff cmd ### 2015.4.22 Ver X27.2.1 * LiteIDE * fix editor change crash ### 2015.4.20 Ver X27.2 * LiteIDE * add output option * add windows native open explorer * add Ukrainian translation thanks Roman Shmelev * LiteEditor * add block selection mode (use Alt key) * fix text mimetype print char check. * fix code completer ...type * fix insert key * LiteEnv * optimization go env reload * LiteBuild * fix build config * LiteFind * fix editor match case replace * fix file search matchWord * GolangEdit * fix init option * fix embeded struct find * add oracle support * gotools * fix embeded struct type find * add oracle ### 2015.2.16 Ver X27.1 * LiteIDE * fix code navigate history ( build / astview / debug / link) * fix UNC path crash check * LiteEditor * add copy/cut/move/join line action * fix selection color * fix link color * GolangEdit * add global find usages and refactor(GOPATH) * add refactor revert mode * add golang symbol document on tooltip * fix no jump code tooltip * fix syntax for Non-English symbol name * LiteFind * add find swith replace mode * add replace revert mode * LiteBuild * fix build lock custom config * GolangAst * fix Non-English symbol name * gotools: * type - simple object info * type - add global usages * type - add symbol doc search * type - add XTest files support * type - fix field pos search * astview - update type var and factor to global ### 2015.2.4 Ver X27 * LiteIDE * create independent project gotools and replace liteide_stub * move build toolbar to the main window * move editor tab to editor widget * fix multi window keyshort invalid * fix treeview scroll bar * fix sidebar keyshort * GolangEdit * add editor mouse under symbol tooltip * add ctrl + left mouse button to link navigate * fix embeded func navigate * fix golang syntax parser * LiteBuild * add build lock action * update build config file * fix output enter offset * LiteFind * update find text by under cursor * LiteEditor * add whitespace visible setup option * add line end setup option * fix google pinying editor cursor hide bug * fix editor navigate action * JsonEdit * re-implement json format * RustEdit * add simple rust support ### 2014.12.25 Ver X26 * LiteIDE * add lang package support * fix shortcut key call mechanism * fix editor shortcut key monopolize * LiteEnv * fix system enviroment auto reset by go env * LiteEditor * add simple snippet code * fix enter {} key indent * fix []{} insert and backspace * fix code completer func () insert * GolangCode * fix system enviroment work * add auto update package when its source change option * GdbDebugger * fix system enviroment gdb/gdb64 auto select * GolangEdit * add golang tag highlighter ### 2014.12.16 Ver X25.2 * LiteIDE * default enviroment id system work * LiteApp * fix sort folder on macosx * LiteEnv * add reload current enviroment action * set default enviroment id system * LiteEditor * fix enter key indent * fix import line regexp * fix complete word suspended bug (in non go file) * re-implement full text completer * GolangDoc * fix lookup godoc on system env * fix path name to pkg name * GolangCode * completer import line on GOPATH * GolangEdit * add update dependencies library action * add view import package in godoc action ### 2014.12.12 Ver X25.1 * LiteIDE * both support go1.3 and go1.4 * LiteApp * fix folders sort by folder first in macosx * GolangCode * enable completer import line (standard package) * GolangFmt * fix goimports error report bug * GolangEdit * fix import line find usages * GolangDoc * support go1.4 * LiteFind * fix search result style sheet * FileBorwser * fix sort by folder first in macosx ### 2014.12.4 Ver X25 * LiteApp * default use new style SideBarStyle * add style option SideBarStyle and SplitterStyle * folders use new multi folder class implement * LiteEnv * system env lookup go env * add LITEIDE_SHELL support for multiple terminals * GolangEdit * find usages both support go1.3 and go1.4 * dump find usages error * update goimports standard pkg index * fix find usages Non-English offset * fix faketip on ubuntu * FileBorwser * use new folder class implement * LiteEditor * fix clipboard blocking on linux * fix editor brace insert postion * GolangFmt * default save use gofmt style * add menu action Code Format(gofmt) (Ctrl+I) * and menu action Code Format(goimports) (Ctrl+Alt+I) ### 2014.11.13 Ver X24.3 * liteide_stub * merge and optimization code.google.com/p/goimports * fix astview for decl funcs * fix import line find uses * LiteApp * update german translation, thanks Harald Leinders * fix PATHEXT no default on windows * fix treeview remove crash bug * fix open terminal * GolangEdit * fix import find usages * fix golang func decl syntax highlighter * GolangAst * fix astview view missing funcs * GolangCode * fix goimports incorrectly removing certain no incorrectly removing no convention import paths ### 2014.11.04 Ver X24.2 * GolangCode * fix import style ### 2014.11.03 Ver X24.1 * LiteEditor * fix codecompleter crash * GolangCode * prompt pkg not find , enter key to auto import * fix struct offset for gocode * GolangFmt * merge goimports to liteide_stub * default use goimports ### 2014.10.24 Ver X24 * LiteApp * new codecompleter components * log and build output no wrap * update Japanese translation * update German translation * LiteEditor * new codecompleter components * code completer match by strings.hp => HasPrefix * code completer sort by prefix * code completer list use tooltip * code completer list updown use ctrl+n/ctrl+p short key * smart () [] "" '' `` insert and backspace remove * smart right ) ] " ' ` insert skip * fix code completer up/down key * fix ctrl+enter/ctrl+shift+enter to insert line after/berore * fix selection highlight * LiteBuild * golang config custom add TESTARGS/BENCHMARKARGS * output font family use editor family ### 2014.08.05 Ver X23.2 * gocode add cgo basic completer * update option to dialog mode * fix godoc target for go1.3 * fix golang highlighter, return to kate * fix short key for macosx * fixed Qt5 build crash when exit on macosx ### 2014.07.24 Ver X23 * LiteIDE * add golang simple lexer for editor * add golang code complete tooltip * golang code complete disable on comment or strings * fix escape return editor * LiteEditor * add IHighlighterManager interface * add ITextLexer interface * add new color scheme carbon from William Kennedy * fix kate code fold * fix code completer offset * GolangEdit * add golang simple lexer * add golang highlighter parser * add tooltip for complete * GolangPresent * view by QtWebKit * WebKitHtmlWidget * change to browser view mode ### 2014.04.14 Ver X22 * LiteIDE * add golang find usage support * add golang code refactor support * fast jump to declaration * add reload folder/files option on startup. * LiteIDE * fix code fold bug * LiteDebug * add call frame goto line * LiteEnv * add freebsd env * LiteFind * new find result view from QtCteator * GolangEdit * new golang editor support plugin * find usages * rename symbol under cursor * MarkdownEdit * add Github_Word.css, thanks github.com/lixiaolong ### 2014.03.20 Ver X21.1 * LiteIDE * reduce application memory usage * add new golang doc search (modification from rspace doc tool) * update golang api index * folder add go build context menu * short folder name * optimization litide_stub api tool * add kate solarsooty.xml thanks for Unknown * add code complete short key (ctrl+space) * fix gocode automatically plugin * fix golang present verify plugin ### 2014.03.06 Ver X21 * LiteIDE * fast highlighter for MacOS X 10.9 * fast expression lookup F1/F2 * cancel x20 always open in new window mode. * add new JsonEdit plugin. * add reload/close dialog YesToAll, if modified on the drive. * add auto reload files option, if modified on the drive. * add store setting to local ini file option. * fix folder expand state * fix for case sensitive path comparison on windows * fix memory leak * LiteBuild * add golint support * LiteEnv * recreate system.env * LiteEditor * new color scheme gist-github (thanks William Kennedy ) * fix if/else syntax fold * GolangAst * add type factor to funcs folder * add type const * add import symbol, and view document menu * add context menu * add symbol extra info * GolangFmt * fix timeout * fix GOPATH * GolangDoc * fast expression lookup F1/F2 ### 2013.12.09 Ver X20 * LiteIDE * add folders manager * always open folder with new window (option) * editor add navigate area for code format or build error * add new GolangPresent plugin * tool windows use instantpopup * update editor tab context menu * add evilworks.qss style (by Vedran Vuk ) * LiteEditor * add error navigate area * update kate highlighter * add gopresent.xml syntax * add Visual Studio Theme (by William Kennedy ) * fix goto match braces * update editor menu * LiteEnv: * auto set $PATH for GOROOT/bin and GOBIN and GOPATH/bin and GOPATH/bin/GOOS_GOARCH * fix to use utf8 encoding * GolangCode: * auto update depends package (option) * fix close gocode on last window close * GolangFmt: * use sync code format (option) * use goimports instead gofmt (option) * code format error show in editor navigate area * LiteDebug: * external cmd setting * fix command input foucus * Markdown: * add new Github_Style.css (by Slene ) * FileBrowser: * option show hidden files * LiteBuild: * fix build menu enable * build error show in editor navigate area * add gopm(Go Package Manager) tool * GolangPresent: * support golang present editor * verify present error show in editor navigate area * export golang present to html * Welcome: * update document * add zh_CN document ### 2013.7.17 Ver X19 * LiteIDE * MacOS X 10.8 Retina support * add simple webkit browser * update macosx tool window short key to Ctrl+Alt+1~9 * LiteDebug * add debug go test support, thanks for GoEddie * GdbDebugger * gdb debugger --tty mode support (windows default) * debugger command input foucus * LiteEditor * add wheel zooming option * fix editor extra width * fix init editor update * LiteFind * fix find hide * Markdown * markdown preview fast sync ### 2013.5.21 Ver X18.2 * fast for gocode * add option to close gocode on exit * auto append GOPATH/bin to liteide env PATH * editor extern highlighting "TODO" * go code auto-complete ignores strings and comments ### 2013.5.10 * compiled compatibility for qt5.02 ### 2013.5.8 Ver X18.1 * optimization gocode plugin * execute preload litebuild/command/*.api * execute enable tab key to compiler ### 2013.5.7 Ver X18 * English spelling and grammar corrections throughout, thanks for Nik-U * LiteIDE: * Improved event log * litefind: * Find/Replace commands highlight existing text * enable find file * add close button * liteeditor: * Word wrap support * Added option to trim whitespace on save * Added option to hide edit toolbar * update kate and color scheme * fix kate/highlight tab * fix editor indent guide by tabsize * liteapp: * fix full screen bug * litebuild: * execute use combbox * add close button * litedebug: * add close button * markdown: * enable markdown(sundown) extend ### 2013.2.8 Ver X17 * LiteIDE: * move execute from filesystem to bottom tool * escape for any bottom tool window (find , execute ...) * macosx lion full screen * add color theme highcontrastdark.xml and app theme black.qss, thanks for addxtoy * add tr liteide_de.ts , thanks for Helge Plaschke * fix keybord scheme * liteeditor: * show tab ident guide * show find scope expression * show selection scope expression * show file eof - option * show line wrap (markdown editor) * update current line color * any time focus if need * fix zoom tab width * fix open file cursor position start * fix set color theme not request restart * markdown: * fix export path * filesystem: * fix double clicked item and execute * litedebug: * save/restore start editor * fix breakpoint move in editor * fix debug target args * litefind: * new find and replace * fix find editor and unfold * fix backword find * litebuild: * add test bench * document: * enable zoom font size Ctrl++/Ctrl+-/Ctrl+0 * fix find crash * gopath setup: * fix invalid path ### 2013.1.16 Ver X16 * support keybord mapping scheme * fix: lookup go command in $PATH * fix: remove GOBIN enviroment set * fix: empty editor cursor position * fix: double click error output to jump source and editor set focus ### 2013.1.10 Ver X15.2 * LiteIDE: * use new logo and icon * support go version hg-tip * LiteApp: * update logo * update splash * add action close same/other folder files * fix full screen restore * LiteEnv: * add user env files * LiteEditor: * fix `Insert` key * update sublime color scheme * GolangDoc: * support go tip version * show error output * GolangCode: * fix code completer icon visible * Golang Fmt: * fix timeout option invalid * Markdown: * fix critical messsage * add css Documents.css ### 2012.12.28 Ver X15.1 * LiteIDE: * update logo * LiteApp: * plugins custom load * custom style use css(Qt Style Sheets) * add style coffee * fix template `doc.go` * tabs middle button close editor * fix memory leak * LiteEditor: * font zoom support * add sublime color scheme, thanks for `Henson Lu` * custom tab width and tab to spaces for mimetype * LiteEnv: * add cross-compiler * GolangDoc: * fix goto source ### 2012.12.18 Ver X15 * LiteIDE: * add markdown plugin * changed LiteApp to dynamic library * redesign editor menu and toolbar * update doc to markdown format * add html render twin-engine * internal QHtmlBrowser * plugin QtWebKit, if find qt webkit dynamic library * LiteApp: * changed to dynamic library * support full screen mode * editor tabs change to toolbar * add toolbar icon size option * add splash visible option * add editor tab bar close button visible option * add tab context menu close left or right tabs * LiteEditor: * add overwrite mode (key Insert) * add custom tab width option * redesign editor menu , context menu and toolbar * add right margin line visible option * GolangFmt: * fix comment offset, remove spaces * LiteBuild: * id BuildAndRun before kill old process * redesign build toolbar and menu * support GOBIN * LiteDebug: * add debug before rebuild option * add debug external application action * Markdown: * markdown editor support * action h1-h6, bold, italic, code, list, quote, hr, link, image * syntax highlighting * live preview * sync scroll * export html * export pdf * custom css , css files from [Mou](http://mouapp.com) * markdown batch * separate to html * separate to pdf * merge to html * merge to pdf * GolangDoc: * fix url parser ### 2012.11.15 Ver X14.1 * LiteIDE : quick start * LiteApp : multi instance support * GolangDoc: deply load mode * GolangPackage: deply load mode * GolangAst : fix classview * LiteEditor: fix if/else fold * GolangDoc : goapi enable _test ### 2012.11.6 Ver X14.0 * tools/goapi : new goapi tool * GolangDoc: View Expression Information (F1) * GolangDoc: Jump to Declaration (F2) * GolangDoc: lookup all GOPATH pkg api * LiteApp: fix editor navigate * LiteEditor : add action Move to New Windows * LiteFind : focus in find text and enter * LiteEditor: fix code completer func test () * GolangCode : auto restart gocode if liteide GOPATH changed * GolanPlay: enable gocode and fmt * GolangFmt: auto popup gofmt messsage option * LiteBuild : fix build config custom view * LiteBuild : BUILDARGS / INSTALLARGS support set example -gcflags "-N -l" for debug example -ldflags "-s" for release * remove: Makefile plugin , Profile plugin, x64 Project ### 2012.10.10 Ver X13.2 * GolangCode : the best support for gocode * LiteApp : add editor tab context menu * LiteApp : update view menu * LiteApp : fix check modify and save * GolangFmt : fix fmt editor style restore * GolangDoc : fix go/doc/*.html parser meta "Path=" * GolangAst : fix update model style restore * Welcome : update page * LiteEnv : edit enviroment action * LiteBuild : update gosrc.xml * LiteBuild : fix double click goto line regexp * LiteBuild : show enviroment go env * LiteBuild : execute error use red font * LiteEditor : color theme set currnet line background * LiteEditor : add color theme darktango.xml(Dumitru Ungureanu) * LiteEditor : go wordapi update, keyword types and funcs * LiteEditor : code completer func auto append () * LiteEditor : fix tab indent * FileSystem : fix execute find path * LiteFind : fix current directory ### 2012.9.24 Ver X13.1 * LiteBuild : fix build load crash. * LiteApp : fix double click error output regexp * LiteApp : fix folder drop to liteide * LiteDebug : watch vars load /save by project * LiteDebug : breakpoint load /save by file * LiteDebug : add remove all breakpoint action * LiteDebug : add / remove global or local watch point * LiteEditor : optimization editor mark * LiteEditor : enable drop text * GolangPlay : enable gofmt ### 2012.9.21 Ver X13 * LiteApp : any folder, any file to build * LiteApp : update window style, add editor toolbar and status * LiteEditor : remove editor toolbar * LiteEditor : extra use editor font * LiteBuild : new build toolbar and menu * LiteBuild : clean action tags * GolangFmt : sync execute gofmt * GolangDoc : deply filter index * GolangAst : classview for folder * Outline : alltime expand * FileBrowser : rename to FileSystem * FileSystem : sync editor file to folder * FileSystem : add go command line edit (Ctrl+`) * FileSystem : double click execute file and execute on build output * Windows : include diff bin ### 2012.9.14 Ver X12.5 * LiteApp : move dock style, change to idea style tool windows. * LiteApp : double click editor and maximized or restore editor * LiteApp : esc key to hide bottom tool windows * LiteApp : auto load last session * LiteEditor : add edit navigate histroy * LiteEditor : extra use color scheme * GolangFmt : show error log and goto line ### 2012.7.12 Ver X12.2 * GolangFmt : fix fold error diff bug * LiteDebug : add var watch, example main.var os.Stdout * Welcome : add load last selection * LiteEditor : add fold or unfold all action * LiteEditor : add duplicate action * LiteEditor : add color theme railscast.xml(Alexander Rødseth) * LiteFind : default find use editor selection * LiteEnv : fix windows env LITEIEDE_EXECOPT=/C * LiteApp : fix icon on windows xp unable show ### 2012.6.28 Ver X12.1.1 * LiteEditor : fix fold bug - line include "head{}end" * LiteEditor : kate go.xml breace match add "[]" ### 2012.6.27 Ver X12.1 * LiteIDE : LiteIDE use new logo * LiteEditor : fold / unfold * LiteEditor : color scheme custom selection * LiteEditor : kate go.xml remove linecontinue * LiteEditor : goto line * LiteApp : fix recent file load bug * GdbDebugger : fix frame if not find fullname * LiteIDE : update faq document * LiteIDE : add install document ### 2012.6.13 Ver X12 1.875 * LiteIDE : reset resource directory * LiteEditor : goto next/prev block * LiteEditor : code comment * LiteEditor : braces match * LiteEditor: LRLF check by \n * LiteEditor: no print char conver to . * LiteEditor: move tooltip to status * GolangFmt : enable gofmt diff * GolangFmt : save auto gofmt * LiteBuild: project build toolbar and editor build toolbar. * LiteFind: add file search * PackageBrowser: fast load ### 2012.5.16 Ver X11 1.71875 beta4.1 * LiteBuild: fix execute args for gosrc/gopro/makefile * LiteApp: add option - when close project auto close project editors * PackageBrowser : double click pkg and load project * LiteEditor: add option - completer case sensitive ### 2012.5.15 Ver X11 1.71875 beta4 * GolangPackage : enable local package * GolangDoc : golang api fmt#Println -> fmt.Println * LiteBuild : fix regexp error * FileSystem: (windows) fix rename abc to Abc false * PackageProject : remove auto reload timer * LiteEditor: (linux) redo enable CTRL+Y ### 2012.5.2 Ver X11 1.71875 beta3 * GolangPackage : new golang package plugin for GO1 * GolangPackage : PackageBrowser and PackageProject for GO1 * GolangTool : remove the plugin * GolangDoc: add golang api for GO1 * GolangDoc: add golang api filter * GolangAst: add filter * GolangAst: classview and outline * LiteEditor : completer option * LiteApp : new file wizard support GO1 * Welcome : new recent page * gopromake : update pkg depend ### 2012.3.9 Ver X11 1.71875 beta2 * GolangPlay : new go playground plugin * GolangTool : sync editor, sync project ### 2012.3.1 Ver X11 1.71875 beta1 * GolangTool : new golang plugin for GO1, import GOPATH project * GolangDoc : update to GO1 * LiteBuild : update to GO1 * tools : udpate all tools for GO1 ### 2011.9.26 Ver X10 1.5625 * LiteEditor : add line mark api * LiteDebug : new debug toolbar * LiteDebug : insert/remove break * LiteDebug : breakpoint and current line mark * GdbDebugger : async record view * GdbDebugger : variables expand tree * GdbDebugger : call stack view * GdbDebugger : load library view * TerminalEdit : provided to LiteBuild and LiteDebug ### 2011.9.14 Ver X9 1.40625 * LiteDebug : new debug manager plugin * GdbDebugger : new gdb debugger plugin * LiteBuild : add build config and custom * LiteFind : fix regexp use match case ### 2011.9.1 Ver X8 1.25 * LiteFind : new find and replace plugin, remove CodeSearch plugin * LiteEditor : fix word api completer three parts error * LiteEditor : fix word api completer sorted * LiteApp : fix main window state load/save on linux * LiteApp : change path to standard linux path * LiteBuild : add build option, example execute arguments * FileBrowser : add new file wizard ### 2011.8.12 Ver X7 1.09375 * Welcome : new html page, quick link, session, recent projects and files * GolangDoc : generic document nav * GolangDoc : scheme entry [file|list|find|pdoc] * FileBrowser : add "View Godoc Here" * LiteBuild : auto clean output if line more than 1024 * LiteEditor : word completer sorted * LiteEditor : auto braces last state check * GolangAst : show type struct field * GolangAst : editor state keep self ### 2011.7.28 Ver X6 0.9375 * LiteEnv : new plugin, liteide enviroment setup * Welcome : add LiteIDE document browser * GolangDoc : add package find, example input "zip" and find * GolangDoc : add godoc /src/pkg/ and /src/cmd/ tree * GolangDoc : add go/doc/ document browser * GolangDoc : add document browser text search * LiteEditor : add export html file * FileBrowser : add menu item desktop explorer * LiteEditor : add enable automatic insert brackets * LiteEditor : add option : display and behavior * LiteApp : fix session load last editor or welcome page * LiteApp : fix find mimetype incorrect * GolangCode : fix application exit gocode close * FileBrowser : fix context menu popup on root * LiteBuild : fix ouput html format to plaintext * LiteBuild : fix build does not handle spaces in file paths * LiteBuild : fix output append \n->next append * LiteBuild : fix enviroment depend of LiteBuild ### 2011.7.7 Ver X5 v0.78125 * add CodeSearch plugin : Editor Search and Replace * add GolangDoc plugin : Golang Package Find * add Search and Replace Regex: (Colo)(u)(r) -> \1\3 * add FileBorwser top dir setup * add LiteEditor Copy Syntax Color support (HTML mimedata) * add LiteEditor ReadOnly * add MainWindow all DockWidget saveState * add EditorManager CTRL+TAB switch * update tools/gopromake to r58 * update tools/goexec to r58 * update tools/goastview to r58 * fix filebrowser rename show oldname * fix ENV c:/go/bin;%PATH% order, GOBIN is priority * fix FileBrowser sort incorrect on MACOSX * fix GoFmt reload editor display pos keep * fix Editor Close Ask BUG ret==SaveAll * fix Editor word writed ,completer only one match auto hide ### 2011.6.30 Ver X4 v0.625 * add interface zh_cn * add filebrowser pluing add/change/remove * add editor color style scheme setup * add editor codec check/reload * add editor pdf export * add editor print and preview * editor style line LRLF of source * kate go.xml support "number" style * liteapp last session save/load ### 2011.6.21 Ver X3 v0.46875 * add file browser plugin * source editor pre link project build * source editor outside modify/remove watcher ### 2011.5.20 Ver X2 v0.3125 * add gocode plugin * add build/makefile * add build/lua stdoutput:setvbuf("no") * fix build task stop on error * fix build process write \n ### 2011.5.12 Ver X1 v0.15625 * New LiteIDE X version ------ ## LiteIDE Old version ### 2011.2.25 v0.2.1 * add build on MacOSX10.6 * support Makefile and .pro project * project support GCOPT and GLOPT * global option page * global output pane * set GOROOT option * run shell * run debug * run process can write * run process can kill * clean project opt temp or all * new project wizard : .pro/package/Makefile * new example goinfo, how to use local or search package ### 2011.1.25 v0.1.8 * goastview plugin ### 2011.1.18 v0.1.6 * add build on Linux64 ### 2011.1.12 v0.1.5 * build error and jump to source line ### 2011.1.11 v0.1.2 * gopromake use goroutines ### 2011.1.10 v0.1 * init version ================================================ FILE: liteidex/deploy/welcome/en/forever.md ================================================ Forever ======= ## 道德经 道可道,非常道。名可名,非常名。 无名天地之始;有名万物之母。 ## 2018.02.14 **三十功名尘与土,八千里路云和月。** ## 天行健 **天行健,君子以自强不息。地势坤,君子以厚德载物。** ![](images/liteide.png) ## logo ![](images/liteide400.png) ## @_@ 佛祖问阿难:你有多喜欢这少女? 阿难说:我愿化身石桥,受五百年风吹,五百年日晒,五百年雨打,但求此少女从桥上走过。 ## with you ![](images/flamingo.png) ## forever ![](images/forever.png) ================================================ FILE: liteidex/deploy/welcome/en/guide.md ================================================ # LiteIDE Feature Guide ## How to use the low version Go1.1 and Go1.2 LiteIDE build config default use -i flag, if use Go1.1 or Go1.2 not support. View -> Options -> LiteBuild double click gosrc.xml to edit, modify BUILDARGS value: set value to empty and restart LiteIDE to support Go1.1 and Go1.2. ## Window Style Setup LiteIDE now support splitter style and side style. Options->View->LiteApp-> Style ## Environments The LiteIDE environment setup plugin allows you to quickly switch between multiple system environments for your build. Each environment has its own set of environment variables that can be used to control the build process. ### Selecting an Environment The dropdown in the toolbar can be used to select the environment currently being used for builds. By default, the `system` environment, representing the platform and architecture of the host machine, is used. ![envselect.png](../images/envselect.png) The following environments are provided as part of the supported platforms: * Windows - system win64 win32 * Linux - system linux64 linux32 * MacOSX - system darwin64 darwin32 See the section below on cross-compiling before switching to a non-native environment. ### Configuring an Environment The variables defined as part of the environments can be modified by hand. To edit an environment, simply click the `Edit Environment` button next to the environment dropdown when the desired environment has been selected. Alternatively, environments can be viewed and edited in the `View > Options > LiteEnv` panel. Example `win32.env`: #win32 environment GOROOT=c:\go #GOBIN= GOARCH=386 GOOS=windows PATH=c:\mingw32\bin;%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C Example `linux32.env`: #linux32 environment GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=linux PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e ## Quick Open * QuickOpen Ctrl+P * QuickOpenEditor Ctrl+Alt+P or QuickOpen window input ~ * QuickOpenSymbol Ctrl+Shift+O or QuickOpen window input @ * QuickOpenLines Ctrl+L or QuickOpen window input : * Help QuickOpen window input ? ## Cross-compilation (Go1.5 or high) Change LiteIDE environment , set GOROOT GOARCH GOOS, build project. ## Cross-compilation (before Go1.5) You will need to build or install Go compilers for other platforms and architectures before cross-compiling. If you do not do this, you may receive errors about missing executables or even the following error: %GOROOT%/src/pkg/runtime/extern.go:137: undefined: theGoos See the "Building compilers" subsection for examples. ### Environment variables To cross-compile your project for another operating system or architecture, you will need to define the following variables in your environment: * `$GOOS` - the name of the target operating system (default: `$GOHOSTOS`). Possible values are: * darwin (Mac OS X 10.6 and above) * freebsd * linux * netbsd * openbsd * plan9 * windows * `$GOARCH` - the name of the target architecture (default: `$GOHOSTARCH`). Possible values are: * amd64 (64-bit x86, the most mature port) * 386 (32-bit x86) * arm (32-bit ARM) * `$GOARM` - ARM architecture version the run-time libraries should target (default: 6). * Setting `$GOARM` to 5 causes the linker to emit calls to a software floating point implementation instead of using hardware floating point support. * `$CGO_ENABLED` * This should be set to 0 when cross-compiling. ### Building Compilers To build the compilers for cross-compilation, run the appropriate script from the Go sources directory. The examples below demonstrate how to build some common compilers; you must modify the environment variables appropriately. **go1.5 or high (go1.8 cross-compile CGO_ENABLED auto set 0)** Building cross-compiler for 64-bit Linux on Windows (in MinGW with GCC): > set GOARCH=amd64 > set GOOS=linux > set CGO_ENABLED=0 > go build std Building cross-compiler for 32-bit Windows on macOS: > GOARCH=386 GOOS=window CGO_ENABLED=0 go build std Building cross-compiler for Linux ARM on macOS: > GOARCH=arm GOOS=linux CGO_ENABLED=0 go build std **go 1.0 go1.1 go1.2 go1.3 go1.4** Building cross-compiler for 64-bit Linux on Windows (in MinGW with GCC): > set GOARCH=amd64 > set GOOS=linux > set CGO_ENABLED=0 > cd %GOROOT%\src > all.bat Building cross-compiler for 32-bit Windows on macOS: > export GOARCH=386 > export GOOS=windows > export CGO_ENABLED=0 > cd $GOROOT/src > ./all.bash Building cross-compiler for Linux ARM on macOS: > export GOARCH=arm > export GOOS=linux > export CGO_ENABLED=0 > cd $GOROOT/src > ./all.bash ### Building To actually perform a cross-compilation in LiteIDE, begin by selecting the appropriate environment as described above. Ensure that the environment has the correct variables set. `GOARCH`, `GOOS`, `GOARM`, and `CGO_ENABLED` must be set as outlined previously. Ensure that `GOROOT` and `GOBIN` are also properly defined for your host platform, and that your `PATH` includes the Go binary and Go's `bin` directory. Once the target environment has been selected, simply rebuild your project in the editor. Example configuration for cross-compiling 64-bit Linux binaries on Windows: GOROOT=c:\go GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=0 PATH=%GOBIN%;%GOROOT%\bin;%PATH% ... ## Golang Code Format Automatic formatting when saving. ### Goimports LiteIDE View->Options->GolangFmt-> Use goimports instead of gofmt, for code format This tool updates your Go import lines, adding missing ones and removing unreferenced ones. ## Gocode Code completion use gocode . gocode works by inspecting the .a files from the project dependencies, so if the code completion is not working properly, please update project dependant packages/libraries. ### update dependant packages update dependant packages for gocode, click build menu or toolbar `Get`(go get) ### auto update dependant packages LiteIDE View->Options->Gocode-> auto update depends packages ## Build System LiteIDE's build system is highly configurable, allowing you to define your own custom build actions using XML files. ### Configuring Build Actions To modify the available build options, open `View > Options > LiteBuild`. You can add your own images in this directory to define new icons. Any XML files in this directory are read to load action buttons. Double click on an XML file to edit it. Each XML file defines all of the build actions for one particular type of file. Example XML for Lua (`lua.xml`): ``` ``` ## Godoc Viewer LiteIDE includes an integrated viewer for godoc output. Documentation can be viewed for the Go language itself or for your own packages. Open the viewer using `View > Godoc Viewer` for more details. ## Search and replace The editor provides search and replace functionality in the `Find` menu. Regular expressions are supported. For example: Find: (Colo)(u)(r) Replace: \1\3 The above example will replace all instances of `Colour` with `Color`. Search functionality is also provided for the filesystem through `Find > File Search`. ## Debugging To debug your code with LiteIDE, you must have GDB installed (part of MinGW for Windows users). See `INSTALL` for installation details. The environment variable `LITEIDE_GDB` can be used to control which binary is executed for debugging. 32-bit Windows will use `gdb.exe`, while 64-bit Windows will use `gdb64.exe`. Configure this environment variable in your environment file. ## Keybord Mapping Scheme You can modify the shortcut keys used for all of LiteIDE's features. Open `View > Options > LiteApp > Keyboard` to modify the hotkeys. Double click on the shortcut in the list to edit it, and press `Apply` to apply the changes. Shortcut keys must follow a specific format. You can separate items using a comma (`,`) to form an AND relationship (i.e. both shortcuts must be pressed to activate the item). Separate items with a semicolon (`;`) to form an OR relationship (i.e. any of the shortcuts will activate the item). This is normally what you want. Examples: * `Ctrl+B` * `Ctrl+Shift+B` * `Ctrl+K,Ctrl+U` * `Ctrl+Y;Ctrl+Shift+Z` ================================================ FILE: liteidex/deploy/welcome/en/install.md ================================================ # Installing LiteIDE ## Prerequisites Use LiteIDE development golang need to install the Go language development environment. ### Go Begin by installing the Go language runtime. Detailed instructions can be found at . Testing your installation before continuing is highly recommended. ## Install from binary ### Windows Download the archive and extract it into c:\ ### Linux and MacOSX Download the archive and extract it into /usr/local or $HOME ## Building from Source Source code for LiteIDE can be found at . You will need to install Qt4/Qt5 in order to compile the source. Qt can be obtained from or from your distribution's package manager. For Mac OS X, you don't need to install Qt from source code, but run `brew update && brew install qt` which will save you several hours. ### Windows **Qt4** > git clone https://github.com/visualfc/liteide.git > set QTDIR=c:\Qt\Qt4.8.5 > set MINGWDIR=c:\Qt\MinGW > cd liteide/build > update_pkg.cmd > build_windows_mingw.cmd > deploy_windows_qt4.8_webkit.cmd **Qt5.6** > git clone https://github.com/visualfc/liteide.git > set QTDIR=C:\Qt\Qt5.6.2\5.6\mingw49_32 > set MINGWDIR=C:\Qt\Qt5.6.2\Tools\mingw492_32 > cd liteide/build > update_pkg.cmd > build_windows_mingw.cmd > deploy_windows_qt5.6.cmd ### Ubuntu 16.04 Qt4 ## Install Qt4 ## $ sudo apt-get update $ sudo apt-get install libqt4-dev ## Git clone and build liteide ## $ git clone https://github.com/visualfc/liteide.git $ cd liteide/build $ ./update_pkg.sh $ ./build_linux_qt4.sh ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide ## Deploy it: ## $ cd liteide/build $ ./deploy_linux_x64_qt4.sh ## 32 bit $ ./deploy_linux_x32_qt4.sh ### Ubuntu 16.04 Qt5 ## Install Qt5 ## $ sudo apt-get update $ sudo apt-get install qt5-default ## Git clone and build liteide ## $ git clone https://github.com/visualfc/liteide.git $ cd liteide/build $ ./update_pkg.sh $ ./build_linux_qt5.sh ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide ## Deploy it: ## $ cd liteide/build $ ./deploy_linux_x64_qt5.sh ## 32 bit $ ./deploy_linux_x32_qt5.sh ### Ubuntu 14.04 $ sudo apt-get update $ sudo apt-get install qt4-dev-tools libqt4-dev libqt4-core libqt4-gui libqtwebkit-dev g++ $ git clone https://github.com/visualfc/liteide.git $ cd liteide/build $ ./update_pkg.sh $ QTDIR=/usr ./build_linux.sh ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide ### Linux $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=$HOME/QtSDK/Desktop/Qt/484/gcc $ cd liteide/build $ ./update_pkg.sh $ ./build_linux.sh $ ./deploy_linux_qt4.8_webkit.sh ### Mac OS X / macOS **Qt 4** $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=$HOME/QtSDK/Desktop/Qt/484/gcc #If QT is installed with brew, input: export QTDIR=/usr/local/Cellar/qt/4.8.6 $ cd liteide/build $ ./update_pkg.sh $ ./build_macos_qt4.sh $ ./deploy_macos_qt4.sh $ open liteide/LiteIDE.app **Qt 5 sdk install** Download Qt from http://www.qt.io/download and install. (Qt5.6.2/Qt5.7.1/Qt5.8) $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=$HOME/Qt5.6.2/Qt5.6/clang_64 $ cd liteide/build $ ./update_pkg.sh $ ./build_macos_qt5.sh $ ./deploy_macos_qt5.sh $ open liteide/LiteIDE.app **Qt 5 brew install** Use brew install qt (eg brew install qt. Other versions of qt@5.5 and qt@5.7 works too). $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=/usr/local/Cellar/qt/5.8.0_2 # or modify accordingly for qt@5.5 and qt@5.7 $ cd liteide/build $ ./update_pkg.sh $ ./build_macos_qt5.sh $ open liteide/LiteIDE.app Warning! brew install qt rpath incorrect do not use deploy script. ### OpenBSD $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=/usr/local/lib/qt4 $ cd liteide/build $ ./update_pkg.sh $ ./build_openbsd.sh ## Run it: ## $ export LD_LIBRARY_PATH=$HOME/liteide/build/liteide/bin:$LD_LIBRARY_PATH $ cd liteide/build/liteide/bin $ ./liteide ### Raspbian Jessie $ sudo apt-get update $ sudo apt-get install qt5-default xterm $ git clone https://github.com/visualfc/liteide.git $ cd liteide/build $ ./update_pkg.sh $ QTDIR=/usr ./build_linux.sh The build process from a µSD card takes approx. 105 minutes on a RPi 2. ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide **Addin** Be sure to set `QTDIR` (and `MINGWDIR` for Windows users) accordingly based on your local environment. ## Fedora 27 $ sudo dnf update $ sudo dnf install qt-devel $ git clone https://github.com/visualfc/liteide.git Following this step I had to clone the contents of the following repos in liteide/src/github.com i.e. liteidex/src/github.com/visualfc/gotools/README.md * https://github.com/visualfc/gotools * https://github.com/nsf/gocode * https://github.com/fatih/gomodifytags $ cd liteide/build $ ./update_pkg.sh $ export QTDIR=/usr/bin $ ./build_linux_fedora27_x64.sh ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide ================================================ FILE: liteidex/deploy/welcome/en/liteide.html ================================================ LiteIDE Documentation

LiteIDE Documentation

{header}

{content}
================================================ FILE: liteidex/deploy/welcome/en/readme.md ================================================ LiteIDE X ========= ### Introduction _LiteIDE is a simple, open source, cross-platform Go IDE._ * Version: X38.4 * Author: [visualfc](mailto:visualfc@gmail.com) ### Features * Core features * System environment management * MIME type management * Configurable build commands * Support files search replace and revert * Quick open file, symbol and commands * Plug-in system * Advanced code editor * Code editor supports Golang, Markdown and Golang Present * Rapid code navigation tools * Syntax highlighting and color scheme * Code completion * Code folding * Display save revision * Reload file by internal diff way * Golang support * support Go1.18~Go1.20 generics * Support go1.11 Go modules * Support go1.5 Go vendor * Support go1 GOPATH * Golang build environment management * Compile and test using standard Golang tools * Custom GOPATH support system, IDE and project * Custom project build configuration * Golang package browser * Golang class view and outline * Golang doc search and api index * Source code navigation and information tips * Source code find usages * Source code refactoring and revert * Integrated [gocode](https://github.com/visualfc/gocode) clone of [nsf/gocode](https://github.com/nsf/gocode) * Integrated [gomodifytags](https://github.com/fatih/gomodifytags) * Support source query tools guru * Debug with GDB and [Delve](https://github.com/derekparker/delve) ### Supported Systems * Windows x86 (32-bit or 64-bit) * Linux x86 (32-bit or 64-bit) * MacOS X10.6 or higher (64-bit) * FreeBSD 9.2 or higher (32-bit or 64-bit) * OpenBSD 5.6 or higher (64-bit) ### LiteIDE Command Line liteide [files|folder] [--select-env id] [--local-setting] [--user-setting] [--reset-setting] --select-env [system|win32|cross-linux64|...] select init environment id --local-setting force use local setting --user-setting force use user setting --reset-setting reset current setting ( clear setting file) ### Update liteide tools for support new Golang Version go get -u github.com/visualfc/gotools go get -u github.com/visualfc/gocode Windows/Linux: copy GOPATH/bin gotools and gocode to liteide/bin MacOS: copy GOPATH/bin gotools and gocode to LiteIDE.app/Contents/MacOS ### Website * LiteIDE Home * * Source code * * Binary downloads * * Google group * * FAQ * * Support LiteIDE * ================================================ FILE: liteidex/deploy/welcome/en/shortcuts.html ================================================

Key Shortcuts

These are the default shortcuts for LiteIDE. Note that you can customize these in "View > Options > LiteApp > Keyboard".

Standard
NewCtrl+N
OpenCtrl+O
SaveCtrl+S
CloseCtrl+W
Full ScreenCtrl+Shift+F11
Next TabCtrl+Tab
Prev TabCtrl+Shift+Tab
Hide Bottom WindowsESC
Execute FileCtrl+`
Editor
CutCtrl+X
CopyCtrl+C
PasteCtrl+V
UndoCtrl+Z
RedoCtrl+Shift+Z,Ctrl+Y
PasteCtrl+V
DuplicateCtrl+D
Delete LineCtrl+Shift+K
Select AllCtrl+A
Select BlockCtrl+U
Goto Match BraceCtrl+E
Goto Previous BlockCtrl+[
Goto Next BlockCtrl+]
Goto LineCtrl+G
Fold BlockCtrl+<
Unfold BlockCtrl+>
Increase Font SizeCtrl++
Decrease Font SizeCtrl+-
Reset Font SizeCtrl+0
Go BackwardAlt+←
Go ForwardAlt+→
InsertLineAfterCtrl+Enter
InsertLineBeforeCtrl+Shift+Enter
Code CompleterCtrl+Space
Code Completer List NextCtrl+N
Code Completer List PrevCtrl+P
Golang Editor
Code expression infoCtrl+Shift+I; F1 ; Ctrl+?(MacOS X)
Jump to declarationCtrl+Shift+J; F2
Find UsagesCtrl+Shift+U
Rename Symbol Under CursorCtrl+Shift+R
GofmtShift+F7
Comment/UncommentCtrl+/
Find
FindCtrl+F
Find NextF3
Find PreviousShift+F3
ReplaceCtrl+H
Find in FileCtrl+Shift+F
Build
BuildCtrl+B, F7
InstallCtrl+F8
TestCtrl+T
RunCtrl+F5
Build and RunCtrl+R
Run in TermCtrl+Shift+F5
File RunAlt+F6
Debug
DebugF5
ContinueF5
Insert/Remove BreakPointF9
Stop DebugShift+F5
Step InfoF11
Step OverF10
Step OutShift+F11
Run to LineShift+F10
Markdown Editor
BoldCtrl+B
ItalicCtrl+I
H1-H6Ctrl+1,...,Ctrl+6
Inline CodeCtrl+K
LinkCtrl+Shift+L
ImageCtrl+Shift+I
Unordered ListCtrl+Shift+U
Ordered ListCtrl+Shift+O
BlockquoteCtrl+Shift+Q
Horizontal RuleCtrl+Shift+H
================================================ FILE: liteidex/deploy/welcome/en/website.md ================================================ ### LiteIDE * [LiteIDE Source](https://github.com/visualfc/liteide) * [LiteIDE Download](http://sourceforge.net/projects/liteide/files) * [Support LiteIDE](https://visualfc.github.io/support/) ### LiteIDE Markdown * Markdown parser from [sundown](https://github.com/vmg/sundown) * Markdown CSS files from [Mou](http://mouapp.com) ### Golang * [Golang Home](http://golang.org) * [Golang Source](http://code.google.com/p/go) ### Golang Tools * Golang code compliter form [gocode](https://github.com/nsf/gocode) * Golang code format form [goimports](https://github.com/bradfitz/goimports) * Go Package Manager [gopm](https://github.com/gpmgo/gopm) ### Golang Package Doc * [GoWalker](http://gowalker.org/) * [GoDoc](http://godoc.org) ================================================ FILE: liteidex/deploy/welcome/en/welcome.html ================================================ LiteIDE

Welcome to LiteIDE X

Copyright 2011-2023, Author visualfc, Version {liteide_version}
================================================ FILE: liteidex/deploy/welcome/images/liteide128.xpm ================================================ /* XPM */ static char * C:\Users\max\Desktop\liteide128_xpm[] = { "128 128 411 2", " c None", ". c #E6E6E6", "+ c #E5E5E5", "@ c #E4E4E4", "# c #E7E7E7", "$ c #E8E8E8", "% c #E9E9E9", "& c #EAEAEA", "* c #EBEBEB", "= c #ECECEC", "- c #EDEDED", "; c #EEEEEE", "> c #EFEFEF", ", c #F0F0F0", "' c #F1F1F1", ") c #F2F2F2", "! c #F3F3F3", "~ c #F4F4F4", "{ c #E1E1E1", "] c #E2E2E2", "^ c #E3E3E3", "/ c #F5F5F5", "( c #F6F6F6", "_ c #F7F7F7", ": c #E0E0E0", "< c #DDDDDD", "[ c #DEDEDE", "} c #DFDFDF", "| c #F8F8F8", "1 c #F9F9F9", "2 c #FAFAFA", "3 c #DCDCDC", "4 c #DBDBDB", "5 c #FBFBFB", "6 c #FCFCFC", "7 c #D9D9D9", "8 c #DADADA", "9 c #FDFDFD", "0 c #FEFEFE", "a c #D8D8D8", "b c #D7D7D7", "c c #FFFFFF", "d c #D5D5D5", "e c #D6D6D6", "f c #D3D3D3", "g c #D4D4D4", "h c #D1D1D1", "i c #D2D2D2", "j c #CFCFCF", "k c #D0D0D0", "l c #CECECE", "m c #CDCDCD", "n c #CBCBCB", "o c #CCCCCC", "p c #C9C9C9", "q c #CACACA", "r c #C8C8C8", "s c #C7C7C7", "t c #C6C6C6", "u c #C5C5C5", "v c #C4C4C4", "w c #C3C3C3", "x c #C1C1C1", "y c #C2C2C2", "z c #C0C0C0", "A c #BEBEBF", "B c #BFBFBF", "C c #BCBCBD", "D c #BEBEBE", "E c #BDBDBD", "F c #BDBDBE", "G c #BBBBBC", "H c #BABABB", "I c #BBBBBB", "J c #BCBCBC", "K c #B9B9BA", "L c #B8B8B9", "M c #BABABA", "N c #B7B7B8", "O c #C2C2C1", "P c #B6B6B7", "Q c #C4C4C5", "R c #B5B5B7", "S c #B5B5B6", "T c #BDBDBF", "U c #B4B4B5", "V c #B3B3B4", "W c #B3B3B5", "X c #B4B4B6", "Y c #B2B2B4", "Z c #B1B1B3", "` c #B2B2B3", " . c #AFAFB2", ".. c #B1B1B2", "+. c #B7B7B9", "@. c #AFAFB1", "#. c #B0B0B2", "$. c #B9B9B9", "%. c #AEAEB0", "&. c #AEAEB1", "*. c #EBEBEC", "=. c #B6B6B8", "-. c #ADADAF", ";. c #AEAEAF", ">. c #B1B1B4", ",. c #BCBCBB", "'. c #B6B6B6", "). c #AAAAAD", "!. c #ABABAE", "~. c #ACACAE", "{. c #ACACAF", "]. c #B8B8B8", "^. c #ABABAD", "/. c #BCBCBE", "(. c #A9A9AC", "_. c #AAAAAC", ":. c #A9A9AB", "<. c #C0C0C1", "[. c #A3A3A3", "}. c #6B6B6B", "|. c #3B3B3B", "1. c #282828", "2. c #212121", "3. c #1E1E1E", "4. c #232323", "5. c #2B2B2B", "6. c #484848", "7. c #828282", "8. c #A8A8AB", "9. c #9A9A9B", "0. c #5B5B5C", "a. c #0B0B0B", "b. c #000000", "c. c #383838", "d. c #9D9D9D", "e. c #EDEDEE", "f. c #ADADB0", "g. c #A7A7AA", "h. c #7D7D7E", "i. c #131313", "j. c #030303", "k. c #171717", "l. c #A5A5A5", "m. c #878789", "n. c #272727", "o. c #5A5A5A", "p. c #E1E1E2", "q. c #A5A5A9", "r. c #A6A6A9", "s. c #333334", "t. c #1A1A1A", "u. c #A4A4A8", "v. c #A5A5A8", "w. c #A6A6A8", "x. c #A7A7A9", "y. c #AAAAAE", "z. c #ACACAD", "A. c #858587", "B. c #171718", "C. c #353535", "D. c #CCCCCE", "E. c #AFAFB0", "F. c #B0B0B3", "G. c #A3A3A6", "H. c #A4A4A7", "I. c #79797A", "J. c #4B4B4B", "K. c #BFBFC1", "L. c #B6B6B9", "M. c #A9A9AD", "N. c #A3A3A7", "O. c #535354", "P. c #020202", "Q. c #A2A2A6", "R. c #616162", "S. c #3D3D3D", "T. c #A1A1A5", "U. c #A2A2A5", "V. c #585859", "W. c #CDCDCF", "X. c #A1A1A4", "Y. c #A7A7AB", "Z. c #7B7B7D", "`. c #767676", " + c #A0A0A4", ".+ c #9F9FA3", "++ c #89898B", "@+ c #010101", "#+ c #F1F1F2", "$+ c #9F9FA2", "%+ c #9F9FA4", "&+ c #1F1F20", "*+ c #2F2F2F", "=+ c #DCDCDD", "-+ c #9E9EA2", ";+ c #434343", ">+ c #202020", ",+ c #575757", "'+ c #AAAAAA", ")+ c #9D9DA1", "!+ c #9E9EA1", "~+ c #848487", "{+ c #181818", "]+ c #676767", "^+ c #393939", "/+ c #939393", "(+ c #0C0C0C", "_+ c #ECECED", ":+ c #A6A6AA", "<+ c #9C9CA0", "[+ c #9D9DA0", "}+ c #2C2C2C", "|+ c #0D0D0D", "1+ c #727272", "2+ c #464646", "3+ c #B8B8BB", "4+ c #9B9B9F", "5+ c #9C9C9F", "6+ c #6C6C6E", "7+ c #404040", "8+ c #9B9B9E", "9+ c #98989B", "0+ c #414141", "a+ c #242424", "b+ c #C3C3C5", "c+ c #9A9A9D", "d+ c #99999C", "e+ c #7D7D80", "f+ c #0E0E0E", "g+ c #919191", "h+ c #424242", "i+ c #E8E8E9", "j+ c #272728", "k+ c #151515", "l+ c #686868", "m+ c #989898", "n+ c #B2B2B5", "o+ c #97979A", "p+ c #515151", "q+ c #050505", "r+ c #A8A8A8", "s+ c #252525", "t+ c #DADADD", "u+ c #969699", "v+ c #414142", "w+ c #292929", "x+ c #090909", "y+ c #959598", "z+ c #959597", "A+ c #929294", "B+ c #1B1B1B", "C+ c #949497", "D+ c #949496", "E+ c #8C8C8F", "F+ c #0F0F0F", "G+ c #98989C", "H+ c #979799", "I+ c #939396", "J+ c #939395", "K+ c #969698", "L+ c #070707", "M+ c #3F3F3F", "N+ c #CCCCCD", "O+ c #99999D", "P+ c #9A9A9E", "Q+ c #929295", "R+ c #919194", "S+ c #98989A", "T+ c #161616", "U+ c #191919", "V+ c #C6C6C7", "W+ c #9C9C9E", "X+ c #919193", "Y+ c #040404", "Z+ c #222222", "`+ c #555555", " @ c #CECECF", ".@ c #A0A0A3", "+@ c #909092", "@@ c #8F8F91", "#@ c #777778", "$@ c #101010", "%@ c #2A2A2A", "&@ c #919192", "*@ c #8E8E91", "=@ c #8F8F90", "-@ c #626263", ";@ c #0A0A0A", ">@ c #121212", ",@ c #303030", "'@ c #ADADAE", ")@ c #939397", "!@ c #949498", "~@ c #979798", "{@ c #96969A", "]@ c #99999B", "^@ c #8E8E90", "/@ c #8E8E8F", "(@ c #8D8D8F", "_@ c #49494A", ":@ c #141414", "<@ c #1C1C1C", "[@ c #343434", "}@ c #8D8D8E", "|@ c #8C8C8E", "1@ c #8C8C8D", "2@ c #3B3B3C", "3@ c #333333", "4@ c #444444", "5@ c #AAAAAB", "6@ c #89898A", "7@ c #8B8B8D", "8@ c #313131", "9@ c #1D1D1D", "0@ c #323232", "a@ c #7A7A7A", "b@ c #B1B1B1", "c@ c #868689", "d@ c #8B8B8C", "e@ c #A0A0A2", "f@ c #8A8A8B", "g@ c #111111", "h@ c #3E3E3E", "i@ c #454545", "j@ c #494949", "k@ c #838383", "l@ c #9B9B9C", "m@ c #888889", "n@ c #868687", "o@ c #1F1F1F", "p@ c #373737", "q@ c #4E4E4E", "r@ c #535353", "s@ c #505050", "t@ c #626262", "u@ c #959595", "v@ c #808081", "w@ c #848485", "x@ c #868686", "y@ c #8A8A8C", "z@ c #19191A", "A@ c #3C3C3C", "B@ c #474747", "C@ c #4C4C4C", "D@ c #565656", "E@ c #5E5E5E", "F@ c #616161", "G@ c #6E6E6E", "H@ c #787878", "I@ c #797979", "J@ c #7C7C7C", "K@ c #808080", "L@ c #848484", "M@ c #848486", "N@ c #878788", "O@ c #4F4F4F", "P@ c #545454", "Q@ c #585858", "R@ c #5C5C5C", "S@ c #646464", "T@ c #6C6C6C", "U@ c #6F6F6F", "V@ c #757575", "W@ c #7D7D7D", "X@ c #7F7F7F", "Y@ c #838384", "Z@ c #858585", "`@ c #858586", " # c #878787", ".# c #A2A2A4", "+# c #3A3A3A", "@# c #656565", "## c #6D6D6D", "$# c #707070", "%# c #818181", "&# c #909091", "*# c #262626", "=# c #5F5F5F", "-# c #636363", ";# c #666666", "># c #696969", ",# c #737373", "'# c #8D8D90", ")# c #929293", "!# c #060606", "~# c #2E2E2E", "{# c #4A4A4A", "]# c #525252", "^# c #6A6A6A", "/# c #7E7E7E", "(# c #9A9A9C", "_# c #4D4D4D", ":# c #5B5B5B", "<# c #777777", "[# c #828283", "}# c #5D5D5D", "|# c #606060", "1# c #717171", "2# c #818182", "3# c #363636", "4# c #747474", "5# c #7B7B7B", "6# c #8B8B8B", "7# c #595959", "8# c #080808", "9# c #99999A", "0# c #848483", "a# c #939394", "b# c #2D2D2D", "c# c #8F8F8F", "d# c #898989", " ", " . + @ + + # $ $ % & * * = - ; > > , ' ) ! ~ ", " { ] { { ] ^ @ + + # # $ % & * * = - ; > > , ' ) ) ! ~ / ( _ ", " : < [ [ } } { ] ] ^ @ + + . $ $ % & * * = - ; > > , ' ) ! ~ ~ / ( _ | | 1 2 ", " 3 3 4 3 < [ [ } } : { ] ^ @ + + . $ $ % & * * = - ; > > , ' ) ! ~ ~ / ( _ | 1 1 2 5 5 6 ", " 7 7 7 8 4 3 3 [ [ } } : { ] ^ @ + + . # $ % & * * = - ; > > ' ' ) ! ~ ~ / ( _ | 1 1 2 5 6 9 0 0 ", " a b b a a 7 8 8 3 3 < [ } } : { ] ^ @ @ + . # $ % % * * - - ; > > ' ' ) ! ~ ~ ( _ _ | 1 2 2 5 6 9 0 0 c 0 5 ", " 7 d d e e b a 7 7 8 4 3 < [ [ } : : ] ^ ^ @ + . # $ % % * * - - ; > , ' ' ! ! ~ / ( _ _ 1 1 2 5 6 9 9 0 c c c 6 | | ", " e f f g g d e b b 7 7 8 4 3 < < [ } : { { ^ ^ @ + . # $ % % * * - - ; > , ' ' ! ! ~ / ( _ | 1 1 2 5 6 9 0 0 c c c c 6 ( / ~ ", " f h i f g g d e b b a 7 8 4 4 < < [ } } { { ] ^ @ + . # $ % % * * - - ; > , ' ) ! ~ ~ ( ( _ | 1 1 5 5 6 9 0 c c c c c c 5 ~ ) ) ", " i j k h h i f g d d e b a a 7 8 4 3 < [ [ } : { ] ^ @ + . . $ % % * * - - ; > , ' ) ! ~ / / ( | | 1 2 5 5 9 0 0 c c c c c c c 1 ) , > > ", " f j l j k k h i f g g d e b b 7 7 8 4 3 < [ [ } : { ] ^ @ @ . . $ % % * * - - ; > , ' ) ! ~ / / _ | 1 1 2 5 6 9 0 c c c c c c c c c _ > ; - = = ", " j m l l j j k k i f f g g d e b a 7 8 8 3 3 [ [ } } { ] ^ @ @ . . $ % % * * - - ; > , ' ) ! ~ / ( _ | 1 2 2 5 6 9 0 c c c c c c c c c c ) - = * % % ", " m n o m l l j j k h i f g g d e b a 7 7 8 4 3 < [ } : : ] ] @ @ + . $ % % * * - - ; > , ' ) ~ ~ / ( _ | 1 2 5 6 9 0 0 c c c c c c c c c c c , * & $ . # ", " h p q n o m m l l j k h h i f g d d e b a 7 8 4 3 < [ } } : ] ] @ @ + . $ % % * * - - > , , ) ) ~ ~ / _ _ 1 1 2 5 6 9 0 c c c c c c c c c c c c 9 * $ # . + ^ # ", " o p p q n n o m l l j j k h i f f g d e b a 7 7 4 4 < < [ } : { ] ^ @ + # # % % * * - ; > , , ) ! ~ ~ ( ( | 1 1 5 5 9 9 0 c c c c c c c c c c c c c 1 . . + @ ] { { ", " q r r p p q n n o m l l j k k h i f g g e e a 7 7 8 4 3 < [ } : { ] ^ @ + # # % % * * - ; > > ' ) ! ~ ~ ( _ | 1 2 5 6 9 0 0 c c c c c c c c c c c c c c ' . @ ^ { : } } ", " s t s r r p q q n o m m l l j k h i i g g d e b a 7 8 4 3 < [ } : { ] ^ @ + # # % % * * - ; > > ' ) ! ~ / ( _ | 1 2 5 6 9 0 c c c c c c c c c c c c c c c 0 + ^ { { } [ < 4 ", " s u t t s r p p q q n o m l l j j k h i f g d d b a 7 7 8 3 3 [ } } { ] ^ @ + . # % % * * - ; > > ' ) ! ~ / ( | | 1 2 6 6 0 0 c c c c c c c c c c c c c c c c 1 { { } [ < 4 4 4 ", " v v v u t s s r r p q q n o m l l j k h h f f g e e b a 7 8 4 3 < } } { { ^ @ + . # % % * * - ; > > ' ) ! ~ / _ _ 1 2 5 6 9 0 0 c c c c c c c c c c c c c c c c c = } [ < 4 4 7 b b ", " v w v v v u t s s r p p q n o o m l j j k h i f g d e b a 7 8 4 3 < [ } : { ^ ^ + + # % % * * - ; > , ' ! ~ / / _ | 1 2 5 6 9 0 c c c c c c c c c c c c c c c c c c 6 [ < 3 4 7 a b e e ", " x y y w v v v u t s s r p p q n o o l l j k k i i g g d b b 7 7 4 4 < [ } : { ] ^ @ + # % % * * - ; > , ' ! ~ / ( _ 1 1 5 5 9 0 c c c c c c c c c c c c c c c c c c c c ' 4 4 7 a b e g f f ", " w z x y y w v v u u t s s r p p q n o m l l j k h i f g d e b a 7 8 4 3 [ [ : : ] ^ @ + # $ % * * - ; > ' ' ! ~ / ( | | 2 5 6 9 0 c c c c c c c c c c c c c c c c c c c c 0 } 7 a b e g f i h i ", " w z z z x y y w v v u u t s s r p q n n o l l j j h h f f g e e a 7 8 4 3 [ [ } : ] ^ @ + # $ % * * - ; > ' ) ! ~ / ( | 1 2 5 6 0 0 c c c c c c c c c c c c c c c c c c c c c - a b e g f i h k j h ", " r A B B z z x x y w v v u u t s r p p q q o m m l j k h i f g d e b a 7 8 3 < [ } : ] ^ @ + # $ % * = - ; > ' ) ~ ~ ( _ | 1 2 6 9 0 c c c c c c c c c c c c c c c c c c c c c c c a d g f i h k j l m g ", " C D A B B z z x x y w v v u t t s r p p q n o m l l j k h i g g d b a 7 8 4 < [ } : ] ] @ + . $ % * = - ; > ' ) ~ ~ ( _ | 1 5 6 9 0 c c c c c c c c c c c c c c c c c c c c c c c > g f i h k j m o n q ", " A E E F D B B z z x x y w v v u t t s r p p q n o m l j j h h f g d e b 7 7 4 < < } } { ] @ @ . $ % * = - ; > ' ) ~ / ( _ 1 1 5 9 0 c c c c c c c c c c c c c c c c c c c c c c c c 5 d i h j l l o n n p q ", " z G C E E F D B B z z x x y w v v u t t s r p q n o o l l j k h i g g e b a 7 4 4 < [ } { ] @ @ . $ % * = - ; , ' ) ~ / _ | 1 5 5 9 0 c c c c c c c c c c c c c c c c c c c c c c c c c [ k j l m o n q p r t q ", " y H I G J C E E D B B z z x x y w v v u t t s r p p n o m l l j k i f g d e a 7 8 3 < [ } { ] ^ @ . $ % * = ; ; , ) ! ~ / _ | 1 2 6 0 0 c c c c c c c c c c c c c c c c c c c c c c c c c ~ m l o o n q p s t t u n ", " I K H H I J J E E D D B z z x x y w v v u t t r r p q n o m l j k h i g g e b a 7 4 3 [ } : { ^ @ . $ % * = ; ; , ) ! ~ ( _ | 2 5 9 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c f o n q p r s t t v w w ", " F L K M H I I J J E E D A B z z x x y w v v u t s r r p n n m m l j k i f g d b a 7 4 3 [ [ : { ^ @ . $ % * = ; ; , ) ! / ( | 1 2 5 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c . n q p s s t u v y y x u ", " L L L K K M H I G J C E F D B B z x x y w v v u t s r p q q o m l j j h i g g e b 7 8 4 < [ : { ^ @ . $ % * = ; > , ' ! / ( | 1 5 6 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c ~ q p s t u v w y x x z B ", " H N N L L L K K H I G J C E F D B B z z x y y v v u t s r p q n o m l j k h f g d e a 8 4 < [ } : ^ @ + $ % & = ; > , ! ~ / ( | 1 5 6 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c 6 q s t u v w y x z z B B O ", " F P P N N L L L L K K H I G J C E F A B z z x y y v v u t s r p q n o l l k k i f d e a 7 8 3 < } : ] ^ + # % & = ; > ' ! ~ ( _ 1 2 6 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c f u v v y x x z B B D D F Q ", " R S P P P N N L L K K M H I I J C E D A B z z x y y v v u t s r p q o o l j k h f g d b 7 8 3 < } : ] ^ + # % & = ; > ' ! ~ ( _ 1 2 6 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c $ y w y x z B B B D D F E E ", " T U U S S R P P N N L L K K M H I J J E E D B B z x y y v v u t s p p n n m l j h i g g e a 7 4 3 [ } ] ^ + # $ & = ; > ' ! ~ ( | 2 5 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c 6 D x z z B B D D F E C J J Q ", " S V W U U X S P P P N N L L K K H H G J E E D B B z x y y v u u s s p p n o l j k h f g d b 7 4 3 [ } { ^ @ # $ & = ; > ' ! / _ | 2 6 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c u z B B D D D E J J G G I C ", " L Y V V W W U X S R P P N N L L K K H H I J C E D B B z z y y v u u s s p q n o l j k i f d b a 8 4 [ } { ] @ # $ & = ; > ) ~ / _ 1 5 6 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c j B D D F E C C J G I I H H z ", " X Z ` Y Y V V W U U X S P P N N L L K K H I G J E F D B z z y y v v u s r p q o m l j h f g e b 7 4 < [ : ^ @ . $ * = ; , ) ! ( | 1 5 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c 7 D D E C J G G I I H H K K G ", " ...Z Z ` Y V V W U U X S R P P N L L L K M I I J E F A B z z y y v u u s r p q o l j k h g d b 7 8 3 [ : ] @ . $ & = ; , ) / ( 1 1 6 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c { F E C J G I I H M M K K L +. ", " Y @.@.#.#...Z Z Y Y V V W U X S R P P N N L K K H I J J E D B z z x y v v t s r q n m l j h i g e a 8 3 [ } { @ . $ & = > , ! ~ _ 1 2 9 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c # J G G I I H M K K $.L L N N I ", " %.&.&.@.#.#.#.Z Z ` Y Y V W U U S R P P N L L K K H H G C E D A z z x y v u t s r q n m j k i f d b 7 4 < } { ^ + $ & - > , ! / _ 1 5 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c *.I I I H H K K $.L L N N N =.R ", " W -.-.%.%.%.&.@.#.#.#.Z Z Y Y V W W U X S R P N N L L K H I J E D D B z x y v v t r p q n l l k f g e a 8 3 } : ^ + $ & - > ' ! ( | 2 6 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c , I H M K $.L L L N N =.=.P P P H ", " #.-.-.-.-.;.%.%.%.@.#.#.....` >.Y V W U U S P P N N L L K K I ,.C F D B z x y v v t r p n o l k h g d b 7 3 [ : ^ + # & - > ' ~ ( | 2 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c ) K K L L L L N =.N =.P '.P S S L ", " ).!.~.~.{.-.-.-.%.%.%.@.@.#.#...Z ` Y V W W U X R P N L L K K H G J E D B z x y v u t r p n m l k i d e 7 4 [ } ] + # & - > ) ~ _ 1 5 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c ~ ].L L N N N =.P P S S S X X U U ", " X ).).^.!.!.~.~.{.-.-.-.%.%.%. .@.#.#.Z Z Y V V W U S S P N N L K M H J E F B z x y v v t r p o m j h f d a 8 < } ] @ # & - > ) / _ 2 6 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c ~ N N =.=.P P S S S X U U W W W V /. ", " (._.).).).^.!.!.!.~.{.-.-.-.%.%.%.&.#.#...Z ` Y V W W X S P N N L L K I G E E B z y v w x x w t o k h i g b 7 3 [ { @ # & - , ) / | 2 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c ! P P P P S S S X U U W W W V Y Y Y ", " :.(.(.(.(._._.).).^.!.!.~.~.{.-.-.%.%.%.@.#.#...Z ` V V W U S P P N L K K I <.q [.}.|.1.2.3.3.4.5.6.7.o < b a 4 [ : ^ # % - , ! ( | 5 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c ' S S S X X U U W W V Y Y ` ` Z Z Z ", " 8.8.:.(.(.(.(._._.).).^.!.!.~.~.{.-.-.%.%.&.@. .#.Z Z Y V W U X R P N H N 9.0.a.b.b.b.b.b.b.b.b.b.b.b.b.c.d.k 3 < : ^ . % - , ! ( 1 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c e.U X X U U W V V Y Y ` Z Z Z Z .... ", " f.g.g.g.8.8.8.8.:.(.(.(.(._.).).^.!.~.~.{.-.-.-.%.&.@.#.#.Z ` Y V W X H h.i.j.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.k.l.@ } ] . % - ' ~ _ 2 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c $ U W W Y Y Y ` Z Z Z ....#.#.#.#.#.=. ", " {.g.g.g.g.g.8.8.8.8.:.:.(.(.(._.).).^.!.!.~.{.-.-.-.%.%.@. ...Z Y K m.n.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.o.< ^ + % - ' ~ | 5 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c p.Y Y Y ` Z Z Z Z ....#.#.#.@.@.@.@.X ", " q.q.r.r.r.r.r.g.g.g.g.8.8.8.8.:.(.(.(._.).).^.!.~.~.{.-.-.%.%.@.@.s.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.t.8 + % ; ' / 1 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c 7 Z Z Z ....#.#.#.@.@.@.@.@.%.%.%.%.%. ", " u.u.v.v.v.w.q.q.r.r.x.r.r.g.8.g.8.:.:.8.:.(.(._.).y.z.!.{.{.Z A.B.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.C.* % ; ) ( 2 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c D.#...#.#.@.#.@.%.%.E.%.%.%.f.-.-.-.{. ", " F.G.H.u.u.u.u.v.v.v.v.q.r.r.r.r.g.g.g.g.8.8.8.:.(.(.(._.).^.{.I.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.J.= ; ) ( 5 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c K.#.@.@.@.@.%.%.%.%.f.f.-.-.-.-.{.{.~.L. ", " M.G.G.G.N.N.H.H.H.H.u.u.u.u.v.v.v.q.r.r.r.r.g.g.g.8.8.8.:.!.O.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.D ; ) | 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c %.%.%.%.f.-.-.-.-.{.{.{.{.~.~.~.~.!.!.W ", " N.Q.Q.G.G.G.G.G.N.N.H.H.H.H.u.u.u.v.v.v.q.r.r.r.r.g.g.g.).R.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.S.| ~ 2 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c > (.f.-.-.-.{.{.{.{.~.~.~.~.!.!.^.^.^.^.^. ", " G.T.T.T.U.U.U.Q.Q.Q.Q.Q.G.G.G.G.N.N.H.H.H.u.u.u.v.v.q.g.V.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.h ( 6 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c W.).~.~.~.~.!.!.^.^.^.^.).).).).).)._._.^. ", " X.X.X.X.T.T.T.T.T.U.U.U.Q.Q.Q.Q.G.G.G.G.N.H.H.H.H.u.Y.Z.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.`.| 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c ..!.!.^.^.^.^.^.).).).)._._._.(.(.(.(.(.(. ", " +.+ + + + + + + + + + +X.X.T.T.T.T.T.U.U.Q.Q.Q.Q.G.++@+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.|.2 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c #+{.).)._._.(.(.(.(.(.(.:.:.:.8.8.8.8.8.8.(. ", " +.+$+.+.+.+.+.+.+ + + +%+%+.+ + + +X.X.T.T.T.X.X.r.&+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.2.5.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.*+1 c c c c c c c c c c c c c d < c c c c c c c c c c c c c c c c c c c c c c c c =+:.8.8.(.:.:.:.8.8.8.8.Y.Y.Y.8.8.8.8.g.g.8. ", " .+-+-+-+-+-+-+$+$+$+$+$+.+.+.+.+.+.+.+.+.+.+.+ +u.;+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.>+[ c c c ,+b.b.b.b.b.b.b.b.b.b.b.b.b.*+6 c c c c c c c c c c c '+@+b.b.3.} c c c c c c c c c c c c c c c c c c c c c c =.8.8.8.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.g.8. ", " -+)+)+)+)+)+)+)+)+)+)+)+!+!+!+!+!+!+-+-+-+-+-+-+~+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.{+/ c c c c c ]+b.b.b.b.b.b.b.b.b.b.b.b.^+c c c c c c c c c c c /+b.b.b.b.b.(+* c c c c c c c c c c c c c c c c c c c c _+U.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.:+ ", " <+<+[+[+[+[+[+[+[+[+[+[+[+)+)+)+)+)+)+)+)+)+)+Q.}+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.x c c c c c c c |+b.b.b.b.b.b.b.b.b.b.b.1+c c c c c c c c c c > b.b.b.b.b.b.b.2+c c c c c c c c c c c c c c c c c c c c 3+v.r.r.r.q.q.q.q.q.q.q.q.q.v.v.v.v.v.v.v.v.v. ", " 4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+5+5+5+5+5+)+6+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.0 c c c c c c c 7+b.b.b.b.b.b.b.b.b.b.b.{ c c c c c c c c c c J b.b.b.b.b.b.b.P.c c c c c c c c c c c c c c c c c c c / x.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H.H. ", " 8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+9+i.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.9 c c c c c c c 0+b.b.b.b.b.b.b.b.b.b.a+c c c c c c c c c c c D b.b.b.b.b.b.b.P.9 c c c c c c c c c c c c c c c c c c b+Q.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N. ", " c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+d+d+d+e+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.I c c c c c c c f+b.b.b.b.b.b.b.b.b.b.g+c c c c c c c c c c c ) b.b.b.b.b.b.b.h+c c c c c c c c c c c c c c c c c c i+$+U.U.U.U.U.U.U.U.U.U.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q. ", " c+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+X.j+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.k+~ c c c c c l+b.b.b.b.b.b.b.b.b.b.b.r c c c c c c c c c c c c m+b.b.b.b.b.(+& c c c c c c c c c c c c c c c c c c n+T.T.T.T.T.T.T.T.T.T.T.T.U.U.U.U.U.U.U.U.U.U.U.Q. ", " d+9+9+9+9+9+9+9+9+9+9+9+9+9+o+o+o+o+o+o+o+A.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.>+: c c 0 p+b.b.b.b.b.b.b.b.b.b.b.q+i c c c c c c c c c c c c c r+b.b.b.s+] c c c c c c c c c c c c c c c c c c t+)+.+.+.+.+ + + + + + + + + + + + + +X.X.X.X.X.X.U. ", " d+o+o+9+9+o+o+o+o+o+u+u+u+u+o+o+o+u+u+u+u+v+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.2.w+b.b.b.b.b.b.b.b.b.b.b.b.b.x+f c c c c c c c c c c c c c c c e : c c c c c c c c c c c c c c c c c c c ; 4+)+)+-+-+.+-+-+-+-+-+.+.+.+ + + + +.+.+.+.+ + + +T. ", " 9+o+o+u+u+u+u+u+u+u+u+u+u+y+y+y+y+y+y+z+A+B+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.(+r c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c 0 &.<+[+[+[+[+)+)+)+)+-+-+-+-+-+-+-+-+-+.+.+.+.+.+.+.+ + ", " u+u+y+y+y+y+y+y+z+z+z+z+z+C+C+D+D+D+D+D+E+@+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.F+/+c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c +.G+8+8+8+4+4+5+5+5+<+<+[+[+[+[+)+)+)+)+)+)+-+-+-+-+-+.+ ", " H+y+z+z+z+z+z+z+C+C+D+D+D+D+D+I+I+J+J+K+R.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.L+i.M+c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c N+9+O+c+c+P+8+8+8+8+4+5+5+5+5+<+<+[+[+[+[+[+)+)+)+)+)+)+-+ ", " y+C+D+D+D+D+D+I+I+J+J+J+J+Q+A+A+A+A+R+S+n.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+a.T+U+q c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c V+u+9+9+9+9+d+d+d+O+c+c+c+P+P+8+8+8+4+4+4+5+5+5+5+<+<+<+[+!+ ", " W+J+I+I+I+J+J+J+J+Q+Q+A+A+A+R+R+X+X+X+z+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.Y+f+k.Z+`+0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c @C+u+H+o+o+9+9+9+9+d+d+d+O+O+c+c+c+P+8+8+8+8+4+4+4+5+5+5+8+H. ", " .@A+Q+Q+A+A+A+R+R+X+X+X++@+@+@+@+@+@@@#@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+L+$@t.4.%@B c c c c c c c c c c c c c c c c c c c c c c c c c c c c c P I+C+C+y+y+K+u+u+H+o+o+9+9+9+9+9+d+d+d+O+O+c+c+c+P+P+P+8+8+8+g. ", " X+A+A+R+R+X+&@&@X++@+@+@+@+@@@@@*@=@-@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.;@>@t.4.}+,@f c c c c c c c c c c c c c c c c c c c c c c c c c c #+'@@@J+Q+I+)@C+z+!@y+u+u+~@H+{@o+9+9+9+9+9+]@]@9+d+O+O+c+c+c+P+O+ ", " X+X++@+@+@+@+@+@+@@@@@@@=@^@^@/@/@(@_@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.q+(+:@<@a+}+[@h+& c c c c c c c c c c c c c c c c c c c c c c c c p.+@+@X+X+A+A+J+J+I+D+C+C+z+y+y+K+u+u+H+H+o+o+9+9+9+9+9+9+d+d+d+d+O+ ", " H++@+@+@@@@@@@=@^@^@^@/@(@(@}@|@|@1@2@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+L+f+k+<@a+5.3@^+4@'.c c c c c c c c c c c c c c c c c c c c c $ 5@6@/@^@@@@@+@+@X+X+A+A+J+J+I+D+C+C+z+y+y+y+K+u+u+H+H+o+o+9+9+9+9+9+.@ ", " S+@@@@@@=@=@^@^@/@(@(@(@}@|@|@1@1@7@8@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.x+F+k.9@s+5.0@^+7+7+a@- c c c c c c c c c c c c c c c c 9 ~ b@c@d@1@|@(@^@^@@@@@+@+@X+A+A+A+J+J+I+D+C+C+z+z+y+y+K+u+u+H+H+o+o+o+9+9+e@ ", " ^@^@^@/@(@(@(@}@|@|@1@7@7@d@d@f@d@a+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.q+a.g@{+3.s+5.8@c.h@i@j@,+k@d c c c c c c c c c c c c 2 t l@m@n@6@++f@d@7@|@(@(@^@^@@@@@+@+@X+X+A+A+A+J+J+I+I+C+C+C+y+y+y+K+u+u+u+H+H+ ", " /@(@(@(@}@|@|@|@1@7@7@d@d@f@f@f@f@B+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.L+|+>@U+o@s+5.8@p@h@;+j@q@r@s@t@d.n : . & * % @ a M u@I.v@w@x@n@m@m@6@++y@d@1@}@(@/@^@@@@@+@+@+@X+X+A+A+A+J+J+I+I+C+C+C+z+y+y+y+K+u+u+ ", " E+}@|@|@1@7@7@d@d@d@f@f@6@6@6@m@6@z@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.Y+x+f+:@U+o@s+5.,@p@A@h+B@C@p+D@o.E@F@l+G@1+`.H@I@I@J@K@K@7.k@L@M@x@N@N@m@6@f@f@d@1@|@(@(@^@^@@@@@+@+@+@X+X+A+A+A+J+J+I+I+D+D+C+C+z+y+u+ ", " l@7@1@7@7@d@d@d@f@f@6@6@6@6@m@m@m@U+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+q+;@$@:@t.>+s+5.,@C.|.7+i@J.O@P@Q@R@F@S@l+T@U@1+V@H@a@W@X@K@7.Y@L@Z@`@ #N@m@6@++++d@7@1@}@(@/@^@^@@@@@+@+@X+X+X+A+A+A+J+J+I+I+I+D+C+I+.# ", " y@d@d@f@f@f@6@6@6@m@m@m@N@N@n@N@U+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.L+(+g@T+B+2.s+5.*+C.+#M+;+j@q@p+D@o.E@t@@#l+##$#1+V@H@a@J@K@K@%#7.Y@L@`@n@n@m@m@6@6@f@d@d@1@1@(@(@/@^@^@@@@@+@+@+@X+X+A+A+A+A+J+J+I+Q+ ", " &#f@f@6@6@6@m@m@m@m@N@N@n@x@n@ #t.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.Y+x+|+>@k.<@>+*#5.,@[@^+h@;+B@J.s@P@Q@R@=#-#;#>###$#,#V@H@a@J@X@K@%#7.k@L@w@x@n@N@N@6@6@++y@y@7@7@1@|@(@'#^@*@^@@@@@+@X++@X+X+A+A+A+A+S+ ", " )#6@6@6@m@m@m@N@N@n@n@n@x@`@`@`@>+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.!#;@F+>@{+<@>+*#5.~#[@^+S.0+i@{#q@]#D@o.E@F@S@]+^#G@$#,#V@H@a@J@/#K@%#7.k@L@w@`@x@N@N@m@m@6@f@f@d@d@1@1@}@(@/@^@^@@@@@@@+@+@X+X+X+X+A+(# ", " m@m@m@N@N@N@n@n@n@`@Z@Z@L@L@L@}+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.L+a.F+:@{+9@2.*#5.*+3@p@A@7+i@j@_#s@P@Q@:#=#t@@#l+}.G@$#,#V@<#a@J@/#K@%#%#[#k@L@w@`@n@N@N@m@6@6@++y@d@7@1@1@|@(@(@/@^@^@@@@@@@+@+@X++@ ", " }@N@N@N@n@n@x@x@`@Z@w@L@Y@k@[#p@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+q+x+(+g@:@U+9@2.*#5.*+3@p@|.M+4@B@J.O@r@D@o.}#|#-#;#>#T@U@1#,#V@<#a@J@/#K@K@%#[#Y@L@w@`@n@n@N@m@m@6@++f@y@d@1@1@|@}@(@/@^@^@^@@@@@+@+@K+ ", " n@n@n@x@`@`@w@L@L@k@k@[#7.2#h@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.!#x+f+>@k+U+3.Z+*#%@*+0@3#|.h@;+2+{#q@p+P@Q@:#E@F@S@]+>#T@G@1#4#V@<#a@5#W@X@K@%#7.[#Y@L@Z@`@n@N@N@m@m@6@++f@y@d@7@1@1@|@(@(@/@^@^@@@^@ ", " 6#n@`@`@Z@w@L@Y@k@k@[#7.%#%#`+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.Y+L+a.F+i.T+t.3.Z+*#%@~#0@3#+#h@0+i@j@C@O@r@D@7#}#=#t@@#]+^###U@1#4#V@<#a@5#W@X@K@%#7.k@Y@w@w@`@x@n@N@m@m@6@6@++f@d@d@1@1@|@}@(@(@^@^@A+ ", " &#w@w@L@L@Y@k@[#7.2#%#%#K@K@t@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+q+8#a.$@i.k.B+o@Z+*#%@~#0@3#^+A@7+4@6.J.O@p+P@Q@o.E@F@-#;#l+}.##U@1#4#V@<#a@5#W@/#K@K@%#[#k@L@w@Z@`@n@n@N@m@m@6@6@f@f@y@d@7@1@1@}@(@E+9# ", " #L@Y@k@k@[#7.%#%#%#K@X@W@5#b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.!#x+|+$@:@{+B+o@Z+*#%@~#8@C.c.A@7+;+2+{#_#p+P@D@7#R@=#F@S@;#>#}.G@$#1#4#`.<#a@5#W@X@K@K@%#[#k@0#L@Z@`@x@N@N@m@m@6@6@++f@y@d@d@1@1@1@=@ ", " a#k@k@7.7.2#%#%#K@K@/#5#a@/#|+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+Y+L+;@f+g@k+{+B+o@Z+*#%@~#8@[@c.|.M+h+2+j@C@O@]#`+Q@o.}#|#t@@#l+>#T@##1#1+4#`.<#a@5#W@/#K@K@%#7.[#Y@L@w@Z@`@x@N@N@m@m@6@6@6@f@y@d@d@7@l@ ", " L@7.%#%#%#K@K@X@J@5#I@<#H@c.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.q+8#a.F+>@k+U+<@o@4.*#%@b#8@[@p@|.h@0+i@6.{#q@s@P@,+7#R@E@F@-#@#l+^###G@$#1+4#<#<#a@5#W@/#K@K@%#%#[#k@Y@w@w@`@`@n@n@N@N@m@6@6@++f@f@1@ ", " =@K@%#K@K@X@W@J@a@H@V@4#1#S@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.!#x+(+$@i.T+U+<@>+4.*#%@b#8@[@p@+#S.7+4@B@{#_#O@]#`+Q@o.}#=#t@S@;#>#^###G@1#1+4#<#<#a@5#J@/#K@K@%#7.7.k@Y@L@w@`@x@n@N@N@m@m@6@6@6@6@~@ ", " #K@K@/#J@a@H@`.V@1+1#G@>#;@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.Y+L+;@|+$@i.k.t.9@>+4.*#%@b#,@3@3#^+S.7+;+2+j@J.q@p+r@,+7#:#E@|#-#S@]+>#}.##U@1#1+4#<#<#a@5#J@/#X@K@%#%#7.[#k@L@w@Z@`@x@n@N@N@m@m@m@=@ ", " X@W@5#a@<#`.4#1+$###}.l+t.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.q+8#;@f+g@:@k.t.9@>+4.*#%@b#,@3@3#^+A@M+h+i@6.J._#s@r@`+Q@:#}#=#F@-#@#]+>#T@G@U@1#,#4#<#<#I@5#J@W@X@K@K@%#7.k@k@L@L@w@`@`@n@n@N@N@m@ ", " L@a@H@<#V@,#1#U@##^#l+;#|.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+Y+!#x+(+f+>@k+{+t.9@>+4.*#%@b#,@3@3#c.|.h@h+4@B@{#C@O@p+P@,+7#:#}#|#t@S@;#l+}.T@G@U@1+1+V@`.<#I@5#J@W@X@K@K@%#%#[#k@Y@L@w@w@`@`@n@n@c# ", " a@`.4#1+$#G@T@>#l+;#-#}#b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.Y+L+x+|+F+i.k+{+B+9@2.4.*#%@b#,@0@C.c.|.S.7+;+2+j@J.q@s@r@`+Q@o.}#E@F@t@@#]+l+}.T@G@$#1+,#V@<#<#I@5#J@W@X@K@K@%#%#7.k@Y@L@w@Z@`@x@m@ ", " Z@,#1#$###T@>#]+S@-#F@F@Z+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+j.!#8#a.|+$@i.T+{+B+3.2.4.*#%@}+*+0@C.p@+#S.7+;+i@6.{#_#O@]#P@,+Q@:#E@=#F@-#@#]+>#}.##G@$#1+,#V@`.<#I@5#J@W@/#K@K@K@%#7.[#k@Y@L@w@Z@a# ", " a@G@T@^#l+]+S@t@|#}#:#{#b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+Y+!#x+a.f+$@i.T+U+<@3.2.a+*#%@}+*+0@C.p@+#A@M+h+4@B@{#C@O@p+r@`+Q@7#R@E@|#t@S@;#]+>#T@##U@$#1+,#V@<#<#I@a@J@W@/#X@K@K@%#7.7.k@k@Y@}@ ", " 1#^#l+;#-#t@=#}#:#Q@r@;@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.q+L+;@(+F+g@:@k.U+<@3.2.a+n.%@}+*+8@[@p@^+A@M+0+4@2+j@J._#s@]#P@,+7#o.}#=#|#-#S@]+l+^#T@##U@$#1+,#V@<#<#I@a@J@W@/#X@K@%#%#7.7.k@ # ", " @#@#-#t@=#}#o.Q@`+P@}+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+j.q+8#;@|+F+>@k+k.t.<@o@2.a+n.%@}+*+8@[@3#^+|.h@7+;+2+6.{#_#O@p+r@`+Q@o.:#E@|#t@-#@#]+l+^#T@##U@1#1+,#V@`.<#I@a@J@J@/#X@K@K@%#%#v@ ", " W@-#F@E@R@o.Q@`+r@p+,+@+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.Y+L+x+a.|+$@>@k+k.t.<@o@Z+a+n.%@}+*+8@3@3#^+|.h@7+;+4@B@{#C@q@s@r@P@,+Q@:#}#E@F@t@S@;#l+>#}.####$#1#1+,#V@<#<#I@a@J@J@/#X@K@K@%#u@ ", " }.}#}#o.Q@`+r@s@q@J.8@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+j.q+L+x+(+f+g@i.k+{+t.<@o@Z+a+n.%@}+~#8@3@3#c.|.S.M+h+4@2+j@{#q@O@p+P@D@Q@7#R@}#=#F@-#@#;#l+>#}.T@G@$#1#1+4#V@`.<#I@a@J@J@/#/#X@d# ", " @#7#,+`+r@s@q@C@j@4@j.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+Y+!#8#;@(+f+g@i.T+{+B+9@o@Z+a+n.%@}+~#8@3@C.p@+#S.M+0+;+2+6.{#C@q@s@r@`+,+7#:#R@E@|#t@-#@#]+l+^#T@##G@$#1#1+4#V@<#<#I@a@5#J@/#x@ ", " o.`+r@s@q@J.j@B@i@~#b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.Y+L+8#a.f+F+>@i.k.U+B+9@>+2.a+n.w+}+~#,@3@C.p@+#A@h@7+;+i@B@j@C@_#s@]#P@D@Q@7#:#}#=#|#-#S@;#]+>#^#T@##U@$#1#,#4#`.`.<#I@a@5#/# ", " 7#s@q@C@j@B@4@0+i@F+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+j.q+L+x+a.|+$@>@:@k.U+B+9@>+Z+a+n.w+}+~#,@0@C.p@^+A@h@7+h+i@2+j@J._#O@p+r@`+,+7#o.R@E@|#F@t@S@;#]+>#^#T@##U@1#1#,#4#V@`.<#I@X@ ", " O@C@j@B@i@0+M+A@*+b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.@+Y+!#8#;@(+f+$@i.k+k.U+<@3.>+Z+a+n.w+}+~#,@0@C.p@^+|.S.7+0+4@2+6.{#C@q@s@]#r@D@Q@7#:#}#E@F@t@S@@#]+l+^#}.T@G@U@1#1#,#4#`.`.H@ ", " s@B@i@h+7+S.|.|.t.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.j.Y+!#8#;@|+F+g@i.k+{+U+<@3.>+4.a+n.w+}+b#,@0@[@p@c.|.S.M+0+;+i@B@{#J.q@O@p+r@P@,+Q@o.R@}#=#|#t@S@@#]+l+^#}.####U@1#1+,#4#5# ", " 2+h+7+h@+#^+C.p@8#b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.j.!#L+x+(+|+F+g@:@k+{+t.<@3.2.4.a+n.w+}+b#,@0@[@3#c.|.A@M+7+;+i@B@j@{#_#q@p+]#P@D@Q@7#:#}#E@|#F@-#@#;#l+l+^#}.##G@U@1#1+V@ ", " {#S.|.^+3#[@,@5.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.P.Y+!#8#;@(+f+F+>@:@T+{+t.<@3.2.4.s+n.w+5.b#,@8@3@3#c.+#A@h@7+h+i@2+6.j@C@q@O@]#r@`+,+Q@o.:#E@E@|#t@-#@#;#l+>#}.T@##U@G@I@ ", " j@^+3#[@8@*+*+<@b.b.b.b.b.b.b.b.b.b.b.b.b.@+j.Y+L+8#a.(+f+g@>@:@T+{+t.9@3.2.4.s+n.w+5.b#,@0@3@3#p@+#A@h@M+h+;+i@B@j@C@_#O@s@r@r@D@Q@7#:#R@E@|#F@-#S@@#]+l+>#}.T@##a@ ", " D@0@8@,@}+%@w+x+b.b.b.b.b.b.b.b.b.b.b.b.P.Y+q+L+x+a.|+F+g@i.k+k.U+B+9@3.2.4.s+n.w+5.b#*+0@3@3#p@+#|.S.7+0+;+i@B@j@{#_#q@s@p+P@P@,+Q@o.R@}#=#|#t@-#S@;#]+l+^#^#k@ ", " 3#}+5.1.s+5.!#b.b.b.b.b.b.b.b.b.b.@+P.Y+!#8#x+a.|+F+g@i.k+k.U+B+9@o@2.4.s+n.w+5.b#*+,@3@C.p@^+|.S.M+7+;+4@2+6.{#J.q@O@p+]#P@D@Q@7#o.}#E@=#|#t@-#@#]+;#G@ ", " +#w+*#a+>+4.P.b.b.b.b.b.b.b.b.b.@+j.q+!#x+;@(+|+$@>@i.T+k.t.B+9@>+2.4.s+n.w+5.b#*+,@3@C.3#^++#S.h@7+h+4@2+6.j@J._#O@s@]#r@`+,+Q@7#:#}#E@|#F@-#-#@#1+ ", " 7+1.>+o@9@9@@+b.b.b.b.b.b.b.b.P.Y+q+L+x+a.|+f+$@>@:@T+k.t.B+9@>+2.4.s+n.w+5.b#*+,@3@C.3#c.+#A@h@7+0+4@i@B@j@{#C@q@O@p+r@P@D@Q@7#:#R@E@=#|#F@;#<# ", " ~#9@t.T+U+b.b.b.b.b.b.b.@+j.Y+!#8#x+a.|+F+$@i.:@T+{+t.B+9@>+2.4.s+n.w+5.b#*+8@0@[@3#c.+#A@S.M+0+;+i@2+j@j@C@_#O@s@]#P@`+,+7#7#:#}#E@=#T@ ", " a+:@:@t.b.b.b.b.b.b.P.Y+q+L+8#;@a.f+F+g@>@k+k.{+t.<@3.>+2.4.s+n.w+5.b#~#8@0@[@3#c.^+|.S.M+0+h+4@2+B@{#{#_#q@s@p+r@P@D@Q@7#o.o.;# ", " b#k+|+:@b.b.b.b.b.j.j.!#L+x+;@(+f+F+>@i.k+k.{+t.<@3.>+Z+4.s+n.w+5.}+~#8@0@[@C.c.^+|.A@M+7+h+4@i@B@j@{#C@q@q@p+r@r@`+D@Q@R@G@ ", " ~#$@k+@+b.b.@+j.Y+!#8#x+a.|+f+$@>@:@k+k.{+B+<@3.>+Z+a+s+n.w+5.}+~#8@8@[@C.p@^+|.S.h@7+0+4@4@B@6.{#J._#O@O@p+P@r@o.U@ ", " 9@<@@+b.P.j.q+!#x+;@(+|+F+g@>@:@k+{+U+B+<@3.>+Z+a+s+n.w+5.}+~#,@8@[@C.p@^++#A@h@7+0+;+4@2+6.j@J.C@q@O@s@7#S@ ", " (+@+Y+q+L+x+;@(+|+F+g@i.:@T+{+U+B+<@o@>+Z+a+s+n.w+5.}+~#,@8@3@C.p@c.+#|.S.M+7+h+4@i@B@j@{#C@C@,+ ", " k.>@L+8#a.|+f+$@g@i.k+T+{+U+<@9@o@>+Z+a+*#n.w+5.}+~#,@8@3@C.3#c.+#|.S.M+7+h+4@i@i@B@]#Q@ ", " 1.a.|+f+$@g@i.:@k.{+t.<@9@o@>+Z+a+*#n.w+5.}+~#,@8@3@C.3#c.+#|.S.M+7+h+4@i@E@ ", " 4.4.i.:@T+k.t.<@9@o@>+Z+a+*#n.w+5.}+~#,@8@3@[@3#3#c.^+S.J.s@ ", " C.}+<@o@o@Z+a+s+s+n.n.w+5.~#,@3@3@[@p@p@j@s@ ", " "}; ================================================ FILE: liteidex/deploy/welcome/zh_CN/LGPL_EXCEPTION.TXT ================================================ LiteIDE is distributed under the terms of the LGPLv2.1 license with an exception: License exception: In addition, as a special exception, that plugins developed for LiteIDE, are allowed to remain closed sourced and can be distributed under any license . ================================================ FILE: liteidex/deploy/welcome/zh_CN/LICENSE.LGPL ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: liteidex/deploy/welcome/zh_CN/changes.md ================================================ ## LiteIDE X Version LiteIDE is a simple, open source, cross-platform Go IDE. ### 2025.5.20 Ver X38.4 * LiteIDE * support Go1.24 * LiteFind * fix FindFilesThread stop ### 2023.08.14 Ver X38.3 * LiteIDE * support Go1.21 * LiteEnv * support Go1.21 `go env` * LiteFind * support enter on directory searches * Terminal * fix source for not bash ### 2023.02.14 Ver X38.2 * LiteIDE * fix and update gotools & gocode * refactor astview outline * update dlv debugger plugin * GolangAst * new outline view by pos * support typeparams * LiteDebug * add disassemble view * DlvDebugger * fix generics func sync * fix dlv process exit on windows * refactor gorountines model * support disassemble model * LiteBuild * gosrc.xml TARGETNAME use BUILD_DIR_PATH * GolangEdit * support any and comparable * GolangCode * support any and comparable * gotools * types fix find obj field * types fix object string * gotest fix run test file use -run mode * astview add new -outline for outline * astview add new -tp for typeparams * astview fix interface embedded type * gocode * fix identifier comparable * update lookup object ### 2023.01.22 Ver X38.1 * LiteIDE * gotools & gocode support Go1.18 generics * support build for windows vs2019 * support build for freebsd/openbsd * fix memory leak * GolangCode * support Go1.18 generics * remove options and default set * uncheck GOPATH for set-lib * LiteEnv * fix memory leak * filter go env * LiteBuild * fix memory leak * fix buildconfigdialog twice accept * LiteEditor * fix selection navigation saved * check backspace empty completion unpopup * GolangEdit * update actions for GO111MODULE * GolangPlay * load depends * Bookmarks * fix memory leak * Terminal * libterm fix build for vs2019 * add option for set font * ptyqt use conptyprocess for vs2019 * ptyqt fix unixptyprocess for freebsd/openbsd * gotools * types support generics method lookup * gocode * support generics type autocomplete * support incomplete dep autocomplete ### 2022.05.22 Ver X38.0 * LiteIDE * support Go1.18 go.work * support Go1.18 format/types/gocode * LiteApp & LiteEditor * add 'Detroit Future' theme (thanks donuts-are-good) * LiteEditor * add go.work syntax * add color/dart-blue.xml (thanks qAison) * LiteBuild * only check first run action and output * update GoPlus config * LiteEnv * windows env use %PROGRAMFILES%\Go * Terminal * fix copy text containing tab in terminal * add context menu copy/paste/selectall * gotools * support Go1.18 format * support Go1.18 types * support go.work * gocode * support Go1.18 code completer * support go.work * update unsafe pkg * fix gomod imports completer ### 2021.03.02 Ver X37.4 * LiteIDE * move to trash use api on macos * fix find&replace repaint * update terminal action * add copy fullpath action * LiteApp * editor context menu add integrated terminal action * folder view update integrated terminal action * folder view add copy full path action * move to trash use api on macos * LiteFind * fix find&replace editor repaint * fix file search replace repaint * windows fileserach shortcuts add ctrl+atl+f * LiteEditor: * gomod.xml add retract * Terminal: * move to core plugin * DlvDebugger: * add pass flags options ### 2020.10.10 Ver X37.3 * LiteIDE * fix dlv debug exit crash on window * support mingw-64 build for window * LiteApp * update icon for hight-dpi * LiteBuild: * gosrc.xml add tool cover html command * gosrc.xml add make command * LiteEditor: * add dark-gray.xml color scheme, thanks for qAison * fix showlink tooltip bug for Qt5.12 * GolangEdit: * add find usages skip tests action * Terminal: * fix winpty load for Q_OS_WIN64 * add closeall action * DlvDebugger * fix exit crash on window * fix handle response regexp * gotools & gocode * update fastmod for go1.14 GOMOD * gotools * types add skip tests flag ### 2020.04.24 Ver X37.1 * LiteIDE * add new integrated terminal plugin * change LiteApi, IToolWindowManager and IFileManager api * Terminal: * new terminal plugin * export open in integrated terminal action * support open multiple shells (/etc/shells) on unix * support open cmd/powershell/git bash on window * support dark mode * support login mode --login (unix) * load enviroment from LiteIDE action (unix) * tab style multiple terminal * auto save / restore terminal info * ctrl+c key interrupt support * mouse to select, enter key copy to clipboard (ctrl+c/command+c) * ctrl+v / command+v to paste from clipboard * LiteApp * folder add open integrated terminal action * update hide tool window action icon. * folder view enable create folder in files * fix SideWindowStyle::moveToolWindow crash * fix #1106, options widget add ScrollArea, enable resize, init check screen size * LiteEditor * change copy/paste/cut/selectall/undo/redo unregister shortcut for macos * FileBorwser: * add open integrated terminal action * enable create folder in files * simple, remove litefind/terminal depends * LiteFind * SearchResultWidget add expandAll and collapseAll button * GolangEdit * fix fold by GO_ELSE * gotools & gocode * fix & update for Go 1.14 ### 2020.01.15 Ver X36.3 * LiteIDE * fix and update gotools&gocode for support Go Module. * refactor option, update all plugin option page * LiteApp * refactor option page, load/save and keep option page. * LiteEditor * fix code complete escape for Qt5.12 * Markdown * add CommonMark/cmark for markdown to html, replace sundown * GolangPackage * add GOPRIVATE,GONOPROXY,GONOSUMDB option * add goproxy.cn for GOPROXY list * merge GOPATH/GoModule setup to global options. * LiteBuild * add `go mod vendor` action * DlvDebugger * update stack frame to RPC api * gotools & gocode * fix fastmod match full version, example `github.com/mypkg/v2` * types check add basic type ### 2019.10.30 Ver X36.2 * LiteIDE * add new image viewer plugin * folder view support multi copy & paste * folder view support move to trash * fix gocode crash * update uk (Ukrainian) translation, thanks for cl0ne * LiteApp * fix floating dock widet style * add dock widget floating toolbar * folder view support multi copy and paste * folder view support move to trash action * ImageEditor * add new image viewer plugin * support image viewer and gif video play * GolangEdit * support go1.13 number literal syntax highlight * gotools & gocode * fix bad parser crash ### 2019.08.28 Ver X36.1 * LiteIDE * folder view support copy and paste * fix find usages and declinfo for _ start symbol * LiteApp * multi folder view support copy and parse * tool window support floating window action * LiteEditor * cached text layout, optimization long line paint * check and disable document too long line ( > 4096) syntax. * GolangEdit * fix findusage and declinfo for _ start symbol * GolangPackage * add custom GOPROXY setup * update GO111MODULE env reload check * GolangDoc * remove godoc command, use gotools godoc * FileBorwser * folder view support copy and paste * Others * linux env add x-terminal-emulator * update Russian translation, thanks Sergey Belyashov * gotools & gocode * fix mod priority vendor check * gotools * godoc add go doc -all flags ### 2019.03.15 Ver X36 * LiteIDE * add new editor path navigation toolbar * QuickOpen * quickopenfile filter text length less than 3 use editor files, otherwise search in folder files. * add new quickfilesystem filter * GolangEdit * use new quickfilesystem for import jump * LiteEditor * add new path navigation toolbar (use quickfilesystem) * GolangCode * fix number+dot issues completer * FileUtil * show in Finder fast on macOS ### 2019.02.05 Ver X35.5 * LiteIDE * bug fix version * GolangEdit * fix cursor selections usages lookup * add byteOffsetToColumn to fix gotools/guru output byte offset to editor offset * LiteEditor * add allow vertical scrolling to the last line option * check file writed size != data.size and show error message * LiteFind * update search result item text for all same linenumber ### 2019.01.30 Ver X35.4 * LiteIDE * source code navigation can be used in wrong source code * imports completer support gomod depends and local imports for gomod project * imports completer support lookup all imports by source for GOPATH project * LiteApp * fix vs-dark.qss menu icon bug for windows10 * LiteEditor * fuzzy golang imports completer * fix complter imports offset * fix enter auto insert tab or space check by previous line * GolangCode * fix receive imports line process * GolangEdit * support lookup types info wrong source code * add jump to declaration toolbar * fix jump to declaration save history * gotools & gocode * source code navigation can be used in wrong source code * lookup gomod depends and local imports for gomod project * lookup all imports from source for GOPATH project ### 2018.12.22 Ver X35.3 * LiteIDE * optimization gotools & gocode, update editor and find plugin. * LiteApp * fix liteoutput antialias setup invalid * LiteEditor * enable vertical scrollbar move last block to top viewport * add the cut current line operator for cut action if not selected * add convert tab/spaces action * add tabtospace/tabwidth set by litapp/mimetype/liteeditor.xml or options * update line wrap mode for mimetype * update tabtospace mode for mimetype * LiteFind * file search check and skip binary file * add folders/filesystem context menu file search action * GolangEdit, GolangCode, LiteBuild * fix process start with cmd contains space on macOS * GolangDoc * support check go1.12 godoc remove -html, use text mode * gotools & gocode * fix lookup named method embedded * optimization, check save/load pkgconfig * add godoc command for check go1.12 use text mode * gocode * fixed global var completion ### 2018.11.12 Ver X35.2 * LiteIDE * fixed types info jump position * optimization types info lookup cache * LiteEditor * single line comment set after white spaces and add space * go.mod editor support comment action * color scheme support MatchBrackets background, default gray #808080 * Bookmarks * sort bookmark model by name/line, add context menu goto/remove/removeThisFile/removeAllFiles action * GolangDoc * fix mod package godoc import path view * GolangEdit * fix lookup types info by gocode cache * gotools & gocode * fixed types jump info position * optimization types info lookup cache ### 2018.10.24 Ver X35.1 * LiteIDE * BUG fixed, gocode code jump and import line jump * GolangEdit * fix jump def for import line * gotools & gocode * fix types jump ### 2018.10.24 Ver X35 * LiteIDE * all support Go1.11 Go modules * fast lookup types info by cache * fix delve debug recurse set blocking * LiteApp * side window style enable move tool window to any left/right/bottom side. * side window style output bar shortcut change to command+meta+number (macos) or ctrl+shift+number * GolangEdit * fast lookup types info by gocode cache * find all usages support Go modules work dir * refactor symbol support Go module work dir * GolangAst * support import path gopath/vendor/modules doc view * LiteDebug * add automatically add breakpoint main.main when debugging option (default disable) * DlvDebugger * fix dlv list variables blocking, change LoadConfig recurse to 3 * LiteBuild * update gosrc.xml for support custom target workdir * gotools & gocode * import https://github/visualfc/fastmod for fast parse go.mod depends * fast parse Go modules and fix issues https://github.com/visualfc/liteide/issues/986 * gotools * find all usages support Go module work dir * gotools * fast completer for Go module project * provide types info for liteide by cache ### 2018.10.05 Ver X34.3 * LiteIDE * fix support go1.11 modules * GolangEdit * fix jump import line * fix find usages for import line * LiteEditor * fix gocode completer item kind update * GolangCode * enviroment changed to reset gocode * gotools & gocode * types: fix module-based project with several subpackages https://github.com/visualfc/liteide/issues/977 * types: fix redeclared file parser cursor first * types: fix source file update check in stdin * types: fix x test files check * gomod: fix lookup module for go list * gocode * fix gocode crash https://github.com/visualfc/liteide/issues/978 ### 2018.09.15 Ver X34.2 * LiteIDE * fix gotools & gocode support go1.11 modules sub folder * support custom GO111MODULE setup * LiteApp * fix #939 display right margin at column wrong * change mime type check fullname first * GolangCode * fix #970 goplay editor cgo crash * GolangEdit * find usages / rename symbol add skip GOROOT actions * GolangPackage * add custom GO111MODULE setup * LiteEditor * add extra mouse navagite go back and forward * add gomod.xml for go.mod syntax * LiteBuild * add gomod.xml for go.mod build command * gotools & gocode * fix go1.11 modules sub folder ### 2018.08.12 Ver X34.1 * LiteIDE * update gotools support go1.11 modules * update gocode support go1.11 modules and vendor * LiteEditor * enable open binary file for editor * change widget readonly by binary file (ignore text file) * gocode * change parser by source use gotools/types * fix parser vendor & modules ### 2018.07.26 Ver X34 * LiteIDE * update gotools support go1.11 modules * update gocode for https://github.com/visualfc/gocode support go1.11 modules * LiteApp * refactor folder model code, remove depends * fix dock widget for Qt5.9.6 bug * move view godoc from folderview to litebuild * LiteBuild * update BUILDARGS, remove -i for go1.11 build * GolangCode * change to github.com/visualfc/gocode for support go1.11 modules * GolangDoc * pdoc support real ImportPath display for Go modules or vendor * fix docs.html $.GoogleCN code * GolangEdit * support go1.11 modules, view info / jump / find usages * support parser import path for Go modules or vendor for godoc view * GolangPackage * add pkg/mod tree for Go modules * QuickOpen * fix view pos for editor manager * support open file with fullpath on editor input * DlvDebugger * fix continue * gotools * types support go1.11 modules * add pkgcheck support modules or vendor check * gocode * clone https://github.com/nsf/gocode support go1.11 modules ### 2018.07.04 Ver X33.4 * LiteIDE * update gocode for mdempsky/gocode support go1.11 * update DlvDebugger plugin for Delve detail information * LiteDebug * add threads/goroutines/registers view * watch view support double clicked change and update * DlvDebugger * add dlv rcp-mode for get more info * variable and watch support detail information * watch support local/package variable * support threads/gorountines/registers model * GolangCode * support * QuickOpen * add dly filter editor for optimize many files search * fix quick open symbol action ### 2018.04.23 Ver X33.3 * LiteIDE * support import jump to package source file * support import hints for all package on code completer * add build & debug action to build menu * fix build debug gcflags for go version * LiteApp * fix tab style sheet for Qt5.9 on macOS * project wizard add gocmdex/gopkgex for anywhere * LiteBuild * build config file add debug support * golang build add debug/debugtest action * fix golang build debug gcflags depends for go version * LiteDebug * filesystem add debug file action * remove internal golang build function * LiteEditor * reimplemented backspace quotes audo insert/remove action * GolangCode * parser import package for GOPATH * fix vendor import for code completer * add import hints for all package option (default) * add parser cgo completer list on editor * GolangEdit * fix import line navigate show link source * add import line jump to package file list * QuickOpen * add quickopenfolder implement * gotools * add new debugflag action for print debug gcflags for go version * types find import dir check vendor * types add import info and doc * fix astview pkg nil check ### 2018.02.14 Ver X33.2 * LiteIDE * add folder tool window split mode swith * add archlinux makepkg * add tcl syntax and build * LiteEditor * support function color, thanks [discoverfly](https://github.com/discoverfly) * add default-func color theme * add style for scroll bars in sublime.qss, thanks [hauke96](https://github.com/hauke96) * add marks for selections and findings, thanks [jinq0123](https://github.com/jinq0123) * LiteFind * fix editor regexp replace * LiteBuild * add context menu go tool action ### 2017.12.12 Ver X33.1 * LiteIDE * support quick open command * support gomodifytags * fix libpng warning on qt5 build * LiteApp * add tools menu for quick open actions * standard and rename tool window title * enable edit menu anytime, fix edit menu disable on editor lost focus. * fix editor load large file bad_alloc recover * LiteEnv * add select env to tools menu * LiteEditor * check and not open large file * fix edit hide edit sub menu 'setup' on macos * LiteFind * fix find editor replace all wrap around* GolangEdit * Integrated [gomodifytags](https://github.com/fatih/gomodifytags) and gui tools support gomodifytags all options * QuickOpen * add quick open command action (ctrl+shift+p/command+shift+p) * quickopenfiles use thread for fast and cancel * fix quickopenfile cancel loading for esc or liteapp quit ### 2017.11.2 Ver X33 * LiteIDE * optimization editor plugin, load file check codec, reload file by diff * add astview TodoList * add new bookmarks plugin * fix liteapp clean plugin order * LiteApp * filemanager auto reload file default YesToAll * fix liteapp clean plugins reverse order * fix #832, sidebar change action by combox * fix folder sync editor same prefix error * LiteEditor * reload file use diff to keep state and mark * load file check is binary and report * load file check codec use libucd if utf8 decode failed. * load file check decode error and report * load file is readonly set editor widget readonly * load and save file support utf8 bom * add codec and lineend info on statusbar * add copied text into the clipboard as HTML option * add Solarized Dark color theme, thanks xgdgsc * reimplemented editor mark api * fix copy to clipboard tab escape * GolangAst * add TodoList for classview and outline * fix #848, astwidget double clicked index check. * GolangCode * update pkglist to go1.9 * GolangEdit * add stop source query action * add source query action implement_GOPATH for GOPATH scope * fix golang lexer parser folding end * fix GolangHighlighter fold indent error set * fix findUsage wordUnderCursor offset * fix find usages findStart signal late * GolangFmt * load diff check modify current block text * GolangCode * fix update gopath process stop and wait * LiteDebug * fix cmd to native separator * build target add -a build flag * change debug targget name to target.debug (custom by LiteBuild) * LiteBuild * add custom debug name in build config * LiteFind * fix memory leak by GolangEdit GolangFileSearch * fix findInFiles berore saveAllEditor * fix FindEditor replace all * Bookmarks * new plugin for show open editors bookmarks and jump * gotools * update stdlib for go1.9.1 * astview add TodoList support ### 2017.7.18 Ver X32.2 * LiteApp * fix editor file watcher is invalid for many change * GolangEdit * fix TODO/BUG/FIXME comment syntax * DlvDebugger * fix dlv headless process workdir * LiteDebug * fix debug tests action * fix load and save breakpoint for editor ### 2017.7.7 Ver X32.1 * LiteIDE * build config custom gopath support inherit parent path's gopath setup * GolangCode * update gocode lib-path by build config custom gopath * LiteEnv * optimization check go enviroment * LiteBuild * build config custom gopath inherit parent path * fix BuildAndRun kill old on window * fix build config custom gopath action * GolangPackage * fix load package treeview error * DlvDebugger * dlv use headless mode * fix dlv kill process ### 2017.6.12 Ver X32 * LiteIDE * support folder build config custom GOPATH * support folder build config BUILDFLAGS -tags setup * support folder build config TARGETBASENAME setup * support session switching for folder/editor * support load custom icon library from liteapp/qrc folder (default and folder) * reimplemented multifolder model, it took me a long time :) * add macOS session menu for native dock menu * recent menu sync for multi windows * gotools support +build source navigate (single file or -tags setup) * LiteApp * add the session switching function * add autosavedocument emit message option * add max editor tab count option * add option action to standard toolbar * add tool window use shortcuts option for unstandard keyboard option * add exit liteide ctrl+q on windows * add themes (carbon.qss gray.qss sublime.qss) for liteide & beautify old themes, thanks for hope hook * editor tab context add open terminal here action * folders context menu add open in new windows action (new folder session) * folder view add show showdetails action * fix folder sync editor incorrect on macOS * fix webview and debug console qss * fix folders tool window enter key to jump * fix exit error save session by ctrl+q on macos * fix newfile dialog space name * update folder tool window showInExporer showInShell action text * LiteFind * find files add auto swith current folder checkbox * find in editor add show replace mode checkbox * filesearch enable replace whitespace or empty * editor replace all in one edit block for ctrl+z once undo * LiteBuild * add custom GOPATH in build config for build/debug/GolangEdit * add custom share-value BUILDFLAGS in build config for build/debug/GolangEdit * add custom TARGETBASENAME in build config for build/debug * support BUILDFLAGS -tags for build/debug/GolangEdit * update gosrc.xml to export custom value and share-value * folders tool window context menu add Go build configuration action * folders tool window context go tool use Go build configuration setup * fix stop action for kill process * LiteDebug * console use editor color scheme * support LiteBuild folder build config BUILDFLAGS/BUILDARGS -tags flag setup * DlvDebugger * fix process identify for auto exit * LiteEnv * default env /usr/local/go on macosx * update macosx cross env GOROOT for system * LiteEditor * context menu add convert case menu * go.snippet add iferr * update sublime.xml / sublime-bold.xml, thanks for hopehook * alt+backspace delete serial whitespaces * option font QComboBox to QFontComboBox, add restore DefaultFont action * option add show monospace font check * option file types sort mimetype, show custom extsition first * GolangPackage * gopath setup add use sysgopath/litegopath check * GolangPlay * fix goplay use goenvironment * GolangDoc * change golang api index search for go/api folder * GolangEdit * add go root source readonly setup option * support folder go build config BUILDFLAGS/BUILDARGS -tags flag setup * fix interface type by gotools * fix find process stop and run * fix lookup guru for source query * GolangAst * fix astview enter key to jump * FileBorwser * fix file system enter key to jump * gotools * fix types interface method * types support +build for single source * types support -tags flag * tools * add new exportqrc tool for export liteide all build-in images ### 2017.3.9 Ver X31.1 * LiteApp * restore folder first on MacOS * GolangEdit * update pkglist ### 2017.3.2 Ver X31 * LiteIDE * add command line `liteide [files|folder] [--select-env id] [--local-setting] [--user-setting] [--reset-setting]` * LiteApp * add application idle timer automatic save documents option * folders are not sorted to resolve sync editing errors on MacOS * update new file wizard * GolangPackage * update GOPATH setup * GolangCode * update env load * GolangAst * classview and outline add sync editor action * DlvDebugger * fix dlv execution on MacOS * FakeVim * option add load default command list action * LiteEditor * fix editor restore vertical scrollbar postion * fix codecompleter prefix min setup * restore the editor toolbar * option add mimetype custom extsition setup * LiteBuild * build config xml file enable custom $() on cmd and args ### 2016.12.6 Ver X30.3 * LiteEnv * remove GO15VENDOREXPERIMENT env * LiteEditor * add fuzzy completion option, default setup * add clear completion cache when save files option * support drop file to open editor * add case convert actions * GolangEdit * add guru support (backup oracle) * GolangFmt * fmt try to keep the original location * DlvDebugger * use native stepout * filter term color * LiteBuild * filter term color * FileTest support TESTARGS * gotools * always use vendor * gotest support [build|test args] * update vendor for oracle ### 2016.7.12 Ver X30.2 * LiteApp * add new vs-dark css, thanks [tupunco](https://github.com/tupunco) * fix and re-implement editor list menu * QuickOpen * QuickOpenFile skip same folder and same files * QuickOpneFile add current editor local files ### 2016.7.5 Ver X30.1 * LiteIDE * add OpenEditor tool windows * add GolangSymbol for QuickOpen (CTRL+SHIFT+O) * fix gotools vendor error * LiteApp * add OpenEditor tool windows * update view menu * GolangAst * add GolangSymbol for QuickOpen * add GolangSymbol option * fix goto symbol * QuickOpen * optimization QuickOpenFile and QuickOpenEditor search * add QuickOpen option * gotools * fix vendor error ### 2016.7.2 Ver X30 * LiteIDE * add new QuickOpen plugin * add new FakeVim plugin, thanks for [jsuppe](https://github.com/jsuppe) * add custom env LITEIDE_TOOL_PATH/LITEIDE_PLUGIN_PATH/LITEIDE_RES_PATH * LiteApp * action tooltip shortcut show native text * option keyboard map show native text * QuickOpen * quick open files action CTRL+P * quick open editor action ATL+ALT+P * quick go to line action CTRL+L * quick open help * FakeVim * editor add vim style mode editing * LiteEditor * add goto line start/end action * add goto doc start/end action * add goto previous/next line action * add goto previous/next charater action * add goto previous/next word action * change '' braces only go source * fix codecompleter number first * MacOS fix move line up/down shortcut command+shift+up/down * GolangEdit * CTRL+mouse navigate preview source info * LiteFind * MacOS fix edit replace shortcut command+shift+F * Welcome * fix doc css style * gotools * types fix limit parser * types simple field info ### 2016.4.15 Ver X29 * LiteIDE * support for multiple debuggers * support Delve debugger * env GO15VENDOREXPERIMENT=1 default setup * LiteBuild * fix project folder id named go, error find go tool * fix project folder contains spaces run failed * fix output number of rows exceeds the maximum input fails * add output add automatic positioning cursor option * add single go file test action * add folder context menu more go tool action * LiteEnv * env GO15VENDOREXPERIMENT=1 default setup * LiteDebug * support for multiple debuggers * debug berore auto go build -gcflags "-N -l" * fix stack frame clicked to doubleClocked * DlvDebugger * support dlv debugger * simulation execution 'step-out' * GdbDebugger * fix show frame line locate * fix goto line action * LiteEditor * display limit tip line info * GolangEdit * fix folder contains spaces, gotools fails * gotools * add gotest action, test single go file * fix types info, display pkg real name ### 2015.12.10 Ver X28 * LiteIDE * gotools add go1.5 vendor support if env GO15VENDOREXPERIMENT=1 set * LiteApp * folder add sync edit action * fix close folder bug * LiteBuild * add folder context lock build path * add folder context gofmt * add output menu auto clear and line wrap action * LiteOutput * add set max line option * GolangFmt * add new gotools gofmt action * add sortimports option (default) * LiteEnv * add var GO15VENDOREXPERIMENT=1 (default comment) * GolangAst * support go1.5 vendor * LiteEditor * fix selection identifier regexp * GolangEdit * support go1.5 vendor * enable oracle enable referres action * GolangCode * use set lib-path action * gotools * types add go1.5 support if GO15VGOROOTXPERIMENT=1 set * types fix cycle import check * types fix pkg find bug * types add unsafe builtin info * astview add go1.5 support if GO15VGOROOTXPERIMENT=1 set * stdlib update to go1.5 * add new gofmt action * gofmt import godiff replace diff cmd ### 2015.4.22 Ver X27.2.1 * LiteIDE * fix editor change crash ### 2015.4.20 Ver X27.2 * LiteIDE * add output option * add windows native open explorer * add Ukrainian translation thanks Roman Shmelev * LiteEditor * add block selection mode (use Alt key) * fix text mimetype print char check. * fix code completer ...type * fix insert key * LiteEnv * optimization go env reload * LiteBuild * fix build config * LiteFind * fix editor match case replace * fix file search matchWord * GolangEdit * fix init option * fix embeded struct find * add oracle support * gotools * fix embeded struct type find * add oracle ### 2015.2.16 Ver X27.1 * LiteIDE * fix code navigate history ( build / astview / debug / link) * fix UNC path crash check * LiteEditor * add copy/cut/move/join line action * fix selection color * fix link color * GolangEdit * add global find usages and refactor(GOPATH) * add refactor revert mode * add golang symbol document on tooltip * fix no jump code tooltip * fix syntax for Non-English symbol name * LiteFind * add find swith replace mode * add replace revert mode * LiteBuild * fix build lock custom config * GolangAst * fix Non-English symbol name * gotools: * type - simple object info * type - add global usages * type - add symbol doc search * type - add XTest files support * type - fix field pos search * astview - update type var and factor to global ### 2015.2.4 Ver X27 * LiteIDE * create independent project gotools and replace liteide_stub * move build toolbar to the main window * move editor tab to editor widget * fix multi window keyshort invalid * fix treeview scroll bar * fix sidebar keyshort * GolangEdit * add editor mouse under symbol tooltip * add ctrl + left mouse button to link navigate * fix embeded func navigate * fix golang syntax parser * LiteBuild * add build lock action * update build config file * fix output enter offset * LiteFind * update find text by under cursor * LiteEditor * add whitespace visible setup option * add line end setup option * fix google pinying editor cursor hide bug * fix editor navigate action * JsonEdit * re-implement json format * RustEdit * add simple rust support ### 2014.12.25 Ver X26 * LiteIDE * add lang package support * fix shortcut key call mechanism * fix editor shortcut key monopolize * LiteEnv * fix system enviroment auto reset by go env * LiteEditor * add simple snippet code * fix enter {} key indent * fix []{} insert and backspace * fix code completer func () insert * GolangCode * fix system enviroment work * add auto update package when its source change option * GdbDebugger * fix system enviroment gdb/gdb64 auto select * GolangEdit * add golang tag highlighter ### 2014.12.16 Ver X25.2 * LiteIDE * default enviroment id system work * LiteApp * fix sort folder on macosx * LiteEnv * add reload current enviroment action * set default enviroment id system * LiteEditor * fix enter key indent * fix import line regexp * fix complete word suspended bug (in non go file) * re-implement full text completer * GolangDoc * fix lookup godoc on system env * fix path name to pkg name * GolangCode * completer import line on GOPATH * GolangEdit * add update dependencies library action * add view import package in godoc action ### 2014.12.12 Ver X25.1 * LiteIDE * both support go1.3 and go1.4 * LiteApp * fix folders sort by folder first in macosx * GolangCode * enable completer import line (standard package) * GolangFmt * fix goimports error report bug * GolangEdit * fix import line find usages * GolangDoc * support go1.4 * LiteFind * fix search result style sheet * FileBorwser * fix sort by folder first in macosx ### 2014.12.4 Ver X25 * LiteApp * default use new style SideBarStyle * add style option SideBarStyle and SplitterStyle * folders use new multi folder class implement * LiteEnv * system env lookup go env * add LITEIDE_SHELL support for multiple terminals * GolangEdit * find usages both support go1.3 and go1.4 * dump find usages error * update goimports standard pkg index * fix find usages Non-English offset * fix faketip on ubuntu * FileBorwser * use new folder class implement * LiteEditor * fix clipboard blocking on linux * fix editor brace insert postion * GolangFmt * default save use gofmt style * add menu action Code Format(gofmt) (Ctrl+I) * and menu action Code Format(goimports) (Ctrl+Alt+I) ### 2014.11.13 Ver X24.3 * liteide_stub * merge and optimization code.google.com/p/goimports * fix astview for decl funcs * fix import line find uses * LiteApp * update german translation, thanks Harald Leinders * fix PATHEXT no default on windows * fix treeview remove crash bug * fix open terminal * GolangEdit * fix import find usages * fix golang func decl syntax highlighter * GolangAst * fix astview view missing funcs * GolangCode * fix goimports incorrectly removing certain no incorrectly removing no convention import paths ### 2014.11.04 Ver X24.2 * GolangCode * fix import style ### 2014.11.03 Ver X24.1 * LiteEditor * fix codecompleter crash * GolangCode * prompt pkg not find , enter key to auto import * fix struct offset for gocode * GolangFmt * merge goimports to liteide_stub * default use goimports ### 2014.10.24 Ver X24 * LiteApp * new codecompleter components * log and build output no wrap * update Japanese translation * update German translation * LiteEditor * new codecompleter components * code completer match by strings.hp => HasPrefix * code completer sort by prefix * code completer list use tooltip * code completer list updown use ctrl+n/ctrl+p short key * smart () [] "" '' `` insert and backspace remove * smart right ) ] " ' ` insert skip * fix code completer up/down key * fix ctrl+enter/ctrl+shift+enter to insert line after/berore * fix selection highlight * LiteBuild * golang config custom add TESTARGS/BENCHMARKARGS * output font family use editor family ### 2014.08.05 Ver X23.2 * gocode add cgo basic completer * update option to dialog mode * fix godoc target for go1.3 * fix golang highlighter, return to kate * fix short key for macosx * fixed Qt5 build crash when exit on macosx ### 2014.07.24 Ver X23 * LiteIDE * add golang simple lexer for editor * add golang code complete tooltip * golang code complete disable on comment or strings * fix escape return editor * LiteEditor * add IHighlighterManager interface * add ITextLexer interface * add new color scheme carbon from William Kennedy * fix kate code fold * fix code completer offset * GolangEdit * add golang simple lexer * add golang highlighter parser * add tooltip for complete * GolangPresent * view by QtWebKit * WebKitHtmlWidget * change to browser view mode ### 2014.04.14 Ver X22 * LiteIDE * add golang find usage support * add golang code refactor support * fast jump to declaration * add reload folder/files option on startup. * LiteIDE * fix code fold bug * LiteDebug * add call frame goto line * LiteEnv * add freebsd env * LiteFind * new find result view from QtCteator * GolangEdit * new golang editor support plugin * find usages * rename symbol under cursor * MarkdownEdit * add Github_Word.css, thanks github.com/lixiaolong ### 2014.03.20 Ver X21.1 * LiteIDE * reduce application memory usage * add new golang doc search (modification from rspace doc tool) * update golang api index * folder add go build context menu * short folder name * optimization litide_stub api tool * add kate solarsooty.xml thanks for Unknown * add code complete short key (ctrl+space) * fix gocode automatically plugin * fix golang present verify plugin ### 2014.03.06 Ver X21 * LiteIDE * fast highlighter for MacOS X 10.9 * fast expression lookup F1/F2 * cancel x20 always open in new window mode. * add new JsonEdit plugin. * add reload/close dialog YesToAll, if modified on the drive. * add auto reload files option, if modified on the drive. * add store setting to local ini file option. * fix folder expand state * fix for case sensitive path comparison on windows * fix memory leak * LiteBuild * add golint support * LiteEnv * recreate system.env * LiteEditor * new color scheme gist-github (thanks William Kennedy ) * fix if/else syntax fold * GolangAst * add type factor to funcs folder * add type const * add import symbol, and view document menu * add context menu * add symbol extra info * GolangFmt * fix timeout * fix GOPATH * GolangDoc * fast expression lookup F1/F2 ### 2013.12.09 Ver X20 * LiteIDE * add folders manager * always open folder with new window (option) * editor add navigate area for code format or build error * add new GolangPresent plugin * tool windows use instantpopup * update editor tab context menu * add evilworks.qss style (by Vedran Vuk ) * LiteEditor * add error navigate area * update kate highlighter * add gopresent.xml syntax * add Visual Studio Theme (by William Kennedy ) * fix goto match braces * update editor menu * LiteEnv: * auto set $PATH for GOROOT/bin and GOBIN and GOPATH/bin and GOPATH/bin/GOOS_GOARCH * fix to use utf8 encoding * GolangCode: * auto update depends package (option) * fix close gocode on last window close * GolangFmt: * use sync code format (option) * use goimports instead gofmt (option) * code format error show in editor navigate area * LiteDebug: * external cmd setting * fix command input foucus * Markdown: * add new Github_Style.css (by Slene ) * FileBrowser: * option show hidden files * LiteBuild: * fix build menu enable * build error show in editor navigate area * add gopm(Go Package Manager) tool * GolangPresent: * support golang present editor * verify present error show in editor navigate area * export golang present to html * Welcome: * update document * add zh_CN document ### 2013.7.17 Ver X19 * LiteIDE * MacOS X 10.8 Retina support * add simple webkit browser * update macosx tool window short key to Ctrl+Alt+1~9 * LiteDebug * add debug go test support, thanks for GoEddie * GdbDebugger * gdb debugger --tty mode support (windows default) * debugger command input foucus * LiteEditor * add wheel zooming option * fix editor extra width * fix init editor update * LiteFind * fix find hide * Markdown * markdown preview fast sync ### 2013.5.21 Ver X18.2 * fast for gocode * add option to close gocode on exit * auto append GOPATH/bin to liteide env PATH * editor extern highlighting "TODO" * go code auto-complete ignores strings and comments ### 2013.5.10 * compiled compatibility for qt5.02 ### 2013.5.8 Ver X18.1 * optimization gocode plugin * execute preload litebuild/command/*.api * execute enable tab key to compiler ### 2013.5.7 Ver X18 * English spelling and grammar corrections throughout, thanks for Nik-U * LiteIDE: * Improved event log * litefind: * Find/Replace commands highlight existing text * enable find file * add close button * liteeditor: * Word wrap support * Added option to trim whitespace on save * Added option to hide edit toolbar * update kate and color scheme * fix kate/highlight tab * fix editor indent guide by tabsize * liteapp: * fix full screen bug * litebuild: * execute use combbox * add close button * litedebug: * add close button * markdown: * enable markdown(sundown) extend ### 2013.2.8 Ver X17 * LiteIDE: * move execute from filesystem to bottom tool * escape for any bottom tool window (find , execute ...) * macosx lion full screen * add color theme highcontrastdark.xml and app theme black.qss, thanks for addxtoy * add tr liteide_de.ts , thanks for Helge Plaschke * fix keybord scheme * liteeditor: * show tab ident guide * show find scope expression * show selection scope expression * show file eof - option * show line wrap (markdown editor) * update current line color * any time focus if need * fix zoom tab width * fix open file cursor position start * fix set color theme not request restart * markdown: * fix export path * filesystem: * fix double clicked item and execute * litedebug: * save/restore start editor * fix breakpoint move in editor * fix debug target args * litefind: * new find and replace * fix find editor and unfold * fix backword find * litebuild: * add test bench * document: * enable zoom font size Ctrl++/Ctrl+-/Ctrl+0 * fix find crash * gopath setup: * fix invalid path ### 2013.1.16 Ver X16 * support keybord mapping scheme * fix: lookup go command in $PATH * fix: remove GOBIN enviroment set * fix: empty editor cursor position * fix: double click error output to jump source and editor set focus ### 2013.1.10 Ver X15.2 * LiteIDE: * use new logo and icon * support go version hg-tip * LiteApp: * update logo * update splash * add action close same/other folder files * fix full screen restore * LiteEnv: * add user env files * LiteEditor: * fix `Insert` key * update sublime color scheme * GolangDoc: * support go tip version * show error output * GolangCode: * fix code completer icon visible * Golang Fmt: * fix timeout option invalid * Markdown: * fix critical messsage * add css Documents.css ### 2012.12.28 Ver X15.1 * LiteIDE: * update logo * LiteApp: * plugins custom load * custom style use css(Qt Style Sheets) * add style coffee * fix template `doc.go` * tabs middle button close editor * fix memory leak * LiteEditor: * font zoom support * add sublime color scheme, thanks for `Henson Lu` * custom tab width and tab to spaces for mimetype * LiteEnv: * add cross-compiler * GolangDoc: * fix goto source ### 2012.12.18 Ver X15 * LiteIDE: * add markdown plugin * changed LiteApp to dynamic library * redesign editor menu and toolbar * update doc to markdown format * add html render twin-engine * internal QHtmlBrowser * plugin QtWebKit, if find qt webkit dynamic library * LiteApp: * changed to dynamic library * support full screen mode * editor tabs change to toolbar * add toolbar icon size option * add splash visible option * add editor tab bar close button visible option * add tab context menu close left or right tabs * LiteEditor: * add overwrite mode (key Insert) * add custom tab width option * redesign editor menu , context menu and toolbar * add right margin line visible option * GolangFmt: * fix comment offset, remove spaces * LiteBuild: * id BuildAndRun before kill old process * redesign build toolbar and menu * support GOBIN * LiteDebug: * add debug before rebuild option * add debug external application action * Markdown: * markdown editor support * action h1-h6, bold, italic, code, list, quote, hr, link, image * syntax highlighting * live preview * sync scroll * export html * export pdf * custom css , css files from [Mou](http://mouapp.com) * markdown batch * separate to html * separate to pdf * merge to html * merge to pdf * GolangDoc: * fix url parser ### 2012.11.15 Ver X14.1 * LiteIDE : quick start * LiteApp : multi instance support * GolangDoc: deply load mode * GolangPackage: deply load mode * GolangAst : fix classview * LiteEditor: fix if/else fold * GolangDoc : goapi enable _test ### 2012.11.6 Ver X14.0 * tools/goapi : new goapi tool * GolangDoc: View Expression Information (F1) * GolangDoc: Jump to Declaration (F2) * GolangDoc: lookup all GOPATH pkg api * LiteApp: fix editor navigate * LiteEditor : add action Move to New Windows * LiteFind : focus in find text and enter * LiteEditor: fix code completer func test () * GolangCode : auto restart gocode if liteide GOPATH changed * GolanPlay: enable gocode and fmt * GolangFmt: auto popup gofmt messsage option * LiteBuild : fix build config custom view * LiteBuild : BUILDARGS / INSTALLARGS support set example -gcflags "-N -l" for debug example -ldflags "-s" for release * remove: Makefile plugin , Profile plugin, x64 Project ### 2012.10.10 Ver X13.2 * GolangCode : the best support for gocode * LiteApp : add editor tab context menu * LiteApp : update view menu * LiteApp : fix check modify and save * GolangFmt : fix fmt editor style restore * GolangDoc : fix go/doc/*.html parser meta "Path=" * GolangAst : fix update model style restore * Welcome : update page * LiteEnv : edit enviroment action * LiteBuild : update gosrc.xml * LiteBuild : fix double click goto line regexp * LiteBuild : show enviroment go env * LiteBuild : execute error use red font * LiteEditor : color theme set currnet line background * LiteEditor : add color theme darktango.xml(Dumitru Ungureanu) * LiteEditor : go wordapi update, keyword types and funcs * LiteEditor : code completer func auto append () * LiteEditor : fix tab indent * FileSystem : fix execute find path * LiteFind : fix current directory ### 2012.9.24 Ver X13.1 * LiteBuild : fix build load crash. * LiteApp : fix double click error output regexp * LiteApp : fix folder drop to liteide * LiteDebug : watch vars load /save by project * LiteDebug : breakpoint load /save by file * LiteDebug : add remove all breakpoint action * LiteDebug : add / remove global or local watch point * LiteEditor : optimization editor mark * LiteEditor : enable drop text * GolangPlay : enable gofmt ### 2012.9.21 Ver X13 * LiteApp : any folder, any file to build * LiteApp : update window style, add editor toolbar and status * LiteEditor : remove editor toolbar * LiteEditor : extra use editor font * LiteBuild : new build toolbar and menu * LiteBuild : clean action tags * GolangFmt : sync execute gofmt * GolangDoc : deply filter index * GolangAst : classview for folder * Outline : alltime expand * FileBrowser : rename to FileSystem * FileSystem : sync editor file to folder * FileSystem : add go command line edit (Ctrl+`) * FileSystem : double click execute file and execute on build output * Windows : include diff bin ### 2012.9.14 Ver X12.5 * LiteApp : move dock style, change to idea style tool windows. * LiteApp : double click editor and maximized or restore editor * LiteApp : esc key to hide bottom tool windows * LiteApp : auto load last session * LiteEditor : add edit navigate histroy * LiteEditor : extra use color scheme * GolangFmt : show error log and goto line ### 2012.7.12 Ver X12.2 * GolangFmt : fix fold error diff bug * LiteDebug : add var watch, example main.var os.Stdout * Welcome : add load last selection * LiteEditor : add fold or unfold all action * LiteEditor : add duplicate action * LiteEditor : add color theme railscast.xml(Alexander Rødseth) * LiteFind : default find use editor selection * LiteEnv : fix windows env LITEIEDE_EXECOPT=/C * LiteApp : fix icon on windows xp unable show ### 2012.6.28 Ver X12.1.1 * LiteEditor : fix fold bug - line include "head{}end" * LiteEditor : kate go.xml breace match add "[]" ### 2012.6.27 Ver X12.1 * LiteIDE : LiteIDE use new logo * LiteEditor : fold / unfold * LiteEditor : color scheme custom selection * LiteEditor : kate go.xml remove linecontinue * LiteEditor : goto line * LiteApp : fix recent file load bug * GdbDebugger : fix frame if not find fullname * LiteIDE : update faq document * LiteIDE : add install document ### 2012.6.13 Ver X12 1.875 * LiteIDE : reset resource directory * LiteEditor : goto next/prev block * LiteEditor : code comment * LiteEditor : braces match * LiteEditor: LRLF check by \n * LiteEditor: no print char conver to . * LiteEditor: move tooltip to status * GolangFmt : enable gofmt diff * GolangFmt : save auto gofmt * LiteBuild: project build toolbar and editor build toolbar. * LiteFind: add file search * PackageBrowser: fast load ### 2012.5.16 Ver X11 1.71875 beta4.1 * LiteBuild: fix execute args for gosrc/gopro/makefile * LiteApp: add option - when close project auto close project editors * PackageBrowser : double click pkg and load project * LiteEditor: add option - completer case sensitive ### 2012.5.15 Ver X11 1.71875 beta4 * GolangPackage : enable local package * GolangDoc : golang api fmt#Println -> fmt.Println * LiteBuild : fix regexp error * FileSystem: (windows) fix rename abc to Abc false * PackageProject : remove auto reload timer * LiteEditor: (linux) redo enable CTRL+Y ### 2012.5.2 Ver X11 1.71875 beta3 * GolangPackage : new golang package plugin for GO1 * GolangPackage : PackageBrowser and PackageProject for GO1 * GolangTool : remove the plugin * GolangDoc: add golang api for GO1 * GolangDoc: add golang api filter * GolangAst: add filter * GolangAst: classview and outline * LiteEditor : completer option * LiteApp : new file wizard support GO1 * Welcome : new recent page * gopromake : update pkg depend ### 2012.3.9 Ver X11 1.71875 beta2 * GolangPlay : new go playground plugin * GolangTool : sync editor, sync project ### 2012.3.1 Ver X11 1.71875 beta1 * GolangTool : new golang plugin for GO1, import GOPATH project * GolangDoc : update to GO1 * LiteBuild : update to GO1 * tools : udpate all tools for GO1 ### 2011.9.26 Ver X10 1.5625 * LiteEditor : add line mark api * LiteDebug : new debug toolbar * LiteDebug : insert/remove break * LiteDebug : breakpoint and current line mark * GdbDebugger : async record view * GdbDebugger : variables expand tree * GdbDebugger : call stack view * GdbDebugger : load library view * TerminalEdit : provided to LiteBuild and LiteDebug ### 2011.9.14 Ver X9 1.40625 * LiteDebug : new debug manager plugin * GdbDebugger : new gdb debugger plugin * LiteBuild : add build config and custom * LiteFind : fix regexp use match case ### 2011.9.1 Ver X8 1.25 * LiteFind : new find and replace plugin, remove CodeSearch plugin * LiteEditor : fix word api completer three parts error * LiteEditor : fix word api completer sorted * LiteApp : fix main window state load/save on linux * LiteApp : change path to standard linux path * LiteBuild : add build option, example execute arguments * FileBrowser : add new file wizard ### 2011.8.12 Ver X7 1.09375 * Welcome : new html page, quick link, session, recent projects and files * GolangDoc : generic document nav * GolangDoc : scheme entry [file|list|find|pdoc] * FileBrowser : add "View Godoc Here" * LiteBuild : auto clean output if line more than 1024 * LiteEditor : word completer sorted * LiteEditor : auto braces last state check * GolangAst : show type struct field * GolangAst : editor state keep self ### 2011.7.28 Ver X6 0.9375 * LiteEnv : new plugin, liteide enviroment setup * Welcome : add LiteIDE document browser * GolangDoc : add package find, example input "zip" and find * GolangDoc : add godoc /src/pkg/ and /src/cmd/ tree * GolangDoc : add go/doc/ document browser * GolangDoc : add document browser text search * LiteEditor : add export html file * FileBrowser : add menu item desktop explorer * LiteEditor : add enable automatic insert brackets * LiteEditor : add option : display and behavior * LiteApp : fix session load last editor or welcome page * LiteApp : fix find mimetype incorrect * GolangCode : fix application exit gocode close * FileBrowser : fix context menu popup on root * LiteBuild : fix ouput html format to plaintext * LiteBuild : fix build does not handle spaces in file paths * LiteBuild : fix output append \n->next append * LiteBuild : fix enviroment depend of LiteBuild ### 2011.7.7 Ver X5 v0.78125 * add CodeSearch plugin : Editor Search and Replace * add GolangDoc plugin : Golang Package Find * add Search and Replace Regex: (Colo)(u)(r) -> \1\3 * add FileBorwser top dir setup * add LiteEditor Copy Syntax Color support (HTML mimedata) * add LiteEditor ReadOnly * add MainWindow all DockWidget saveState * add EditorManager CTRL+TAB switch * update tools/gopromake to r58 * update tools/goexec to r58 * update tools/goastview to r58 * fix filebrowser rename show oldname * fix ENV c:/go/bin;%PATH% order, GOBIN is priority * fix FileBrowser sort incorrect on MACOSX * fix GoFmt reload editor display pos keep * fix Editor Close Ask BUG ret==SaveAll * fix Editor word writed ,completer only one match auto hide ### 2011.6.30 Ver X4 v0.625 * add interface zh_cn * add filebrowser pluing add/change/remove * add editor color style scheme setup * add editor codec check/reload * add editor pdf export * add editor print and preview * editor style line LRLF of source * kate go.xml support "number" style * liteapp last session save/load ### 2011.6.21 Ver X3 v0.46875 * add file browser plugin * source editor pre link project build * source editor outside modify/remove watcher ### 2011.5.20 Ver X2 v0.3125 * add gocode plugin * add build/makefile * add build/lua stdoutput:setvbuf("no") * fix build task stop on error * fix build process write \n ### 2011.5.12 Ver X1 v0.15625 * New LiteIDE X version ------ ## LiteIDE Old version ### 2011.2.25 v0.2.1 * add build on MacOSX10.6 * support Makefile and .pro project * project support GCOPT and GLOPT * global option page * global output pane * set GOROOT option * run shell * run debug * run process can write * run process can kill * clean project opt temp or all * new project wizard : .pro/package/Makefile * new example goinfo, how to use local or search package ### 2011.1.25 v0.1.8 * goastview plugin ### 2011.1.18 v0.1.6 * add build on Linux64 ### 2011.1.12 v0.1.5 * build error and jump to source line ### 2011.1.11 v0.1.2 * gopromake use goroutines ### 2011.1.10 v0.1 * init version ================================================ FILE: liteidex/deploy/welcome/zh_CN/forever.md ================================================ Forever ======= ## 道德经 道可道,非常道。名可名,非常名。 无名天地之始;有名万物之母。 ## 2018.02.14 **三十功名尘与土,八千里路云和月。** ## 天行健 **天行健,君子以自强不息。地势坤,君子以厚德载物。** ![](images/liteide.png) ## logo ![](images/liteide400.png) ## @_@ 佛祖问阿难:你有多喜欢这少女? 阿难说:我愿化身石桥,受五百年风吹,五百年日晒,五百年雨打,但求此少女从桥上走过。 ## with you ![](images/flamingo.png) ## forever ![](images/forever.png) ================================================ FILE: liteidex/deploy/welcome/zh_CN/guide.md ================================================ # LiteIDE 功能手册 ## 如何支持低版本Go1.1和Go1.2 LiteIDE的编译设置使用了-i编译参数。如果使用Go1.1或Go1.2则不支持此参数。选项->查看->LiteBuild 双击gosrc.xml进行编辑。修改BUILDARGS默认设置: 将value设置为空存盘重启LiteIDE即可支持Go1.1和Go1.2。 ## 窗口样式设置 LiteIDE目前有两种窗口样式分离式和侧边栏式。 选项->查看->LiteApp-> 窗口样式。 ## 环境设置 LiteIDE环境设置插件可以让你快速设置切换多个系统环境,以便编译构建,每个环境都可配置自己需要的环境变量。 ### 选择当前环境 工具栏中的下拉菜单可以用来选择目前用于编译构建/运行的环境。 ![envselect.png](../images/envselect.png) 主要系统的一些常用环境列表 * Windows - win64 win32 * Linux - linux64 linux32 * MacOSX - darwin64 darwin32 可选择使用交叉编译环境,请参看下面的交叉编译设置。 ### 配置环境 环境中的变量可以通过手工进行修改。要编辑当前环境,只要按一下环境下拉列表旁的`编辑环境`按钮。 另外,也可以`查看>选项> LiteEnv`面板中对所有环境进行查看和编辑。 举例 `win32.env`: #win32 environment GOROOT=c:\go #GOBIN= GOARCH=386 GOOS=windows PATH=c:\mingw32\bin;%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C 举例 `linux32.env`: #linux32 environment GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=linux PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e ## 快速打开窗口 * 快速打开 Ctrl+P * 快速打开文档 Ctrl+Alt+P 或者在快速打开窗口输入 ~ * 快速跳转符号 Ctrl+Shift+O 或者在快速打开窗口输入 @ * 快速跳转到行 Ctrl+L 或者在快速打开窗口输入 : * 获取帮助 在快速打开窗口输入 ? ## 交叉编译 (Go1.5或更高版本) 选择LiteIDE的环境并设置相应的GOROOT、GOARCH、GOOS,重新编译即可。 ## 交叉编译 (Go1.5之前) 必须先建立交叉编译器所需要的平台和架构。如果你不这样做,将出现类似下面的错误: go build runtime: linux/amd64 must be bootstrapped using make.bat 请查看 "Building compilers" subsection for examples. ### 环境变量 交叉编译将把项目为编译为另一个操作系统或体系结构,需要定义环境中的以下变量: * `$GOOS` - 目标操作系统 (默认值等同于`$GOHOSTOS`). 可选值包括: * darwin (Mac OS X 10.6 或更高版本) * freebsd * linux * netbsd * openbsd * plan9 * windows * `$GOARCH` - 目标平台体系 (默认值等同于`$GOHOSTARCH`). 可选值包括: * amd64 (64-bit x86, 最成熟) * 386 (32-bit x86) * arm (32-bit ARM) * `$GOARM` - ARM 架构运行库 (默认值: 6). * 设置 `$GOARM` 为5 时将导致链接器使用软件浮点实现,而不是使用硬件浮点支持。 * `$CGO_ENABLED` * 交叉编辑时值自动设置为0。 ### 构建编译器 要构建编译器到交叉编译,需要转到源目录中并运行相应的脚本。下面的例子演示了如何构建一些常见的编译器,你必须自己机器上相应设置来修改环境变量。 **go1.5 以下 ( go1.8 交叉编译时会自动设置 CGO_ENABLED 为 0)** 在Windows平台上交叉编译 64-bit Linux (使用MinGW和GCC): > set GOARCH=amd64 > set GOOS=linux > set CGO_ENABLED=0 > go build std 在Mac OS X平台上交叉编译 32-bit windows: > GOARCH=386 GOOS=window CGO_ENABLED=0 go build std 在Mac OS X平台上交叉编译 ARM : > GOARCH=arm GOOS=linux CGO_ENABLED=0 go build std **go 1.0 go1.1 go1.2 go1.3 go1.4** 在Windows平台上交叉编译 64-bit Linux (使用MinGW和GCC): > set GOARCH=amd64 > set GOOS=linux > set CGO_ENABLED=0 > cd %GOROOT%\src > all.bat 在macOS平台上交叉编译 32-bit windows: > export GOARCH=386 > export GOOS=windows > export CGO_ENABLED=0 > cd $GOROOT/src > ./all.bash 在macOS平台上交叉编译 ARM : > export GOARCH=arm > export GOOS=linux > export CGO_ENABLED=0 > cd $GOROOT/src > ./all.bash ## Go语言代码格式化 存盘时自动格式化 ### Goimports样式格式化 LiteIDE 查看->选项->GolangFmt-> 使用Goimports代替gofmt进行代码格式化 这个工具自动更新您的Go语言import行,增加缺少的pkg和移除未引用的pkg。 ## Gocode代码完成 Go语言代码完成使用gocode ,gocode的工作原理是从项目的依赖库.a文件中读取,所以不能代码完成时请更新项目的依赖库。 ### 更新依赖库 更新当前项目的依赖库, 点击编译菜单或工具栏`Get`(go get) ### 自动更新依赖库 LiteIDE 查看->选项->Gocode-> 自动更新依赖库 ### 编译 在LiteIDE中执行交叉编译,通过选择上述相应的交叉编译环境。并且确保环境已经设置了正确的变量。包括 `GOARCH`,`GOOS`,`GOARM`和`CGO_ENABLED`,如上面所述。 一旦交叉目标环境中已被选中并切换,只需要重新编译文件/项目即可。 举例在Windows平台上配置交叉环境 64-bit Linux: GOROOT=c:\go GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=0 PATH=%GOBIN%;%GOROOT%\bin;%PATH% ... ## 编译系统 LiteIDE的编译系统是高度可配置的,可使用XML文件自定义生成相应的命令操作。 ### 配置编译行为 要修改现有的编译选项,打开`查看>选项> LiteBuild`。你可以在这个目录中添加自己的图片来定义新的图标。双击一个XML文件进行编辑。每个XML文件都使用Mime格式定义了针对特定文件类型的相应操作。 举例 Go语言的 XML 配置 (`gosrc.xml`): ## Go文档查看 LiteIDE可使用godoc来输出需要Go文档并浏览。可以查看标准包文档或自定义包文档。打开使用`查看> Godoc文档查看`可以查看关于此的更多细节。 ## 查找和替换 编辑器提供了搜索和替换功能,并支持正则表达式。例如: Find: (Colo)(u)(r) Replace: \1\3 The above example will replace all instances of `Colour` with `Color`. 上面的例子将取代`Colour`为`Color` 文件系统的搜索功能可通过 `查找 -> 文件搜索`实现. ## 调试 LiteIDE调试Go语言需要安装GDB(Windows上可使用MinGW). 环境变量`LITEIDE_GDB`可指定使用哪一个gdb来执行调试。在Windows平台上,32位环境使用`gdb.exe`而64位环境默认使用`gdb64.exe`。在环境配置文件中可对这个环境变量进行手工配置。 ## 键盘映射 您可以修改用于LiteIDE所有的功能快捷键。打开 `查看 -> 选项 -> LiteApp -> 键盘` 并修改快捷键。双击该快捷键列表进行编辑,然后按'应用'以执行更改。 快捷键必须遵循特定的格式。快捷键通常可以使用逗号(`,`)分隔,即按顺序按下对应的快捷键以启动功能。而定义支持多个快捷键则用分号(';')进行分隔。 举例: * `Ctrl+B` * `Ctrl+Shift+B` * `Ctrl+K,Ctrl+U` * `Ctrl+Y;Ctrl+Shift+Z` ================================================ FILE: liteidex/deploy/welcome/zh_CN/install.md ================================================ # 安装 LiteIDE ## 先决条件 使用LiteIDE开发golang需要安装Go语言开发环境。 ### Go 先要安装Go语言,详细情况请参看. 在安装LiteIDE之前一定要先安装Go语言。 ## 安装二进制文件 ### Windows 下载压缩包并解压至c:\盘 ### Linux and MacOSX 下载压缩包并解压到/usr/local或者是$HOME ## 从源代码编译 LiteIDE源码位于上。需要使用Qt4/Qt5来编译源代码,Qt库可以从上获取。Mac OS X用户可以不从源代码编译Qt,直接在终端中运行`brew update && brew install qt`,节省大量时间。下面的编译以Qt4为例。 ### Windows **Qt4** > git clone https://github.com/visualfc/liteide.git > set QTDIR=c:\Qt\Qt4.8.5 > set MINGWDIR=c:\Qt\MinGW > cd liteide/build > update_pkg.cmd > build_windows_mingw.cmd > deploy_windows_qt4.8_webkit.cmd **Qt5.6** > git clone https://github.com/visualfc/liteide.git > set QTDIR=C:\Qt\Qt5.6.2\5.6\mingw49_32 > set MINGWDIR=C:\Qt\Qt5.6.2\Tools\mingw492_32 > cd liteide/build > update_pkg.cmd > build_windows_mingw.cmd > deploy_windows_qt5.6.cmd ### Ubuntu 16.04 Qt4 ## Install Qt4 ## $ sudo apt-get update $ sudo apt-get install libqt4-dev ## Git clone and build liteide ## $ git clone https://github.com/visualfc/liteide.git $ cd liteide/build $ ./update_pkg.sh $ ./build_linux_qt4.sh ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide ## Deploy it: ## $ cd liteide/build $ ./deploy_linux_x64_qt4.sh ## 32 bit $ ./deploy_linux_x32_qt4.sh ### Ubuntu 16.04 Qt5 ## Install Qt5 ## $ sudo apt-get update $ sudo apt-get install qt5-default ## Git clone and build liteide ## $ git clone https://github.com/visualfc/liteide.git $ cd liteide/build $ ./update_pkg.sh $ ./build_linux_qt5.sh ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide ## Deploy it: ## $ cd liteide/build $ ./deploy_linux_x64_qt5.sh ## 32 bit $ ./deploy_linux_x32_qt5.sh ### Ubuntu 14.04 $ git clone https://github.com/visualfc/liteide.git $ sudo apt-get update $ sudo apt-get install qt4-dev-tools libqt4-dev libqt4-core libqt4-gui libqtwebkit-dev g++ $ cd liteide/build $ ./update_pkg.sh $ QTDIR=/usr ./build_linux.sh ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide ### Linux $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=$HOME/QtSDK/Desktop/Qt/484/gcc $ cd liteide/build $ ./update_pkg.sh $ ./build_linux.sh $ ./deploy_linux_qt4.8_webkit.sh ### Mac OS X / macOS **Qt 4** $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=$HOME/QtSDK/Desktop/Qt/484/gcc #如果Qt是通过brew安装,输入: export QTDIR=/usr/local/Cellar/qt/4.8.6 $ cd liteide/build $ ./update_pkg.sh $ ./build_maoos_qt4.sh $ ./deploy_macos_qt4.sh $ open liteide/LiteIDE.app **Qt 5 sdk install** 从 http://www.qt.io/download 下载并安装Qt. (Qt5.6.2/Qt5.7.1/Qt5.8) $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=$HOME/Qt5.6.2/Qt5.6/clang_64 $ cd liteide/build $ ./update_pkg.sh $ ./build_macos_qt5.sh $ ./deploy_macos_qt5.sh $ open liteide/LiteIDE.app **Qt 5 brew install** 使用 brew 安装 Qt. (比如使用 brew install qt. 其他版本如 qt@5.5 qt@5.6 qt@5.7 ). $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=/usr/local/Cellar/qt/5.8.0_2 # or modify accordingly for qt@5.5 and qt@5.7 $ cd liteide/build $ ./update_pkg.sh $ ./build_macos_qt5.sh $ open liteide/LiteIDE.app 警告! 使用 brew 安装的 Qt rpath 不正确,不要使用 deploy 脚本进行打包。 ### OpenBSD $ git clone https://github.com/visualfc/liteide.git $ export QTDIR=/usr/local/lib/qt4 $ cd liteide/build $ ./update_pkg.sh $ ./build_openbsd.sh ## Run it: ## $ export LD_LIBRARY_PATH=$HOME/liteide/build/liteide/bin:$LD_LIBRARY_PATH $ cd liteide/build/liteide/bin $ ./liteide ### Raspbian Jessie $ sudo apt-get update $ sudo apt-get install qt5-default xterm $ git clone https://github.com/visualfc/liteide.git $ cd liteide/build $ ./update_pkg.sh $ QTDIR=/usr ./build_linux.sh The build process from a µSD card takes approx. 105 minutes on a RPi 2. ## Run it: ## $ cd liteide/build/liteide/bin $ ./liteide **补充:** 根据自己的环境设置好 `QTDIR` (在Windows上还需要设置`MINGWDIR`) ================================================ FILE: liteidex/deploy/welcome/zh_CN/liteide.html ================================================ LiteIDE Documentation

LiteIDE Documentation

{header}

{content}
================================================ FILE: liteidex/deploy/welcome/zh_CN/readme.md ================================================ LiteIDE X ========= ### 简介 _LiteIDE 是一个轻量级的开源跨平台 Go语言 IDE._ * 版本: X38.4 * 作者: [七叶 (visualfc)](mailto:visualfc@gmail.com) ### 功能 * 核心功能 * 系统环境管理 * MIME类型管理 * 可配置编译命令 * 支持文件搜索替换和恢复 * 快速打开文件、符号和命令 * 插件系统 * 高级代码编辑器 * 代码编辑支持 Go语言、Markdown 和 Golang Present * 快速代码导航工具 * 语法高亮和配色方案 * 代码完成 * 代码折叠 * 显示保存修订 * 重读文件使用代码差异方式 * Go 语言支持 * 支持 Go1.18~Go1.21 泛型 * 支持 Go1.11 Go modules * 支持 Go1.5 Go vendor * 支持 Go1 GOPATH * Go 编译环境管理 * 使用标准 Go 工具编译和测试 * 自定义 GOPATH 支持 系统定义、IDE 定义和项目定义 * 自定义项目编译配置 * Go 包浏览器 * Go 类视图和大纲 * Go 文档搜索和 API 索引 * 代码导航和信息提示 * 代码查找引用 * 代码重构和恢复 * 集成 [gocode](https://github.com/visualfc/gocode) clone of [nsf/gocode](https://github.com/nsf/gocode) * 集成 [gomodifytags](https://github.com/fatih/gomodifytags) * 支持代码查询工具 guru * 调试支持 GDB 和 [Delve](https://github.com/derekparker/delve) ### 系统支持 * Windows x86 (32-bit or 64-bit) * Linux x86 (32-bit or 64-bit) * MacOS X10.6 or higher (64-bit) * FreeBSD 9.2 or higher (32-bit or 64-bit) * OpenBSD 5.6 or higher (64-bit) ### LiteIDE 命令行 liteide [files|folder] [--select-env id] [--local-setting] [--user-setting] [--reset-setting] --select-env [system|win32|cross-linux64|...] 选择初始环境ID --local-setting 强制使用本地配置 --user-setting 强制使用用户配置 --reset-setting 重置当前配置 ( 清除配置文件 ) ### 更新 liteide 工具支持新的 Go语言版本 go get -u github.com/visualfc/gotools go get -u github.com/visualfc/gocode Windows/Linux: 复制 GOPATH/bin gotools 和 gocode 到 liteide/bin MacOS: 复制 GOPATH/bin gotools 和 gocode 到 LiteIDE.app/Contents/MacOS ### 网址 * LiteIDE 主页 * * 源代码下载 * * 发行版下载 * * Google用户组 * * FAQ * * 支持LiteIDE * ================================================ FILE: liteidex/deploy/welcome/zh_CN/shortcuts.html ================================================

Key Shortcuts

These are the default shortcuts for LiteIDE. Note that you can customize these in "View > Options > LiteApp > Keyboard".

Standard
NewCtrl+N
OpenCtrl+O
SaveCtrl+S
CloseCtrl+W
Full ScreenCtrl+Shift+F11
Next TabCtrl+Tab
Prev TabCtrl+Shift+Tab
Hide Bottom WindowsESC
Execute FileCtrl+`
Editor
CutCtrl+X
CopyCtrl+C
PasteCtrl+V
UndoCtrl+Z
RedoCtrl+Shift+Z,Ctrl+Y
PasteCtrl+V
DuplicateCtrl+D
Delete LineCtrl+Shift+K
Select AllCtrl+A
Select BlockCtrl+U
Goto Match BraceCtrl+E
Goto Previous BlockCtrl+[
Goto Next BlockCtrl+]
Goto LineCtrl+G
Fold BlockCtrl+<
Unfold BlockCtrl+>
Increase Font SizeCtrl++
Decrease Font SizeCtrl+-
Reset Font SizeCtrl+0
Go BackwardAlt+←
Go ForwardAlt+→
InsertLineAfterCtrl+Enter
InsertLineBeforeCtrl+Shift+Enter
Code CompleterCtrl+Space
Code Completer List NextCtrl+N
Code Completer List PrevCtrl+P
Golang Editor
Code expression infoCtrl+Shift+I; F1 ; Ctrl+?(MacOS X)
Jump to declarationCtrl+Shift+J; F2
Find UsagesCtrl+Shift+U
Rename Symbol Under CursorCtrl+Shift+R
GofmtShift+F7
Comment/UncommentCtrl+/
Find
FindCtrl+F
Find NextF3
Find PreviousShift+F3
ReplaceCtrl+H
Find in FileCtrl+Shift+F
Build
BuildCtrl+B, F7
InstallCtrl+F8
TestCtrl+T
RunCtrl+F5
Build and RunCtrl+R
Run in TermCtrl+Shift+F5
File RunAlt+F6
Debug
DebugF5
ContinueF5
Insert/Remove BreakPointF9
Stop DebugShift+F5
Step InfoF11
Step OverF10
Step OutShift+F11
Run to LineShift+F10
Markdown Editor
BoldCtrl+B
ItalicCtrl+I
H1-H6Ctrl+1,...,Ctrl+6
Inline CodeCtrl+K
LinkCtrl+Shift+L
ImageCtrl+Shift+I
Unordered ListCtrl+Shift+U
Ordered ListCtrl+Shift+O
BlockquoteCtrl+Shift+Q
Horizontal RuleCtrl+Shift+H
================================================ FILE: liteidex/deploy/welcome/zh_CN/website.md ================================================ ### LiteIDE * [LiteIDE Source](https://github.com/visualfc/liteide) * [LiteIDE Download](http://sourceforge.net/projects/liteide/files) * [Support LiteIDE](http://visualfc.github.com/support) ### LiteIDE Markdown * Markdown parser from [sundown](https://github.com/vmg/sundown) * Markdown CSS files from [Mou](http://mouapp.com) ### Golang * [Golang Home](http://golang.org) * [Golang Source](http://code.google.com/p/go) ### Golang Tools * Golang code compliter form [gocode](https://github.com/nsf/gocode) * Golang code format form [goimports](https://github.com/bradfitz/goimports) * Go Package Manager [gopm](https://github.com/gpmgo/gopm) ### Golang Package Doc * [GoWalker](http://gowalker.org/) * [GoDoc](http://godoc.org) ================================================ FILE: liteidex/deploy/welcome/zh_CN/welcome.html ================================================ LiteIDE

欢迎使用 LiteIDE X

版权所有 2011-2023, 作者 七叶 (visualfc), 版本 {liteide_version}
================================================ FILE: liteidex/export_qrc.cmd ================================================ @echo off if defined %GOPATH ( set GOPATH=%CD%;%GOPATH% ) else ( set GOPATH=%CD% ) go run src/tools/exportqrc/main.go -root . ================================================ FILE: liteidex/export_qrc.sh ================================================ #!/bin/sh go run src/tools/exportqrc/main.go -root . ================================================ FILE: liteidex/install-icon.sh ================================================ #!/bin/bash SCRIPT=$(readlink -f $0) SCRIPTPATH=`dirname $SCRIPT` echo " [Desktop Entry] Type=Application Name=LiteIDE Comment=IDE for editing and building projects written in the Go programming language Exec=${SCRIPTPATH}/bin/liteide Icon=${SCRIPTPATH}/share/liteide/welcome/images/liteide128.xpm Terminal=false StartupNotify=false Categories=Development; " > ./liteide.desktop # must run with current user instead of root cp ./liteide.desktop ~/Desktop/ chmod u+x ~/Desktop/liteide.desktop #desktop-file-validate ./liteide.desktop #desktop-file-install ./liteide.desktop ================================================ FILE: liteidex/linux_deploy.sh ================================================ #!/bin/sh cp -v LICENSE.LGPL liteide cp -v LGPL_EXCEPTION.TXT liteide cp -v ../README.md liteide mkdir -p liteide/share/liteide/ cp bin/gotools liteide/bin cp bin/gocode liteide/bin cp bin/gomodifytags liteide/bin cp -r -v deploy/* liteide/share/liteide/ cp -r -v os_deploy/linux/* liteide/share/liteide/ ================================================ FILE: liteidex/liteide.desktop ================================================ [Desktop Entry] #Encoding=UTF-8 Type=Application Name=LiteIDE Comment=IDE for editing and building projects written in the Go programming language #Exec=/... your liteide path .../liteide/bin/liteide #Icon=/... your liteide path .../liteide/share/liteide/welcome/images/liteide128.xpm Exec=liteide Icon=liteide Terminal=false StartupNotify=false Categories=Development; # desktop-file-validate ./liteide.desktop # desktop-file-install ./liteide.desktop ================================================ FILE: liteidex/liteide_de.ts ================================================ AboutDialog About LiteIDE About Liteide Über LiteIDE Information Infomation Informationen Welcome: Willkommen: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Willkommen in LiteIDE X! LiteIDE ist eine einfache, quelloffene, plattformunabhängige IDE. Project: Projekt: Name: Name: Author: Autor: Version: Version: Build: Based on Qt Based on Qt Version Basierend auf Qt Source Code: Quelltext: Support LiteIDE: Support Unterstütze LiteIDE: Developers Entwickler Translations Übersetzungen Chinese Chinesisch Japanese Japanisch Russian Russisch French Französisch Traditional Chinese Traditionelles Chinesisch German Deutsch Ukrainian Thanks to... Danke an... License Lizenz Close Schließen Based on Qt %1 (%2 bit) Basierend auf Qt %1 (%2 bit) ActionManager &File On Linux and Windows the menu item is called "Datei", but "Ablage" on Mac OS. &Datei &Recent Note to the Developer: This shoud be a sub menu of "File" ("Ablage") &Zuletzt verwendet &Edit &Bearbeiten F&ind &Find &Suchen &View &Ansicht &Tools &Build Ausführen &Debug &Debug &Help &Hilfe Standard Toolbar Standard ToolBar Standardwerkzeugleiste AstWidget Go To Definition Springe zu Definition View Import Document Not sure about that Import-Dokument ansehen BaseDockWidget Hide Ausblenden Hide Tool Window Werkzeugfenster ausblenden Floating Window BaseFolderView Open In New Window Open File Datei öffnen New File... Neue Datei... New File Wizard... Neue Datei Assistent... Rename File... Datei umbenennen... Delete File Datei löschen New Folder... Neuer Ordner... Rename Folder... Ordner umbenennen... Delete Folder Ordner löschen Open Terminal Here Terminal hier öffnen Show in Explorer Open Explorer Here Im Dateimanager öffnen Open Application Show in Finder Show Containing Folder Open Command Prompt Here Open in Integrated Terminal Open Folder... Add Folder... Ordner hinzufügen... Reload Folder Close Folder Ordner schließen Close All Folders Alle Ordner schließen Copy Kopieren Paste Einfügen Copy Path Move To Trash Create File Datei erstellen A file with that name already exists! Eine Datei mit diesem Namen existiert bereits! Failed to create the file! Die Datei konnte nicht erstellt werden! Rename File Datei umbenennen New Name: Neuer Name: Failed to rename the file! Die Datei konnte nicht umbenannt werden! An item "%1" already exists in this location. Do you want to replace it and move old item to trash? Stop Stop Keep Both Keep Both All Replace Ersetzen Replace All Alle ersetzen Are you sure that you want move to trash this item? Are you sure that you want move to trash %1 items? Move to Trash Open With System Editor Create Folder Ordner erstellen A folder with that name already exists! Ein Ordner mit diesem Namen existiert bereits! Failed to create the folder! Der Ordner konnte nicht erstellt werden! Rename Folder Ordner umbenennen Folder Name Ordnername Failed to rename the folder! Der Ordner konnte nicht umbenannt werden! Are you sure that you want to permanently delete this folder and all of its contents? Sind Sie sicher, dass Sie den ganzen Ordner und dessen Inhalt unwiderruflich löschen wollen? Failed to delete the folder! Der Ordner konnte nicht gelöscht werden! BookmarkManager Toggle Bookmark Goto bookmark Remove bookmark Remove all bookmarks for this file Remove all bookmarks for all files Bookmarks BookmarkRecent Bookmarks BuildConfigDialog Build Configuration Build Config Dialog Build Konfiguration Build ID Build ID Build Path Build File Build Pfad GOPATH GOPATH information Use Custom GOPATH for Build Path Inherit System GOPATH Inherit LiteIDE GOPATH Custom GOPATH (one per line) Add Directory... Ordner hinzufügen... Clear LiteIDE LiteIDE Config Konfiguration Action Custom Build Custom Benutzerdefiniert Reset all to initial value Name Name Value Wert SharedValue Id Cmd Choose directory to add to GOPATH: Verzeichnis zu GOPATH hinzufügen: CreateDirDialog Create Folder Ordner erstellen Directory: Ordner: Dir Name: Create Erstellen Cancel Abbrechen CreateFileDialog Create File Create File Dialog Datei erstellen Directory: Ordner: File Name: Dateiname: Create Erstellen Create and Edit Erstellen und bearbeiten Cancel Abbrechen DebugWidget Add Watch Async Record AsyncRecord Variables Variablen Watch Überwachen Call Stack CallStack Threads Goroutines Registers Libraries Library Bibliotheken Console Konsole Watch expression (e.g. buf main.var os.Stdout): Remove Watch Überwachung entfernen Remove All Watches Alle Überwachungen entfernen DlvDebuggerOption Form Formular delve debug pass flags: (example --check-go-version=false) DocumentBrowser Back Backward Zurück Forward Weiter Reload Neu laden Increase Font Size Schrift vergrößern Decrease Font Size Schrift verkleinern Reset Font Size Schriftgröße zurücksetzen DocumentBrowserFactory DocumentBrowser EditorManager Close Schließen Move to New Window Move To New Window In neues Fenster verschieben Navigate Forward GoForward Gehe weiter Close Others Close Others Tabs Andere Tabs schließen Open Editor Close All Close All Tabs Alle Tabs schließen Close Left Tabs Tabs links schließen Close Right Tabs Tabs rechts schließen Close Files in Same Folder Close Same Folder Files Dateien aus gleichem Ordner schließen Close Files in Other Folders Close Other Folder Files Dateien aus anderen Ordnern schließen Copy Full Path to Clipboard Copy Path to Clipboard Vollständigen Pfad in die Zwischenablage legen Show in Explorer Im Dateimanager öffnen Show in Finder Show Containing Folder Open Command Prompt Here Open Terminal Here Terminal hier öffnen Open in Integrated Terminal Navigate Backward Gehe zurück Save changes to %1? Änderung an %1 speichern? Unsaved Modifications Save Modify Ungesicherte Änderungen All Files (*) Alle Dateien (*) Save As Speichern unter EnvManager Environment Toolbar Environment ToolBar Umgebungswerkzeugleiste Switching current environment Switch Current Environment Umgebung Edit current environment Edit Current Environment Umgebung bearbeiten Reload current environment Reload Current Environment Select Environment ExportDialog Dialog Export-Dialog Name: Name: Export Exportieren ExportAndView Exportieren und anzeigen FakeVim::Internal Use Vim-style Editing Read .vimrc Path to .vimrc FakeVim::Internal::FakeVimHandler Unknown option: %1 Argument must be positive: %1=%2 Mark "%1" not set. %1%2% %1All Not implemented in FakeVim. Unknown option: Invalid argument: Trailing characters: Move lines into themselves. %n lines moved. File "%1" exists (add ! to override) Cannot open file "%1" for writing "%1" %2 %3L, %4C written. Cannot open file "%1" for reading "%1" %2L, %3C %n lines filtered. Cannot open file %1 Invalid regular expression: %1 Pattern not found: %1 Search hit BOTTOM, continuing at TOP. Search hit TOP, continuing at BOTTOM. Search hit BOTTOM without match for: %1 Search hit TOP without match for: %1 %n lines indented. %n lines %1ed %2 time. %n lines yanked. Already at oldest change. Already at newest change. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Type Alt-V, Alt-V to quit FakeVim mode. [New] Not an editor command: %1 FakeVimEdit Use FakeVim Editing FakeVimEditOption Form Formular FakeVim initialization command list (# start is comment): Load default init command list FiFoTty Cannot create temporary file: %1 Temporäre Datei kann nicht erstellt werden: %1 Cannot create FiFo %1: %2 FiFo kann nicht erstellt werden %1:%2 Cannot open FiFo %1: %2 FiFo kann nicht geöffnet werden %1:%2 FileBrowser Synchronize with editor Mit Editor synchronisieren Show Hidden Files Versteckte Dateien anzeigen Set As Root Folder Set Folder To Root Ordner als Root setzen Execute File Datei ausführen Reload Folder Show Details Debug File Open Folder in New Window Öffne Ordner in neuem Fenster Add to Folders Zu Ordnern hinzufügen Open Parent Open to Parent Übergeordneten Ordner öffnen Filter File System Dateisystem FileBrowserOption Form Formular Terminal Terminal Command: Kommando: Arguments: Argumente: FileManager All Files (*) Alle Dateien (*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? Projekt '%1' wurde erstellt. Soll es geöffnet werden? Open Project or File Projekt oder Datei öffnen Show Hidden Files Versteckte Dateien anzeigen Folders Folers Ordner All Support Files (%1) Alle unterstützen Dateien (%1) Select a folder: Open Folder Ordner auswählen: %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 This file has been deleted from the drive. Do you want to close the editor? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 This file has been modified on the drive. Do you want to reload the file from disk? Open Files Dateien öffnen Show Details Synchronize with editor Mit Editor synchronisieren Split Mode Filter Open Project Projekt öffnen LiteIDE X LiteIDE X FileRecent Files FileSearch Match whole word Match word Nur ganzes Wort Match case Groß-/Kleinschreibung Regular expression Regulärer Ausdruck Scan subdirectories Look in subdirs Unterordner durchsuchen Search for: Suche nach: Options: Optionen: Browse... Browser Durchsuchen... Filter: Filter: Files on File System Dateien im Dateisystem Search Suche Cancel Abbrechen Current Folder Auto Switch Clear Leeren Open Directory Öffne Ordner FileSearchManager Search Item: Gegenstand: Only golang file changes can be revert! This file change cannot be undone! Diese Dateiänderung kann nicht rückgängig gemacht werden! New Search Neue Suche File Search Dateisuche Search Result Suchergebnis LiteIDE X LiteIDE X Warning! Replace text is empty. Want to remove all the search items? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? The following files have no write permissions. Do you want to change the permissions? Die folgenden Dateien haben keine Schreibrechte. Möchten Sie die Berechtigungen ändern? File is readonly Datei ist nur lesbar FileSystemWidget Open File Open Editor Datei öffnen New File... New File Neue Datei... New File Wizard... New File Wizard Neue Datei Assistent... Rename File Datei umbenennen Delete File Remove File Datei löschen New Folder... New Folder Neuer Ordner... Are you sure that you want to permanently delete this file? Sind Sie sicher, dass Sie diese Datei unwiderruflich löschen wollen? Rename Folder Ordner umbenennen Delete Folder Remove Folder Ordner löschen Rename File... Datei umbenennen... Rename Folder... Ordner umbenennen... Open Terminal Here Terminal hier öffnen Open Explorer Here Dateimanager hier öffnen View Godoc Here Godoc hier anzeigen Add Folder Ordner hinzufügen Close Folder Ordner schließen Add Folder... Ordner hinzufügen... Close All Folders Alle Ordner schließen Create File Datei erstellen A file with that name already exists! The file already exists! Eine Datei mit diesem Namen existiert bereits! Failed to create the file! Die Datei konnte nicht erstellt werden! New Name: Neuer Name: Failed to rename the file! Die Datei konnte nicht umbenannt werden! Are you sure that you want to permanently delete this folder and all of its contents? Sind Sie sicher, dass Sie den ganzen Ordner und dessen Inhalt unwiderruflich löschen wollen? Failed to delete the file! Failed to remove the file! Die Datei konnte nicht gelöscht werden! Create Folder Ordner erstellen A folder with that name already exists! The folder name is exists! Ein Ordner mit diesem Namen existiert bereits! Failed to create the folder! Der Ordner konnte nicht erstellt werden! Folder Name Ordnername Failed to rename the folder! Der Ordner konnte nicht umbenannt werden! Failed to delete the folder! Failed to remove the folder! Der Ordner konnte nicht gelöscht werden! Find::Internal::SearchResultWidget Search was canceled. Die Suche wurde abgebrochen. Cancel Abbrechen Repeat the search with same parameters Suche mit gleichen Parametern wiederholen Search again Erneut suchen Set show replace mode ui Show Replace Replace with: Ersetzen mit: Replace all occurrences Alle Vorkommen ersetzen Replace Ersetzen Preserve case Groß-/Kleinschreibung beibehalten Expand all items Collapse all items Revert with: Revert Revert all occurrences %n matches replaced. searching... %n matches found. searching ... No matches found. Keine Treffer. %n matches found. %n Treffer. %n Treffer. FindApiEdit Search Suche Stop Search Suche abbrechen FindApiWidget Search Suche Find Suchen FindDocWidget Search Suche Find Suchen Find All Alle suchen Find const Suche const Find func Suche func Find interface Suche interface Find pkg Suche pkg Find struct Suche struct Find type Suche type Find var Suche var Use Regexp Benutze regulären Ausdruck Match Case Groß-/Kleinschreibung beachten Match Word Nur ganzes Wort Help Hilfe FindEditor Match case Groß-/Kleinschreibung Regular expression Regulärer Ausdruck Wrap around Am Dateiende von vorn beginnen Find Next Weitersuchen Find Previous Find Prev Vorheriges Replace With: Ersetzen mit: Replace Ersetzen Replace All Alle ersetzen Match whole word only Nur ganzes Wort Ready Bereit Close Schließen Show Replace Find What: Suche nach: Options: Find Option: Optionen: Not found Nicht gefunden FolderListView Delete File Datei löschen Are you sure that you want to permanently delete this file? Sind Sie sicher, dass Sie diese Datei unwiderruflich löschen wollen? Failed to delete the file! Die Datei konnte nicht gelöscht werden! Delete Folder Ordner löschen Are you sure that you want to permanently delete this folder and all of its contents? Sind Sie sicher, dass Sie den ganzen Ordner und dessen Inhalt unwiderruflich löschen wollen? Failed to delete the folder! Der Ordner konnte nicht gelöscht werden! FolderRecent Folders Ordner FolderView Delete File Datei löschen Are you sure that you want to permanently delete this file? Sind Sie sicher, dass Sie diese Datei unwiderruflich löschen wollen? Failed to delete the file! Die Datei konnte nicht gelöscht werden! Delete Folder Ordner löschen Are you sure that you want to permanently delete this folder and all of its contents? Sind Sie sicher, dass Sie den ganzen Ordner und dessen Inhalt unwiderruflich löschen wollen? Failed to delete the folder! Der Ordner konnte nicht gelöscht werden! GdbDebuggerOption Form Formular Enable --tty for program being debugged. Aktiviere --tty für das untersuchte Programm. GoAddTagsDialog Add Tags To Struct Field Add JSON Tag Options Optionen Multiple options separated by commas Multiple options are separated by commas Add XML Tag Add Custom Tags Tag Name Setup custom tag name Sort sorts the tags in increasing order according to the key name Override current tags when adding tags Info Info GoRemoveTagsDialog Remove Tags From Struct Field Remove Tags And Options Clear All Tags Clear All Tags Options Clear All Tag Options Remove JSON Tag Remove XML Tag Remove Custom Tag Multiple tags separated by commas Multiple tags are separated by commas Remove JSON Options Multiple options separated by commas Multiple options are separated by commas Remove XML Options Remove Custom Tag Options Setup remove custom tag and option, example tag=opt1,tag=opt2 Setup remove custom tag option, example tag=opt1,tag=opt2 tag=option Info Info GolangAst No outline available Keine Übersicht verfügbar Synchronize with editor Mit Editor synchronisieren Go Class View Class View Klassen Go Outline Outline Übersicht GolangAstOption Form Formular QuickOpenSymbol Show import path Match case sensitive GolangCodeOption Form Formular PKG automitic import prompt PKG automatic import hints for all packages (GOPATH) PKG automatic import hints for standard package Gocode Go API Auto update depends package when it's source changed. Auto update depends package when its source is changed. Close gocode when exiting Gocode beim Verlassen beenden GolangDoc Godoc Search Godoc Suche Go Doc Search Golang Doc Search Golang Doc Suche Go Api Index Golang Api Index Find Package: GolangDocOption Form Formular Go API Use default context (fast) Standardkontext benutzen (schnell) Only load standard API documentation Only load standard api Nur Standard-Api-Dokumentation laden GolangEdit View import package use godoc View Expression Information Zeige Ausdrucks-Information Jump to Declaration Zur Deklaration springen Find Usages Nutzungen suchen Rename Symbol Under Cursor Symbol unter Cursor umbenennen %1 (Module/GOPATH) with GOROOT Stop Stop Go Source Query SourceQuery What Callees Callers Callstack Definition Describe Freevars Implements Implements(GOPATH) Peers Referrers Pointsto Whicherrs Add Tags To Struct Field Remove Tags From Struct Field Refactor Refaktor SourceQuery Below files in package %1 GolangEditOption Form Formular Mouse Go root source file editor setup read only Enable view expression infomation on mouse Enable mouse navigation GolangFileSearch Golang Find Usages Golang Nutzungen suchen GolangFmtOption Form Formular Format Options Golang Format Format-Optionen Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Goimports aktualisiert die Go-import-Zeilen, fügt fehlende hinzu und entfernt unbenutzte. Enable update imports line, adding missing ones and removing unreferenced ones. Synchronous Fortlaufende Formatierung Synchronous code formatting Synchronous code formatting Fortlaufende Code-Formatierung benutzen Synchronous code formatting timeout in milliseconds (500ms or more): Timeout für die fortlaufende Formatierung in Millisekunden (>= 500ms): Automatically format code when saving When the editor is saved automatically gofmt Code beim Speichern automatisch formatieren GolangFmtPlugin Format Code Format Code (goimports) Code formatieren Format Code (Adjusts Imports) GolangPackageOption Choose directory to add to GOPATH: Verzeichnis zu GOPATH hinzufügen: Manage GOPATH / Modules GOPATH verwalten Go Modules Custom GONOPROXY Custom GOPROXY Custom GO111MODULE Custom GONOSUMDB Custom GOPRIVATE TextLabel GOPATH Use System GOPATH Reload Neu laden Use Custom GOPATH (one per line) Add Directory... Ordner hinzufügen... Clear GolangPresentEdit Section (s1) Subsection (s2) Sub-subsection (s3) Bold Fett Italic Kursiv Inline Code Eingebetteter Code Switch Bullets Bullets umschalten Comment/Uncomment Selection Auswahl kommentieren/auskommentieren Export HTML Exportiere HTML Verify Present Present verify success Present verify false Export PDF Exportiere PDF GolangSymbol Quick Open Symbol by Name GoplayBrowser Go Playground Go Spielwiese Run Ausführen Stop Stop New Neu Load... Laden... Save... Speichern... Explore Folder Ordner untersuchen Running... Running... Führe aus... Error: %1. Error: %1. Fehler: %1. Success: %2. Success: %2. Erfolg: %2. Load File Datei laden Select a file to load: Datei auswählen: Save File Datei speichern New File Name: Neuer Dateiname: HtmlPreview Page Style Seitenstil Reload Neu laden Export Html Exportiere HTML Export PDF Exportiere PDF Print Preview Druckvorschau Synchronize preview and code scrollbars Scrollbalken von Code und Vorschau synchronisieren Config Konfiguration Plain HTML Flaches HTML Export Failed Export fehlgeschlagen Automatically display preview Automatically Display Preview Vorschau automatisch anzeigen HTML Preview Html Preview HTML-Vorschau Could not open %1 for writing! Can not write file %1 Kann Datei %1 nicht schreiben! ImageEditor ZoomIn ZoomOut Reset to original size Fit to view Play movie Prev frame Next frame Pause movie ImageEditorFactory Image Viewer ImportPkgTip warning, pkg not find, please enter to import : Achtung: Pkg nicht gefunden, bitte eingeben: JsonEdit Verify Prüfen Format Json Compact Json LiteApp Event Log Ereignisanzeige Escape Close File Datei schließen Close All Files Alle Dateien schließen Save File Datei speichern Save File As... Datei speichern unter... Save All Files Alle Dateien speichern Open Project Projekt öffnen Options Optionen New... Neu... Open File... Datei öffnen... Open Folder... Ordner öffnen... Open Folder in New Window... Ordner in neuem Fenster öffnen... Close All Folders Add Folder... Ordner hinzufügen... New Window Neues Fenster Close Window Fenster schließen Save Project Projekt speichern Close Project Projekt schließen Exit Beenden Full Screen Vollbild About LiteIDE Über LiteIDE About Plugins Über Plugins LiteAppOption Form Formular Store [*] Store Speicherort Language: Sprache: Icon [*] Reload files in session Recent Files Recent File Zuletzt verwendete Dateien Max Count: Max Recent: Maximale Anzahl: Monitoring files for modifications Überwache Dateiveränderungen Store settings to local ini file Interface [*] Style: Use tool window shortcuts Theme [*] Fallback build-in icon library and liteapp/qrc/default Load the external file icon library Load custome icon from liteapp/qrc folder Automatically save documents Automatically save documents when application is idle sec Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. Automatisches Neuladen oder Schließen des Editor-Fensters, wenn die darunter liegende Datei verändert oder gelöscht wurde. Session 0-99 Editor Tabs 10-999 Display Anzeige Display [*] Show splash screen on startup Splash-Screen beim Start zeigen Show welcome page on startup Willkommen-Seite beim Start zeigen Editor Editor tab [*] Show close buttons on each editor tab "Schließen"-Knopf bei jedem Editor-Tab anzeigen Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab Toolbar Icon Size [*] Editor navigate Enable mouse extra 'Back' button and 'Forward' button for go back and forward Keyboard Tastatur Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Formatierung: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands Standard-Kommandos verbergen Reset Zurücksetzen Reset All Alles zurücksetzen Import... Importieren... Export... Exportieren... Generic Generisch Theme: Theme: Reload session on startup Auto load last session Automatisch letzte Session laden SideBarStyle SplitterStyle Command Kommando Label Label Shortcuts Shortcuts NativeText Standard Standard Import Keyboard Mapping Scheme Tastaturbelegungsschema importieren Keyboard Mapping Scheme (%1) Tastaturbelegungsschema (%1) Could not read scheme from %1! Schema (%1) kann nicht gelesen werden! Export Keyboard Mapping Scheme Tastaturbelegungsschema exportieren Could not write scheme to %1! Schema (%1) kann nicht geschrieben werden! LiteBuild Build Toolbar Build Configuration... Build Config Build Konfiguration... Stop Action Aktion stoppen Clear Output Clear All Ausgabe löschen Execute File Datei ausführen Debug File Lock Build Path Lock Go Build Path Build Path Configuration Go Build Configuration Use godoc View Line Wrap Auto Clear Automatic positioning cursor Setup Build Output Build Build Ausgabe Current environment change id "%1" Id "%1" der aktuellem Umgebung ändern Lock Build Lock Build: %1 Error: %1. Error: %1. Fehler: %1. Command exited with code %1. Prozess beendet mit Rückgabewert %1. Success: %1. Success: %1. Erfolg: %1. A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. Es wird bereits ein Prozess ausgeführt. Bitte beenden Sie die aktuelle Aktion zuerst. Killing current process... Killing current process... Beende aktuellen Prozess... Failed to terminate the existing process! Failed to terminate the existing process! Der Prozess konnte nicht beendet werden! Started process successfully Started process successfully Prozess erfolgreich gestartet Failed to start process Prozess konnten nicht gestartet werden LiteBuildOption Form Formular Recheck Go installation when changing environments Recheck go env if enviroment changed Prüfe go env ob die Umgebung sich geändert hat Build command configuration files [*] Build command configuration files: Konfigurationsdateien des Build-Kommandos: LiteBuildPlugin Close Schließen Execute: Exec: Ausführen: Execute File Execute Datei Ausführen LiteDebug Stop Stop Clear Löschen Continue Fortfahren Show Current Line Aktuelle Zeile anzeigen Debug Output Debug Debug Ausgabe Start Debugging External Application... Start Debugging External Application Starte Debugging einer externen Anwendung... Close Schließen Start Debugging Starte Debugging Step Into Step Over Step Out Run to Line Ausführung bis zur Zeile Insert/Remove Breakpoint Breakpoint einfügen/entfernen Remove All Breakpoints Alle Breakpoints entfernen LiteDebugOption Form Formular Debug Debug Automatically insert breakpoint main.main when debugging Automatically add breakpoint main.main when debugging LiteDebugPlugin Debug Window Debug Debug Fenster LiteDoc LiteIDE Documentation LiteIDE Document Browser LiteIDE Dokumentation LiteEditor Undo Rückgängig Redo Wiederholen Cut Ausschneiden Copy Kopieren Paste Einfügen Select All Alles auswählen Go to Doc Start Go to Doc End Go to Line Start Go to Line End Go to Previous Line Go to Next Line Go to Previous Character Go to Next Charater Go to Previous Word Go to Next Word Go to Line File is readonly Datei ist nur lesbar File is writable Line Wrap (MimeType) Word Wrap (MimeType) Toggle Comment Toggle Block Commnet Auto-indent Selection Tab To Spaces (MimeType) Line End Windows (\r\n) Line End Unix (\n) Visualize Whitespace (Global) Move Line Up Move Line Down Copy Line Up Copy Line Down Join Lines Title Case Upper Case Lower Case Swap Case Tab To Spaces Spaces To Tab Advanced Erweitert Goto Convert Tab Code Folding Code-Faltung Convert Case Export HTML Exportiere HTML Export Failed Export fehlgeschlagen Could not open %1 for writing. Konnte %1 nicht zum Schreiben öffnen. Export PDF Exportiere PDF Print Document Dokument drucken Print Preview... Print Preview Document Druckvorschau... Export HTML... Exportiere HTML... Export PDF... Exportiere PDF... Print... Drucken... Go to Previous Block Go To Previous Block Zu vorherigem Block springen Select Block Block auswählen Go to Matching Brace Go To Matching Brace Springe zu passender Klammer Fold Einklappen Unfold Ausklappen Fold All Alle einklappen Unfold All Alle ausklappen Go To Line Goto Line Springe zu Zeile Duplicate Duplizieren Delete Line Zeile löschen Copy Line Cut Line Insert Line Before Zeile einfügen vor Insert Line After Zeile einfügen nach Increase Font Size Schriftgröße erhöhen Decrease Font Size Schriftgröße verringern Reset Font Size Schriftgröße zurücksetzen Clean Whitespace Whitespaces bereinigen Code Complete Code vervollständigen Settings File Setup Reload File Datei neu laden Do you want to permanently discard unsaved modifications and reload %1? Möchten Sie ihre Änderungen verwerfen und die Datei neu laden: %1? Go to Next Block Go To Next Block Springe zu nächstem Block ReadOnly Line: Zeile: LiteEditorFileFactory Text Editor LiteEditorOption Form Formular Load File Datei laden Check and convert no printable char to '.' Prüfe und konvertiere nicht druckbare Zeichen zu '.' Font Schrift Font && Colors Schrift && Farben Family: Familie: Show Monospace Font Size: Größe: Zoom: Zoom: % % Antialias Kanten glätten Restore Default Font Editor Color Scheme ColorStyle Scheme Farbschema (Editor) File: Datei: Edit Bearbeiten Syntax Auto-completion Auto complete brackets Automatische Vervollständigung Fuzzy code completion Clean completion cache when saving files Clean whitespace when saving files Leerzeichen beim Speichern bereinigen Enable scroll wheel zooming Zoom durch Mausrad aktivieren Add copied text into the clipboard as HTML Allow vertical scrolling to the last line [*] Display VisualizeWhitespace Word wrap by default Automatischer Umbruch Display code fold Display offset position Offset-Position anzeigen File Types Dateitypen Behavior Verhalten Display EOF Dateiende (EOF) anzeigen Display line numbers Zeilennummern anzeigen Display indent guide Display indent guide Indent-Marker anzeigen Display right margin at column Zeige rechten Einzug in Spalten Automatic indentation Enable automatic indentation Automatisch Einrücken Case sensitive code completion Completer case sensitive Bei Code-Vervollständigung Groß-/Kleinschreibung beachten Code completion prefix length: Word Complete Prefix Length Code-Vervollständigung Präfix-Länge: Display Anzeige MIME Type MIME-Type Tab Width Tab-Weite Tab To Spaces File Extensions Dateierweiterungen Custom Extensions LiteEditorPlugin Edit ToolBar Edit Navigation Bar LiteEnvOption Form Formular Environment definition files: Umgebungsdefinitionsdateien: Environment changes will take effect after switching environments. Umgebungsänderungen werden erst nach Umschalten der Umgebung wirksam. LiteFindPlugin Find Suchen Find Next Weitersuchen Find Previous Vorheriges Suchen Replace Ersetzen File Search Dateisuche LiteTabWidget Open a new tab Neues Tab öffnen List All Tabs Close Tab MarkdownBatchBrowser Markdown Exporter Markdown Batch All Files (*) Alle Dateien (*) Select the folder containing your markdown files: Select Markdown Folder Ordner auswählen der die Markdown-Dateien enthält: Select Markdown Files Markdown-Dateien auswählen Select the folder to contain separated markdown exports: Ordner auswählen für getrennten Markdown-Export: Export Merged HTML Export Html Exportiere gemeinsames HTML Export Merged PDF Export PDF Exportiere gemeinsames PDF MarkdownBatchWidget Form Formular Markdown Source Files Markdown Files Markdown Dateien Import Folder... Import Folder Ordner importieren... Add Files... Add Files Dateien hinzufügen... Move Up Nach oben Move Down Nach unten Remove Entfernen Remove All Alle entfernen Options Optionen Export Folder: Export Ordner: Browse... Browser Auswählen... Use CSS CSS verwenden Insert horizontal line between merged files Merge files insert split <hr> Horizontale Linie zwischen zusammengefassten Dateien einfügen Insert page break between merged files Merge files insert page break Seitenumbruch zwischen zusammengefassten Dateien einfügen Export Export Util Exportmöglichkeiten Export Separated HTML Separate Html HTML teilen Export Separated PDF Separate PDF PDF teilen Export Merged HTML... Merge Html HTML zusammenführen... Export Merged PDF... Merge PDF PDF zusammenführen... Print Preview Merged... Merge Print Preview Vorschau (zus.)... Print Merged Merge Print Drucken (zus.) Log Log MarkdownEdit Header (h1) Header <h1> Überschrift (h1) Header (h2) Header <h2> Überschrift (h2) Header (h3) Header <h3> Überschrift (h3) Header (h4) Header <h4> Überschrift (h4) Header (h5) Header <h5> Überschrift (h5) Header (h6) Header <h6> Überschrift (h6) Bold Fett Italic Kursiv Inline Code Eingebetteter Code Link Link Image Bild Unordered List Ungeordnete Liste Ordered List Geordnete Liste Blockquote Blocksatz Horizontal Rule Horizontales Lineal Heading Überschrift MultiFolderView Delete Folder Ordner löschen Are you sure that you want to permanently delete this folder and all of its contents? Sind Sie sicher, dass Sie den ganzen Ordner und dessen Inhalt unwiderruflich löschen wollen? Failed to delete the folder! Der Ordner konnte nicht gelöscht werden! Delete File Datei löschen Are you sure that you want to permanently delete this file? Sind Sie sicher, dass Sie diese Datei unwiderruflich löschen wollen? Failed to delete the file! Die Datei konnte nicht gelöscht werden! NavigateBar Browser Files in %1 NewFileDialog New Project or File Neues Projekt oder Datei Browse... Durchsuchen... GOPATH: Template: Template Vorlage: Type Typ Information Information Name: Name: Location: Verzeichnis: Error Fehler Could not create the target directory: %1 Zielverzeichnis konnte nicht angelegt werden: %1 Warning Warnung Location %1 is not empty. Use the target directory anyway? Zielverzeichnis %1 ist nicht leer. Trotzdem verwenden? Overwrite File Datei überschreiben %1 already exists. Do you want to replace it? %1 existiert bereits. Soll es ersetzt werden? No files could be created. Es konnten keine Dateien erstellt werden. File template details: Informationen Dateivorlage: Project template details: New project wizard: Informationen Projektvorlage: Choose a directory for the new content: Verzeichnis für den neuen Inhalt auswählen: OpenEditorsWidget Open Documents OptionsBrowser Options Options Page Optionen OptionsWidget Options Optionen Info Info [*] item request restart of LiteIDE [*] item requeset restart LiteIDE OutputDockWidget Move To Verschieben LeftSideBar RightSideBar BottomDockWidget OutputOption Form Formular Font Schrift Family: Familie: Size: Größe: Zoom: Zoom: % % Antialias Kanten glätten Display Anzeige Use editor color scheme Sets the maximum number of lines PackageBrowser Manage GOPATH/Modules ... Manage GOPATH... GOPATH verwalten... Reload All Alle neu laden Use godoc View Load Package in New Window Paket in neuem Fenster laden Add Package to Folders Paket zu Ordnern hinzufügen Open Source File Quelldatei öffnen Copy Name to Clipboard Copy Name To Clipboard Name in Zwischenablage kopieren Go Package Browser Package Browser Paket Browser Loading Go package list... Loading go package ... Lade go Paketliste... PackageProject Reload Package Paket neu laden Open Explorer Here Explorer hier öffnen Add Source File Quelltextdatei hinzufügen File Name: Dateiname: Error Fehler File %1 already exists. Datei %1 existiert bereits. Could not open %1 for writing. Konnte %1 nicht zum Schreiben öffnen. PluginsDialog Installed Plugins Install Plugins Installierte Plugins Close Schließen Name Name Author Autor Enabled Aktiviert Details Details Version Last Ver Version File Name FileName Dateiname ProcessEx process exited with code %1 Prozess beendet mit Rückgabewert %1 process crashed or was terminated Prozess beendet oder abgestürzt process exited with an unknown status Prozess beendet mit unbekanntem Rückgabewert process failed to start Prozess konnte nicht gestartet werden process crashed or was terminated while running Prozess abgestürzt oder während der Ausführung beendet timed out waiting for process Time out beim Warten auf Prozess couldn't read from the process Konnte nicht vom Prozess lesen couldn't write to the process Konnte nicht zum Prozess schreiben an unknown error occurred Ein unbekannter Fehler ist aufgetreten ProjectManager Project <%1> Projekt <%1> Import Directory <%1> Import Ordner <%1> QFileSystemModel %1 TB %1 GB %1 MB %1 KB %1 bytes QJson::ParserRunnable An error occurred while parsing json: %1 Beim Parsen von Json ist ein Fehler aufgetreten: %1 QJsonParseError no error occurred unterminated object missing name separator unterminated array missing value separator illegal value invalid termination by number illegal number invalid escape sequence invalid UTF8 string unterminated string object is missing after a comma too deeply nested document too large document garbage at the end of the document QuickOpenAction Show and Run Commands QuickOpenEditor Show All Opened Editors Show All Editors QuickOpenFileSystem File System Dateisystem QuickOpenFiles Go to File Type '?' to get help on the actions you can take from here QuickOpenFolder Browser Folder QuickOpenHelp Show All Quick Open Actions Show Quick Open Help QuickOpenLines Go to Line Open a text file first to go to a line Type a line number between %1 and %2 to navigate to Go to Line %1 Go to line %1 QuickOpenManager Quick Open File Quick Open Editor Quick Open Symbol Quick Open Command Show All Quick Open Actions QuickOpenMimeType Go to Symbol in File Open Symbol by Name not found symbol QuickOpenOption Form Formular QuickOpenFiles Match case sensitive Max files count: QuickOpenEditor RecentManager Clear All History Clear Menu SearchEdit Search Suche Stop Search Suche beenden SelectExternalDialog Debug External Application Externe Anwendung debuggen Application: Anwendung: Browse... Browser Wählen... Arguments: Argumente: Working directory: Arbeitsverzeichnis: Select Executable Ausführbare Datei auswählen Select the working directory: Select Working Directory Arbeitsverzeichnis auswählen: SessionRecent Sessions SideDockWidget Move To Verschieben RightSideBar LeftDockWidgt LeftSideBar RightDockWidget OutputBar SideBar Show SideBar SideWindowStyle Hide SideBar SideBar Windows Output Windows SplitDockWidget Move To Verschieben Top Oben Top (Split) Oben (geteilt) TopDockWidget (Split) TopDockWidget Bottom Unten Bottom (Split) Unten (geteilt) BottomDockWidget (Split) BottomDockWidget Left Links Left (Split) Links (geteilt) LeftDockWidget (Split) LeftDockWidget Right Rechts Right (Split) Rechts (geteilt) RightDockWidget (Split) RightDockWidget Unsplit Zusammenführen Split Teilen SplitWindowStyle Hide Sidebars Seitenleisten ausblenden Tool Windows Werkzeugfenster Terminal New Neu Open a new terminal Close Schließen Close current terminal CloseAll Close all terminal LoadEnv Current terminal load environment from LiteIDE Filter Dark Mode Login Mode (shell --login) Terminal Terminal Rename Tab Title TerminalEdit Cut Ausschneiden Copy Kopieren Paste Einfügen Select All Alles auswählen Clear All Auswahl aufheben TextEditor::Internal::ColorScheme Not a color scheme file. Keine Farbschemadatei. Utils::FilterLineEdit Filter Clear text Text löschen VTermWidget Copy Kopieren Paste Einfügen Select All Alles auswählen WebKitBrowser Navigation Navigation Open Html File Open Html HTML-Datei öffnen WebKitBrowser WebKit-Browser False load %1 ! Fehlerhaft geladen: %1 ! Open Html or Markdown File Open Html or Markdown Files HTML- oder Markdown-Datei öffnen WebKitHtmlWidgetPlugin Open Html or Markdown File Open Html or Markdown Files HTML- oder Markdown-Datei öffnen WelcomeBrowser New Neu Open Öffnen Open Folder Ordner öffnen Options Optionen Welcome Welcome Page Willkommen WelcomePlugin Welcome Home Willkommen ================================================ FILE: liteidex/liteide_fr.ts ================================================ AboutDialog About LiteIDE About Liteide À propos de LiteIDE Information Infomation Informations Welcome: Bienvenue : Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Bienvenu dans LiteIDE X ! LiteIDE est un IDE simple, open source et indépendant de la plate-forme. Project: Projet : Name: Nom : Author: Auteur : Version: Version : Build: Compilation : Based on Qt Based on Qt Version Basé sur Qt Source Code: Code source : Support LiteIDE: Support Support LiteIDE : Developers Développeurs Translations Traductions Chinese Chinois Japanese Japonais Russian Russe French Français Traditional Chinese Chinois traditionnel German Allemand Ukrainian Ukrainien Thanks to... Remerciements à... License Licence Close Fermer Based on Qt %1 (%2 bit) Basé sur Qt %1 (%2 bits) ActionManager &File &Fichier &Recent &Récent &Edit &Édition F&ind &Find Rec&herche &View &Affichage &Tools &Outils &Build &Compilation &Debug &Débogage &Help A&ide Standard Toolbar Standard ToolBar Barre d'outils standard AstWidget Go To Definition Aller à la définition View Import Document Afficher l'import de document BaseDockWidget Hide Masquer Hide Tool Window Masquer la fenêtre des outils Floating Window Fenêtre flottante BaseFolderView Open In New Window Ouvrir dans une nouvelle fenêtre Open File Ouvrir un fichier New File... Nouveau fichier... New File Wizard... Nouveau fichier guidé... Rename File... Renommer le fichier... Delete File Supprimer le fichier New Folder... Nouveau répertoire... Rename Folder... Renommer le répertoire... Delete Folder Supprimer le répertoire Open Terminal Here Ouvrir un terminal ici Show in Explorer Open Explorer Here Ouvrir un explorateur ici Open Application Ouvrir une application Show in Finder Montrer dans la recherche Show Containing Folder Afficher les répertoires contenus Open Command Prompt Here Ouvrir une ligne de commande ici Open in Integrated Terminal Ouvrir dans le terminal intégré Open Folder... Add Folder... Ouvrir un répertoire... Reload Folder Recharger le répertoire Close Folder Fermer le répertoire Close All Folders Fermer tous les répertoires Copy Copier Paste Coller Copy Path Move To Trash Mettre à la corbeille Create File Créer un fichier A file with that name already exists! Un fichier avec ce nom existe déjà ! Failed to create the file! Création du fichier echouée ! Rename File Renommer le fichier New Name: Nouveau nom : Failed to rename the file! Renommage du fichier échouée ! An item "%1" already exists in this location. Do you want to replace it and move old item to trash? Un éléments "%1" existe déjà à cet endroit. Voulez-vous le remplacer et mettre l'ancien dans la corbeille ? Stop Arrêter Keep Both Garder les deux Keep Both All Conserver les deux pour tous Replace Remplacer Replace All Tout remplacer Are you sure that you want move to trash this item? Êtes-vous certain de vouloir mettre cet élément à la corbeille ? Are you sure that you want move to trash %1 items? Êtes-vous certain de vouloir mettre %1 éléments à la corbeille ? Move to Trash Mettre à la corbeille Open With Ouvrir avec System Editor Éditeur système Create Folder Créer un répertoire A folder with that name already exists! Un répertoire avec ce nom existe déjà ! Failed to create the folder! Création du répertoire échouée ! Rename Folder Renommer le répertoire Folder Name Nom du répertoire Failed to rename the folder! Renommage du répertoire échouée ! Are you sure that you want to permanently delete this folder and all of its contents? Etes vous certain de vouloir supprimer ce répertoire et son contenu ? Failed to delete the folder! Supression du répertoire échouée ! BookmarkManager Toggle Bookmark Basculer le signet Goto bookmark Aller au signet Remove bookmark Supprimer le signet Remove all bookmarks for this file Supprimer tous les signets pour ce fichier Remove all bookmarks for all files Supprimer tous les signets pour tous les fichiers Bookmarks Signets BookmarkRecent Bookmarks Signets BuildConfigDialog Build Configuration Build Config Dialog Configuration de la compilation Build ID ID de compilation Build Path Build File Chemin de configuration GOPATH GOPATH GOPATH information Information GOPATH Use Custom GOPATH for Build Path Utiliser un GOPATH personnalisé pour le chemin de compilation Inherit System GOPATH Hériter du GOPATH System Inherit LiteIDE GOPATH Hériter du GOPATH LiteIDE Custom GOPATH (one per line) GOPATH personnalisé (un par ligne) Add Directory... Ajouter un répertoire... Clear Effacer LiteIDE LiteIDE Config Configuration Action Action Custom Build Custom Personnalisé Reset all to initial value Réaffecter les valeurs initiales Name Nom Value Valeur SharedValue Valeur partagée Id Id Cmd Cmd Choose directory to add to GOPATH: Choisir un répertoire à ajouter à GOPATH : CreateDirDialog Create Folder Créer un répertoire Directory: Répertoire : Dir Name: Nom du répertoire : Create Créer Cancel Annuler CreateFileDialog Create File Create File Dialog Création de fichier guidée Directory: Répertoire : File Name: Nom du fichier : Create Créer Create and Edit Créer et éditer Cancel Annuler DebugWidget Add Watch Ajouter un espion Async Record AsyncRecord Enregistrement asynchrone Variables Variables Watch Espion Call Stack CallStack Pile de rappel Threads Threads Goroutines Goroutines Registers Registres Libraries Library Librairies Console Console Watch expression (e.g. buf main.var os.Stdout): Expression de l'espoin (ex: buf main.var os.Stdout) : Remove Watch Supprimer l'espion Remove All Watches Supprimer tous les espions DlvDebuggerOption Form Formulaire delve debug pass flags: (example --check-go-version=false) DocumentBrowser Back Backward Précédent Forward Suivant Reload Recharger Increase Font Size Agrandir la police Decrease Font Size Réduire la police Reset Font Size Réinitialiser la taille police DocumentBrowserFactory DocumentBrowser Navigateur de document EditorManager Close Fermer Move to New Window Move To New Window Déplacer vers une nouvelle fenêtre Navigate Forward GoForward Suivant Close Others Close Others Tabs Fermer les autres Open Editor Ouvrir l'éditeur Close All Close All Tabs Tout fermer Close Left Tabs Fermer les onglets à gauche Close Right Tabs Fermer les onglets à droite Close Files in Same Folder Close Same Folder Files Fermer les fichiers du même répertoire Close Files in Other Folders Close Other Folder Files Fermer les fichiers d'autres répertoires Copy Full Path to Clipboard Copy Path to Clipboard Copier le chemin complet dans le presse-papier Show in Explorer Montrer dans l'explorateur Show in Finder Montrer dans la recherche Show Containing Folder Montrer son répertoire parent Open Command Prompt Here Ouvrir une ligne de commande ici Open Terminal Here Ouvrir un terminal ici Open in Integrated Terminal Ouvrir dans le terminal intégré Navigate Backward Reculer vers la position précédente Save changes to %1? Enregistrer les changement vers %1 ? Unsaved Modifications Save Modify Modifications non en registrées All Files (*) Tous fichiers (*) Save As Enregistrer sous EnvManager Environment Toolbar Environment ToolBar Barre d'environnement Switching current environment Switch Current Environment Intervertir l'environnement courant Edit current environment Edit Current Environment Modifier l'environnement courant Reload current environment Reload Current Environment Recharger l'environnement courant Select Environment Sélectionner l'environnement ExportDialog Dialog Dialogue Name: Nom : Export Exporter ExportAndView Exporter et afficher FakeVim::Internal Use Vim-style Editing Modifier avec le Style-Vim Read .vimrc Lire .vimrc Path to .vimrc Chemin vers .vimrc FakeVim::Internal::FakeVimHandler Unknown option: %1 Option inconnue : %1 Argument must be positive: %1=%2 L'argument doit être positive : %1=%2 Mark "%1" not set. Marquer "%1" non renseigné. %1%2% %1%2 %1All Tous%1 Not implemented in FakeVim. Non implémenté dans FakeVim. Unknown option: Option inconnue : Invalid argument: Argument invalide : Trailing characters: Caractères de fin : Move lines into themselves. Déplacement des lignes dans elles-mêmes. %n lines moved. %n lignes déplacées. File "%1" exists (add ! to override) Le fichier "%1" existe (ajouter ! pour outrepasser) Cannot open file "%1" for writing Impossible d'ouvrir le fichier "%1" pour écriture "%1" %2 %3L, %4C written. "%1" %2 %3L, %4C écrits. Cannot open file "%1" for reading Impossible d'ouvrir le fichier "%1" pour lecture "%1" %2L, %3C "%1" %2L, %3C %n lines filtered. %n lignes filtrées. Cannot open file %1 Impossible d'ouvrir le fichier %1 Invalid regular expression: %1 Expression régulière invalide : %1 Pattern not found: %1 Pattern non trouvé : %1 Search hit BOTTOM, continuing at TOP. Fin atteinte, reprise reprise le début. Search hit TOP, continuing at BOTTOM. Début atteint, reprise depuis la fin. Search hit BOTTOM without match for: %1 Fin atteinte sans correspondance avec : %1 Search hit TOP without match for: %1 Début atteint sans correspondance avec : %1 %n lines indented. %n lignes indentées. %n lines %1ed %2 time. %n lignes %1 %2 fois. %n lines yanked. %n lignes mémorisées. Already at oldest change. Déjà au plus vieux changement. Already at newest change. Déjà au plus récent changement. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Mapping recursif Type Alt-V, Alt-V to quit FakeVim mode. Tapper Alt-V, Alt-V pour quitter le mode FakeVim. [New] [Nouveau] Not an editor command: %1 N'est pas une commande de l'editeur : %1 FakeVimEdit Use FakeVim Editing Utiliser l'édition FakeVim FakeVimEditOption Form Depuis FakeVim initialization command list (# start is comment): Initialisation de la liste de commandes de FakeVim (# démarre un commentaire) : Load default init command list Charger la liste de commandes par défaut FiFoTty Cannot create temporary file: %1 Impossible de créer le fichier temporaire : %1 Cannot create FiFo %1: %2 Impossible de créer FiFo %1 : %2 Cannot open FiFo %1: %2 Impossible d'ouvrir FiFo %1 : %2 FileBrowser Synchronize with editor Synchroniser avec l'éditeur Set As Root Folder Set Folder To Root Définir comme répertoire racine Open Folder in New Window Ouvrir le répertoire dans une nouvelle fenêtre Open Parent Open to Parent Ouvre le parent Reload Folder Recharger le répertoire Show Hidden Files Afficher les fichiers masqués Show Details Afficher les détails Execute File Exécuter le programme Debug File Dégoguer le programme Add to Folders Ajouter au répertoires Filter Filtrer File System Système de fichiers FileBrowserOption Form Formulaire Terminal Terminal Command: Commande : Arguments: Arguments : FileManager All Files (*) Tous les fichiers (*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? Projet '%1' a été créé. Voulez-vous le charger ? Open Project or File Ouvrir un projet ou un fichier Show Hidden Files Afficher les fichiers masqués Show Details Afficher les détails Split Mode Mode séparé Folders Folers Répertoires All Support Files (%1) Tous les fichiers supportés (%1) Select a folder: Open Folder Sélectionner le répertoire : %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 Ce fichier a été supprimé du disque, mais vous avez des modifications non enregistrées dans votre éditeur LiteIDE. Voulez-vous fermer l'éditeur ? Répondre "Oui" vous fera perdre vos modifications non enregistrées. %1 This file has been deleted from the drive. Do you want to close the editor? %1 Ce fichier a été supprimé du disque. Voulez-vous fermer l'éditeur ? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 Ce fichier a été modifié sur le disque, mais vous avez des modifications non enregistrées dans votre éditeur LiteIDE. Voulez-vous recharger le fichier depuis le disque ? Répondre "Oui" vous fera perdre vos modifications non enregistrées. %1 This file has been modified on the drive. Do you want to reload the file from disk? %1 Ce fichier a été modifié sur le disque. Voulez-vous recharger le fichier depuis le disque ? Open Files Ouvrir des fichiers Synchronize with editor Synchroniser avec l'éditeur Filter Filtrer Open Project Ouvrir un projet LiteIDE X LiteIDE X FileRecent Files Fichiers FileSearch Match whole word Match word Mot entier uniquement Match case Respecter la casse Regular expression Expression régulière Scan subdirectories Look in subdirs Recherche dans les sous-répertoires Search for: Recherche : Options: Options : Browse... Browser Parcourir... Filter: Filtrer : Files on File System Fichiers sur système de fichiers Search Rechercher Cancel Annuler Current Folder Répertoire courant Auto Switch Bascule automatique Clear Effacer Open Directory Ouvrir répertoire FileSearchManager Search Item: Rechercher l'élément : Only golang file changes can be revert! This file change cannot be undone! Seulement les changements de fichier golang sont reversibles ! New Search Nouvelle recherche File Search Recherche de fichier Search Result Resultat de recherche LiteIDE X LiteIDE X Warning! Replace text is empty. Want to remove all the search items? Avertissement ! Le texte de remplacement est vide. Souhaitez-vous supprimer toutes les correspondances ? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? Avertissement ! Le texte de remplacement est composé d'espaces. Souhaitez-vous supprimer toutes les correspondances par des espaces ? The following files have no write permissions. Do you want to change the permissions? Les fichiers suivants n'ont pas de permissions en écriture. Voulez-vous changer les permissions ? File is readonly Le fichier est en lecture seule FileSystemWidget Open File Open Editor Ouvrir un fichier New File... New File Nouveau fichier... New File Wizard... New File Wizard Nouveau fichier (dialogue)... Rename File Renommer le fichier Delete File Remove File Supprimer le fichier New Folder... New Folder Nouveau répertoire... Are you sure that you want to permanently delete this file? Êtes-vous certain de vouloir supprimer ce fichier définitivement ? Rename Folder Renommer le répertoire Delete Folder Remove Folder Supprimer le répertoire Rename File... Renommer le fichier... Rename Folder... Renommer le répertoire... Open Terminal Here Ouvrir le terminal ici Open Explorer Here Ouvrir l'explorateur ici View Godoc Here Afficher Godoc ici Add Folder Ajouter un répertoire Close Folder Fermer le répertoire Add Folder... Ajouter un répertoire... Close All Folders Fermer tous les répertoires Create File Créer un fichier A file with that name already exists! The file already exists! Le fichier existe déjà ! Failed to create the file! Impossible de créer le fichier ! New Name: Nouveau nom : Failed to rename the file! Impossible de renommer le fichier ! Are you sure that you want to permanently delete this folder and all of its contents? Êtes-vous certain de vouloir supprimer définitivement ce répertoire et son contenu ? Failed to delete the file! Failed to remove the file! Impossible de supprimer le fichier ! Create Folder Créer un répertoire A folder with that name already exists! The folder name is exists! Un répertoire avec ce nom existe déjà ! Failed to create the folder! Impossible de créer le répertoire ! Folder Name Nom du répertoire Failed to rename the folder! Impossible de renommer le répertoire ! Failed to delete the folder! Failed to remove the folder! Impossible de supprimer le répertoire ! Find::Internal::SearchResultWidget Search was canceled. La recherche a été abandonnée. Cancel Annuler Repeat the search with same parameters Répéter la recherche avec les même paramètres Search again Rechercher de nouveau Set show replace mode ui Définir le mode d'affichage du remplacement Show Replace Afficher remplacement Replace with: Remplacer par : Replace all occurrences Remplacer toutes les occurences Replace Remplacer Preserve case Respecter la casse Expand all items Etendre tous les éléments Collapse all items Refermer tous les éléments Revert with: Revenir à : Revert Revenir Revert all occurrences Revenir pour toutes les occurences %n matches replaced. %n correspondances remplacées. searching... %n matches found. recherche... %n correspondances trouvées. searching ... recherche... No matches found. Pas de correspondance trouvée. %n matches found. %n correspondances trouvées. FindApiEdit Search Rechercher Stop Search Arrêter la recherche FindApiWidget Search Rechercher Find Trouver FindDocWidget Search Rechercher Find Trouver Find All Trouver tout Find const Trouver des constantes Find func Trouver des fonctions Find interface Trouver des interfaces Find pkg Trouver des packages Find struct Trouver des structures Find type Trouver des types Find var Trouver des variables Use Regexp Utiliser des RegExp Match Case Respecter la casse Match Word Mot entier uniquement Help Aide FindEditor Match case Respecter la casse Regular expression Expression régulière Wrap around Enrouler autour Find Next Suivant Find Previous Find Prev Précédent Replace With: Remplacer par : Replace Remplacer Replace All Tout remplacer Match whole word only Mot entier uniquement Ready Prêt Close Fermer Show Replace Afficher remplacement Find What: Trouver ceci : Options: Find Option: Options : Not found Aucune occurrence FolderListView Delete File Supprimer le fichier Are you sure that you want to permanently delete this file? Êtes-vous certain de supprimer ce fichier définitivement ? Failed to delete the file! Impossible de supprimer ce fichier ! Delete Folder Supprimer le répertoire Are you sure that you want to permanently delete this folder and all of its contents? Êtes-vous certain de supprimer ce répertoire et son contenu définitivement ? Failed to delete the folder! Impossible de supprimer ce répertoire ! FolderRecent Folders Répertoire FolderView Delete File Supprimer ce fichier Are you sure that you want to permanently delete this file? Êtes-vous certain de supprimer ce fichier définitivement ? Failed to delete the file! Impossible de supprimer ce fichier ! Delete Folder Supprimer le répertoire Are you sure that you want to permanently delete this folder and all of its contents? Êtes-vous certain de supprimer ce répertoire et son contenu définitivement ? Failed to delete the folder! Impossible de supprimer ce répertoire ! GdbDebuggerOption Form Formulaire Enable --tty for program being debugged. Active --tty pour les programmes débogués. GoAddTagsDialog Add Tags To Struct Field Ajouter des Tags aux champs de la structure Add JSON Tag Ajouter le Tag JSON Options Options Multiple options separated by commas Multiple options are separated by commas Multiple options séparées by des virgules Add XML Tag Ajouter le Tag XML Add Custom Tags Ajouter des Tags personnalisés Tag Name Nom du Tag Setup custom tag name Définir le nom du tag personnalisé Sort sorts the tags in increasing order according to the key name Trier les tags par ordre croissant du nom de la clé Override current tags when adding tags Surcharger les tags courants avec l'ajout de tags Info Info GoRemoveTagsDialog Remove Tags From Struct Field Supprimer les Tags des champs de structure Remove Tags And Options Supprimer les Tags et Options Clear All Tags Nettoyer tous les Tags Clear All Tags Options Clear All Tag Options Nettoyer toutes les options des Tags Remove JSON Tag Supprimer les Tags JSON Remove XML Tag Supprimer les Tags XML Remove Custom Tag Supprimer les Tags personnalisés Multiple tags separated by commas Multiple tags are separated by commas Les Tags multiples sont séparés par des virgules Remove JSON Options Supprimer les options des Tags JSON Multiple options separated by commas Multiple options are separated by commas Les options multiples sont séparées par des virgules Remove XML Options Supprimer les options des Tags XML Remove Custom Tag Options Supprimer les options des Tags personnalisés Setup remove custom tag and option, example tag=opt1,tag=opt2 Setup remove custom tag option, example tag=opt1,tag=opt2 Définir l'option de tag personnalisé à supprimer, exemple tag=opt1,tag=opt2 tag=option tag=option Info Info GolangAst No outline available Aucun définition JSON disponible Synchronize with editor Synchroniser avec l'éditeur Go Class View Class View Go Class explorateur Go Outline Outline Go Outline GolangAstOption Form Formulaire QuickOpenSymbol QuickOpenSymbol Show import path Afficher le chemin d'import Match case sensitive Respecter la casse GolangCodeOption Form Formulaire PKG automitic import prompt Invite d'import automatique de packages PKG automatic import hints for all packages (GOPATH) Conseils d'import automatique pour tous les packages (GOPATH) PKG automatic import hints for standard package Conseils d'import automatique pour les packages standard Gocode Go API Gocode Auto update depends package when it's source changed. Auto update depends package when its source is changed. Mise à jour automatique des dépendances quand sa source est changée. Close gocode when exiting Fermer gocode en quittant GolangDoc Godoc Search Recherche Godoc Go Doc Search Golang Doc Search Recherche Golang Doc Go Api Index Golang Api Index Index de l'API Golang Find Package: Trouver le package : GolangDocOption Form Formulaire Go API G API Use default context (fast) Utilisation du contexte par défault (rapide) Only load standard API documentation Only load standard api Charger seulement la documentation standard des API GolangEdit View import package use godoc Afficher godoc pour le package importé View Expression Information Afficher l'information sur l'expression Jump to Declaration Aller à la déclaration Find Usages Trouver les utilisations %1 (Module/GOPATH) with GOROOT %1 (Module/GOPATH) avec GOROOT Rename Symbol Under Cursor Renommer le symbole sous le curseur Stop Arrêter Go Source Query Go Source Query SourceQuery What Go Source Query What Callees Appelées Callers Appelants Callstack Pile d'appel Definition Définition Describe Description Freevars Variables libres Implements Implémentation Implements(GOPATH) Implémentation(GOPATH) Peers Pairs Referrers Référenceurs Pointsto Pointe vers Whicherrs Lesquels Add Tags To Struct Field Ajouter des Tags aux champs de la structure Remove Tags From Struct Field Supprimer des Tags des champs de la structure Refactor Réusinage de code SourceQuery Source Query Below files in package %1 Ci-dessous les fichiers dans le package %1 GolangEditOption Form Formulaire Mouse Souris Go root source file editor setup read only Définir les fichiers source de GO root en lecture seule Enable view expression infomation on mouse Activer l'information sur l'expression à la souris Enable mouse navigation Activer la navigation à la souris GolangFileSearch Golang Find Usages Trouver les utilisations Golang GolangFmtOption Form Formulaire Format Options Golang Format Options de format Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Goimports actualise les lignes d'import Go, ajoutant les manquantes et supprimant les inutilisés. Enable update imports line, adding missing ones and removing unreferenced ones. Actualisation automatique des lignes d'import Go, ajoutant les manquantes et supprimant les inutilisés. Synchronous Synchronisme Synchronous code formatting Synchronous code formatting Formatage du code synchrone Synchronous code formatting timeout in milliseconds (500ms or more): Timeout en millisecondes du formatage du code synchrone (500 ms ou +) : Automatically format code when saving When the editor is saved automatically gofmt Formater le code automatiquement à l'enregistrement GolangFmtPlugin Format Code Format Code (goimports) Formatage du code (goimports) Format Code (Adjusts Imports) Formatage du code (ajustement des imports) GolangPackageOption Choose directory to add to GOPATH: Choisir le répertoire à ajouter à GOPATH : Manage GOPATH / Modules Gérer GOPATH / Modules Go Modules Go Modules Custom GONOPROXY GONOPROXY personnalisé Custom GOPROXY GOPROXY personnalisé Custom GO111MODULE GO111MODULE personnalisé Custom GONOSUMDB GONOSUMDB personnalisé Custom GOPRIVATE GOPRIVATE personnalisé TextLabel Libellé de texte GOPATH GOPATH Use System GOPATH Utiliser GOPATH du système Reload Recharger Use Custom GOPATH (one per line) Personnaliser GOPATH (un par ligne) Add Directory... Ajouter un répertoire... Clear Effacer GolangPresentEdit Section (s1) Section (s1) Subsection (s2) Sous-Section (s2) Sub-subsection (s3) Sous-Sous-Section (s3) Bold Gras Italic Italique Inline Code Code inline Switch Bullets Puces/pas de puces Comment/Uncomment Selection Commenter/Décommenter la sélection Export HTML Exporter en HTML Verify Present Vérifier le format Present Present verify success Present vérifié avec succès Present verify false Present vérifié en échec Export PDF Exporter en PDF GolangSymbol Quick Open Symbol by Name Quick Open Symbol par nom GoplayBrowser Go Playground Go Playground Run Exécuter Stop Arrêter New Nouveau Load... Charger... Save... Enregistrer... Explore Folder Explorer répertoire Running... Running... En cours d'exécution... Error: %1. Error: %1. Erreur : %1. Success: %2. Success: %2. Succès : %2. Load File Charger le fichier Select a file to load: Sélectionner le fichier à charger : Save File Enregistrer le fichier New File Name: Nouveau nom du fichier : HtmlPreview Page Style Style de la page Reload Recharger Export Html Exporter en HTML Export PDF Exporter en PDF Print Preview Prévisualiser l'impression Synchronize preview and code scrollbars Synchroniser le défilement entre l'aperçu et le code Config Configuration Plain HTML Plain HTML Export Failed Exportation échouée Automatically display preview Automatically Display Preview Affichage de l'aperçu automatiquement HTML Preview Html Preview Aperçu HTML Could not open %1 for writing! Can not write file %1 Impossible d'ouvrir le fichier %1 en écriture ! ImageEditor ZoomIn Zoomer ZoomOut Dézoomer Reset to original size Rétablir à la taille d'origine Fit to view Adapter à l'écran Play movie Jouer le film Prev frame Image précédente Next frame Image suivante Pause movie Mettre en pause le film ImageEditorFactory Image Viewer Afficheur d'image ImportPkgTip warning, pkg not find, please enter to import : Avertissement, pkg introuvable, veuillez entrer pour importer : JsonEdit Verify Vérifier Format Json Json formaté Compact Json Json compacté LiteApp Event Log Journal d'événements Escape Échappe Close File Fermer le fichier Close All Files Fermer tous les fichiers Save File Enregistrer le fichier Save File As... Enregistrer le fichier sous... Save All Files Enregistrer tous les fichiers Open Project Ouvrir un projet Options Options New... Nouveau... Open File... Ouvrir le fichier... Open Folder... Ouvrir le répertoire... Open Folder in New Window... Ouvrir le répertoire dans une nouvelle fenêtre... Close All Folders Add Folder... Fermer tous les répertoires New Window Nouvelle fenêtre Close Window Fermer la fenêtre Save Project Enregistrer un projet Close Project Fermer le projet Exit Quitter Full Screen Tout l'écran About LiteIDE À propos de LiteIDE About Plugins À propos des plugins LiteAppOption Form Formulaire Store [*] Store Magasin [*] Language: Langue : Icon [*] Icône [*] Reload files in session Recharger les fichiers de la session Recent Files Recent File Fichiers récents Max Count: Max Recent: Nombre max : Monitoring files for modifications Surveillance des fichiers pour les modifications Store settings to local ini file Stocker la configuration dans le fichier ini local Interface [*] Interface [*] Style: Style : Use tool window shortcuts Utiliser les raccourcis de la fenêtre d'outils Theme [*] Thème [*] Fallback build-in icon library and liteapp/qrc/default Utiliser en secours la librairie d'icônes et liteapp/qrc/default intégrée Load the external file icon library Load custome icon from liteapp/qrc folder Charger le fichier librairie d'icône externe Automatically save documents Enregistrer automatiquement des documents Automatically save documents when application is idle Enregistrer automatiquement des documents quand l'application est inactive sec sec Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. Auto recharger ou fermer le buffer de l'éditeur, si le fichier sous-jacent est modifié/supprimé. Session Session 0-99 0-99 Editor Tabs Onglets de l'éditeur 10-999 10-999 Display Afficher Display [*] Affichage [*] Show splash screen on startup Afficher l'écran de démarrage au lancement Show welcome page on startup Afficher l'écran de bienvenue au lancement Editor Éditeur Editor tab [*] Onglet de l'éditeur [*] Show close buttons on each editor tab Afficher le bouton de fermeture sur chaque onglet de l'éditeur Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab Activer la navigation d'onglet avec la roulette de la souris Toolbar Icon Size [*] Taille des icônes de la barre d'outils Editor navigate Nagivation de l'éditeur Enable mouse extra 'Back' button and 'Forward' button for go back and forward Activer les boutons 'En arrière' et 'En avant' de la souris pour aller en arrière et en avant Keyboard Clavier Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Format : {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands Masquer les commandes standard Reset Réinitialiser Reset All Tout réinitialiser Import... Importer... Export... Exporter... Generic Générique Theme: Thème : Reload session on startup Auto load last session Recharger la session au lancement SideBarStyle Barre de style latérale SplitterStyle Style séparateur Command Commande Label Libellé Shortcuts Raccourcis NativeText TexteNatif Standard Standard Import Keyboard Mapping Scheme Importer le schéma de disposition du clavier Keyboard Mapping Scheme (%1) Schéma de disposition du clavier (%1) Could not read scheme from %1! Impossible de lire le schéma depuis %1 ! Export Keyboard Mapping Scheme Exporter le schéma de disposition du clavier Could not write scheme to %1! Impossible d'écrire le schéma vers %1 ! LiteBuild Build Toolbar Barre d'outils de compilation Build Configuration... Build Config Configuration de la compilation... Stop Action Arrêter l'action Clear Output Clear All Tout effacer Execute File Exécuter le fichier Debug File Déboguer le fichier Lock Build Path Lock Go Build Path Verrouiller le chemin de compilation Go Build Path Configuration Go Build Configuration Configuration de la compilation Go Use godoc View Utiliser la vue godoc Line Wrap Retour à la ligne Auto Clear Emplacement automatique Automatic positioning cursor Positionnement automatique du curseur Setup Lancement Build Output Build Sortie de la compilation Current environment change id "%1" ID du changement courant d'environement "%1" Lock Build Lock Build: %1 Verrou de compilation Error: %1. Error: %1. Erreur : %1. Command exited with code %1. La commande s'est terminée avec le code %1. Success: %1. Success: %1. Succès : %1. A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. Un processus est en fonctionnement. Arrêter l'action courante d'abord. Killing current process... Killing current process... Arrêt du processus courant... Failed to terminate the existing process! Failed to terminate the existing process! Terminaison du processus existant échouée ! Started process successfully Started process successfully Démarrage du processus avec succès Failed to start process Impossible de démarrer le processus LiteBuildOption Form Formulaire Recheck Go installation when changing environments Recheck go env if enviroment changed Revérifier l'installation de Go lors du changement d'environnement Build command configuration files [*] Build command configuration files: Fichers de configuration des commandes de compilation [*] LiteBuildPlugin Close Fermer Execute: Exec: Exécuter : Execute File Execute Exécuter le fichier LiteDebug Stop Arrêter Clear Effacer Continue Continuer Show Current Line Afficher la ligne courante Debug Output Debug Sortie du débogueur Start Debugging External Application... Start Debugging External Application Démarrer le débogage de l'application externe... Close Fermer Start Debugging Démarrer le débogage Step Into Entrer dans Step Over Enjamber Step Out Resortir Run to Line Exécuter jusqu'à la line Insert/Remove Breakpoint Ajouter/supprimer des points d'arrêt Remove All Breakpoints Supprimer tous les points d'arrêt LiteDebugOption Form Formulaire Debug Déboguer Automatically insert breakpoint main.main when debugging Automatically add breakpoint main.main when debugging Ajouter automatiquement le point d'arrêt main.main lors du débogage LiteDebugPlugin Debug Window Debug Fenêtre de débogage LiteDoc LiteIDE Documentation LiteIDE Document Browser Explorateur de documents LiteIDE LiteEditor Undo Défaire Redo Refaire Cut Couper Copy Copier Paste Coller Select All Sélectionner tout Go to Doc Start Aller au début du Doc Go to Doc End Aller à la fin du Doc Go to Line Start Aller au début de la ligne Go to Line End Aller à la fin de la ligne Go to Previous Line Aller à la ligne précédente Go to Next Line Aller à la ligne suivante Go to Previous Character Aller au caractère précédent Go to Next Charater Aller au caractère suivant Go to Previous Word Aller au mot précédent Go to Next Word Aller au mot suivant Go to Line Aller à la ligne File is readonly l fichier est en lecture seule File is writable Le fichier est accessible en écriture Line Wrap (MimeType) Word Wrap (MimeType) Retour à la ligne (TypeMime) Toggle Comment Commenter/décommenter Toggle Block Commnet Commenter/décommenter le bloc Auto-indent Selection Indenter automatiquement la sélection Tab To Spaces (MimeType) Tabulation vers espace (TypeMime) Line End Windows (\r\n) Fin de ligne Windows (\r\n) Line End Unix (\n) Fin de ligne Unix (\n) Visualize Whitespace (Global) Afficher les espaces (Global) Title Case Casse de titre Upper Case Majuscule Lower Case Minuscule Swap Case Inverser la casse Tab To Spaces Tabulations vers espaces Spaces To Tab Espaces vers tabulations Advanced Avancé Goto Aller à Convert Tab Conversion de tabulations Code Folding Pliage de bloc Convert Case Conversion de la casse Export HTML Exporter en HTML Export Failed Export échoué Could not open %1 for writing. Impossible d'ouvrir %1 pour écriture. Export PDF Exporter en PDF Print Document Imprimer le document Print Preview... Print Preview Document Aperçu de l'impression... Export HTML... Exporter en HTML... Export PDF... Exporter en PDF... Print... Imprimer... Go to Previous Block Go To Previous Block Aller au bloc précédent Select Block Sélectionner le bloc Go to Matching Brace Go To Matching Brace Aller à l'acolade correspondante Fold Replier le bloc Unfold Déplier le bloc Fold All Replier tous les blocs Unfold All Déplier tous les blocs Go To Line Goto Line Aller à la ligne Duplicate Dupliquer Delete Line Supprimer la ligne Copy Line Copier la ligne Cut Line Couper la ligne Insert Line Before Insérer la ligne au dessus Insert Line After Insérer la ligne en dessous Increase Font Size Augmenter la taille de la police Decrease Font Size Réduire la taille de la police Reset Font Size Réinitialiser la taille de la police Clean Whitespace Effacer les espaces Code Complete Code complet Move Line Up Déplacer la ligne vers le haut Move Line Down Déplacer la ligne vers le bas Copy Line Up Copier la ligne au dessus Copy Line Down Copier la ligen en dessous Join Lines Joindre les lignes Settings File Setup Configuration Reload File Recharger le fichier Do you want to permanently discard unsaved modifications and reload %1? Voulez-vous perdre définitivement les modifications et recharger %1 ? Go to Next Block Go To Next Block Aller au bloc suivant ReadOnly Lecture seule Line: Ligne : LiteEditorFileFactory Text Editor Éditeur de texte LiteEditorOption Form Formulaire Load File Charger le fichier Check and convert no printable char to '.' Vérifier et convertir les caractères non imprimables en '.' Font Police Font && Colors Police && Couleurs Family: Famille : Show Monospace Font Afficher les polices régulières Size: Taille : Zoom: Zoom : % % Antialias Anti crénelage Restore Default Font Restaurer les polices par défaut Editor Color Scheme ColorStyle Scheme Schéma des couleurs de l'éditeur File: Fichier : Edit Édition Syntax Auto-completion Auto complete brackets Auto-complétion syntaxique Fuzzy code completion Complétion de code flou Clean completion cache when saving files Effacer le cache de complétion des fichiers enregistrés Clean whitespace when saving files Effacer les espaces des fichiers enregistrés Enable scroll wheel zooming Activer le zoom sur la molette de défilement Add copied text into the clipboard as HTML Ajouter le texte copié dans le presse-papier en HTML Allow vertical scrolling to the last line [*] Permettre le défilement verticale vers la dernière ligne [*] Display VisualizeWhitespace Afficher les caractères d'espacement Word wrap by default Retour à la ligne par mot Display code fold Afficher les marqueurs de pliage par bloc de code Display offset position Afficher la position en caractères depuis le début du fichier File Types Types de fichier Behavior Comportement Display EOF Afficher la fin de fichier Display line numbers Afficher les numéros de lignes Display indent guide Display indent guide Afficher le repère d'indentation Display right margin at column Afficher la marge droite dans la colonne Automatic indentation Enable automatic indentation Activer l'indentation automatique Case sensitive code completion Completer case sensitive Complétion de code sensible à la casse Code completion prefix length: Word Complete Prefix Length Longueur du préfixe de la complétion de code : Display Affichage MIME Type Type MIME Tab Width Largeur de tabulation Tab To Spaces Tabulation vers espaces File Extensions Extensions de fichier Custom Extensions Extensions personnalisées LiteEditorPlugin Edit ToolBar Modifier la barre d'outils Edit Navigation Bar Modifier la barre de navigation LiteEnvOption Form Formulaire Environment definition files: Fichier de définition d'environnement : Environment changes will take effect after switching environments. Le changement de l'environnement prendra effet après bascule d'environnements. LiteFindPlugin Find Trouver Find Next Suivant Find Previous Précédent Replace Remplacer File Search Recherche de fichier LiteTabWidget Open a new tab Ouvrir un nouvel onglet List All Tabs Lister tous les onglets Close Tab Fermer l'onglet MarkdownBatchBrowser Markdown Exporter Markdown Batch Exporteur de Markdown All Files (*) Tous les fichiers (*) Select the folder containing your markdown files: Select Markdown Folder Sélectionner le répertoire de vos fichiers Markdown : Select Markdown Files Sélectionner les fichiers Markdown Select the folder to contain separated markdown exports: Sélectionner le répertoire pour contenir vos fichiers Markdown séparés : Export Merged HTML Export Html Exporter en HTML fusionné Export Merged PDF Export PDF Exporter en PDF fusionné MarkdownBatchWidget Form Formulaire Markdown Source Files Markdown Files Fichiers source des Markdown Import Folder... Import Folder Importer un répertoire... Add Files... Add Files Ajouter des fichiers... Move Up Déplacer vers le haut Move Down Déplacer vers le bas Remove Supprimer Remove All Supprimer tout Options Options Export Folder: Répertoire d'export : Browse... Browser Parcourir... Use CSS Utiliser CSS Insert horizontal line between merged files Merge files insert split <hr> Insérer une ligne horizontale entre les fichiers fussionnés Insert page break between merged files Merge files insert page break Insérer un saut de page entre les fichiers fussionnés Export Export Util Export Export Separated HTML Separate Html Export HTML séparés Export Separated PDF Separate PDF Export PDF séparés Export Merged HTML... Merge Html Export HTML fusionné... Export Merged PDF... Merge PDF Export PDF fusionné... Print Preview Merged... Merge Print Preview Aperçu impr. fusionnée... Print Merged Merge Print Impression fusionnée Log Journal MarkdownEdit Header (h1) Header <h1> Entête (h1) Header (h2) Header <h2> Entête (h2) Header (h3) Header <h3> Entête (h3) Header (h4) Header <h4> Entête (h4) Header (h5) Header <h5> Entête (h5) Header (h6) Header <h6> Entête (h6) Bold Gras Italic Italique Inline Code Bloc de code inséré Link Lien Image Image Unordered List Liste à puces Ordered List Liste numérotée Blockquote Bloc indenté Horizontal Rule Ligne Horizontal Heading Entête MultiFolderView Delete Folder Supprimer le répertoire Are you sure that you want to permanently delete this folder and all of its contents? Êtes-vous certain de supprimer ce répertoire et son contenu définitivement ? Failed to delete the folder! Impossible de supprimer le répertoire ! Delete File Supprimer le fichier Are you sure that you want to permanently delete this file? Êtes-vous certain de supprimer ce fichier définitivement ? Failed to delete the file! Impossible de supprimer le fichier ! NavigateBar Browser Files in %1 Naviguer les fichiers dans %1 NewFileDialog New Project or File Nouveau projet ou fichier Browse... Parcourir... GOPATH: GOPATH : Template: Template Caneva : Type Type Information Information Name: Nom : Location: Emplacement : Error Erreur Could not create the target directory: %1 Impossible de créer le répertoire de destination : %1 Warning Avertissement Location %1 is not empty. Use the target directory anyway? L'emplacement %1 n'est pas vide. Utiliser cet emplacement malgré tout ? Overwrite File Ecraser le fichier %1 already exists. Do you want to replace it? %1 existe déjà. Voulez-vous le remplacer ? No files could be created. Aucun fichier à créer. File template details: Détails du canevas de fichier : Project template details: New project wizard: Dialogue de nouveau projet : Choose a directory for the new content: Choisir un répertoire pour le nouveau contenu : OpenEditorsWidget Open Documents Ouvrir les documents OptionsBrowser Options Options Page Options OptionsWidget Options Options Info Info [*] item request restart of LiteIDE [*] item requeset restart LiteIDE [*] élément qui requiert le redémarrage de LiteIDE OutputDockWidget Move To Déplacer vers LeftSideBar Barre côté gauche RightSideBar Barre côté droit BottomDockWidget Widget du bas OutputOption Form Formulaire Font Police Family: Famille : Size: Taille : Zoom: Zoom : % % Antialias Anti crénelage Display Affichage Use editor color scheme Utiliser l'éditeur de schéma de couleur Sets the maximum number of lines Définir le nombre maximum de lignes PackageBrowser Manage GOPATH/Modules ... Manage GOPATH... Définir GOPATH/Modules... Reload All Tout recharger Use godoc View Utiliser la vue godoc Load Package in New Window Charge un package dans une nouvelle fenêtre Add Package to Folders Ajouter le Package au répertoire Open Source File Ouvrir le fichier source Copy Name to Clipboard Copy Name To Clipboard Copier le nom dans le presse-papier Go Package Browser Package Browser Navigateur de Packages Go Loading Go package list... Loading go package ... Chargement de la liste des package Go... PackageProject Reload Package Recharger le package Open Explorer Here Ouvrir l'explorateur ici Add Source File Ajouter le fichier source File Name: Nom du fichier : Error Erreur File %1 already exists. Le fichier %1 existe déjà. Could not open %1 for writing. Impossible d'ouvrir %1 pour écriture. PluginsDialog Installed Plugins Install Plugins Plugins installés Close Fermer Name Nom Author Anchor Auteur Enabled Activé Details Détails Version Last Ver Version File Name FileName Nom du fichier ProcessEx process exited with code %1 le processus s'est terminé avec le code %1 process crashed or was terminated le processus s'est arrêté ou a été terminé process exited with an unknown status le processus s'est terminé avec un statut inconnu process failed to start le processus n'a pas pu démarrer process crashed or was terminated while running le processus s'est arrêté ou a été terminé pendant son exécution timed out waiting for process time out pendant l'attente du processus couldn't read from the process Impossible de lire depuis le processus couldn't write to the process Impossible d'écrire vers le processus an unknown error occurred une erreur inconnue s'est produite ProjectManager Project <%1> Projet <%1> Import Directory <%1> Répertoire d'import <%1> QFileSystemModel %1 TB %1 To %1 GB %1 Go %1 MB %1 Mo %1 KB %1 Ko %1 bytes %1 octets QJson::ParserRunnable An error occurred while parsing json: %1 Une erreur s'est produite pendant le interprétation json : %1 QJsonParseError no error occurred Aucune erreur s'est produite unterminated object objet non terminé missing name separator séparateur de nom manquant unterminated array tableau non terminé missing value separator séparateur de valeur manquant illegal value valeur illégale invalid termination by number terminaison par un nombre invalide illegal number nombre illégal invalid escape sequence séquence d'espace invalide invalid UTF8 string chaîne UTF8 invalide unterminated string chaîne non terminée object is missing after a comma un objet est manquant après la virgule too deeply nested document document inclu trop profondément too large document document trop volumineux garbage at the end of the document données salles à la fin du document QuickOpenAction Show and Run Commands Afficher et exécuter des commandes QuickOpenEditor Show All Opened Editors Show All Editors Afficher tous les éditeurs QuickOpenFileSystem File System Système de fichier QuickOpenFiles Go to File Aller au fichier Type '?' to get help on the actions you can take from here Tapper '?' pour avoire de l'aide sur les actions possibles ici QuickOpenFolder Browser Folder Naviguer dans les répertoires QuickOpenHelp Show All Quick Open Actions Show Quick Open Help Afficher toutes les actions ouverture rapide QuickOpenLines Go to Line Aller à la ligne Open a text file first to go to a line Ouvrir un fichier texte avant d'aller à une ligne Type a line number between %1 and %2 to navigate to Tapper a numéro de ligne entre %1 et %2 pour y aller Go to Line %1 Go to line %1 Aller à la ligne %1 QuickOpenManager Quick Open File Ouvrir rapidement un fichier Quick Open Editor Ouvrir rapidement un éditeur Quick Open Symbol Ouvrir rapidement un symbole Quick Open Command Ouvrir rapidement une commande Show All Quick Open Actions Afficher toutes les actions ouverture rapide QuickOpenMimeType Go to Symbol in File Open Symbol by Name Ouvrir un symbole par nom not found symbol symbole non trouvé QuickOpenOption Form Formulaire QuickOpenFiles Ouvrir rapidement les fichiers Match case sensitive Respecter la casse Max files count: Nombre de fichiers max : QuickOpenEditor Ouvrir rapidement l'éditeur RecentManager Clear All History Effacer tout l'historique Clear Menu Effacer le menu SearchEdit Search Rechercher Stop Search Arrêter la recherche SelectExternalDialog Debug External Application Déboguer une application externe Application: Application : Browse... Browser Parcourir... Arguments: Arguments : Working directory: Répertoire de travail : Select Executable Sélectionner l'exécutable Select the working directory: Select Working Directory Sélectionner le répertoire de travail : SessionRecent Sessions Sessions SideDockWidget Move To Déplacer vers RightSideBar Barre latérale droite LeftDockWidgt Widget gauche LeftSideBar Barre latérale gauche RightDockWidget Widget droite OutputBar Barre de sortie SideBar Barre latérale Show SideBar Afficher la barre latérale SideWindowStyle Hide SideBar Masquer la barre latérale SideBar Windows Fenêtre de la barre latérale Output Windows Fenêtre de sortie SplitDockWidget Move To Déplacer vers Top Haut Top (Split) Haut (Scinder) TopDockWidget (Split) Widget Haut (Scinder) TopDockWidget Widget Haut Bottom Bas Bottom (Split) Bas (Scinder) BottomDockWidget (Split) Widget bas (Scinder) BottomDockWidget Widget bas Left Gauche Left (Split) Gauche (Scinder) LeftDockWidget (Split) Widget gauche (Scinder) LeftDockWidget Widget gauche Right Droite Right (Split) Droite (Scinder) RightDockWidget (Split) Bandeau droite (Scinder) RightDockWidget Bandeau droite Unsplit Joindre Split Scinder SplitWindowStyle Hide Sidebars Masquer le bandeau latéral Tool Windows Outils Terminal New Nouveau Open a new terminal Ouvrir un nouveau terminal Close Fermer Close current terminal Fermer le terminal courant CloseAll Close all terminal LoadEnv Charge l'environement Current terminal load environment from LiteIDE Le terminal courant charge l'environnement depuis LiteIDE Filter Filtrer Dark Mode Mode sombre Login Mode (shell --login) Mode de Login (shell --login) Terminal Terminal Rename Tab Title Renommer l'onglet TerminalEdit Cut Couper Copy Copier Paste Coller Select All Tout sélectionner Clear All Tout effacer TextEditor::Internal::ColorScheme Not a color scheme file. N'est pas un fichier de schéma de couleurs. Utils::FilterLineEdit Filter Filtrer Clear text Effacer le texte VTermWidget Copy Copier Paste Coller Select All WebKitBrowser Navigation Navigation Open Html File Open Html Ouvrir un fichier HTML WebKitBrowser WebKitBrowser False load %1 ! Chargement erroné de %1 ! Open Html or Markdown File Open Html or Markdown Files Ouvrir des fichiers HTML ou Markdown WebKitHtmlWidgetPlugin Open Html or Markdown File Open Html or Markdown Files Ouvrir des fichiers HTML ou Markdown WelcomeBrowser New Nouveau Open Ouvrir Open Folder Ouvrir le répertoire Options Options Welcome Welcome Page Bienvenue WelcomePlugin Welcome Home Bienvenue ================================================ FILE: liteidex/liteide_ja.ts ================================================ AboutDialog About LiteIDE About Liteide Liteide について Information 情報 Welcome: ようこそ: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. LiteIDE X へようこそ! LiteIDE はシンプルでオープンソース、クロスプラットフォームなIDEです。 Project: プロジェクト: Name: 名前: Author: 作者: Version: バージョン: Build: ビルド: Based on Qt Based on Qt Version Source Code: ソースコード: Support LiteIDE: Support LiteIDE をサポート: Developers 開発者 Translations 翻訳者 Chinese 中国語 Japanese 日本語 Russian ロシア語 French フランス語 Traditional Chinese 繁体字 German ドイツ語 Ukrainian Thanks to... 謝辞... License ライセンス Close 閉じる Based on Qt %1 (%2 bit) ActionManager &File ファイル(&F) &Recent 最近使用した...(&R) &Edit 編集(&E) F&ind &Find 検索(&F) &View 表示(&V) &Tools &Build ビルド(&B) &Debug デバッグ(&D) &Help ヘルプ(&H) Standard Toolbar Standard ToolBar 標準ツールバー AstWidget Go To Definition 定義へ移動 View Import Document インポートドキュメントを表示 BaseDockWidget Hide 非表示 Hide Tool Window ツールウィンドウを非表示 Floating Window BaseFolderView Open In New Window Open File ファイルを開く New File... 新しいファイル... New File Wizard... 新規ファイルウィザード Rename File... ファイル名の変更... Delete File ファイルを削除 New Folder... 新しいフォルダ... Rename Folder... フォルダ名の変更... Delete Folder フォルダを削除 Open Terminal Here ここでターミナルを開く Show in Explorer Open Explorer Here ここでエクスプローラを開く Open Application Show in Finder Show Containing Folder Open Command Prompt Here Open in Integrated Terminal Open Folder... Add Folder... フォルダを追加... Reload Folder Close Folder フォルダを閉じる Close All Folders 全てのフォルダを閉じる Copy コピー Paste 貼り付け Copy Path Move To Trash Create File ファイルを作成 A file with that name already exists! ファイル名は既に使用されています! Failed to create the file! ファイルの作成に失敗しました! Rename File ファイル名を変更 New Name: 新しい名前 Failed to rename the file! ファイル名の変更に失敗しました! An item "%1" already exists in this location. Do you want to replace it and move old item to trash? Stop 停止 Keep Both Keep Both All Replace 置換 Replace All 全てを置換 Are you sure that you want move to trash this item? Are you sure that you want move to trash %1 items? Move to Trash Open With System Editor Create Folder フォルダを作成 A folder with that name already exists! フォルダ名は既に使用されています! Failed to create the folder! フォルダの作成に失敗しました! Rename Folder フォルダ名を変更 Folder Name フォルダ名 Failed to rename the folder! フォルダ名の変更に失敗しました! Are you sure that you want to permanently delete this folder and all of its contents? このフォルダと全てのコンテンツを完全に削除しますか? Failed to delete the folder! フォルダの削除に失敗しました! BookmarkManager Toggle Bookmark Goto bookmark Remove bookmark Remove all bookmarks for this file Remove all bookmarks for all files Bookmarks BookmarkRecent Bookmarks BuildConfigDialog Build Configuration Build Config Dialog ビルド設定 Build ID ビルドID Build Path Build File ビルドパス GOPATH GOPATH information Use Custom GOPATH for Build Path Inherit System GOPATH Inherit LiteIDE GOPATH Custom GOPATH (one per line) Add Directory... ディレクトリを追加... Clear クリア LiteIDE LiteIDE Config 設定 Action Custom Build Custom カスタム Reset all to initial value Name 名前 Value SharedValue Id Cmd Choose directory to add to GOPATH: GOPATHに追加するディレクトリを選択: CreateDirDialog Create Folder フォルダを作成 Directory: ディレクトリ: Dir Name: Create 作成 Cancel キャンセル CreateFileDialog Create File Create File Dialog ファイルを作成 Directory: ディレクトリ: File Name: ファイル名: Create 作成 Create and Edit 作成して編集 Cancel キャンセル DebugWidget Add Watch Async Record AsyncRecord レコードを同期 Variables 変数 Watch ウォッチ Call Stack CallStack 呼び出し履歴 Threads Goroutines Registers Libraries Library ライブラリ Console コンソール Watch expression (e.g. buf main.var os.Stdout): Remove Watch ウォッチを削除 Remove All Watches 全てのウォッチを削除 DlvDebuggerOption Form フォーム delve debug pass flags: (example --check-go-version=false) DocumentBrowser Back Backward 戻る Forward 進む Reload 再読み込み Increase Font Size フォントサイズを増やす Decrease Font Size フォントサイズを減らす Reset Font Size フォントサイズをリセット DocumentBrowserFactory DocumentBrowser EditorManager Close 閉じる Move to New Window Move To New Window 新しいウィンドウへ移動 Navigate Forward GoForward 進む Close Others Close Others Tabs 他を閉じる Open Editor Close All Close All Tabs 全て閉じる Close Left Tabs 左のタブを閉じる Close Right Tabs 右のタブを閉じる Close Files in Same Folder Close Same Folder Files 同じフォルダのファイルを閉じる Close Files in Other Folders Close Other Folder Files 他のフォルダのファイルを閉じる Copy Full Path to Clipboard Copy Path to Clipboard フルパスをクリップボードにコピーする Show in Explorer エクスプローラで表示 Show in Finder Show Containing Folder Open Command Prompt Here Open Terminal Here ここでターミナルを開く Open in Integrated Terminal Navigate Backward 戻る Save changes to %1? %1 へ変更を保存する Unsaved Modifications Save Modify 変更が保存されていない All Files (*) 全てのファイル (*) Save As 名前を付けて保存... EnvManager Environment Toolbar Environment ToolBar 環境ツールバー Switching current environment Switch Current Environment 環境 Edit current environment Edit Current Environment 環境を編集 Reload current environment Reload Current Environment Select Environment ExportDialog Dialog ダイアログ Name: 名前: Export エクスポート ExportAndView エクスポートして表示 FakeVim::Internal Use Vim-style Editing Read .vimrc Path to .vimrc FakeVim::Internal::FakeVimHandler Unknown option: %1 Argument must be positive: %1=%2 Mark "%1" not set. %1%2% %1All Not implemented in FakeVim. Unknown option: Invalid argument: Trailing characters: Move lines into themselves. %n lines moved. File "%1" exists (add ! to override) Cannot open file "%1" for writing "%1" %2 %3L, %4C written. Cannot open file "%1" for reading "%1" %2L, %3C %n lines filtered. Cannot open file %1 Invalid regular expression: %1 Pattern not found: %1 Search hit BOTTOM, continuing at TOP. Search hit TOP, continuing at BOTTOM. Search hit BOTTOM without match for: %1 Search hit TOP without match for: %1 %n lines indented. %n lines %1ed %2 time. %n lines yanked. Already at oldest change. Already at newest change. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Type Alt-V, Alt-V to quit FakeVim mode. [New] Not an editor command: %1 FakeVimEdit Use FakeVim Editing FakeVimEditOption Form フォーム FakeVim initialization command list (# start is comment): Load default init command list FiFoTty Cannot create temporary file: %1 テンポラリファイルが作れません: %1 Cannot create FiFo %1: %2 FiFo %1 を作成出来ません: %2 Cannot open FiFo %1: %2 FiFo %1 を開けません: %2 FileBrowser Synchronize with editor エディタと同期 Show Hidden Files 非表示ファイルを表示 Set As Root Folder Set Folder To Root フォルダをルートへ設定 Execute File ファイルを実行 Reload Folder Show Details Debug File Open Folder in New Window 新しいウィンドウでフォルダを開く Add to Folders フォルダを追加 Open Parent Open to Parent 親ディレクトリを開く Filter フィルタ File System ファイルシステム FileBrowserOption Form フォーム Terminal ターミナル Command: コマンド: Arguments: 引数: FileManager All Files (*) 全てのファイル (*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? プロジェクト '%1' が作成されました。 読み込みますか? Open Project or File プロジェクトもしくはファイルを開く... Show Hidden Files 非表示ファイルを表示 Show Details Split Mode Folders Folers フォルダ All Support Files (%1) サポートしている全てのファイル(%1) Select a folder: Open Folder フォルダを選択: %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 This file has been deleted from the drive. Do you want to close the editor? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 This file has been modified on the drive. Do you want to reload the file from disk? Open Files ファイルを開く... Synchronize with editor エディタと同期 Filter フィルタ Open Project プロジェクトを開く LiteIDE X LiteIDE X FileRecent Files FileSearch Match whole word Match word 単語にマッチ Match case 大文字/小文字の区別 Regular expression 正規表現 Scan subdirectories Look in subdirs サブディレクトリをスキャン Search for: 検索: Options: オプション: Browse... Browser 開く... Filter: フィルタ: Files on File System ファイルシステム上のファイル Search 検索 Cancel キャンセル Current Folder Auto Switch Clear クリア Open Directory ディレクトリを開く FileSearchManager Search Item: 検索対象 Only golang file changes can be revert! This file change cannot be undone! この変更は戻せません! New Search 新しい検索 File Search ファイル検索 Search Result 検索結果 LiteIDE X LiteIDE X Warning! Replace text is empty. Want to remove all the search items? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? The following files have no write permissions. Do you want to change the permissions? 以下のファイルは書き込み権限がありません。権限を変更しますか? File is readonly 読み取り専用ファイル FileSystemWidget Open File Open Editor ファイルを開く New File... New File 新しいファイル... New File Wizard... New File Wizard 新規ファイルウィザード Rename File ファイル名を変更 Delete File Remove File ファイルを削除 New Folder... New Folder 新しいフォルダ... Are you sure that you want to permanently delete this file? このファイルを完全に削除しますか? Rename Folder フォルダ名を変更 Delete Folder Remove Folder フォルダを削除 Rename File... ファイル名の変更... Rename Folder... フォルダ名の変更... Open Terminal Here ここでターミナルを開く Open Explorer Here ここでエクスプローラを開く View Godoc Here ここでGodocを見る Add Folder フォルダを追加 Close Folder フォルダを閉じる Add Folder... フォルダを追加... Close All Folders 全てのフォルダを閉じる Create File ファイルを作成 A file with that name already exists! The file already exists! ファイル名は既に使用されています! Failed to create the file! ファイルの作成に失敗しました! New Name: 新しい名前 Failed to rename the file! ファイル名の変更に失敗しました! Are you sure that you want to permanently delete this folder and all of its contents? このフォルダと全てのコンテンツを完全に削除しますか? Failed to delete the file! Failed to remove the file! ファイルの削除に失敗しました! Create Folder フォルダを作成 A folder with that name already exists! The folder name is exists! フォルダ名は既に使用されています! Failed to create the folder! フォルダの作成に失敗しました! Folder Name フォルダ名 Failed to rename the folder! フォルダ名の変更に失敗しました! Failed to delete the folder! Failed to remove the folder! フォルダの削除に失敗しました! Find::Internal::SearchResultWidget Search was canceled. 検索は中断されました Cancel キャンセル Repeat the search with same parameters 同じパラメータで検索を繰り返す Search again 再度検索 Set show replace mode ui Show Replace Replace with: 置換: Replace all occurrences 全て置換 Replace 置換 Preserve case 大文字/小文字を維持する Expand all items Collapse all items Revert with: Revert Revert all occurrences %n matches replaced. searching... %n matches found. searching ... No matches found. 見つかりませんでした %n matches found. FindApiEdit Search 検索 Stop Search 検索を中断 FindApiWidget Search 検索 Find 検索 FindDocWidget Search 検索 Find 検索 Find All 全て検索 Find const 定数を検索 Find func 関数を検索 Find interface インタフェースを検索 Find pkg パッケージを検索 Find struct 構造体を検索 Find type 型を検索 Find var 変数を検索 Use Regexp 正規表現 Match Case 大文字/小文字の区別 Match Word 単語にマッチ Help ヘルプ FindEditor Match case 大文字/小文字の区別 Regular expression 正規表現 Wrap around 折り返す Find Next 次を検索 Find Previous Find Prev 前を検索 Replace With: 置換: Replace 置換 Replace All 全てを置換 Match whole word only 単語の検索 Ready 準備 Close 閉じる Show Replace Find What: 検索: Options: Find Option: オプション: Not found 見つかりませんでした FolderListView Delete File ファイルを削除 Are you sure that you want to permanently delete this file? このファイルを完全に削除しますか? Failed to delete the file! ファイルの削除に失敗しました! Delete Folder フォルダを削除 Are you sure that you want to permanently delete this folder and all of its contents? このフォルダと全てのコンテンツを完全に削除しますか? Failed to delete the folder! フォルダの削除に失敗しました! FolderRecent Folders フォルダ FolderView Delete File ファイルを削除 Are you sure that you want to permanently delete this file? このファイルを完全に削除しますか? Failed to delete the file! ファイルの削除に失敗しました! Delete Folder フォルダを削除 Are you sure that you want to permanently delete this folder and all of its contents? このフォルダと全てのコンテンツを完全に削除しますか? Failed to delete the folder! フォルダの削除に失敗しました! GdbDebuggerOption Form フォーム Enable --tty for program being debugged. プログラムのデバッグで --tty を有効にする GoAddTagsDialog Add Tags To Struct Field Add JSON Tag Options オプション Multiple options separated by commas Multiple options are separated by commas Add XML Tag Add Custom Tags Tag Name Setup custom tag name Sort sorts the tags in increasing order according to the key name Override current tags when adding tags Info 情報 GoRemoveTagsDialog Remove Tags From Struct Field Remove Tags And Options Clear All Tags Clear All Tags Options Clear All Tag Options Remove JSON Tag Remove XML Tag Remove Custom Tag Multiple tags separated by commas Multiple tags are separated by commas Remove JSON Options Multiple options separated by commas Multiple options are separated by commas Remove XML Options Remove Custom Tag Options Setup remove custom tag and option, example tag=opt1,tag=opt2 Setup remove custom tag option, example tag=opt1,tag=opt2 tag=option Info 情報 GolangAst No outline available アウトラインが見つかりません Synchronize with editor エディタと同期 Go Class View Class View クラス表示 Go Outline Outline アウトライン GolangAstOption Form フォーム QuickOpenSymbol Show import path Match case sensitive GolangCodeOption Form フォーム PKG automitic import prompt PKG automatic import hints for all packages (GOPATH) PKG automatic import hints for standard package Gocode Go API Auto update depends package when it's source changed. Auto update depends package when its source is changed. Close gocode when exiting 終了時にgocodeを閉じる GolangDoc Godoc Search Godocを検索 Go Doc Search Golang Doc Search Golangドキュメント検索 Go Api Index Golang Api Index Golang APIインデックス Find Package: GolangDocOption Form フォーム Go API Use default context (fast) デフォルトのコンテキストを使用する(高速) Only load standard API documentation Only load standard api 標準 API ドキュメントのみ読み込む GolangEdit View import package use godoc View Expression Information 式の情報を表示 Jump to Declaration 定義へジャンプ Find Usages 使用箇所を検索 Rename Symbol Under Cursor カーソル下のシンボルをリネーム %1 (Module/GOPATH) with GOROOT Stop 停止 Go Source Query SourceQuery What Callees Callers Callstack Definition Describe Freevars Implements Implements(GOPATH) Peers Referrers Pointsto Whicherrs Add Tags To Struct Field Remove Tags From Struct Field Refactor リファクタリング SourceQuery Below files in package %1 GolangEditOption Form フォーム Mouse Go root source file editor setup read only Enable view expression infomation on mouse Enable mouse navigation GolangFileSearch Golang Find Usages Golang の使用箇所を検索 GolangFmtOption Form フォーム Format Options Golang Format 整形オプション Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Goimports はインポート行を変更し、必要なインポートを追加したり不要なインポートを削除します。 Enable update imports line, adding missing ones and removing unreferenced ones. Synchronous 同期 Synchronous code formatting Synchronous code formatting コード整形を同期して行う Synchronous code formatting timeout in milliseconds (500ms or more): 同期コード整形時のタイムアウト(500ms もしくはそれ以上): Automatically format code when saving When the editor is saved automatically gofmt 保存時に自動でコード整形を行う GolangFmtPlugin Format Code Format Code (goimports) コードを整形 Format Code (Adjusts Imports) GolangPackageOption Choose directory to add to GOPATH: GOPATHに追加するディレクトリを選択: Manage GOPATH / Modules GOPATHを管理 Go Modules Custom GONOPROXY Custom GOPROXY Custom GO111MODULE Custom GONOSUMDB Custom GOPRIVATE TextLabel GOPATH Use System GOPATH Reload 再読み込み Use Custom GOPATH (one per line) Add Directory... ディレクトリを追加... Clear クリア GolangPresentEdit Section (s1) セクション(s1) Subsection (s2) セクション(s2) Sub-subsection (s3) セクション(s3) Bold 太字 Italic 斜字 Inline Code コード Switch Bullets 箇条書き Comment/Uncomment Selection 選択をコメント/コメント解除 Export HTML HTMLへエクスポート Verify Present プレゼンを検証 Present verify success プレゼンの検証が成功しました Present verify false プレゼンの検証が失敗しました Export PDF PDFへエクスポート GolangSymbol Quick Open Symbol by Name GoplayBrowser Go Playground Run 実行 Stop 停止 New 新規 Load... 読み込み... Save... 保存... Explore Folder フォルダを探索 Running... Running... 起動中... Error: %1. Error: %1. エラー: %1 Success: %2. Success: %2. 成功: %2 Load File ファイルを読み込む Select a file to load: 読み込むファイルを選択: Save File ファイルを保存 New File Name: 新しいファイルの名前: HtmlPreview Page Style ページスタイル Reload 再読み込み Export Html HTMLへエクスポート Export PDF PDFへエクスポート Print Preview 印刷プレビュー Synchronize preview and code scrollbars コードのスクロールバーをプレビューと同期する Config 設定 Plain HTML 単純なHTML Export Failed エクスポートに失敗しました Automatically display preview Automatically Display Preview プレビューを自動で表示 HTML Preview Html Preview HTMLプレビュー Could not open %1 for writing! Can not write file %1 %1 を書き込み用に開けませんでした ImageEditor ZoomIn ZoomOut Reset to original size Fit to view Play movie Prev frame Next frame Pause movie ImageEditorFactory Image Viewer ImportPkgTip warning, pkg not find, please enter to import : JsonEdit Verify 検証 Format Json Compact Json LiteApp Event Log イベントログ Escape エスケープ Close File ファイルを閉じる Close All Files 全てのファイルを閉じる Save File ファイルを保存 Save File As... 名前を付けてファイルを保存... Save All Files 全てのファイルを保存 Open Project プロジェクトを開く Options オプション New... 新規... Open File... ファイルを開く... Open Folder... フォルダを開く... Open Folder in New Window... 新しいウィンドウでフォルダを開く... Close All Folders Add Folder... フォルダを追加... New Window 新しいウィンドウ Close Window ウィンドウを閉じる Save Project プロジェクトを保存 Close Project プロジェクトを閉じる Exit 終了 Full Screen 全画面 About LiteIDE Liteide について About Plugins プラグインについて LiteAppOption Form フォーム Store [*] Store 保存 Language: 言語: Icon [*] Reload files in session Recent Files Recent File 最近使用したファイル Max Count: Max Recent: 最大個数: Monitoring files for modifications ファイルの変更を監視 Store settings to local ini file Interface [*] Style: Use tool window shortcuts Theme [*] Fallback build-in icon library and liteapp/qrc/default Load the external file icon library Load custome icon from liteapp/qrc folder Automatically save documents Automatically save documents when application is idle sec Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. 元のファイルが変更/削除された場合、自動でリロード/クローズする Session セクション 0-99 Editor Tabs 10-999 Display 表示 Display [*] Show splash screen on startup 起動時にスプラッシュ画面を表示 Show welcome page on startup 起動時にようこそのページを表示 Editor Editor tab [*] Show close buttons on each editor tab タブ毎に閉じるボタンを表示 Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab Toolbar Icon Size [*] Editor navigate Enable mouse extra 'Back' button and 'Forward' button for go back and forward Keyboard キーボード Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} 整形: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands 標準コマンドを隠す Reset リセット Reset All 全てをリセット Import... インポート... Export... エクスポート... Generic 一般 Theme: テーマ Reload session on startup Auto load last session 起動時にセッションを再読み込み SideBarStyle SplitterStyle Command コマンド Label ラベル Shortcuts ショートカット NativeText Standard 標準 Import Keyboard Mapping Scheme キーボードマッピングスキームをインポート Keyboard Mapping Scheme (%1) キーボードマッピングスキーム(%1) Could not read scheme from %1! %1 からスキームを読み込めません Export Keyboard Mapping Scheme キーボードマッピングスキームをエクスポート Could not write scheme to %1! スキーム %1 を書き込めません! LiteBuild Build Toolbar Build Configuration... Build Config ビルドの設定 Stop Action アクションを停止 Clear Output Clear All 全てクリア Execute File ファイルを実行 Debug File Lock Build Path Lock Go Build Path Build Path Configuration Go Build Configuration Use godoc View ここでGodocを見る Line Wrap Auto Clear Automatic positioning cursor Setup Build Output Build ビルドオプション Current environment change id "%1" 現在の環境は id "%1" を変更します Lock Build Lock Build: %1 Error: %1. Error: %1. エラー: %1 Command exited with code %1. コマンドはコード %1 で終了しました Success: %1. Success: %1. 成功: %1 A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. プロセスが実行中です。まずアクションを停止して下さい。 Killing current process... Killing current process... このプロセスを強制終了する... Failed to terminate the existing process! Failed to terminate the existing process! 起動中プロセスの停止に失敗しました Started process successfully Started process successfully プロセスの起動に成功しました Failed to start process プロセスの起動に失敗しました LiteBuildOption Form フォーム Recheck Go installation when changing environments Recheck go env if enviroment changed 環境の変更時にGoのインストールを再チェックする Build command configuration files [*] Build command configuration files: ビルドコマンドの設定ファイル: LiteBuildPlugin Close 閉じる Execute: Exec: 実行: Execute File Execute ファイルを実行 LiteDebug Stop 停止 Clear クリア Continue 続行 Show Current Line 現在行を表示 Debug Output Debug デバッグ出力 Start Debugging External Application... Start Debugging External Application 外部のアプリケーションをデバッグ起動 Close 閉じる Start Debugging デバッグ開始 Step Into ステップ実行(入る) Step Over ステップ実行(通過) Step Out ステップ実行(出る) Run to Line 指定行まで実行 Insert/Remove Breakpoint ブレイクポイントの追加と削除 Remove All Breakpoints 全てのブレイクポイントを削除 LiteDebugOption Form フォーム Debug デバッグ Automatically insert breakpoint main.main when debugging Automatically add breakpoint main.main when debugging LiteDebugPlugin Debug Window Debug デバッグウィンドウ LiteDoc LiteIDE Documentation LiteIDE Document Browser LiteIDEドキュメントブラウザ LiteEditor Undo 元に戻す Redo やり直し Cut 切り取り Copy コピー Paste 貼り付け Select All 全てを選択 Go to Doc Start Go to Doc End Go to Line Start Go to Line End Go to Previous Line Go to Next Line Go to Previous Character Go to Next Charater Go to Previous Word Go to Next Word Go to Line File is readonly 読み取り専用ファイル File is writable Line Wrap (MimeType) Word Wrap (MimeType) Toggle Comment Toggle Block Commnet Auto-indent Selection Tab To Spaces (MimeType) Line End Windows (\r\n) Line End Unix (\n) Visualize Whitespace (Global) Move Line Up Move Line Down Copy Line Up Copy Line Down Join Lines Title Case Upper Case Lower Case Swap Case Tab To Spaces Spaces To Tab Advanced 高度な操作 Goto Convert Tab Code Folding コードの折りたたみ Convert Case Export HTML HTMLへエクスポート Export Failed エクスポートに失敗しました Could not open %1 for writing. %1 を書き込み用に開けませんでした Export PDF PDFへエクスポート Print Document 印刷 Print Preview... Print Preview Document 印刷プレビュー... Export HTML... HTMLへエクスポート... Export PDF... PDFへエクスポート... Print... 印刷... Go to Previous Block Go To Previous Block 前のブロックに移動 Select Block ブロックを選択 Go to Matching Brace Go To Matching Brace 対照へ移動 Fold 折りたたみ Unfold 折りたたみを展開 Fold All 全て折りたたみ Unfold All 全ての折りたたみを展開 Go To Line Goto Line 指定行へ移動 Duplicate 重複 Delete Line 行を削除 Copy Line Cut Line Insert Line Before 前の行で挿入 Insert Line After 後の行で挿入 Increase Font Size フォントサイズを増やす Decrease Font Size フォントサイズを減らす Reset Font Size フォントサイズをリセット Clean Whitespace 空白を除去 Code Complete コード補完 Settings File Setup Reload File ファイルを再読み込み Do you want to permanently discard unsaved modifications and reload %1? 未保存な変更を破棄して %1 を再読み込みしますか? Go to Next Block Go To Next Block 次のブロックに移動 ReadOnly Line: 行: LiteEditorFileFactory Text Editor LiteEditorOption Form フォーム Load File ファイルを読み込む Check and convert no printable char to '.' 不可視文字をチェックし '.' に変換する Font フォント Font && Colors フォントと色 Family: フォント名: Show Monospace Font Size: サイズ: Zoom: ズーム: % Antialias アンチエイリアス Restore Default Font Editor Color Scheme ColorStyle Scheme カラースキームエディタ File: ファイル: Edit 編集 Syntax Auto-completion Auto complete brackets ブラケットを自動補完 Fuzzy code completion Clean completion cache when saving files Clean whitespace when saving files ファイル保存時に空白を除去 Enable scroll wheel zooming マウスホィールによるスクロールを許可 Add copied text into the clipboard as HTML Allow vertical scrolling to the last line [*] Display VisualizeWhitespace Word wrap by default デフォルトで折り返す Display code fold Display offset position オフセット位置を表示 File Types ファイルタイプ Behavior 動作 Display EOF EOF を表示 Display line numbers 行番号を表示 Display indent guide Display indent guide インデントガイドを表示 Display right margin at column 右マージを表示 Automatic indentation Enable automatic indentation 自動インデント Case sensitive code completion Completer case sensitive 大文字/小文字を区別したコード補完 Code completion prefix length: Word Complete Prefix Length コード補完を行う文字数: Display 表示 MIME Type MIMEタイプ Tab Width タブ幅 Tab To Spaces File Extensions ファイルの拡張子 Custom Extensions LiteEditorPlugin Edit ToolBar Edit Navigation Bar LiteEnvOption Form フォーム Environment definition files: 環境定義ファイル: Environment changes will take effect after switching environments. 環境の変更は切り替え後に有効となります LiteFindPlugin Find 検索 Find Next 次を検索 Find Previous 前を検索 Replace 置換 File Search ファイル検索 LiteTabWidget Open a new tab 新しいタブを開く List All Tabs Close Tab MarkdownBatchBrowser Markdown Exporter Markdown Batch Markdownエクスポート All Files (*) 全てのファイル (*) Select the folder containing your markdown files: Select Markdown Folder Markdownファイルがあるフォルダを選択 Select Markdown Files Markdownファイルを選択 Select the folder to contain separated markdown exports: 分割してエクスポートされたmarkdownが含まれるフォルダを選択: Export Merged HTML Export Html マージしてHTMLへエクスポート Export Merged PDF Export PDF PDFへエクスポート MarkdownBatchWidget Form フォーム Markdown Source Files Markdown Files Markdownソースファイル Import Folder... Import Folder フォルダをインポート... Add Files... Add Files ファイルを追加... Move Up 上へ移動 Move Down 下へ移動 Remove 削除 Remove All 全て削除 Options オプション Export Folder: エクスポートフォルダ: Browse... Browser 参照... Use CSS CSSを使用 Insert horizontal line between merged files Merge files insert split <hr> マージされるファイルの間に区切り線を挿入する Insert page break between merged files Merge files insert page break マージされるファイルの間にページ区切りを挿入する Export Export Util エクスポート Export Separated HTML Separate Html 別のHTMLへエクスポート Export Separated PDF Separate PDF 別のPDFへエクスポート Export Merged HTML... Merge Html HTMLにマージしてエクスポート Export Merged PDF... Merge PDF PDFにマージしてエクスポート Print Preview Merged... Merge Print Preview マージして印刷プレビュー Print Merged Merge Print マージして印刷 Log ログ MarkdownEdit Header (h1) Header <h1> ヘッダ(h1) Header (h2) Header <h2> ヘッダ(h2) Header (h3) Header <h3> ヘッダ(h3) Header (h4) Header <h4> ヘッダ(h4) Header (h5) Header <h5> ヘッダ(h5) Header (h6) Header <h6> ヘッダ(h6) Bold 太字 Italic 斜字 Inline Code コード Link リンク Image 画像 Unordered List 箇条書き Ordered List 一覧 Blockquote 引用 Horizontal Rule 区切り Heading ヘッダ MultiFolderView Delete Folder フォルダを削除 Are you sure that you want to permanently delete this folder and all of its contents? このフォルダと全てのコンテンツを完全に削除しますか? Failed to delete the folder! フォルダの削除に失敗しました! Delete File ファイルを削除 Are you sure that you want to permanently delete this file? このファイルを完全に削除しますか? Failed to delete the file! ファイルの削除に失敗しました! NavigateBar Browser Files in %1 NewFileDialog New Project or File 新規プロジェクト/ファイル Browse... 参照... GOPATH: Template: Template テンプレート: Type 種別 Information 情報 Name: 名前: Location: 位置: Error エラー Could not create the target directory: %1 ターゲットディレクトリが作成出来ませんでした: %1 Warning 警告 Location %1 is not empty. Use the target directory anyway? 場所 %1 は空です。 それでもこのディレクトリを使用しますか? Overwrite File ファイルの上書き %1 already exists. Do you want to replace it? %1 は既に存在しています。 置き換えますか? No files could be created. ファイルが作成出来ませんでした File template details: ファイルテンプレートの詳細: Project template details: New project wizard: 新規プロジェクトウィザード: Choose a directory for the new content: 新しいコンテンツを置くディレクトリ選択: OpenEditorsWidget Open Documents OptionsBrowser Options Options Page オプション OptionsWidget Options オプション Info 情報 [*] item request restart of LiteIDE [*] item requeset restart LiteIDE OutputDockWidget Move To 移動 LeftSideBar RightSideBar BottomDockWidget OutputOption Form フォーム Font フォント Family: フォント名: Size: サイズ: Zoom: ズーム: % Antialias アンチエイリアス Display 表示 Use editor color scheme Sets the maximum number of lines PackageBrowser Manage GOPATH/Modules ... Manage GOPATH... GOPATHを管理... Reload All 全て再読み込み Use godoc View ここでGodocを見る Load Package in New Window 新しいウィンドウでパッケージを読み込む Add Package to Folders フォルダにパッケージを追加 Open Source File ソースファイルを開く Copy Name to Clipboard Copy Name To Clipboard 名前をクリップボードにコピー Go Package Browser Package Browser パッケージブラウザ Loading Go package list... Loading go package ... Goのパッケージリストを読み込み中... PackageProject Reload Package パッケージをリロード Open Explorer Here ここでエクスプローラを開く Add Source File ソースファイルを追加 File Name: ファイル名: Error エラー File %1 already exists. ファイル %1 は既に存在しています Could not open %1 for writing. %1 を書き込み用に開けませんでした PluginsDialog Installed Plugins Install Plugins プラグインをインストール Close 閉じる Name 名前 Author Anchor 作者 Enabled 有効 Details 詳細 Version Last Ver バージョン File Name FileName ファイル名 ProcessEx process exited with code %1 プロセスがコード %1 で終了しました process crashed or was terminated プロセスがクラッシュしたか強制終了しました process exited with an unknown status 原因不明のステータスでプロセスが終了しました process failed to start プロセスの起動に失敗しました process crashed or was terminated while running プロセスがクラッシュしたか実行中に強制終了しました timed out waiting for process プロセス待機がタイムアウトしました couldn't read from the process プロセスから読み込めませんでした couldn't write to the process プロセスに書き込めませんでした an unknown error occurred エラーが発生 ProjectManager Project <%1> プロジェクト <%1> Import Directory <%1> インポートディレクトリ <%1> QFileSystemModel %1 TB %1 GB %1 MB %1 KB %1 bytes QJson::ParserRunnable An error occurred while parsing json: %1 jsonの解析中にエラーが発生: %1 QJsonParseError no error occurred unterminated object missing name separator unterminated array missing value separator illegal value invalid termination by number illegal number invalid escape sequence invalid UTF8 string unterminated string object is missing after a comma too deeply nested document too large document garbage at the end of the document QuickOpenAction Show and Run Commands QuickOpenEditor Show All Opened Editors Show All Editors QuickOpenFileSystem File System ファイルシステム QuickOpenFiles Go to File Type '?' to get help on the actions you can take from here QuickOpenFolder Browser Folder QuickOpenHelp Show All Quick Open Actions Show Quick Open Help QuickOpenLines Go to Line Open a text file first to go to a line Type a line number between %1 and %2 to navigate to Go to Line %1 Go to line %1 QuickOpenManager Quick Open File Quick Open Editor Quick Open Symbol Quick Open Command Show All Quick Open Actions QuickOpenMimeType Go to Symbol in File Open Symbol by Name not found symbol QuickOpenOption Form フォーム QuickOpenFiles Match case sensitive Max files count: QuickOpenEditor RecentManager Clear All History Clear Menu SearchEdit Search 検索 Stop Search 検索を中断 SelectExternalDialog Debug External Application 外部のアプリケーションをデバッグ Application: アプリケーション: Browse... Browser 参照... Arguments: 引数: Working directory: 作業ディレクトリ: Select Executable 実行ファイルを選択 Select the working directory: Select Working Directory 作業ディレクトリを選択 SessionRecent Sessions SideDockWidget Move To 移動 RightSideBar LeftDockWidgt LeftSideBar RightDockWidget OutputBar SideBar Show SideBar SideWindowStyle Hide SideBar SideBar Windows Output Windows SplitDockWidget Move To 移動 Top 一番上 Top (Split) 一番上(分割) TopDockWidget (Split) TopDockWidget Bottom 一番下 Bottom (Split) 一番下(分割) BottomDockWidget (Split) BottomDockWidget Left Left (Split) 左(分割) LeftDockWidget (Split) LeftDockWidget Right Right (Split) 右(分割) RightDockWidget (Split) RightDockWidget Unsplit 分割しない Split 分割 SplitWindowStyle Hide Sidebars Tool Windows ツールウィンドウ Terminal New 新規 Open a new terminal Close 閉じる Close current terminal CloseAll Close all terminal LoadEnv Current terminal load environment from LiteIDE Filter フィルタ Dark Mode Login Mode (shell --login) Terminal ターミナル Rename Tab Title TerminalEdit Cut 切り取り Copy コピー Paste 貼り付け Select All 全て選択 Clear All 全てクリア TextEditor::Internal::ColorScheme Not a color scheme file. 色スキームファイルではありません Utils::FilterLineEdit Filter フィルタ Clear text テキストをクリア VTermWidget Copy コピー Paste 貼り付け Select All WebKitBrowser Navigation ナビゲーション Open Html File Open Html HTMLファイルを開く WebKitBrowser False load %1 ! %1 の読み込み失敗! Open Html or Markdown File Open Html or Markdown Files HTMLもしくはMarkdownファイルを開く WebKitHtmlWidgetPlugin Open Html or Markdown File HTMLもしくはMarkdownファイルを開く WelcomeBrowser New 新規 Open 開く Open Folder フォルダを開く Options オプション Welcome Welcome Page ようこそ WelcomePlugin Welcome Home ホーム ================================================ FILE: liteidex/liteide_ru.ts ================================================ AboutDialog About LiteIDE About Liteide О программе LiteIDE Information Infomation Информация Welcome: Добро пожаловать: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Добро пожаловать в LiteIDE X! LiteIDE это простая кросплатформенная среда разработки с открытым исходным кодом. Project: Проект: Name: Название: Author: Автор: Version: Версия: Build: Сборка: Based on Qt Based on Qt Version На основе Qt Source Code: Исходный код: Support LiteIDE: Support Поддержка LiteIDE: Developers Разработчики Translations Перевод Chinese Китайский Japanese Японский Russian Русский French Французский Traditional Chinese Китайский традиционный German Немецкий Ukrainian Украинский Thanks to... Благодарности... License Лицензия Close Закрыть Based on Qt %1 (%2 bit) Основано на Qt %1 (%2 бит) ActionManager &File &Файл &Recent &Последние &Edit &Правка F&ind &Find П&оиск &View &Вид &Help &Справка Standard Toolbar Standard ToolBar Стандартная панель &Tools &Инструменты &Build С&борка &Debug &Отладка AstWidget Go To Definition Перейти к определению View Import Document Открыть документацию импорта BaseDockWidget Hide Скрыть Hide Tool Window Скрыть окно инструментов Floating Window Плавающее окно BaseFolderView Open File Открыть файл New File... Создать файл... New File Wizard... Мастер создания файла... Rename File... Переименовать файл... Delete File Удалить файл New Folder... Создать папку... Rename Folder... Переименовать папку... Delete Folder Удалить папку Open Terminal Here Запустить терминал в папке Open Folder... Add Folder... Открыть папку... Reload Folder Обновить папку Close Folder Закрыть папку Close All Folders Закрыть все папки Create File Создание файла A file with that name already exists! Файл с этим именем уже существует! Failed to create the file! Не удалось создать файл! Rename File Переименование файла New Name: Новое имя: Failed to rename the file! Не удалось переименовать файл! Create Folder Создание папки A folder with that name already exists! Папка с этим именем уже существует! Failed to create the folder! Не удалось создать папку! Rename Folder Переименование папки Folder Name Имя папки Failed to rename the folder! Не удалось переименовать папку! Are you sure that you want to permanently delete this folder and all of its contents? Удалить эту папку со всем содержимым? Failed to delete the folder! Не удалось удалить папку! Open In New Window Открыть в новом окне Show in Explorer Открыть в проводнике Show in Finder Открыть в Finder Show Containing Folder Открыть каталог файла Open Command Prompt Here Запустить консоль в каталоге Open Application Открыть приложение Copy Копировать Paste Вставить Move To Trash An item "%1" already exists in this location. Do you want to replace it and move old item to trash? Stop Остановить Keep Both Keep Both All Replace Заменить Replace All Заменить всё Are you sure that you want move to trash this item? Are you sure that you want move to trash %1 items? Move to Trash Open With System Editor Open in Integrated Terminal Copy Path BookmarkManager Toggle Bookmark Переключить закладку Bookmarks Закладки Goto bookmark Перейти к закладке Remove bookmark Удалить закладку Remove all bookmarks for this file Удалить все закладки в этом файле Remove all bookmarks for all files Удалить все закладки для всех файлов BookmarkRecent Bookmarks Закладки BuildConfigDialog Build Configuration Build Config Dialog Конфигурация сборки Build ID ID сборки Build Path Build File Каталог сборки LiteIDE LiteIDE Custom Build Custom Другое GOPATH GOPATH Use Custom GOPATH for Build Path Использовать особый GOPATH для путей сборки Inherit System GOPATH Наследовать системный GOPATH Inherit LiteIDE GOPATH Наследовать GOPATH от LiteIDE Custom GOPATH (one per line) Особый GOPATH (по-одному в строку) Add Directory... Добавить... Clear Очистить Reset all to initial value Сбросить всё в исходное состояние Choose directory to add to GOPATH: Выбор каталога для добавления в GOPATH Action Действие Name Имя Value Значение SharedValue Общее значение Id ID Cmd Команда Config Конфигурация GOPATH information Информация о GOPATH CreateDirDialog Create Folder Создание папки Directory: Каталог: Dir Name: Имя каталога: Create Создать Cancel Отмена CreateFileDialog Create File Create File Dialog Создание файла Directory: Каталог: File Name: Имя файла: Create Создать Create and Edit Создать и открыть Cancel Отмена DebugWidget Async Record AsyncRecord Асинхронная запись Variables Переменные Watch Наблюдаемые Call Stack CallStack Стек вызовов Libraries Library Библиотеки Console Консоль Remove Watch Удалить из наблюдения Remove All Watches Удалить все наблюдаемые Add Watch Добавить в наблюдаемые Threads Потоки Goroutines Горутины Registers Регистры Watch expression (e.g. buf main.var os.Stdout): Наблюдаемое выражение (например: buf main.var os.Stdout): DlvDebuggerOption Form delve debug pass flags: (example --check-go-version=false) DocumentBrowser Back Backward Назад Forward Далее Reload Обновить Increase Font Size Увеличить шрифт Decrease Font Size Уменьшить шрифт Reset Font Size Стандартный размер шрифта DocumentBrowserFactory DocumentBrowser EditorManager Close Закрыть Move to New Window Move To New Window Переместить в новое окно Navigate Forward GoForward Перейти вперёд Close Others Close Others Tabs Закрыть другие Close All Close All Tabs Закрыть всё Close Left Tabs Закрыть вкладки слева Close Right Tabs Закрыть вкладки справа Close Files in Same Folder Close Same Folder Files Закрыть файлы в этой папке Close Files in Other Folders Close Other Folder Files Закрыть файлы в других папках Copy Full Path to Clipboard Copy Path to Clipboard Скопировать полный путь в буфер Show in Explorer Открыть в проводнике Navigate Backward Перейти назад Save changes to %1? Сохранить изменения в %1? Unsaved Modifications Save Modify Несохранённые изменения All Files (*) Все файлы (*) Save As Сохранить как... Open Terminal Here Запустить терминал в каталоге Show in Finder Открыть в Finder Show Containing Folder Открыть каталог файла Open Command Prompt Here Запустить консоль в каталоге Open Editor Открыть редактор Open in Integrated Terminal EnvManager Environment Toolbar Environment ToolBar Панель среды Switching current environment Switch Current Environment Переключение текущей среды Edit current environment Edit Current Environment Изменить текущую среду Reload current environment Reload Current Environment Обновить текущую среду Select Environment Выбор среды ExportDialog Dialog Name: Название: Export Экспортировать ExportAndView Экспортировать и просмотреть FakeVim::Internal Use Vim-style Editing Редактирования в стиле Vim Read .vimrc Читать .vimrc Path to .vimrc Путь к .vimrc FakeVim::Internal::FakeVimHandler Unknown option: %1 Неизвестный параметр: %1 Argument must be positive: %1=%2 Аргумент должен быть положительным: %1=%2 Mark "%1" not set. Метка «%1» не задана. %1%2% %1%2% %1All %1Все Not implemented in FakeVim. Не реализовано в FakeVim. Unknown option: Неизвестный параметр: Invalid argument: Неверный аргумент: Trailing characters: Завершающие символы: Move lines into themselves. Перемещать строки в себя. %n lines moved. Перемещена %n строка. Перемещено %n строки. Перемещено %n строк. File "%1" exists (add ! to override) Файл «%1» существует (добавьте ! для перезаписи) Cannot open file "%1" for writing Невозможно открыть файл «%1» для записи "%1" %2 %3L, %4C written. "%1" %2 %3L, %4C записано. Cannot open file "%1" for reading Невозможно открыть файл «%1» для чтения "%1" %2L, %3C "%1" %2L, %3C %n lines filtered. Отфильтрована %n строка. Отфильтровано %n строки. Отфильтровано %n строк. Cannot open file %1 Невозможно открыть файл %1 Invalid regular expression: %1 Неверное регулярное выражение: %1 Pattern not found: %1 Шаблон не найден: %1 Search hit BOTTOM, continuing at TOP. Поиск достиг НИЗА и продолжен с ВЕРХА. Search hit TOP, continuing at BOTTOM. Поиск достиг ВЕРХА и продолжен с НИЗА. Search hit BOTTOM without match for: %1 Поиск достиг НИЗА, не найдено совпадений с: %1 Search hit TOP without match for: %1 Поиск достиг ВЕРХА, не найдено совпадений с: %1 %n lines indented. Сделаны отступы для %n строки. Сделаны отступы для %n строк. Сделаны отступы для %n строк. %n lines %1ed %2 time. %n строка %1 %2 раз(а). %n строки %1 %2 раз(а). %n строк %1 %2 раз(а). %n lines yanked. Скопирована %n строка. Скопировано %n строки. Скопировано %n строк. Already at oldest change. Уже на старейшем изменении. Already at newest change. Уже на новейшем изменении. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Рекурсивное связывание Type Alt-V, Alt-V to quit FakeVim mode. Type Alt-V, Alt-V to quit FakeVim mode. [New] [Новый] Not an editor command: %1 Не команда редактора: %1 FakeVimEdit Use FakeVim Editing Использовать редактирование FakeVim FakeVimEditOption Form FakeVim initialization command list (# start is comment): Список команд инициализации FakeVim (с # начинаются комментарии): Load default init command list Загрузить стандартные команды FiFoTty Cannot create temporary file: %1 Не удалось создать временный файл: %1 Cannot create FiFo %1: %2 Не удалось создать FIFO %1: %2 Cannot open FiFo %1: %2 Не удалось открыть FIFO %1: %2 FileBrowser Synchronize with editor Синхронизировать с редактором Show Hidden Files Показать скрытые файлы Set As Root Folder Set Folder To Root Установить как корневую папку Execute File Запустить файл Reload Folder Обновить папку Open Folder in New Window Открыть папку в новом окне Add to Folders Добавить в папки Open Parent Open to Parent Открыть родительский Filter Фильтр File System Файловая система Show Details Подробнее Debug File Отладить файл FileBrowserOption Form Форма Terminal Командная строка Command: Команда: Arguments: Аргументы: FileManager All Files (*) Все файлы (*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? Проект «%1» создан. Желаете его открыть? Open Project or File Открытие файла или проекта Show Hidden Files Показать скрытые файлы Folders Folers Папки All Support Files (%1) Все поддерживаемые (%1) Select a folder: Open Folder Выбор папки %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 Этот файл был удалён с диска, но у вас остались несохранённые изменения в редакторе LiteIDE. Закрыть редактор? Ответив «Да», вы потеряете несохранённые данные. %1 This file has been deleted from the drive. Do you want to close the editor? %1 Этот файл был удалён с диска. Закрыть редактор? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 Этот файл был изменён на диске, но у вас остались несохранённые изменения в редакторе LiteIDE. Перезагрузить файл с диска? Ответив «Да», вы потеряете несохранённые данные. %1 This file has been modified on the drive. Do you want to reload the file from disk? %1 Этот файл изменился на диске. Перезагрузить его? Open Files Открытие файлов Synchronize with editor Синхронизировать с редактором Filter Фильтр Open Project Открытие проекта LiteIDE X LiteIDE X Show Details Подробнее Split Mode Раздельный режим FileRecent Files Файлы FileSearch Match whole word Match word Слово целиком Match case Учёт регистра Regular expression Регулярное выражение Scan subdirectories Look in subdirs Искать рекурсивно Search for: Искать: Options: Параметры: Browse... Browser Открыть... Filter: Фильтр: Files on File System Файлы в файловой системе Search Найти Cancel Отмена Clear Очистить Open Directory Открытие каталога Current Folder Текущий каталог Auto Switch Автопереключение FileSearchManager Search Item: Искать элемент: Only golang file changes can be revert! This file change cannot be undone! Можно откатить только изменения файлов golang! New Search Новый поиск Search Result Результаты поиска The following files have no write permissions. Do you want to change the permissions? Следующие файлы недоступны для записи. Сменить права доступа? File is readonly Файл только для чтения LiteIDE X LiteIDE X Warning! Replace text is empty. Want to remove all the search items? Внимание, замещающий текст отсутствует. Удалить все найденные элементы? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? Внимание, замена на пробельный символ(ы). Заменить все найденные элементы на него? File Search Поиск файлов FileSystemWidget Open File Open Editor Открыть файл New File... New File Создать файл... New File Wizard... New File Wizard Мастер создания файла... Rename File Переименовать файл Delete File Remove File Удалить файл New Folder... New Folder Создать папку... Are you sure that you want to permanently delete this file? Удалить этот файл навсегда? Rename Folder Переименовать папку Delete Folder Remove Folder Удалить папку Rename File... Переименовать файл... Rename Folder... Переименовать папку... Open Terminal Here Запустить терминал в папке Open Explorer Here Открыть папку в проводнике View Godoc Here Открыть Godoc в папке Add Folder Добавить папку Close Folder Закрыть папку Add Folder... Добавить папку... Close All Folders Закрыть все папки Create File Создание файла A file with that name already exists! The file already exists! Файл с этим именем уже существует! Failed to create the file! Не удалось создать файл! New Name: Новое имя: Failed to rename the file! Не удалось переименовать файл! Are you sure that you want to permanently delete this folder and all of its contents? Удалить эту папку со всем содержимым? Failed to delete the file! Failed to remove the file! Не удалось удалить файл! Create Folder Создание папки A folder with that name already exists! The folder name is exists! Папка с этим именем уже существует! Failed to create the folder! Не удалось создать папку! Folder Name Имя папки Failed to rename the folder! Не удалось переименовать папку! Failed to delete the folder! Failed to remove the folder! Не удалось удалить папку! Find::Internal::SearchResultWidget Search was canceled. Поиск был отменён. Cancel Отмена Repeat the search with same parameters Повтор поиска с теми же параметрами Search again Повторить поиск Set show replace mode ui Включить режим замены Show Replace Режим замены Replace with: Заменить на: Replace all occurrences Заменить все совпадения Replace Заменить Preserve case Сохранять регистр Revert with: Откатить на: Revert Откатить Revert all occurrences Откатить все совпадения %n matches replaced. %n совпадение заменено. %n совпадения заменено. %n совпадений заменено. searching... %n matches found. поиск... %n совпадение. поиск... %n совпадения. поиск... %n совпадений. searching ... поиск... No matches found. Совпадений не найдено. %n matches found. %n совпадение. %n совпадения. %n совпадений. Expand all items Collapse all items FindApiEdit Search Найти Stop Search Остановить поиск FindApiWidget Search Найти Find Найти FindDocWidget Search Искать Find Найти Find All Найти всё Find const Найти const Find func Найти func Find interface Найти interface Find pkg Найти pkg Find struct Найти struct Find type Найти type Find var Найти var Use Regexp Регулярное выражение Match Case Учёт регистра Match Word Слово целиком Help Справка FindEditor Match case Учёт регистра Regular expression Регулярное выражение Wrap around Продолжить сначала Find Next Найти следующее Find Previous Find Prev Найти предыдущее Replace With: Заменить на: Replace Заменить Replace All Заменить всё Match whole word only Слово целиком Ready Готово Close Закрыть Find What: Искать: Options: Find Option: Параметры: Not found Не найдено Show Replace Режим замены FolderListView Delete File Удаление файла Are you sure that you want to permanently delete this file? Удалить этот файл навсегда? Failed to delete the file! Не удалось удалить файл! Delete Folder Удаление папки Are you sure that you want to permanently delete this folder and all of its contents? Удалить эту папку со всем содержимым? Failed to delete the folder! Не удалось удалить папку! FolderRecent Folders Каталоги FolderView Delete File Удаление файла Are you sure that you want to permanently delete this file? Удалить этот файл навсегда? Failed to delete the file! Не удалось удалить файл! Delete Folder Удаление папки Are you sure that you want to permanently delete this folder and all of its contents? Удалить эту папку со всем содержимым? Failed to delete the folder! Не удалось удалить папку! GdbDebuggerOption Form Enable --tty for program being debugged. Включить --tty для отлаживаемой программы. GoAddTagsDialog Add Tags To Struct Field Добавлять теги в поля структуры Add JSON Tag Добавлять тег JSON Options Параметры Add XML Tag Добавлять тег XML Add Custom Tags Добавлять другие теги Tag Name Имя тега Setup custom tag name Название особого тега Sort sorts the tags in increasing order according to the key name Сортировать теги в порядке возрастания имени ключа Override current tags when adding tags Перезаписывать текущие теги при добавлении Info Информация Multiple options separated by commas Несколько параметров, разделённых запятыми GoRemoveTagsDialog Remove Tags From Struct Field Удаление тегов из поля структуры Remove Tags And Options Удалить теги и параметры Clear All Tags Очистить все теги Remove JSON Tag Удалить тег JSON Remove XML Tag Удалить тег XML Remove Custom Tag Удалить другой тег Remove JSON Options Удалить параметры JSON Remove XML Options Удалить параметры XML Remove Custom Tag Options Удалить другие параметры tag=option тег=параметр Info Информация Setup remove custom tag and option, example tag=opt1,tag=opt2 Настройка удаления других тегов и параметров, например: тег=парам1,тег=парам2 Multiple tags separated by commas Несколько тегов через запятую Multiple options separated by commas Несколько параметров через запятую Clear All Tags Options Удалить параметры всех тегов GolangAst No outline available Схема недоступна Synchronize with editor Синхронизировать с редактором Go Class View Обзор классов Go Go Outline Схема Go GolangAstOption Form QuickOpenSymbol QuickOpenSymbol Show import path Показывать путь импорта Match case sensitive Регистрозависимый поиск GolangCodeOption Form Gocode Go API Gocode Auto update depends package when it's source changed. Auto update depends package when its source is changed. Обновлять зависимости при изменении их исходников. Close gocode when exiting Закрывать gocode при выходе PKG automitic import prompt PKG: автоматический запрос импорта PKG automatic import hints for all packages (GOPATH) PKG: подсказки автоматического импорта для всех пакетов (GOPATH) PKG automatic import hints for standard package PKG: подсказки автоматического импорта для стандартных пакетов GolangDoc Godoc Search Поиск в Godoc Find Package: Найти пакет: Go Doc Search Поиск по Go Doc Go Api Index Индекс Go Api GolangDocOption Form Go API Go API Use default context (fast) Использовать умолчальный контекст (быстро) Only load standard API documentation Only load standard api Загружать только документацию по стандартному API GolangEdit View import package use godoc Обзор импортируемого пакета с помощью godoc View Expression Information Информация о выражении Jump to Declaration Перейти к объявлению Find Usages Найти использование Rename Symbol Under Cursor Переименовать символ под курсором Callees Вызываемые Callers Вызывающие Callstack Стек вызовов Definition Определение Describe Описание Freevars Свободные переменные Implements Реализации Peers Участники Referrers Ссылающиеся Pointsto Указывающие Whicherrs Определения ошибок Refactor Рефакторинг Go Source Query Go SourceQuery SourceQuery What SourceQuery: Что это SourceQuery SourceQuery Stop Остановить Implements(GOPATH) Реализации (GOPATH) Add Tags To Struct Field Добавить теги в поля структуры Remove Tags From Struct Field Удалить теги из полей структуры Below files in package %1 Ниже приведены файлы пакета %1 %1 (Module/GOPATH) with GOROOT GolangEditOption Form Mouse Мышь Enable view expression infomation on mouse Показывать информацию о выражении под курсором Enable mouse navigation Навигация мышью Go root source file editor setup read only Открывать файлы из Go root в режиме только для чтения GolangFileSearch Golang Find Usages Использование поиска Golang GolangFmtOption Form Format Options Golang Format Параметры форматирования Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Goimports обновляет импорты Go, добавляя пропущенные и удаляя ненужные. Enable update imports line, adding missing ones and removing unreferenced ones. Обновлять строки импорта, добавляя необходимые и удаляя ненужные Synchronous Синхронное форматирование Synchronous code formatting Synchronous code formatting Синхронное форматирование кода Synchronous code formatting timeout in milliseconds (500ms or more): Таймаут синхронного форматирования кода (500 мс или более): Automatically format code when saving When the editor is saved automatically gofmt Автоматически форматировать код при сохранении GolangFmtPlugin Format Code Format Code (goimports) Отформатировать код Format Code (Adjusts Imports) Отформатировать код с настройкой импортов GolangPackageOption Choose directory to add to GOPATH: Выбор каталога для добавления в GOPATH Manage GOPATH / Modules Управление GOPATH/Modules Go Modules Модули Go Custom GONOPROXY Custom GOPROXY Custom GO111MODULE Особый GO111MODULE Custom GONOSUMDB Custom GOPRIVATE TextLabel GOPATH GOPATH Use System GOPATH Использовать системый GOPATH Reload Обновить Use Custom GOPATH (one per line) Особый GOPATH (по-одному в строку) Add Directory... Добавить... Clear Очистить GolangPresentEdit Section (s1) Секция (s1) Subsection (s2) Подсекция (s2) Sub-subsection (s3) Под-подсекция (s2) Bold Полужирный Italic Курсив Inline Code Исходный код Switch Bullets Список Comment/Uncomment Selection Комментировать/раскомментировать Export HTML Экспорт HTML Verify Present Проверить презентацию Present verify success Проверка презентации прошла успешно Present verify false Проверка презентации прошла неудачно Export PDF Экспортировать в PDF GolangSymbol Quick Open Symbol by Name Быстрое открытие символа по имени GoplayBrowser Go Playground Песочница Go Run Выполнить Stop Остановить New Создать... Load... Загрузить... Save... Сохранить... Explore Folder Открыть папку в проводнике Running... Running... Выполнение... Error: %1. Error: %1. Ошибка: %1. Success: %2. Success: %2. Успешно: %2. Load File Загрузка файла Select a file to load: Выберите файл: Save File Сохранение файла New File Name: Имя файла: HtmlPreview Page Style Стиль страницы Reload Обновить Export Html Экспорт в HTML Export PDF Экспортировать в PDF Print Preview Предпросмотр печати Synchronize preview and code scrollbars Синхронизировать положение кода и предпросмотра Config Конфигурация Plain HTML Чистый HTML Export Failed Ошибка экспорта Automatically display preview Automatically Display Preview Автоматически показывать предпросмотр HTML Preview Html Preview Просмотр HTML Could not open %1 for writing! Can not write file %1 Невозможно открыть %1 для записи! ImageEditor ZoomIn ZoomOut Reset to original size Fit to view Play movie Prev frame Next frame Pause movie ImageEditorFactory Image Viewer ImportPkgTip warning, pkg not find, please enter to import : предупреждение: пакет не найден, нажмите enter для импорта: JsonEdit Verify Проверить Format Json Отформатировать JSON Compact Json Сжать JSON LiteApp Event Log Журнал событий Escape Выйти Close File Закрыть файл Close All Files Закрыть все файлы Save File Сохранить файл Save File As... Сохранить файл как... Save All Files Сохранить все файлы Open Project Открыть проект... Options Параметры New... Создать... Open File... Открыть файл... Open Folder... Открыть папку... Open Folder in New Window... Открыть папку в новом окне... Close All Folders Add Folder... Закрыть все папки New Window Новое окно Close Window Закрыть окно Save Project Сохранить проект Close Project Закрыть проект Exit Выход Full Screen Полный экран About LiteIDE О программе LiteIDE About Plugins О расширениях LiteAppOption Form Форма Store [*] Store Хранилище [*] Language: Язык: Recent Files Recent File Недавние файлы Max Count: Max Recent: Не более: Monitoring files for modifications Внешнее изменение файлов Store settings to local ini file Хранить настройки в локальном файле .ini Interface [*] Интерфейс [*] Style: Стиль: Theme [*] Тема [*] Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. Автоматически перезагружать или закрывать окно редактирования, если файл был изменён или удалён Session Сессия Display Вид Display [*] Вид [*] Show splash screen on startup Показывать заставку при старте Show welcome page on startup Открывать страницу «Добро пожаловать» при запуске Editor tab [*] Вкладка редактора [*] Show close buttons on each editor tab Показывать кнопку закрытия на каждой вкладке редактора Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab Разрешить переход по вкладкам колесом мыши Toolbar Icon Size [*] Размер значка панели инструментов [*] Keyboard Клавиатура Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Формат: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands Скрыть стандартные команды Reset Сбросить Reset All Сбросить всё Import... Импорт... Export... Экспорт... Generic Общее Theme: Тема: Reload session on startup Auto load last session Загружать последнюю сессию при старте SideBarStyle SideBarStyle SplitterStyle SplitterStyle Command Команда Label Название Shortcuts Комбинация клавиш Standard Стандартная Import Keyboard Mapping Scheme Импорт схемы комбинаций клавиш Keyboard Mapping Scheme (%1) Файл схемы комбинаций клавиш (%1) Could not read scheme from %1! Не удалось прочитать схему комбинаций клавиш из %1! Export Keyboard Mapping Scheme Экспорт схемы комбинаций клавиш Could not write scheme to %1! Не удалось записать схему комбинаций клавиш в %1! NativeText Обычный текст Automatically save documents Автоматически сохранять документы Automatically save documents when application is idle Автоматически сохранять документы при простое sec с Reload files in session Перезагружать файлы сессии Fallback build-in icon library and liteapp/qrc/default В резерве встроенные значки и liteapp/qrc/default Icon [*] Значок [*] Load the external file icon library Загрузить внешний файл значков Use tool window shortcuts Клавиатурные сокращения для иструментальных окон 0-99 0-99 Editor Tabs Вкладок редактора 10-999 10-999 Editor Редактор Editor navigate Навигация Enable mouse extra 'Back' button and 'Forward' button for go back and forward Использовать дополнительные кнопки мыши «Назад» и «Вперёд» для перехода LiteBuild Build Toolbar Панель сборки Build Configuration... Build Config Конфигурация сборки... Stop Action Прервать Clear Output Clear All Очистить вывод Execute File Запустить файл Lock Build Path Зафиксировать путь сборки Line Wrap Переносить строки Auto Clear Автоочистка Setup Настроить Build Output Build Вывод сборки Current environment change id "%1" ID изменения текущей среды: «%1» Lock Build Lock Build: %1 Зафиксировать сборку Error: %1. Error: %1. Ошибка: %1. Command exited with code %1. Команда завершилась с кодом %1. Success: %1. Success: %1. Успех: %1. A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. Процесс уже выполняется. Необходимо сначала остановить текущую операцию. Killing current process... Killing current process... Остановка текущего процесса... Failed to terminate the existing process! Failed to terminate the existing process! Не удалось завершить существующий процесс! Started process successfully Started process successfully Процесс запущен успешно Failed to start process Не удалось запустить процесс Automatic positioning cursor Автоматическое позиционирование курсора Build Path Configuration Конфигурация пути сборки Debug File Отладить файл Use godoc View Открыть Godoc LiteBuildOption Form Recheck Go installation when changing environments Recheck go env if enviroment changed Проверить установку Go после смены среды Build command configuration files [*] Build command configuration files: Конфигурационные файлы команды сборки [*] LiteBuildPlugin Close Закрыть Execute: Exec: Выполнить: Execute File Execute Запустить файл LiteDebug Stop Остановить Clear Очистить Continue Продолжить Show Current Line Показать текущую строку Debug Output Debug Отладка Start Debugging External Application... Start Debugging External Application Отладка внешнего приложения... Close Закрыть Start Debugging Запустить отладку Step Into Войти Step Over Обойти Step Out Выйти Run to Line Выполнить до позиции курсора Insert/Remove Breakpoint Вставить/удалить точку останова Remove All Breakpoints Удалить все точки останова LiteDebugOption Form Debug Отладка Automatically insert breakpoint main.main when debugging Автоматически останавливаться при отладке на main.main LiteDebugPlugin Debug Window Debug Окно отладки LiteDoc LiteIDE Documentation LiteIDE Document Browser Документация LiteIDE LiteEditor Undo Отменить Redo Повторить Cut Вырезать Copy Копировать Paste Вставить Select All Выбрать всё Toggle Comment Закомментировать/раскомментировать Toggle Block Commnet Установить/снять блочный комментарий Auto-indent Selection Расставить отступы в выделенном Tab To Spaces (MimeType) Табуляция в пробелы (MimeType) Line End Windows (\r\n) Конец строк в стиле Windows (\r\n) Line End Unix (\n) Конец строк в стиле Unix (\n) Visualize Whitespace (Global) Отображать пробелы (глобально) Move Line Up Сдвинуть строку вверх Move Line Down Сдвинуть строку вниз Copy Line Up Скопировать строку наверх Copy Line Down Скопировать строку вниз Join Lines Объединить строки Advanced Дополнительно Code Folding Сворачивание кода Export HTML Экспорт в HTML Export Failed Ошибка экспорта Could not open %1 for writing. Не удалось открыть %1 для записи. Export PDF Экспорт в PDF Print Document Печать документа Print Preview... Print Preview Document Предпросмотр печати... Export HTML... Экспорт в HTML... Export PDF... Экспорт в PDF... Print... Печать... Select Block Выбрать блок Fold Свернуть Unfold Развернуть Fold All Свернуть всё Unfold All Развернуть всё Go To Line Goto Line Перейти к строке Duplicate Дублировать Delete Line Удалить строку Copy Line Копировать строку Cut Line Вырезать строку Insert Line Before Вставить строку перед Insert Line After Вставить строку после Increase Font Size Увеличить шрифт Decrease Font Size Уменьшить шрифт Reset Font Size Стандартный размер шрифта Clean Whitespace Очистить пробелы Code Complete Дополнить код Reload File Перезагрузить файл Do you want to permanently discard unsaved modifications and reload %1? Перезагрузить %1 с утратой несохранённых изменений? ReadOnly Только для чтения Line: Строка: Go to Previous Block К предыдущему блоку Go to Next Block К следующему блоку Go to Matching Brace К соответствующей скобке Go to Line Start К началу строки Go to Line End К концу строки Go to Previous Line К предыдущей строке Go to Next Line К следующей строке Go to Previous Character К предыдущему символу Go to Next Charater К следующему символу Go to Previous Word К предыдущему слову Go to Next Word К следующему слову Go to Line Перейти к строке Goto Перейти Go to Doc Start К началу документации Go to Doc End К концу документации Title Case Регистр заголовка Upper Case Верхний регистр Lower Case Нижний регистр Swap Case Инвертировать регистр Convert Case Изменение регистра File is readonly Файл только для чтения File is writable В файл можно писать Settings Настройки Tab To Spaces Табуляции в пробелы Spaces To Tab Пробелы в табуляции Convert Tab Изменение табуляций Line Wrap (MimeType) Перенос строк (MimeType) LiteEditorFileFactory Text Editor LiteEditorOption Form Форма Load File Загрузка файла Check and convert no printable char to '.' Проверять и конвертировать неотображаемые символы в «.» Font Шрифт Font && Colors Шрифт и цвет Family: Семейство: Size: Размер: Zoom: Масштаб: % % Antialias Сглаживание Editor Color Scheme ColorStyle Scheme Цветовая схема File: Файл: Edit Изменить Syntax Auto-completion Auto complete brackets Автоматическое добавление закрывающих элементов Clean whitespace when saving files Удалять избыточные пробелы при сохранении файлов Enable scroll wheel zooming Масштабирование колесом мыши Display VisualizeWhitespace Отображать пробельные символы Word wrap by default Переносить слова Display code fold Отображать сворачивание кода Display offset position Отображать смещение File Types Типы файлов Behavior Поведение Display EOF Отображать символ конца файла (EOF) Display line numbers Отображать номера строк Display right margin at column Отображать границу по столбцу Automatic indentation Enable automatic indentation Автоматически делать отступы Case sensitive code completion Completer case sensitive Регистрозависимое дополнение кода Code completion prefix length: Word Complete Prefix Length Длина слова для дополнения кода: Display Вид MIME Type Тип MIME Tab Width Ширина табуляции Tab To Spaces Табуляции в пробелы File Extensions Расширения файлов Fuzzy code completion Нечёткое дополнение кода Clean completion cache when saving files Очищать кэш дополнений после сохранения файлов Custom Extensions Особые расширения Show Monospace Font Показать моноширинный шрифт Restore Default Font Восстановить шрифт Add copied text into the clipboard as HTML Добавлять скопированные текст в буфер обмена в виде HTML Display indent guide Показывать направляющую отступа Allow vertical scrolling to the last line [*] Разрешить вертикальную прокрутку до последней строки [*] LiteEditorPlugin Edit ToolBar Панель инструментов редактора Edit Navigation Bar Панель навигации редактора LiteEnvOption Form Environment definition files: Файлы определения среды: Environment changes will take effect after switching environments. Изменения среды вступят в силу после её переключения. LiteFindPlugin Find Найти Find Next Найти следующее Find Previous Найти предыдущее Replace Заменить File Search Поиск файлов LiteTabWidget Open a new tab Открыть в новой вкладке List All Tabs Показать все вкладки Close Tab Закрыть вкладку MarkdownBatchBrowser Markdown Exporter Markdown Batch Экспорт в Markdown All Files (*) Все файлы (*) Select the folder containing your markdown files: Select Markdown Folder Выбор папки, содержащей файлы Markdown Select Markdown Files Выбор файлов Markdown Select the folder to contain separated markdown exports: Выбор папки для раздельных файлов Markdown Export Merged HTML Export Html Экспорт объединённого в HTML Export Merged PDF Export PDF Экспорт объединённого в PDF MarkdownBatchWidget Form Markdown Source Files Markdown Files Исходники Markdown Import Folder... Import Folder Импортировать папку... Add Files... Add Files Добавить файлы... Move Up Переместить вверх Move Down Переместить вниз Remove Удалить Remove All Удалить все Options Параметры Export Folder: Папка экспорта: Browse... Browser Открыть... Use CSS Использовать CSS Insert horizontal line between merged files Merge files insert split <hr> Вставлять горизонтальную строку между объединяемыми файлами Insert page break between merged files Merge files insert page break Вставлять разрыв страницы между объединяемыми файлами Export Export Util Экспорт Export Separated HTML Separate Html Отдельные HTML Export Separated PDF Separate PDF Отдельные PDF Export Merged HTML... Merge Html Объединённые HTML... Export Merged PDF... Merge PDF Объединённые PDF... Print Preview Merged... Merge Print Preview Предпросмотр печати объединённого... Print Merged Merge Print Печать объединённого Log Журнал MarkdownEdit Header (h1) Header <h1> Заголовок (h1) Header (h2) Header <h2> Заголовок (h2) Header (h3) Header <h3> Заголовок (h3) Header (h4) Header <h4> Заголовок (h4) Header (h5) Header <h5> Заголовок (h5) Header (h6) Header <h6> Заголовок (h6) Bold Полужирный Italic Курсив Inline Code Исходный код Link Ссылка Image Изображение Unordered List Неупорядоченный список Ordered List Упорядоченный список Blockquote Цитата Horizontal Rule Горизонтальная строка Heading Шапка MultiFolderView Delete Folder Удалить каталог Are you sure that you want to permanently delete this folder and all of its contents? Удалить безвозвратно этот каталог со всем содержимым? Failed to delete the folder! Не удалось удалить каталог! Delete File Удаление файла Are you sure that you want to permanently delete this file? Удалить безвозвратно этот файл? Failed to delete the file! Не удалось удалить файл! NavigateBar Browser Files in %1 Обзор файлов в %1 NewFileDialog New Project or File Новый проект или файл Browse... ... GOPATH: GOPATH: Template: Template Шаблон: Type Тип Information Информация Name: Название: Location: Расположение: Error Ошибка Could not create the target directory: %1 Не удалось создать каталог назначения: %1 Warning Предупреждение Location %1 is not empty. Use the target directory anyway? Каталог %1 не пуст. Использовать этот каталог назначения? Overwrite File Перезапись файла %1 already exists. Do you want to replace it? %1 уже существует. Перезаписать его? No files could be created. Не удалось создать файлы. File template details: Детали шаблона файла: Project template details: New project wizard: Детали шаблона проекта: Choose a directory for the new content: Выбор каталога для новых данных OpenEditorsWidget Open Documents Открытые документы OptionsBrowser Options Options Page Параметры OptionsWidget Options Параметры Info Информация [*] item request restart of LiteIDE [*] элемент требует перезапуска LiteIDE OutputDockWidget Move To Переместить в LeftSideBar Левая боковая панель RightSideBar Правая боковая панель BottomDockWidget OutputOption Form Font Шрифт Family: Семейство: Size: Размер: Zoom: Масштаб: % % Antialias Сглаживание Display Вид Use editor color scheme Цветовая схема редактора Sets the maximum number of lines Максимальное число строк PackageBrowser Reload All Обновить всё Use godoc View Открыть Godoc Load Package in New Window Загрузить пакет в новом окне Add Package to Folders Добавить пакет в папки Open Source File Открыть исходник Copy Name to Clipboard Copy Name To Clipboard Скопировать имя в буфер обмена Loading Go package list... Loading go package ... Загрузка списка пакетов Go... Go Package Browser Обозреватель пакетов Go Manage GOPATH/Modules ... Управление GOPATH/Modules ... PackageProject Reload Package Перезагрузить пакет Open Explorer Here Открыть папку в проводнике Add Source File Добавить исходник Error Ошибка File %1 already exists. Файл %1 уже существует. Could not open %1 for writing. Не удалось открыть %1 для записи. File Name: Имя файла: PluginsDialog Installed Plugins Install Plugins Установленные расширения Close Закрыть Name Название Author Anchor Автор Enabled Включён Details Подробнее Version Last Ver Версия File Name FileName Имя файла ProcessEx process exited with code %1 процесс завершился с кодом %1 process crashed or was terminated процесс завершился аварийно или был завершён извне process exited with an unknown status процесс завершился с неизвестным статусом process failed to start не удалось запустить процесс process crashed or was terminated while running процесс завершился аварийно или был завершён извне timed out waiting for process истекло время ожидания процесса couldn't read from the process не удалось прочитать из процесса couldn't write to the process не удалось записать в процесс an unknown error occurred возникла неизвестная ошибка ProjectManager Project <%1> Проект <%1> Import Directory <%1> Импорт каталога <%1> QFileSystemModel %1 TB %1 ТБ %1 GB %1 ГБ %1 MB %1 МБ %1 KB %1 КБ %1 bytes %1 байт QJson::ParserRunnable An error occurred while parsing json: %1 Возникла ошибка при разборе json: %1 QJsonParseError no error occurred ошибок нет unterminated object незавершённый объект missing name separator отсутствует разделитель имён unterminated array незавершённый массив missing value separator отсутствует разделитель значений illegal value неверное значение invalid termination by number неверное завершение числом illegal number неверное число invalid escape sequence неверная ESC-последовательность invalid UTF8 string неверная строка UTF8 unterminated string незавершённая строка object is missing after a comma после запятой отсутствует объект too deeply nested document слишком много вложений too large document слишком большой документ garbage at the end of the document мусор в конце документа QuickOpenAction Show and Run Commands Показ и выполнение команд QuickOpenEditor Show All Opened Editors Отобразить все открытые редакторы QuickOpenFileSystem File System Файловая система QuickOpenFiles Go to File Перейти к файлу Type '?' to get help on the actions you can take from here Введите «?» для получения справки по возможным действиям QuickOpenFolder Browser Folder Открыть каталог QuickOpenHelp Show All Quick Open Actions Показать все действия Quick Open QuickOpenLines Go to Line Перейти к строке Open a text file first to go to a line Перед переходом к строке необходимо открыть текстовый файл Type a line number between %1 and %2 to navigate to Введите номер желаемой строки от %1 до %2 Go to Line %1 Переход к строке %1 QuickOpenManager Quick Open Editor Quick Open редактор Quick Open Symbol Quick Open символ Quick Open Command Quick Open команда Quick Open File Quick Open файл Show All Quick Open Actions Показать все действия Quick Open QuickOpenMimeType not found symbol символ не найден Go to Symbol in File Перейти к символу в файле QuickOpenOption Form QuickOpenFiles Quick Open файлы Match case sensitive Регистрозависимый поиск Max files count: Файлов не более: QuickOpenEditor Quick Open редактор RecentManager Clear All History Очистить всю историю Clear Menu Очистить меню SearchEdit Search Найти Stop Search Остановить поиск SelectExternalDialog Debug External Application Отладка внешнего приложения Application: Приложение: Browse... Browser ... Arguments: Аргументы: Working directory: Рабочий каталог: Select Executable Выбор программы Select the working directory: Select Working Directory Выбор рабочего каталога SessionRecent Sessions Сессии SideDockWidget SideBar Боковая панель Show SideBar Показать боковую панель Move To Переместить в RightSideBar Правая боковая панель LeftSideBar Левая боковая панель OutputBar Панель вывода LeftDockWidgt RightDockWidget SideWindowStyle Hide SideBar Скрыть боковую панель SideBar Windows Окна боковой панели Output Windows Окна вывода SplitDockWidget Move To Переместить в Top Наверх Top (Split) Наверх (разделить) Bottom Вниз Bottom (Split) Вниз (разделить) Left Влево Left (Split) Влево (разделить) Right Вправо Right (Split) Вправо (разделить) Unsplit Объединить Split Разделить TopDockWidget (Split) TopDockWidget BottomDockWidget (Split) BottomDockWidget LeftDockWidget (Split) LeftDockWidget RightDockWidget (Split) RightDockWidget SplitWindowStyle Hide Sidebars Скрыть боковые панели Tool Windows Панели инструментов Terminal Open a new terminal Close current terminal Current terminal load environment from LiteIDE Filter Фильтр Dark Mode Login Mode (shell --login) Terminal Командная строка Rename Tab Title New Close Закрыть LoadEnv CloseAll Close all terminal TerminalEdit Cut Вырезать Copy Копировать Paste Вставить Select All Выбрать всё Clear All Очистить всё TextEditor::Internal::ColorScheme Not a color scheme file. Файл не является цветовой схемой. Utils::FilterLineEdit Filter Фильтр Clear text Очистиьт текст VTermWidget Copy Копировать Paste Вставить Select All Выбрать всё WebKitBrowser Navigation Навигация Open Html File Open Html Открыть файл HTML WebKitBrowser WebKitBrowser False load %1 ! какое-то служебное сообщение Ложная загрузка %1! Open Html or Markdown File Open Html or Markdown Files Открыть файл HTML или Markdown WebKitHtmlWidgetPlugin Open Html or Markdown File Open Html or Markdown Files Открыть файл HTML или Markdown WelcomeBrowser New Создать Open Открыть Open Folder Открыть папку Options Параметры Welcome Welcome Page Добро пожаловать WelcomePlugin Welcome Home В начало ================================================ FILE: liteidex/liteide_tr.ts ================================================ AboutDialog About LiteIDE About Liteide LiteIDE Hakkında Information Infomation Bilgi Welcome: Hoşgeldiniz: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. LiteIDE X'e hoşgeldiniz! LiteIDE sade, açık kaynaklı ve platform bağımsız bir geliştirme ortamıdır. Project: Proje: Name: Adı: Author: Geliştirici: Version: Versiyon: Build: Derleme: Based on Qt Based on Qt Version Temel Qt sürümü Source Code: Kaynak Kod: Support LiteIDE: Support LiteIDE'yi destekle:: Developers Geliştiriciler Translations Çeviriler Chinese Çince Japanese Japonca Russian Rusça French Fransızca Traditional Chinese Geleneksel Çince German Almanca Ukrainian Ukraynaca Thanks to... Teşekkürler... License Lisans Close Kapat Based on Qt %1 (%2 bit) Qt sürüm %1 (%2 bit) tabanlıdır ActionManager &File &Dosya &Recent &Son kullanılanlar &Edit Düzen&le F&ind &Find &Ara &View &Göster &Tools A&raçlar &Build &Derle &Debug &Hata Ayıklama &Help &Yardım Standard Toolbar Standard ToolBar Standart Araç Çubuğu AstWidget Go To Definition Tanımlamaya Git View Import Document İçeri Aktarma Görünümü BaseDockWidget Hide Gizle Hide Tool Window Araç Penceresini Gizle Floating Window Sabit Olmayan Pencere BaseFolderView Open In New Window Yeni Pencerede Aç Open File Dosya Aç New File... Yeni Dosya... New File Wizard... Yeni Dosya Sihirbazı... Rename File... Dosya Adı Değiştir... Delete File Dosya Sil New Folder... Yeni Klasör... Rename Folder... Klasör Adı Değiştir... Delete Folder Klasör Sil Open Terminal Here Burada Terminal Aç Show in Explorer Open Explorer Here Explorer ile Aç Open Application Uygulamayı Aç Show in Finder Finder ile Aç Show Containing Folder İçeren Klasörü Göster Open Command Prompt Here Burada Komut Satırını Aç Open Folder... Add Folder... Klasör Aç... Reload Folder Klasörü Tekrar Yükle Close Folder Klasörü Kapat Close All Folders Bütük Klasörleri Kapat Copy Kopyala Paste Yapıştır Move To Trash Çöp Kutusuna Taşı Create File Dosya Oluştur A file with that name already exists! Bu İsimde Dosya Mevcut! Failed to create the file! Dosya Oluşturulamadı! Rename File Dosya Adını Değiştir New Name: Yrni İsim: Failed to rename the file! İsim Değiştirilemedi! An item "%1" already exists in this location. Do you want to replace it and move old item to trash? "%1" burada zaten var. Eski dosyanın üzerine yazmak istermisiniz? Stop Dur Keep Both İkisini de Koru Keep Both All Her İkisini de Koru Replace Üzerine Yaz Replace All Hepsinin Üzerine Yaz Are you sure that you want move to trash this item? Bu öğeyi çöp kutusuna taşımak istediğinizden emin misiniz? Are you sure that you want move to trash %1 items? %1 öğeyi çöp kutusuna taşımak istediğinizden emin misiniz? Move to Trash Çöp Kutusuna Taşı Open With Birlikte Aç System Editor Sistem Editörü Create Folder Klasör Oluştur A folder with that name already exists! Bu isimde bir klasör zaten var! Failed to create the folder! Klasör Oluşturulamadı! Rename Folder Klasör Adını Değiştir Folder Name Klasö Adı Failed to rename the folder! Klasör Adı Değiştirilemedi! Are you sure that you want to permanently delete this folder and all of its contents? Bu klasörü ve tüm içeriğini kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the folder! Klasör Silinemedi! BookmarkManager Toggle Bookmark Yer İşaretini Değiştir Goto bookmark Yer İşaretine Git Remove bookmark Yer İşaretini Sil Remove all bookmarks for this file Bu dosya için tüm yer işaretlerini kaldırın Remove all bookmarks for all files Bütün dosyalar için tüm yer işaretlerini kaldırın Bookmarks Yer imleri BookmarkRecent Bookmarks Yer imleri BuildConfigDialog Build Configuration Build Config Dialog Derleme Ayarları Build ID Derleme ID Build Path Build File Derleme Yolu GOPATH GOPATH GOPATH information GOPATH bilgisi Use Custom GOPATH for Build Path Derleme Yolu için Özel GOPATH Kullanın Inherit System GOPATH Sistem'de Tanımlı GOPATH Inherit LiteIDE GOPATH LiteIDE'de Tanımlı GOPAT Custom GOPATH (one per line) Özel GOPATH (satır başına bir) Add Directory... Klasör Ekle... Clear Temizle LiteIDE LiteIDE Config Ayarlar Action Eylem Custom Build Custom Özel Derleme Reset all to initial value Tümünü başlangıç değerine sıfırla Name İsim Value Değer SharedValue Paylaşımlı Değer Id ID Cmd Cmd Choose directory to add to GOPATH: GOPATH'a eklenecek dizini seçin: CreateDirDialog Create Folder Klasör Oluştur Directory: Klasör: Dir Name: Klasör Adı: Create Oluştur Cancel İptal CreateFileDialog Create File Create File Dialog Dosya Oluştur Directory: Klasör: File Name: Dosya Adı: Create Oluştur Create and Edit Oluştur ve Düzenle Cancel İptal DebugWidget Add Watch İzleyici Ekle Async Record AsyncRecord Eşzamansız Kayıt Variables Değişkenler Watch İzle Call Stack CallStack Yığın Çağrıları Threads İş Parçacığı Goroutines Goroutines Registers Registers Libraries Library Kitaplık Console Konsol Watch expression (e.g. buf main.var os.Stdout): İfadeyi izle (ör. Buf main.var os.Stdout): Remove Watch İzleyiciyi Sil Remove All Watches Bütün İzleyicileri Sil DlvDebuggerOption Form Form DocumentBrowser Back Backward Geri Forward İleri Reload Yenile Increase Font Size Font Büyüklüğünü Arttır Decrease Font Size Font Büyüklüğünü Azalt Reset Font Size Font Büyüklüğünü Sıfırla DocumentBrowserFactory DocumentBrowser Belge Tarayıcı EditorManager Close Kapat Move to New Window Move To New Window Yeni Pencereye Taşı Navigate Forward GoForward İlerle Close Others Close Others Tabs Diğerlerini Kapat Open Editor Editör Aç Close All Close All Tabs Hepsini Kapat Close Left Tabs Soldaki Tabları Kapat Close Right Tabs Sağdaki Tabları Kapat Close Files in Same Folder Close Same Folder Files Aynı Klasördeki Dosyaları Kapat Close Files in Other Folders Close Other Folder Files Diğer Klasörlerdeki Dosyaları Kapat Copy Full Path to Clipboard Copy Path to Clipboard Tam Yolu Panoya Kopyala Show in Explorer Explorer'de Göster Show in Finder Finder'de Göster Show Containing Folder İçeren Klasörü Göster Open Command Prompt Here Komut İstemi'ni Burada Açın Open Terminal Here Terminal'i Burada Açın Navigate Backward Geri Git Save changes to %1? %1'deki değişiklikler kaydedilsin mi? Unsaved Modifications Save Modify Kaydedilmemiş Değişiklikler All Files (*) Tüm Dosyalar (*) Save As Farklı Kaydet EnvManager Environment Toolbar Environment ToolBar Ortam Araç Çubuğu Switching current environment Switch Current Environment Mevcut ortamı değiştirme Edit current environment Edit Current Environment Mevcut ortamı değiştir Reload current environment Reload Current Environment Mevcut ortamı yeniden yükle Select Environment Ortam Seç ExportDialog Dialog Diyalog Name: İsim: Export Dışa Aktar ExportAndView Dışa Aktar ve İncele FakeVim::Internal Use Vim-style Editing Vim Tarzı Editör Kullan Read .vimrc .vimrc Oku Path to .vimrc .vimrc Yolu FakeVim::Internal::FakeVimHandler Unknown option: %1 Bilinmeyen seçenek:%1 Argument must be positive: %1=%2 Argüman pozitif olmalıdır:%1=%2 Mark "%1" not set. "%1" işareti ayarlanmadı. %1%2% %1%2% %1All %1 Hespsi Not implemented in FakeVim. FakeVim'de uygulanmaz. Unknown option: Bilinmeyen seçenek: Invalid argument: Geçersiz argüman: Trailing characters: Sondaki karakterler: Move lines into themselves. Çizgileri kendi içlerine taşıyın. %n lines moved. %n satır geçildi. File "%1" exists (add ! to override) "%1" dosyası var (geçersiz kılmak için! ekleyin) Cannot open file "%1" for writing "%1" dosyası yazmak için açılamıyor "%1" %2 %3L, %4C written. "%1" %2 %3L, %4C yazıldı. Cannot open file "%1" for reading "%1" dosyası okumak için açılamıyor "%1" %2L, %3C "%1" %2L, %3C %n lines filtered. %n satır filtrelendi. Cannot open file %1 %1 dosyası açılamadı Invalid regular expression: %1 Geçersiz düzenli ifade: %1 Pattern not found: %1 Kalıp bulunamadı: %1 Search hit BOTTOM, continuing at TOP. Arama SON'a geldi, BAŞ'tan devam edecek. Search hit TOP, continuing at BOTTOM. Arama, SONDAN'da devam ederek BAŞA'a ulaştı. Search hit BOTTOM without match for: %1 Eşleşmeden SONA ulaşıldı:%1 Search hit TOP without match for: %1 Eşleşmeden BAŞA ulaşıldı:%1 %n lines indented. %n satır girintili. %n lines %1ed %2 time. %n satır %1er %2 kez. %n lines yanked. %n çizgi çekildi. Already at oldest change. Zaten en eski değişimde. Already at newest change. Zaten son değişiklikte. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Yinelemeli haritalama Type Alt-V, Alt-V to quit FakeVim mode. FakeVim modundan çıkmak için Alt-V, Alt-V yapın. [New] [Yeni] Not an editor command: %1 %1 düzenleyici komutu değil FakeVimEdit Use FakeVim Editing FakeVim Düzenlemeyi Kullanın FakeVimEditOption Form Form FakeVim initialization command list (# start is comment): FakeVim başlatma komut listesi (# başlangıç yorumdur): Load default init command list Varsayılan başlangıç komut listesini yükle FiFoTty Cannot create temporary file: %1 Geçici dosya oluşturulamıyor: %1 Cannot create FiFo %1: %2 FiFo oluşturulamıyor %1:%2 Cannot open FiFo %1: %2 FiFo açılamıyor %1:%2 FileBrowser Synchronize with editor Editörle senkronize et Show Hidden Files Gizli Dosyaları Göster Set As Root Folder Set Folder To Root Kök Klasör olarak ayarla Execute File Dosyayı Çalıştır Reload Folder Klasörü Tekrak Yükle Show Details Ayrıntıları Göster Debug File Hata Ayıklama Dosyası Open Folder in New Window Klasörü Yeni Pencerede Aç Add to Folders Klasörlere Ekle Open Parent Open to Parent Üst Öğeyi Aç Filter Filtrele File System Dosya Sistemi FileBrowserOption Form Form Terminal Terminal Command: Komut: Arguments: Argümanlar: FileManager All Files (*) Tüm Dosyalar (*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? '%1' projesi oluşturuldu. Şimdi açmak ister misin? Open Project or File Proje veya Dosya Aç Show Hidden Files Gizli Dosyaları Göster Folders Folers Klasörler All Support Files (%1) Tüm Desteklenen Dosyalar (%1) Select a folder: Open Folder Klasör Seç: %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 Bu dosya sürücüden silindi, ancak LiteIDE düzenleyicinizde kaydedilmemiş değişiklikleriniz var. Editörü kapatmak istiyor musunuz? "Evet" cevabı, kaydedilmemiş değişikliklerinizin silinmesine neden olur. %1 This file has been deleted from the drive. Do you want to close the editor? %1 Bu dosya sürücüden silinmiştir. Editörü kapatmak istiyor musunuz? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 Bu dosya sürücüde değiştirildi, ancak LiteIDE düzenleyicinizde kaydedilmemiş değişiklikleriniz var. Dosyayı diskten yeniden yüklemek istiyor musunuz? "Evet" cevabı, kaydedilmemiş değişikliklerinizin silinmesine neden olur. %1 This file has been modified on the drive. Do you want to reload the file from disk? %1 Sürücüdeki dosya değiştirilmiş. Diskteki dosyayı yeniden yüklemek istermisiniz? Open Files Dosyaları Aç Show Details Ayrıntıları Göster Synchronize with editor Editörle Senkronizasyon Split Mode Bölme Modu Filter Filtrele Open Project Proje Aç LiteIDE X LiteIDE X FileRecent Files Dosyalar FileSearch Match whole word Match word Tüm kelimeyi eşleştir Match case Büyük / küçük harf eşleştir Regular expression Düzenli ifade Scan subdirectories Look in subdirs Alt dizinleri tara Search for: Aranacak: Options: Ayarlar: Browse... Browser Araştır... Filter: Filtre: Files on File System Sistemdeki dosyalar Search Ara Cancel İptal Current Folder Geçerli Klasör Auto Switch Otomatik Geçiş Clear Temizle Open Directory Klasör Aç FileSearchManager Search Item: Arama Öğesi: Only golang file changes can be revert! This file change cannot be undone! Yalnızca golang dosyası değişiklikleri geri alınabilir! New Search Yeni Arama File Search Dosya Ara Search Result Arama Sonucu LiteIDE X LiteIDE X Warning! Replace text is empty. Want to remove all the search items? Uyarı! Değiştirme metni boş Tüm arama öğelerini silmek mı istiyorsunuz? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? Uyarı! Değiştirme metni boşluk karakteri Tüm arama öğelerini boşluk karkteri yapmak mı istiyorsunuz? The following files have no write permissions. Do you want to change the permissions? Aşağıdaki dosyaların yazma izni yoktur. İzinleri değiştirmek istiyor musunuz? File is readonly Dosya saltokunur FileSystemWidget Open File Open Editor Dosya Aç New File... New File Yeni Dosya... New File Wizard... New File Wizard Yeni Dosya Sihirbazı... Rename File Dosya Yeniden Adlandır Delete File Remove File Dosya Sil New Folder... New Folder Yeni Klasör... Are you sure that you want to permanently delete this file? Bu dosyayı kalıcı olarak silmek istediğinizden emin misiniz? Rename Folder Klasör Yeniden Adlandır Delete Folder Remove Folder Klasör Sil Rename File... Dosya Adı Değiştir... Rename Folder... Klasör Adı Değiştir... Open Terminal Here Terminali Burada Aç Open Explorer Here Exploreri Burada Aç View Godoc Here Godoc Görüntüle Add Folder Klasör Ekle Close Folder Klasörü Kapat Add Folder... Klasör Ekle... Close All Folders Bütün Klasörleri Kapat Create File Dosya Oluştur A file with that name already exists! The file already exists! Bu isimde bir dosya zaten var! Failed to create the file! Dosya oluşturulamadı! New Name: Yeni İsim: Failed to rename the file! Dosya yeniden adlandırılamadı! Are you sure that you want to permanently delete this folder and all of its contents? Bu klasörü ve tüm içeriğini kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the file! Failed to remove the file! Dosya Silinemedi! Create Folder Klasör Oluştır A folder with that name already exists! The folder name is exists! Bu isimde bir klasör zaten var! Failed to create the folder! Klasör oluşturulamadı! Folder Name Klasör Adı Failed to rename the folder! Klasör Adı Değiştirilemedi! Failed to delete the folder! Failed to remove the folder! Klasör silinemedi! Find::Internal::SearchResultWidget Search was canceled. Arama iptal edildi. Cancel İptal Repeat the search with same parameters Aramayı aynı parametrelerle yap Search again Tekrar ara Set show replace mode ui UI modunu ayarla Show Replace Değiştir'i Göster Replace with: Değiştir: Replace all occurrences Tümünü değiştir Replace Değiştir Preserve case Cümleyi koru Expand all items Tüm öğeleri genişlet Collapse all items Tüm öğeleri daralt Revert with: Şununla geri dön: Revert Geri al Revert all occurrences Tüm değişiklikleri geri al %n matches replaced. %n eşleşme değiştirildi. searching... %n matches found. aranıyor... %n eşleşme bulundu. searching ... aranıyor... No matches found. Eşleşme bulunamadı. %n matches found. %n eşleşme bulundu. FindApiEdit Search Ara Stop Search Aramayı Durdur FindApiWidget Search Ara Find Bul FindDocWidget Search Ara Find Bul Find All Hepsini Bul Find const Const Bul Find func Fonksiyon Bul Find interface Arayüz Bul Find pkg pkg Bul Find struct struct Bul Find type Tür Bul Find var var Bul Use Regexp Düzenli ifade kullan Match Case Büyük / küçük harf eşleştir Match Word Kelime Eşleştir Help Yardım FindEditor Match case Büyük / küçük harf eşleştir Regular expression Düzenli İfade Wrap around Sözcük Kaydırma Find Next Sonrakini Bul Find Previous Find Prev Öncekini Bul Replace With: Değiştir: Replace Değiştir Replace All Tümünü Değiştir Match whole word only Tüm Kelimeyi Eşleştir Ready Hazır Close Kapat Show Replace Değiştirmeyi Göster Find What: Aranan: Options: Find Option: Ayarlar: Not found Bulunamadı FolderListView Delete File Dosya Sil Are you sure that you want to permanently delete this file? Bu dosyayı kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the file! Dosya silinemedi! Delete Folder Klasör Sil Are you sure that you want to permanently delete this folder and all of its contents? Bu klasörü ve tüm içeriğini kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the folder! Klasör Silinemedi! FolderRecent Folders Klasörler FolderView Delete File Dosya Sil Are you sure that you want to permanently delete this file? Bu dosyayı kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the file! Dosya Silinemedi! Delete Folder Klasör Sil Are you sure that you want to permanently delete this folder and all of its contents? Bu klasörü ve tüm içeriğini kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the folder! Klasör Silinemedi! GdbDebuggerOption Form Form Enable --tty for program being debugged. Hata ayıklanan program için --tty'yi etkinleştirin. GoAddTagsDialog Add Tags To Struct Field Struct Alanına Etiket Ekle Add JSON Tag JSON etiketi ekle Options Ayarlar Multiple options separated by commas Multiple options are separated by commas Virgülle ayrılmış birden çok seçenek Add XML Tag XML etiketi ekle Add Custom Tags Özel etiket ekle Tag Name Etilet İsmi Setup custom tag name Özel etiket adı ayarla Sort sorts the tags in increasing order according to the key name Etiket anahtarları adına göre artan şekilde sıralar Override current tags when adding tags Etiket eklerken mevcut etiketleri geçersiz kıl Info Bilgi GoRemoveTagsDialog Remove Tags From Struct Field Struct Alanından Etiketleri Kaldır Remove Tags And Options Etiketleri ve Seçenekleri Kaldır Clear All Tags Tüm Etiketleri Temizle Clear All Tags Options Clear All Tag Options Tüm Etiket Seçeneklerini Temizle Remove JSON Tag JSON etiketlerini temizle Remove XML Tag XML etiketlerini temizle Remove Custom Tag Özel etiketleri teminzle Multiple tags separated by commas Multiple tags are separated by commas Birden çok etiket, virgülle ayır Remove JSON Options JSON ayarlarını kaldır Multiple options separated by commas Multiple options are separated by commas Çoklu seçenekler virgülle ayrılır Remove XML Options XML ayarlarını kaldır Remove Custom Tag Options Özel etiket ayarlarını temizle Setup remove custom tag and option, example tag=opt1,tag=opt2 Setup remove custom tag option, example tag=opt1,tag=opt2 Özel etiketi ve seçeneği kaldır, örnek etiket = opt1, etiket = opt2 tag=option etiket=ayar Info Bilgi GolangAst No outline available Taslak mevcut değil Synchronize with editor Düzenletici ile senkronizasyon Go Class View Class View Go Sınıf Görünümü Go Outline Outline Go Taslağı GolangAstOption Form Form QuickOpenSymbol Hızlı Açma Sembolü Show import path İçe Aktarma Yolunu Göster Match case sensitive Büyük / küçük harfe duyarlı GolangCodeOption Form Form PKG automitic import prompt PKG otomatik içe aktarma istemi PKG automatic import hints for all packages (GOPATH) Tüm paketler için PKG otomatik içe aktarma ipuçları (GOPATH) PKG automatic import hints for standard package Standart paket için PKG otomatik içe aktarma ipuçları Gocode Go API Gocode Auto update depends package when it's source changed. Auto update depends package when its source is changed. Kaynak değiştiğinde pakete bağımlılıklarını otomatik güncelle. Close gocode when exiting Çıkışta gocode kapat GolangDoc Godoc Search Godoc Arama Go Doc Search Golang Doc Search Golang Doc Arama Go Api Index Golang Api Index API indeksine git Find Package: Aranan Paket: GolangDocOption Form Form Go API API'ye Git Use default context (fast) Standart kaynakları kullan (hızlı) Only load standard API documentation Only load standard api Yalnızca standart API belgelerini yükleyin GolangEdit View import package use godoc İçe aktarma paketini görüntüleyin, godoc kullanın View Expression Information İfade Bilgilerini Görüntüle Jump to Declaration Dekorasyona Git Find Usages Kullanım Ara Rename Symbol Under Cursor İmleç Altındaki Sembolü Yeniden Adlandır %1 (Module/GOPATH) with GOROOT %1 (Module/GOPATH) GOROOT ile Stop Dur Go Source Query Go Kaynak Sorgusu SourceQuery What Kaynak Sorgusu Callees Arananlar Callers Arayıcılar Callstack Çağrı yığını Definition Tanım Describe Tanımlamak Freevars Taımsız Değişkenler Implements Yerine getirme Implements(GOPATH) Sağlanan (GOPATH) Peers Peers Referrers Yönlendirenler Pointsto Puanlar Whicherrs Hangisi Add Tags To Struct Field Struct Alanına Etiket Ekle Remove Tags From Struct Field Struct Alanından Etiketleri Kaldır Refactor Yeniden düzenleme SourceQuery Kaynak Sorgusu Below files in package %1 %1 paketindeki dosyalar GolangEditOption Form Form Mouse Fare Go root source file editor setup read only Go kaynak dosya düzenleyici kurulumunu salt okunur yap Enable view expression infomation on mouse Fareyle görünüm ifadesi bilgilerini etkinleştir Enable mouse navigation Fareyle gezinmeyi etkinleştir GolangFileSearch Golang Find Usages Golang Kullanımları Bul GolangFmtOption Form Form Format Options Golang Format Format-Ayarları Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Goimports, Go içe aktarma satırlarınızı günceller, eksik olanları ekler ve referans verilmeyenleri kaldırır. Enable update imports line, adding missing ones and removing unreferenced ones. Güncelleme içe aktarım satırını etkinleştirin, eksik olanları ekleyin ve referans verilmeyenleri kaldırın. Synchronous Eşzamanlı Synchronous code formatting Synchronous code formatting Eşzamanlı kod biçimlendirme Synchronous code formatting timeout in milliseconds (500ms or more): Milisaniye cinsinden eşzamanlı kod biçimlendirme zaman aşımı (500 ms veya daha fazla): Automatically format code when saving When the editor is saved automatically gofmt Kaydederken kodu otomatik olarak biçimlendir GolangFmtPlugin Format Code Format Code (goimports) Kodu Biçimlendir Format Code (Adjusts Imports) Kodu Biçimlendir (İçe Aktarmaları Ayarlar) GolangPackageOption Choose directory to add to GOPATH: GOPATH'a eklenecek dizini seçin: Manage GOPATH / Modules GOPATH modüllerini yönet Go Modules Go Modülleri Custom GONOPROXY Özel GONOPROXY Custom GOPROXY Özel GOPROXY Custom GO111MODULE Özel GO111MODULE Custom GONOSUMDB Özel GONOSUMDB Custom GOPRIVATE Özel GOPRIVATE TextLabel Etiket GOPATH GOPATH Use System GOPATH Sistemde öntanımlı GOPATH kullan Reload Yenile Use Custom GOPATH (one per line) Özel GOPATH kullan (her satırda bir adet) Add Directory... Klasör Ekle... Clear Temizle GolangPresentEdit Section (s1) Bölüm (s1) Subsection (s2) Alt Bölüm (s2) Sub-subsection (s3) Alt Bölüm (s3) Bold Kalın Italic İtalik Inline Code Satır içi kod Switch Bullets İzleri Değiştir Comment/Uncomment Selection Seçimi Yorum Satırı Yap/Kaldır Export HTML HTML olarak dışa aktar Verify Present Sunumu Doğrula Present verify success Mevcut doğrulama başarılı Present verify false Mevcut doğrulama başarısız Export PDF PDF dışa aktar GolangSymbol Quick Open Symbol by Name Ada Göre Hızlı Sembol Aç GoplayBrowser Go Playground Go Playground Run Çalıştır Stop Durdur New Yeni Load... Yükle... Save... Kaydet... Explore Folder Klasörleri Araştır Running... Running... Çalışıyor... Error: %1. Error: %1. Hata: %1. Success: %2. Success: %2. Başarılı: %2. Load File Dosya Yükle Select a file to load: Yüklenecek dosya seç: Save File Dosya Kaydet New File Name: Yeni Dosya Adı: HtmlPreview Page Style Sayfa Yapısı Reload Yenile Export Html HTML Dışa Aktar Export PDF PDF Dışa Aktar Print Preview Baskı Önizleme Synchronize preview and code scrollbars Önizleme ve kod kaydırma çubuklarını senkronize edin Config Ayar Plain HTML Düz HTML Export Failed Dışa Aktarım Başarısız Automatically display preview Automatically Display Preview Önizlemeyi otomatik göster HTML Preview Html Preview HTML Önizleme Could not open %1 for writing! Can not write file %1 %1 kaydetmek için açılamadı! ImageEditor ZoomIn Büyüt ZoomOut Küçült Reset to original size Orjinal boyuta sıfırla Fit to view Görüntüleyiciye sığdır Play movie Video Oynat Prev frame Önceki Çerçeve Next frame Sonraki Çerçeve Pause movie Duraklat ImageEditorFactory Image Viewer Resim görüntüleyici ImportPkgTip warning, pkg not find, please enter to import : uyarı, paket bulunamıyor, lütfen içe aktarmak için girin: JsonEdit Verify Doğrulama Format Json Json Formatı Compact Json Sıkılaştırılmış Json LiteApp Event Log Olay Günlüğü Escape Vazgeç Close File Dosyayı Kapat Close All Files Bütün Dosyaları Kapat Save File Dosyayı Kaydet Save File As... Dosyayı Farklı Kaydet... Save All Files Bütün Dosyaları Kaydet Open Project Proje Aç Options Ayarlar New... Yeni... Open File... Dosya Aç... Open Folder... Klasör Aç... Open Folder in New Window... Klasörü Yeni Pencerede Aç... Close All Folders Add Folder... Bütün Klasörleri Kapat New Window Yeni Pencere Close Window Pencereyi Kapat Save Project Projeyi Kaydet Close Project Projeyi Kapat Exit Çıkış Full Screen Tam Ekran About LiteIDE LiteIDE Hakkında About Plugins Pluginler Hahhında LiteAppOption Form Form Store [*] Store Kayıt [*] Language: Dil: Icon [*] İkon [*] Reload files in session Oturumdaki dosyaları geri yükle Recent Files Recent File Son kullanılanlar Max Count: Max Recent: En Fazla: Monitoring files for modifications Dosyaları değişikliğe karşı izleme Store settings to local ini file Ayarları yerel ini dosyasında sakla Interface [*] Arayüz [*] Style: Stil: Use tool window shortcuts Araç penceresi kısayollarını kullanın Theme [*] Tema [*] Fallback build-in icon library and liteapp/qrc/default Yedek yerleşik simge kitaplığı ve liteapp / qrc / default Load the external file icon library Load custome icon from liteapp/qrc folder Harici dosya simgesi kitaplığını yükleyin Automatically save documents Dosyaları otomatik kaydet Automatically save documents when application is idle Uygulama boştayken dosyaları otomatik olarak kaydedin sec sn Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. Ana dosya değiştirilirse / silinirse, düzenleyici arabelleğini otomatik olarak yeniden yükleyin veya kapatın. Session Oturum 0-99 0-99 Editor Tabs Tab Düzenle 10-999 10-999 Display Ekran Display [*] Göster [*] Show splash screen on startup Aaçılışa başlangıç ekranını göster Show welcome page on startup Başlangıçta karşılama sayfasını göster Editor Düzenleyici Editor tab [*] Düzenleyici sekmesi [*] Show close buttons on each editor tab Editörün her sekmesinde kapatma butonu göster Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab Sekmelerde fare tekerleği ile gezinmeyi etkinleştirin Toolbar Icon Size [*] Araç Çubuğu İkon Boyutu Editor navigate Düzenleyicide gezinme Enable mouse extra 'Back' button and 'Forward' button for go back and forward Geri ve ileri gitmek için farenin ekstra 'Geri' düğmesini ve 'İleri' düğmesini etkinleştirin Keyboard Klavye Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands Standart komutları gizle Reset Sıfırla Reset All Tümünü Sıfırla Import... İçe Aktar... Export... Dışa Aktar... Generic Genel Theme: Tema: Reload session on startup Auto load last session Açılışta oturumu geri yükle SideBarStyle Araç Çubuğu Stili SplitterStyle Bölme Stili Command Komut Label Etiket Shortcuts Kısayol NativeText Yerel Metin Standard Standart Import Keyboard Mapping Scheme Klavye Eşleme Şemasını İçe Aktar Keyboard Mapping Scheme (%1) Klavye Eşleme Şeması (%1) Could not read scheme from %1! (%1) Klavye Eşleme Şeması okunamadı! Export Keyboard Mapping Scheme Klavye Eşleme Şemasını Dışa Aktar Could not write scheme to %1! Klavye Eşleme Şeması (%1) yazılamadı! LiteBuild Build Toolbar Derleme Araç Çubuğu Build Configuration... Build Config Derleme Ayarları... Stop Action İşlemi Durdur Clear Output Clear All Çıktıları Temizle Execute File Dosyayı Çalıştır Debug File Dosya Hata Ayıklaması Lock Build Path Lock Go Build Path Derleme Yolunu Kilitle Build Path Configuration Go Build Configuration Derleme Yolu Ayarları Use godoc View godoc görünümünü kullanın Line Wrap Satır Kaydırma Auto Clear Otomatik temizleme Automatic positioning cursor Otomatik imleç konumlandırma Setup Ayarlar Build Output Build Derleme Çıktısı Current environment change id "%1" Mevcut ortam değişiklik kimliği "%1" Lock Build Lock Build: %1 Derlemeyi Kilitle Error: %1. Error: %1. Hata: %1. Command exited with code %1. Komut sonlandırma durumu %1. Success: %1. Success: %1. Başarılı: %1. A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. Şu anda bir işlem çalışıyor. Önce mevcut eylemi durdurun. Killing current process... Killing current process... Mevcut işlem sonlandırılıyor... Failed to terminate the existing process! Failed to terminate the existing process! Mevcut işlem sonlandırılamadı! Started process successfully Started process successfully İşlem başarıyla başlatıldı Failed to start process İşlem başlatma hatası LiteBuildOption Form Form Recheck Go installation when changing environments Recheck go env if enviroment changed Ortam değişkenleri değiştirilince Go kurulumunu tekrar kontrol et Build command configuration files [*] Build command configuration files: Komutla yapılandırma dosyalarını oluşturun [*] LiteBuildPlugin Close Kapat Execute: Exec: Çalıştır: Execute File Execute Dosya Çalıştır LiteDebug Stop Dur Clear Temizle Continue Devam Show Current Line Geçerli Satırı Göster Debug Output Debug Hata Ayıklama Çıktısı Start Debugging External Application... Start Debugging External Application Dış Uygulama Hata Ayıklaması... Close Kapat Start Debugging Hata Ayıklamaya Başla Step Into Adım İleri Step Over Adım İleri Step Out Dışarı Çık Run to Line Satıra kadar çalıştır Insert/Remove Breakpoint Kesme Ekle/Kaldır Remove All Breakpoints Tüm Kesmeleri Kaldır LiteDebugOption Form Form Debug Hata Ayıkla Automatically insert breakpoint main.main when debugging Automatically add breakpoint main.main when debugging Hata ayıklamada main için otomatik olarak breakpoint yerleştir LiteDebugPlugin Debug Window Debug Hata Ayıklama Penceresi LiteDoc LiteIDE Documentation LiteIDE Document Browser LiteIDE Dökümantasyonu LiteEditor Undo Geri al Redo Yinele Cut Kes Copy Kplyala Paste Yapıştır Select All Tümünü Seç Go to Doc Start Döküman Başına Git Go to Doc End Döküman Sonuna Git Go to Line Start Satır Başına Git Go to Line End Satırın Sonuna Git Go to Previous Line Önceki Satıra Git Go to Next Line Sonraki Satır Git Go to Previous Character Önceki Karaktere Git Go to Next Charater Sonraki Karaktere Git Go to Previous Word Önceki Kelimeye Git Go to Next Word Sonraki Kelimeye Git Go to Line Satır Git File is readonly Dosya Saltokunur File is writable Dosya Yazılabilir Line Wrap (MimeType) Word Wrap (MimeType) Satır Kaydırma (Mime Türü) Toggle Comment Yorumu Aç / Kapat Toggle Block Commnet Blok Yorumunu Aç / Kapat Auto-indent Selection Otomatik girinti Seçimi Tab To Spaces (MimeType) Boşluklara Sekme (Mime Türü) Line End Windows (\r\n) Satır Sonu Windows (\r\n) Line End Unix (\n) Satır Sonu Unix (\n) Visualize Whitespace (Global) Beyaz Alanı Görselleştir (Global) Move Line Up Satırı Yukarı Taşı Move Line Down Satırı Aşağı Taşı Copy Line Up Satırı Yukarı Kopyala Copy Line Down Satırı Aşağı Kopyala Join Lines Satırları Birleştir Title Case Baş Harfler Upper Case Büyük Harfler Lower Case Küçük Harfler Swap Case Kılıf Takası Tab To Spaces Boşluklu Sekme Spaces To Tab Tab boşlokları Advanced Gelişmiş Goto Git Convert Tab Tab Dönüştürme Code Folding Kodu Kapat Convert Case Karakter Dönüştürme Export HTML HTML Dışa Aktar Export Failed Dışarı Aktarılamadı Could not open %1 for writing. %1 yazmak için açılamadı. Export PDF PDF Dışa Aktar Print Document Dosya Yazdır Print Preview... Print Preview Document Baskı-Önizleme... Export HTML... HTML Dışa AktarL... Export PDF... PDF Dışa Aktar... Print... Yazdır... Go to Previous Block Go To Previous Block Önceki Bloğa Git Select Block Blok Seç Go to Matching Brace Go To Matching Brace Eşleşen Ayraç'a git Fold Kapa Unfold Fold All Tümünü Kapa Unfold All Tümünü Aç Go To Line Goto Line Satıra Git Duplicate Kopya Oluştur Delete Line Satır Sil Copy Line Satır Koplaya Cut Line Satırı Kes Insert Line Before Önüne Çizgi Ekle Insert Line After Arkasına Çizgi Ekle Increase Font Size Yazı Tipi Boyutunu Arttır Decrease Font Size Yazı Tipi Boyutunu Küçült Reset Font Size Yazı Tipi Boyutunu Sıfırla Clean Whitespace Boşlukları temizle Code Complete Kod Tamamlandı Settings File Setup Ayarlar Reload File Dosyayı Tekrar Yükle Do you want to permanently discard unsaved modifications and reload %1? Kaydedilmemiş değişiklikleri kalıcı olarak silmek ve%1'i yeniden yüklemek istiyor musunuz? Go to Next Block Go To Next Block Sonraki Bloğa Git ReadOnly SaltOkunur Line: Satır: LiteEditorFileFactory Text Editor Metin Düzenleyici LiteEditorOption Form Form Load File Dosyayı Yükle Check and convert no printable char to '.' Yazdırılamayan karakteri kontrol edin ve "." yap Font Font Font && Colors Font && Renkler Family: Küme: Show Monospace Font Tek Aralıklı Yazı Tipini Göster Size: Büyüklük: Zoom: Zoom: % % Antialias Antialias Restore Default Font Varsayılan Yazı Tipini Geri Yükle Editor Color Scheme ColorStyle Scheme Editörün Renk Şeması File: Dosya: Edit Düzenle Syntax Auto-completion Auto complete brackets Sözdizimi Otomatik Tamamlama Fuzzy code completion Belirsiz kod tamamlama Clean completion cache when saving files Dosyaları kaydederken tamamlama önbelleğini temizleyin Clean whitespace when saving files Dosyaları kaydederken boşlukları temizleyin Enable scroll wheel zooming Kaydırma tekerleği ile yakınlaştırmayi etkinleştir Add copied text into the clipboard as HTML Kopyalanan metni panoya HTML olarak ekle Allow vertical scrolling to the last line [*] Son satıra [*] dikey kaydırmaya izin ver Display VisualizeWhitespace Beyaz Alanı Görselleştir Word wrap by default Varsayılan olarak kelime kaydırma Display code fold Kod katlamalarını göster Display offset position Ofset konumunu göster File Types Dosya Türleri Behavior Davranışı Display EOF Dosyasonunu (EOF) göster Display line numbers Satır numaralarını göster Display indent guide Display indent guide Girinti kılavuzunu görüntüle Display right margin at column Sütunda sağ kenar boşluğunu görüntüle Automatic indentation Enable automatic indentation Otomatik girinti Case sensitive code completion Completer case sensitive Büyük / küçük harfe duyarlı kod tamamlama Code completion prefix length: Word Complete Prefix Length Kod tamamlama önek uzunluğu: Display Görüntüleme MIME Type MIME Türü Tab Width Tab-Genişliği Tab To Spaces Sekmeleri boşluk işaretine dönüştür File Extensions Dosya Uzantıları Custom Extensions Özel Uzantılar LiteEditorPlugin Edit ToolBar Araç Çubuğunu Düzenle Edit Navigation Bar Gezinme Çubuğunu Düzenle LiteEnvOption Form Form Environment definition files: Ortam değişkeni tanımlama dosyası: Environment changes will take effect after switching environments. Ortam değişkenleri değişikliği, ortam değiştirildikten sonra etkili olacaktır. LiteFindPlugin Find Ara Find Next Sonrakini Ara Find Previous Öncekini Ara Replace Değiştir File Search Dosya Ara LiteTabWidget Open a new tab Yeni tab aç List All Tabs Bütün Tabları Listele Close Tab Tabı Kapat MarkdownBatchBrowser Markdown Exporter Markdown Batch Markdown Aktarıcı All Files (*) Tüm Dosyalar (*) Select the folder containing your markdown files: Select Markdown Folder Markdown dosyalarınızı içeren klasörü seçin: Select Markdown Files Markdown dosyalarınız seçin Select the folder to contain separated markdown exports: Markdown aktarımlarını içeren klasörü seçin: Export Merged HTML Export Html Birleştirilmiş HTML Dışa Aktar Export Merged PDF Export PDF Birleştirilmiş PDF Dışa Aktar MarkdownBatchWidget Form Form Markdown Source Files Markdown Files Kaynak Dosyayı İşaretleyin Import Folder... Import Folder Klasörü İçe Aktar... Add Files... Add Files Dosyaları Ekleyin... Move Up Yukarı Taşı Move Down Aşağı Taşı Remove Sil Remove All Tümünü Sil Options Ayarlar Export Folder: Klasörü Dışa Aktar: Browse... Browser Araştır... Use CSS CSS Kullan Insert horizontal line between merged files Merge files insert split <hr> Birleştirilmiş dosyaların drasında çizgi ekle Insert page break between merged files Merge files insert page break Birleştirilmiş dosyaların arasında ayıraç ekle Export Export Util Dışa Aktar Export Separated HTML Separate Html HTML Dışa Aktar Export Separated PDF Separate PDF PDF Dışa Aktar Export Merged HTML... Merge Html HTML birleştirlenleri aktar... Export Merged PDF... Merge PDF PDF birleştirilenleri aktar... Print Preview Merged... Merge Print Preview Önizleme (birleştirilmiş.)... Print Merged Merge Print Yazdır (birleştirlilmiş.) Log Log MarkdownEdit Header (h1) Header <h1> Başlık (h1) Header (h2) Header <h2> Başlık (h2) Header (h3) Header <h3> Başlık (h3) Header (h4) Header <h4> Başlık (h4) Header (h5) Header <h5> Başlık (h5) Header (h6) Header <h6> Başlık (h6) Bold Kalın Italic İtalik Inline Code Çizili Link Bağlantı Image Resim Unordered List Sırasız liste Ordered List Sıralı Liste Blockquote Blockquote Horizontal Rule Yatay Ayıraç Heading Başlık MultiFolderView Delete Folder Klasör Sil Are you sure that you want to permanently delete this folder and all of its contents? Bu klasörü ve tüm içeriğini kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the folder! Klasör Silinemedi! Delete File Dosya Sil Are you sure that you want to permanently delete this file? Bu dosyayı kalıcı olarak silmek istediğinizden emin misiniz? Failed to delete the file! Dosya Silinemedi! NavigateBar Browser Files in %1 %1'deki Dosyalar NewFileDialog New Project or File Yeni Proje veya Dosya Browse... Araştır... GOPATH: GOPATH: Template: Template Taslak: Type Tür Information Bilgi Name: İsim: Location: Lokasyon: Error Hata Could not create the target directory: %1 Hedef dizin oluşturulamadı:%1 Warning Uyarı Location %1 is not empty. Use the target directory anyway? %1 konumu boş değil. Yine de hedef dizini kullanılsın mı? Overwrite File Dosyanın üzerine yaz %1 already exists. Do you want to replace it? %1 zaten var. Değiştirmek istiyor musun? No files could be created. Dosyalar oluşturulamadı. File template details: Dosya taslak ayrıntıları: Project template details: New project wizard: Proje taslak ayrıntıları: Choose a directory for the new content: Yeni içerik için klasör seçin: OpenEditorsWidget Open Documents Dökümanları Aç OptionsBrowser Options Options Page Ayarlar OptionsWidget Options Ayarlar Info Bilgi [*] item request restart of LiteIDE [*] item requeset restart LiteIDE [*] LiteIDE'nin yeniden başlatılması gerekir OutputDockWidget Move To Buraya Taşı LeftSideBar Sol Araç Çubuğı RightSideBar Sağ Araç Çubuğı BottomDockWidget Alt İskelet Widget'ı OutputOption Form Form Font Font Family: Küme: Size: Boyut: Zoom: Zoom: % % Antialias Antialias Display Ekran Use editor color scheme Düzenleyici renk şemasını kullan Sets the maximum number of lines Maksimum satır sayısı PackageBrowser Manage GOPATH/Modules ... Manage GOPATH... GOPATH modülleri düzenle... Reload All Hepsini Yenile Use godoc View Godoc görüntüleyici kullan Load Package in New Window Paketi yeni pencerede yükle Add Package to Folders Paketi klasöre ekle Open Source File Kaynak Dosyası Aç Copy Name to Clipboard Copy Name To Clipboard Adı Panoya Kopyala Go Package Browser Package Browser Go Paket Gezgini Loading Go package list... Loading go package ... Go Paket listesini yükle... PackageProject Reload Package Paketleri Yeniden Yükle Open Explorer Here Explorer'i Burada Aç Add Source File Kaynak Dosyası Ekle File Name: Dosya Adı: Error Hata File %1 already exists. %1 dosyası zaten var. Could not open %1 for writing. %1 yazma için açılamadı. PluginsDialog Installed Plugins Install Plugins Yüklü Eklentiler Close Kapat Name Adı Author Geliştirici Enabled Aktif Details Ayrıntılar Version Last Ver Versiyon File Name FileName Dosya Adı ProcessEx process exited with code %1 İşlem %1 koduya kapandı process crashed or was terminated işlem çöktü veya sonlandırıldı process exited with an unknown status bilinmeyen bir durumla işlemden çıkıldı process failed to start işlem başlatılamadı process crashed or was terminated while running işlem çalışırken çöktü veya sonlandırıldı timed out waiting for process işlem beklerken zaman aşımına uğradı couldn't read from the process süreç okunamadı couldn't write to the process sürece yazılamadı an unknown error occurred bilinmeyen bir hata oluştu ProjectManager Project <%1> Proje <%1> Import Directory <%1> <%1> Klasörü İçe Aktar QFileSystemModel %1 TB %1 TB %1 GB %1 GB %1 MB %1 MB %1 KB %1 KB %1 bytes %1 byte QJson::ParserRunnable An error occurred while parsing json: %1 %1 Json ayrıştırılırken bir hata oluştu QJsonParseError no error occurred hata oluşmadı unterminated object sonlandırılmamış nesne missing name separator isim ayırıcısı eksik unterminated array sonlandırılmamış dizi missing value separator değer ayırıcısı eksik illegal value geçersiz değer invalid termination by number geçersiz sonlandırma numarası illegal number geçersiz numara invalid escape sequence geçersiz kaçış dizisi invalid UTF8 string geçersiz UTF-8 karakteri unterminated string sonlandırılmamış dize object is missing after a comma virgülden sonra nesne eksik too deeply nested document çok derin iç içe geçmiş belge too large document çok büyük belge garbage at the end of the document belgenin sonunda çöp QuickOpenAction Show and Run Commands Komutları Göster ve Çalıştır QuickOpenEditor Show All Opened Editors Show All Editors Tüm Açılmış Düzenleyicileri Göster QuickOpenFileSystem File System Dosya Sistemi QuickOpenFiles Go to File Dosyaya Git Type '?' to get help on the actions you can take from here Burada yapabileceklerinizle ilgili yardım almak için "?" yazın QuickOpenFolder Browser Folder Tarayıcı Klasörü QuickOpenHelp Show All Quick Open Actions Show Quick Open Help Tüm Hızlı Açılış İşlemlerini Göster QuickOpenLines Go to Line Satır Git Open a text file first to go to a line Bir satıra gitmek için önce bir metin dosyası açın Type a line number between %1 and %2 to navigate to Gitmek için%1 ile%2 arasında bir satır numarası yazın Go to Line %1 Go to line %1 %1 No'lu Satıra Git QuickOpenManager Quick Open File Hızlı Dosya Açma Quick Open Editor Hızlı Editör Açma Quick Open Symbol Hızlı Sembol Açma Quick Open Command Hızlı Komut Açma Show All Quick Open Actions Tüm Hızlı Açmaları Göster QuickOpenMimeType Go to Symbol in File Open Symbol by Name Dosyadaki sembole git not found symbol sembol bulunamadı QuickOpenOption Form Form QuickOpenFiles Hızlı Dosya Açma Match case sensitive Büyük / küçük harfe duyarlı Max files count: En Fazla Dosya Sayısı: QuickOpenEditor Hızlı Açma Düzeni RecentManager Clear All History Tüm Geçmişi Temizle Clear Menu Menüyü Temizle SearchEdit Search Ara Stop Search Aramayı Durdur SelectExternalDialog Debug External Application Harici Uygulamada Hata Ayıklama Application: Uygulama: Browse... Browser Araştır... Arguments: Argümanlar: Working directory: Çalışma Klasörü: Select Executable Uygulama Seçin Select the working directory: Select Working Directory Çalışma klasörü seçimi: SessionRecent Sessions Oturumlar SideDockWidget Move To .. ya taşı RightSideBar Sağ Taraf Paneli LeftDockWidgt Sol Panel Aracı LeftSideBar Sol Taraf Panel RightDockWidget Sağ Panel Aracı OutputBar Çıkış Panel SideBar Panel Show SideBar Paneli Göster SideWindowStyle Hide SideBar Yan Çubuğu Gizle SideBar Windows Yan Çubuk Penceresi Output Windows Çıktı Penceresi SplitDockWidget Move To ..ya taşı Top Üst Top (Split) Üst (bölünmüş) TopDockWidget (Split) Üst Panel Aracı (bölünmüş) TopDockWidget Üst Panel Aracı Bottom Alt Bottom (Split) Alt (bölünmüş) BottomDockWidget (Split) Alt Panel Aracı (bölünmüş) BottomDockWidget Alt Panel Aracı Left Sol Left (Split) Sol (bölünmüş) LeftDockWidget (Split) Sol Panel Aracı (bölünmüş) LeftDockWidget Sol Panel Aracı Right Sağ Right (Split) Sağ (bölünmüş) RightDockWidget (Split) Sağ Panel Aracı (bölünmüş) RightDockWidget Sağ Panel Aracı Unsplit Bölme Split Böl SplitWindowStyle Hide Sidebars Kenar Çubuklarını Gizle Tool Windows Araç Pencereleri Terminal New Yeni Open a new terminal Yeni Terminla Aç Close Kapat Close current terminal Geçerli Terminali Kapat CloseAll Tümünü Kapat Close all terminal Tüm Terminalleri Kapat LoadEnv Ortam Değişkenlerini Yükle Current terminal load environment from LiteIDE LiteIDE'den mevcut terminale ortam değişkenlerini aktar Filter Filter Dark Mode Karanlık Mod Login Mode (shell --login) Giriş Yöntemi (shell --login) Terminal Terminal Open in Integrated Terminal Gömülü Terminalde Aç Rename Tab Title Sekme Başlığını Teniden Adlandır TerminalEdit Cut Kes Copy Kopyala Paste Yapıştır Select All Tümünü Seç Clear All Tümünü Temizle TextEditor::Internal::ColorScheme Not a color scheme file. Renk düzeni dosyası değil. Utils::FilterLineEdit Filter Filtrele Clear text Yazıyı temizle WebKitBrowser Navigation Navigasyon Open Html File Open Html HTML-Dosyası Aç WebKitBrowser WebKit-Browser False load %1 ! %1 Tüklemede Hata! Open Html or Markdown File Open Html or Markdown Files HTMLveya Markdown-Dosyası Aç WebKitHtmlWidgetPlugin Open Html or Markdown File Open Html or Markdown Files Html veya Markdown Dosyasını Açın WelcomeBrowser New Yeni Open Open Folder Klasör Aç Options Ayarlar Welcome Welcome Page Hoşgeldiniz WelcomePlugin Welcome Home Hoşgeldiniz ================================================ FILE: liteidex/liteide_uk.ts ================================================ AboutDialog About LiteIDE About Liteide Про LiteIDE Information Infomation Інформація Welcome: Ласкаво просимо: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Ласкаво просимо в LiteIDE X! LiteIDE - це проста кросплатформена IDE з відкритим кодом. Project: Проект: Name: Назва: Author: Автор: Version: Версія: Build: Збірка: Based on Qt Based on Qt Version На основі Qt Source Code: Програмний код: Support LiteIDE: Support Підтримка LiteIDE: Developers Розробники Translations Переклади Chinese Китайська Japanese Японська Russian Російська French Французька Traditional Chinese Традиційна китайська German Німецька Ukrainian Українська Thanks to... Подяки... License Ліцензія Close Закрити Based on Qt %1 (%2 bit) На основі Qt %1 (%2 біт) ActionManager &File &Файл &Recent &Останні &Edit Р&едагувати F&ind &Find &Пошук &View &Вигляд &Tools &Інструменти &Build З&бирання &Debug Зне&вадження &Help &Допомога Standard Toolbar Standard ToolBar Стандартна панель AstWidget Go To Definition Перейти до визначення View Import Document Документація BaseDockWidget Hide Приховати Hide Tool Window Приховати панель Floating Window Плаваюче вікно BaseFolderView Open In New Window Відкрити в новому вікні Open File Відкрити файл New File... Створити файл... New File Wizard... Майстер створення файлу... Rename File... Перейменувати файл... Delete File Видалити файл New Folder... Створити директорію... Rename Folder... Перейменувати директорію... Delete Folder Видалити директорію Open Terminal Here Відкрити термінал тут Show in Explorer Open Explorer Here Відкрити в Explorer Open Application Відкрити програму Show in Finder Відкрити в Finder Show Containing Folder Показати в батьківській директорії Open Command Prompt Here Відкрити командний рядок тут Open in Integrated Terminal Open Folder... Add Folder... Відкрити директорію... Reload Folder Перезавантажити директорію Close Folder Закрити директорію Close All Folders Закрити всі директорії Copy Копіювати Paste Вставити Copy Path Move To Trash Create File Створити файл A file with that name already exists! Файл з таким іменем вже існує! Failed to create the file! Не вдалося створити створити файл! Rename File Перейменувати файл New Name: Нове ім'я: Failed to rename the file! Не вдалося перейменувати файл! An item "%1" already exists in this location. Do you want to replace it and move old item to trash? Stop Зупинити Keep Both Keep Both All Replace Замінити Replace All Замінити все Are you sure that you want move to trash this item? Are you sure that you want move to trash %1 items? Move to Trash Open With System Editor Create Folder Створити директорію A folder with that name already exists! Директорія з таким іменем вже існує! Failed to create the folder! Не вдалося створити створити директорію! Rename Folder Перейменувати директорію Folder Name Им'я директорії Failed to rename the folder! Не вдалося перейменувати директорію! Are you sure that you want to permanently delete this folder and all of its contents? Видалити цю директорію разом із її вмістом назавжди? Failed to delete the folder! Не вдалося видалити директорію! BookmarkManager Toggle Bookmark Вставити/Видалити закладку Goto bookmark Перейти до закладки Remove bookmark Вилучити закладку Remove all bookmarks for this file Вилучити всі закладки для цього файлу Remove all bookmarks for all files Вилучити всі закладки для всіх файлів Bookmarks Закладки BookmarkRecent Bookmarks Закладки BuildConfigDialog Build Configuration Build Config Dialog Параметри збирання Build ID Ідентифікатор збірки Build Path Build File Шлях збірки GOPATH GOPATH information Інформація про GOPATH Use Custom GOPATH for Build Path Використовувати нестадартний GOPATH Inherit System GOPATH Наслідувати системний GOPATH Inherit LiteIDE GOPATH Наслідувати GOPATH LiteIDE Custom GOPATH (one per line) Шляхи GOPATH (по одному на рядок) Add Directory... Додати директорію... Clear Очистити LiteIDE LiteIDE Config Конфігурація Action Дії Custom Build Custom Розширені Reset all to initial value Відновити початкові значення Name Назва Value Значення SharedValue Спільне значення Id Ідентифікатор Cmd Команда Choose directory to add to GOPATH: Додати обрану директорію в GOPATH: CreateDirDialog Create Folder Створення директорії Directory: Директорія: Dir Name: Ім'я директорії: Create Створити Cancel Скасувати CreateFileDialog Create File Create File Dialog Створення файлу Directory: Директорія: File Name: Ім'я файлу: Create Створити Create and Edit Створити і редагувати Cancel Скасувати DebugWidget Add Watch Додати спостереження Async Record AsyncRecord Асинхронний запис Variables Змінні Watch Спостереження Call Stack CallStack Стек викликів Threads Потоки Goroutines Registers Регістри Libraries Library Бібліотеки Console Консоль Watch expression (e.g. buf main.var os.Stdout): Вираз для спостереження (наприклад, buf main.var os.Stdout): Remove Watch Видалити спостереження Remove All Watches Видалити всі спостереження DlvDebuggerOption Form Форма delve debug pass flags: (example --check-go-version=false) DocumentBrowser Back Backward Назад Forward Вперед Reload Перезавантажити Increase Font Size Збільшити розмір шрифту Decrease Font Size Зменшити розмір шрифту Reset Font Size Відновити розмір шрифту DocumentBrowserFactory DocumentBrowser EditorManager Close Закрити Move to New Window Move To New Window Перенести в нове вікно Navigate Forward GoForward Перейти вперед Close Others Close Others Tabs Закрити інші Open Editor Відкриті редактори Close All Close All Tabs Закрити всі Close Left Tabs Закрити вкладки зліва Close Right Tabs Закрити вкладки справа Close Files in Same Folder Close Same Folder Files Закрити файли з цієї ж директорії Close Files in Other Folders Close Other Folder Files Закрити файли з інших директорій Copy Full Path to Clipboard Copy Path to Clipboard Копіювати повний шлях в буфер обміну Show in Explorer Показати в Explorer Show in Finder Показати в Finder Show Containing Folder Показати в файловому менеджері Open Command Prompt Here Відкрити командний рядок тут Open Terminal Here Відкрити термінал тут Open in Integrated Terminal Navigate Backward Перейти назад Save changes to %1? Зберегти зміни в %1? Unsaved Modifications Save Modify Незбережені зміни All Files (*) Всі файли (*) Save As Зберегти як EnvManager Environment Toolbar Environment ToolBar Панель конфігурації оточення Switching current environment Switch Current Environment Перемкнути поточне оточення Edit current environment Edit Current Environment Редагувати поточне оточення Reload current environment Reload Current Environment Перезавантажити поточне оточення Select Environment Вибрати оточення ExportDialog Dialog Експорт Name: Назва: Export Експортувати ExportAndView Експортувати з переглядом FakeVim::Internal Use Vim-style Editing Використовувати редагування в стилі Vim Read .vimrc Прочитати .vimrc Path to .vimrc Шлях до .vimrc FakeVim::Internal::FakeVimHandler Unknown option: %1 Невідома опція: %1 Argument must be positive: %1=%2 Аргумент має бути додатним: %1=%2 Mark "%1" not set. Позначку "%1" не встановлено. %1%2% %1All Not implemented in FakeVim. Не реалізовано у FakeVim. Unknown option: Невідома опція: Invalid argument: Помилковий аргумент: Trailing characters: Кінцеві символи: Move lines into themselves. Пересування рядків на те саме місце. %n lines moved. %n рядок пересунуто. %n рядки пересунуто. %n рядків пересунуто. File "%1" exists (add ! to override) Файл "%1" існує (додайте ! для перезапису) Cannot open file "%1" for writing Не вдалося відкрити файл "%1" для запису "%1" %2 %3L, %4C written. "%1" %2 %3L, %4C записано. Cannot open file "%1" for reading Не вдалося відкрити файл "%1" для читання "%1" %2L, %3C %n lines filtered. %n рядок змінено. %n рядки змінено. %n рядків змінено. Cannot open file %1 Не вдалося відкрити файл %1 Invalid regular expression: %1 Помилковий регулярний вираз: %1 Pattern not found: %1 Шаблон не знайдно: %1 Search hit BOTTOM, continuing at TOP. Пошук досягнув КІНЦЯ, починаємо з ПОЧАТКУ. Search hit TOP, continuing at BOTTOM. Пошук досягнув ПОЧАТКУ, починаємо з КІНЦЯ. Search hit BOTTOM without match for: %1 Пошук дійшов до КІНЦЯ без співпадінь: %1 Search hit TOP without match for: %1 Пошук дійшов до ПОЧАТКУ без співпадінь: %1 %n lines indented. %n рядок вирівняно. %n рядки вирівняно. %n рядків вирівняно. %n lines %1ed %2 time. %n lines yanked. Already at oldest change. Already at newest change. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Type Alt-V, Alt-V to quit FakeVim mode. [New] [Новий] Not an editor command: %1 Не команда редактора: %1 FakeVimEdit Use FakeVim Editing Викорстовувати редагування FakeVim FakeVimEditOption Form Форма FakeVim initialization command list (# start is comment): Список команд ініціалізації FakeVim (# починає коментар): Load default init command list Завантажити типовий список FiFoTty Cannot create temporary file: %1 Не вдалося створити тимчасовий файл: %1 Cannot create FiFo %1: %2 Неможливо створити FiFo %1: %2 Cannot open FiFo %1: %2 Неможливо відкрити FiFo %1: %2 FileBrowser Synchronize with editor Синхронізувати із редактором Show Hidden Files Показувати приховані файли Set As Root Folder Set Folder To Root Встановити кореневою директорією Execute File Виконати файл Reload Folder Перезавантажити директорію Show Details Показувати подробиці Debug File Зневадження файлу Open Folder in New Window Відкрити директорію у новому вікні Add to Folders Додати до директорій Open Parent Open to Parent Нагору Filter Фільтрувати File System Файлова система FileBrowserOption Form Форма Terminal Термінал Command: Команда: Arguments: Аргументи: FileManager All Files (*) Всі файли (*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? Проект "%1" створено. Бажаєте його відкрити зараз? Open Project or File Відкрити файл або проект Show Hidden Files Показувати приховані файли Show Details Показувати подробиці Split Mode Розділений режим Folders Folers Директорії All Support Files (%1) Всі підтримувані типи файлів (%1) Select a folder: Open Folder Оберіть директорію: %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 Цей файл був видалений з файлової системи, але у вас лишилися незбережені зміни у LiteIDE. Бажаєте закрити редактор? Відповідаючи "Так" ви втратите незбережені зміни. %1 This file has been deleted from the drive. Do you want to close the editor? %1 Цей файл був видалений із файлової системи. Бажаєте закрити редактор? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 Цей файл було змінено на диску, але у вас лишилися незбережені зміни у редакторі LiteIDE. Бажаєте перезавантажити файл із диску? Відповідаючи "Так" ви втратите незбережені зміни. %1 This file has been modified on the drive. Do you want to reload the file from disk? %1 Цей файл було змінено на диску. Бажаєте перезавантажити файл з диску? Open Files Відкрити файли Synchronize with editor Синхронізувати із редактором Filter Фільтрувати дерево Open Project Відкрити проект LiteIDE X LiteIDE X FileRecent Files Файли FileSearch Match whole word Match word Тільки цілі слова Match case Враховувати регістр Regular expression Регулярний вираз Scan subdirectories Look in subdirs Рекурсивно Search for: Шукати входження: Options: Параметри: Browse... Browser Обрати... Filter: Фільтр: Files on File System Файли у файловій системі Search Знайти Cancel Скасувати Current Folder Поточна директорія Auto Switch Обирати автоматично Clear Очистити Open Directory Відкрити директорію FileSearchManager Search Item: Шукаємо: Only golang file changes can be revert! This file change cannot be undone! Лише зміни до файлів golang можуть бути скасовані! New Search Новий пошук File Search Пошук в файлах Search Result Результат пошуку LiteIDE X LiteIDE X Warning! Replace text is empty. Want to remove all the search items? Увага! Текст для заміни пустий. Бажаєте видалити всі знайдені результати? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? Увага! Текст для заміни складається з пробільних символів. Бажаєте замінити всі знайдені результати пробільними символами? The following files have no write permissions. Do you want to change the permissions? Ці файли не мають права на запис. Бажаєте змінити права? File is readonly Файл тільки для читання FileSystemWidget Open File Open Editor Відкрити файл New File... New File Створити файл... New File Wizard... New File Wizard Майстер створення файлу... Rename File Перейменувати файл Delete File Remove File Видалити файл New Folder... New Folder Створити директорію... Are you sure that you want to permanently delete this file? Видалити цей файл назавжди? Rename Folder Перейменувати директорію Delete Folder Remove Folder Видалити директорію Rename File... Перейменувати файл... Rename Folder... Перейменувати директорію... Open Terminal Here Відкрити термінал тут Open Explorer Here Відкрити в файловому менеджері View Godoc Here Відкрити Godoc Add Folder Додати директорію Close Folder Закрити директорію Add Folder... Додати директорію... Close All Folders Закрити всі директорії Create File Створення файлу A file with that name already exists! The file already exists! Файл вже існує! Failed to create the file! Не вдалося створити створити файл! New Name: Нове ім'я: Failed to rename the file! Не вдалося перейменувати файл! Are you sure that you want to permanently delete this folder and all of its contents? Видалити цю директорію разом із її вмістом назавжди? Failed to delete the file! Failed to remove the file! Не вдалося видалити файл! Create Folder Створити директорію A folder with that name already exists! The folder name is exists! Директорія з таким іменем вже існує! Failed to create the folder! Не вдалося створити створити директорію! Folder Name Ім'я директорії Failed to rename the folder! Не вдалося перейменуванні директорію! Failed to delete the folder! Failed to remove the folder! Не вдалося видалити директорію! Find::Internal::SearchResultWidget Search was canceled. Пошук було скасовано. Cancel Скасувати Repeat the search with same parameters Повторити пошук за попередніми параметрами Search again Шукати знову Set show replace mode ui Показати інтерфейс заміни Show Replace Виконати заміну Replace with: Замінити на: Replace all occurrences Замінити всі співпадіння Replace Замінити Preserve case Зберігати регістр Expand all items Collapse all items Revert with: Повернути на: Revert Повернути Revert all occurrences Повернути всі співпадіння %n matches replaced. %n співпадіння замінено. %n співпадіння замінено. %n співпадінь замінено. searching... %n matches found. шукаємо... знайдено %n співпадіння. шукаємо... знайдено %n співпадіння. шукаємо... знайдено %n співпадінь. searching ... шукаємо ... No matches found. Співпадінь не знайдено. %n matches found. Знайдено %n співпадіння. Знайдено %n співпадіння. Знайдено %n співпадінь. FindApiEdit Search Пошук Stop Search Зупинити пошук FindApiWidget Search Шукати Find Знайти FindDocWidget Search Шукати Find Знайти Find All Шукати все Find const Шукати const Find func Шукати func Find interface Шукати interface Find pkg Шукати pkg Find struct Шукати struct Find type Шукати type Find var Шукати var Use Regexp Регулярний вираз Match Case Врахування регістру Match Word Слово цілком Help Допомога FindEditor Match case Враховувати регістр Regular expression Регулярний вираз Wrap around Продовжити із початку Find Next Знайти наступне Find Previous Find Prev Знайти попереднє Replace With: Замінити на: Replace Замінити Replace All Замінити все Match whole word only Тільки цілі слова Ready Готово Close Закрити Show Replace Показувати заміну Find What: Знайти: Options: Find Option: Параметри: Not found Не знайдено FolderListView Delete File Видалити файл Are you sure that you want to permanently delete this file? Видалити цей файл назавжди? Failed to delete the file! Не вдалося видалити файл! Delete Folder Видалити директорію Are you sure that you want to permanently delete this folder and all of its contents? Видалити цю директорію разом із її вмістом назавжди? Failed to delete the folder! Не вдалося видалити директорію! FolderRecent Folders Директорії FolderView Delete File Видалити файл Are you sure that you want to permanently delete this file? Видалити цей файл назавжди? Failed to delete the file! Не вдалося видалити файл! Delete Folder Видалити директорію Are you sure that you want to permanently delete this folder and all of its contents? Видалити цю директорію разом із її вмістом назавжди? Failed to delete the folder! Не вдалося видалити директорію! GdbDebuggerOption Form Форма Enable --tty for program being debugged. Включити --tty для програми, що зневаджується. GoAddTagsDialog Add Tags To Struct Field Add JSON Tag Options Параметри Multiple options separated by commas Multiple options are separated by commas Add XML Tag Add Custom Tags Tag Name Setup custom tag name Sort sorts the tags in increasing order according to the key name Сортування тегів впорядковує за зростанням назви ключа Override current tags when adding tags Перевизначати наявні теги при додаванні тегів Info Інформація GoRemoveTagsDialog Remove Tags From Struct Field Remove Tags And Options Clear All Tags Clear All Tags Options Clear All Tag Options Remove JSON Tag Remove XML Tag Remove Custom Tag Multiple tags separated by commas Multiple tags are separated by commas Remove JSON Options Multiple options separated by commas Multiple options are separated by commas Remove XML Options Remove Custom Tag Options Setup remove custom tag and option, example tag=opt1,tag=opt2 Setup remove custom tag option, example tag=opt1,tag=opt2 tag=option Info Інформація GolangAst No outline available Дерево недоступне Synchronize with editor Синхронізувати із редактором Go Class View Class View Класи Go Go Outline Outline Структура Go GolangAstOption Form Shown in settings dialog Форма QuickOpenSymbol Show import path Відображати шлях імпорту Match case sensitive Враховувати регістр GolangCodeOption Form Shown in settings dialog Форма PKG automitic import prompt PKG automatic import hints for all packages (GOPATH) PKG automatic import hints for standard package Gocode Go API Gocode Auto update depends package when it's source changed. Auto update depends package when its source is changed. autobuild option Оновлювати автоматично при зміні вихідного коду пакету (autobuild). Close gocode when exiting Зупинити gocode після виходу GolangDoc Godoc Search Пошук Godoc Go Doc Search Golang Doc Search Документація Golang Go Api Index Golang Api Index Індекс Golang API Find Package: Знайти пакет: GolangDocOption Form Форма Go API Go API Use default context (fast) Використовувати контекст по замовчанню (швидко) Only load standard API documentation Only load standard api Завантажити лише доки по стандартному API GolangEdit View import package use godoc Переглянути godoc імпортів пакунку View Expression Information Інформація про вираз Jump to Declaration Перейти до оголошення Find Usages Знайти вживання Rename Symbol Under Cursor Перейменувати символ під курсором %1 (Module/GOPATH) with GOROOT Stop Зупинити Go Source Query SourceQuery What Callees Callers Callstack Definition Визначення Describe Freevars Implements Implements(GOPATH) Peers Referrers Pointsto Whicherrs Add Tags To Struct Field Remove Tags From Struct Field Refactor Рефакторинг SourceQuery Below files in package %1 GolangEditOption Form Форма Mouse Миша Go root source file editor setup read only Enable view expression infomation on mouse Показувати інформацію про вираз при наведенні миші Enable mouse navigation Включити навігацію мишею GolangFileSearch Golang Find Usages Golang Знайти використання GolangFmtOption Form Форма Format Options Golang Format Параметри форматування Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Goimports оновлює декларації імпорту Go, додаючи пропущені і видаляючи непотрібні. Enable update imports line, adding missing ones and removing unreferenced ones. Оновлювати оголошення імпорту: додавати відсутні та видаляти невикористовувані. Synchronous Синхронність Synchronous code formatting Synchronous code formatting Синхронне форматування коду Synchronous code formatting timeout in milliseconds (500ms or more): Затримка синхронного форматування коду в мілісекундах (500 мс чи більше): Automatically format code when saving When the editor is saved automatically gofmt Автоматично форматувати код при збереженні GolangFmtPlugin Format Code Format Code (goimports) Форматувати код Format Code (Adjusts Imports) Форматувати код (підправляти import'и) GolangPackageOption Choose directory to add to GOPATH: Додати обрану директорію в GOPATH: Manage GOPATH / Modules Управляти GOPATH Go Modules Custom GONOPROXY Custom GOPROXY Custom GO111MODULE Custom GONOSUMDB Custom GOPRIVATE TextLabel GOPATH Use System GOPATH Reload Перезавантажити Use Custom GOPATH (one per line) Add Directory... Додати директорію... Clear GolangPresentEdit Section (s1) Розділ (s1) Subsection (s2) Підрозділ (s2) Sub-subsection (s3) Під-підрозділ (s2) Bold Напівжирний Italic Курсив Inline Code Програмний код Switch Bullets Список Comment/Uncomment Selection Коментувати/розкоментувати виділення Export HTML Експортувати HTML Verify Present Перевірити презентацію Present verify success Перевірка презентації пройшла успішно Present verify false Перевірка презентації завершилася невдало Export PDF Експортувати в PDF GolangSymbol Quick Open Symbol by Name Відкрити символ за іменем GoplayBrowser Go Playground Ігровий майданчик Go Run Виконати Stop Зупинити New Новий Load... Завантажити... Save... Зберегти... Explore Folder Відкрити директорію в файловому менеджері Running... Running... Виконується... Error: %1. Error: %1. Помилка: %1. Success: %2. Success: %2. Успішно: %2. Load File Завантажити файл Select a file to load: Оберіть файл для завантаження: Save File Зберегти файл New File Name: Назва нового файлу: HtmlPreview Page Style Стиль сторінки Reload Перезавантажити Export Html Експорт HTML Export PDF Експортувати в PDF Print Preview Попередній перегляд друку Synchronize preview and code scrollbars Синхронізувати гортання перегляду та коду Config Конфігурація Plain HTML Чистий HTML Export Failed Експорт не виконано Automatically display preview Automatically Display Preview Автоматично показувати перегляд HTML Preview Html Preview Попередній перегляд HTML Could not open %1 for writing! Can not write file %1 Неможливо відкрити %1 для запису! ImageEditor ZoomIn ZoomOut Reset to original size Fit to view Play movie Prev frame Next frame Pause movie ImageEditorFactory Image Viewer ImportPkgTip warning, pkg not find, please enter to import : увага, пакунок не знайдено, будь ласка введіть для імпорту: JsonEdit Verify Перевірити Format Json Форматувати Json Compact Json Мінімізувати Json LiteApp Event Log Журнал подій Escape Escape Close File Закрити файл Close All Files Закрити всі файли Save File Зберегти файл Save File As... Зберегти файл як... Save All Files Зберегти всі файли Open Project Відкрити проект... Options Параметри New... Новий... Open File... Відкрити файл... Open Folder... Відкрити директорію... Open Folder in New Window... Відкрити директорію у новому вікні... Close All Folders Add Folder... Закрити всі директорії New Window Нове вікно Close Window Закрити вікно Save Project Зберегти проект Close Project Закрити проект Exit Вийти Full Screen На повний екран About LiteIDE Про LiteIDE About Plugins Про розширення LiteAppOption Form Форма Store [*] Store Зберігання [*] Language: Мова: Icon [*] Піктограма [*] Reload files in session Перезавантажувати файли з сесії Recent Files Recent File Нещодавні файли Max Count: Max Recent: Максимальна кількість: Monitoring files for modifications Відслідковувати зовнішні зміни файлів Store settings to local ini file Зберігати параметри в локальному ini-файлі Interface [*] Інтерфейс [*] Style: Стиль: Use tool window shortcuts Використовувати скорочення для панелей Theme [*] Тема [*] Fallback build-in icon library and liteapp/qrc/default Вбудована бібліотека піктограм та liteapp/qrc/default стають резервними Load the external file icon library Load custome icon from liteapp/qrc folder Використовувати зовнішню бібліотеку піктограм Automatically save documents Автоматично зберігати документи Automatically save documents when application is idle Автоматично зберігати документи, коли додаток неактивний sec сек Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. Автоматично перезавантажувати чи закривати редактор, якщо файл змінено/видалено. Session Сесія 0-99 Editor Tabs Вкладки редактора 10-999 Display Зовнішній вигляд Display [*] Вид [*] Show splash screen on startup Показувати заставку на старті Show welcome page on startup Показувати сторінку привітання на старті Editor Редактор Editor tab [*] Вкладки редактора [*] Show close buttons on each editor tab Показувати кнопку закриття на кожній вкладці редактора Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab Використовувати перемикання вкладок колесом миші Toolbar Icon Size [*] Розмір іконок пеналів [*] Editor navigate Навігація редактором Enable mouse extra 'Back' button and 'Forward' button for go back and forward Використовувати додаткові кнопки миші "Назад" та "Вперед" для навігації Keyboard Клавіатура Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Формат: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands Приховати стандартні команди Reset Скинути Reset All Скинути все Import... Імпорт... Export... Експорт... Generic Загальні Theme: Тема: Reload session on startup Auto load last session Завантажувати останню сессію при старті SideBarStyle Стиль бічної панелі SplitterStyle Стиль розділювача Command Команда Label Назва Shortcuts Комбінації клавіш NativeText Standard Стандартна Import Keyboard Mapping Scheme Імпорт комбінацій клавіатури Keyboard Mapping Scheme (%1) Файл комбінацій клавіатури (%1) Could not read scheme from %1! Не вдалося прочитати комбінації з %1! Export Keyboard Mapping Scheme Експорт комбінацій клавіатури Could not write scheme to %1! Помилка запису комбінацій в %1! LiteBuild Build Toolbar Панель збірки Build Configuration... Build Config Параметри збирання... Stop Action Зупинити Clear Output Clear All Очистити журнал Execute File Виконати файл Debug File Зневадження файлу Lock Build Path Lock Go Build Path Build Path Configuration Go Build Configuration Налаштування шляху збирання Use godoc View Відкрити Godoc Line Wrap Перенос рядків Auto Clear Автоматично очищати Automatic positioning cursor Автоматично переносити курсор Setup Настройка Build Output Build Результати збирання Current environment change id "%1" Ідентифікатор конфігурації "%1" Lock Build Lock Build: %1 Замкнути збірку Error: %1. Error: %1. Помилка: %1. Command exited with code %1. Команда завершилась із кодом %1. Success: %1. Success: %1. Все ок: %1. A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. Процес вже виконується. Потрібно його перервати (меню Збірка/Перервати). Killing current process... Killing current process... Зупиняємо поточний процес... Failed to terminate the existing process! Failed to terminate the existing process! Не вдалося зупинити існуючий процес! Started process successfully Started process successfully Процесс запущено успішно Failed to start process Не вдалося запустити процес LiteBuildOption Form Форма Recheck Go installation when changing environments Recheck go env if enviroment changed Перевірити інсталляцію Go після зміни конфігурації оточення Build command configuration files [*] Build command configuration files: Файли конфігурації команд збирання [*] LiteBuildPlugin Close Закрити Execute: Exec: Виконати: Execute File Execute Виконати файл LiteDebug Stop Зупинити Clear Очистити вивід Continue Продовжити Show Current Line Показати точку виконання Debug Output Debug Відлагодження Start Debugging External Application... Start Debugging External Application Зневадження зовнішньої програми... Close Закрити Start Debugging Почати зневадження Step Into Крок із заходом Step Over Крок із обходом Step Out Крок із виходом Run to Line Виконати до позиції курсору Insert/Remove Breakpoint Вставити/Видалити точку зупинки Remove All Breakpoints Видалити всі точки зупинки LiteDebugOption Form Форма Debug Зневадження Automatically insert breakpoint main.main when debugging Automatically add breakpoint main.main when debugging Автоматично додавати точку зупинки в main.main під час зневадження LiteDebugPlugin Debug Window Debug Вікно зневадження LiteDoc LiteIDE Documentation LiteIDE Document Browser Документація LiteIDE LiteEditor Undo Скасувати Redo Повторити Cut Вирізати Copy Копіювати Paste Вставити Select All Виділити все Go to Doc Start Перейти до початку документу Go to Doc End Перейти в кінець документу Go to Line Start Перейти на початок рядка Go to Line End Перейти в кінець рядка Go to Previous Line Перейти до попереднього рядка Go to Next Line Перейти до наступного рядка Go to Previous Character Перейти до попереднього символа Go to Next Charater Перейти до наступного символа Go to Previous Word Перейти до попереднього слова Go to Next Word Перейти до наступного слова Go to Line Перейти до рядка File is readonly Файл тільки для читання File is writable Файл доступний на запис Line Wrap (MimeType) Word Wrap (MimeType) Перенесення тексту Toggle Comment Закоментувати/розкоментувати Toggle Block Commnet Закоментувати/розкоментувати блок Auto-indent Selection Автовідступи у виділеному тексті Tab To Spaces (MimeType) Табуляцію замінити на пробіли Line End Windows (\r\n) Кінці рядків Windows (\r\n) Line End Unix (\n) Кінці рядків Unix (\n) Visualize Whitespace (Global) Візуалізувати пробіли Move Line Up Пересунути рядок угору Move Line Down Пересунути рядок вниз Copy Line Up Копіювати рядок угору Copy Line Down Копіювати рядок вниз Join Lines Об'єднати рядки Title Case Як у реченні Upper Case ВЕРХНІЙ РЕГІСТР Lower Case нижній регістр Swap Case Змінити на зворотній Tab To Spaces Табуляцію в пробіли Spaces To Tab Пробіли в табуляцію Advanced Додатково Goto Перейти Convert Tab Перетворити табуляцію Code Folding Згортання коду Convert Case Змінити регістр Export HTML Експортувати HTML Export Failed Експорт завершився невдало Could not open %1 for writing. Не вдалося відкрити %1 для запису. Export PDF Експорт в PDF Print Document Друк документу Print Preview... Print Preview Document Перегляд перед друком... Export HTML... Експортувати HTML... Export PDF... Експортувати PDF... Print... Друк... Go to Previous Block Go To Previous Block Перейти до попереднього блоку Select Block Вибрати блок Go to Matching Brace Go To Matching Brace Перейти до відповідної фігурної дужки Fold Згорнути Unfold Розгорнути Fold All Згорнути все Unfold All Розгорнути все Go To Line Goto Line Перейти до рядка Duplicate Дублювати Delete Line Видалити рядок Copy Line Копіювати рядок Cut Line Вирізати рядок Insert Line Before Вставити пустий рядок перед поточним Insert Line After Вставити пустий рядок після поточного Increase Font Size Збільшити розмір шрифту Decrease Font Size Зменшити розмір шрифту Reset Font Size Відновити розмір шрифту Clean Whitespace Очистити пробіли Code Complete Доповнити Settings File Setup Налаштування Reload File Перезавантажити файл Do you want to permanently discard unsaved modifications and reload %1? Перезавантажити %1 та відкинути незбережені зміни? Go to Next Block Go To Next Block Перейти до наступного блоку ReadOnly Тільки для читання Line: Рядок: LiteEditorFileFactory Text Editor LiteEditorOption Form Форма Load File Завантаження файлу Check and convert no printable char to '.' Перевіряти та перетворювати символи, що не відображаються, в '.' Font Шрифт Font && Colors Шрифти та Кольори Family: Сімейство: Show Monospace Font Показувати моноширинні шрифти Size: Розмір: Zoom: Масштаб: % Antialias Згладжування Restore Default Font Встановити типовий шрифт Editor Color Scheme ColorStyle Scheme Колірна схема редактора File: Файл: Edit Редагувати Syntax Auto-completion Auto complete brackets Автоматичне додавання парних символів Fuzzy code completion Нечітке доповнення коду Clean completion cache when saving files Очищати кеш автодоповнення при збереженні файлів Clean whitespace when saving files Видаляти надлишкові пробіли при збереженні файлів Enable scroll wheel zooming Включити масштабування колесом миші Add copied text into the clipboard as HTML Додавати копійований текст до буфера обміну як HTML Allow vertical scrolling to the last line [*] Дозволяти вертикальне гортання до останнього рядка [*] Display VisualizeWhitespace Показувати візуалізацію пробілів Word wrap by default Переносити рядки по словах Display code fold Показувати згортання коду Display offset position Показувати позицію в файлі File Types Типи файлів Behavior Поведінка Display EOF Показувати символ кінця файлу (EOF) Display line numbers Показувати номера рядків Display indent guide Display indent guide Показувати відступи Display right margin at column Показувати праву межу в стовпці Automatic indentation Enable automatic indentation Увімкнути автоматичні відступи Case sensitive code completion Completer case sensitive Доповнювати код із врахуванням регістру Code completion prefix length: Word Complete Prefix Length Довжина префіксу для автодоповнення: Display Вигляд MIME Type Типи MIME Tab Width Ширина табуляції Tab To Spaces Табуляцію в пробіли File Extensions Розширення файлів Custom Extensions Нетипові розширення LiteEditorPlugin Edit ToolBar Панель редактора Edit Navigation Bar Панель навігації редактора LiteEnvOption Form Форма Environment definition files: Файли визначення оточення: Environment changes will take effect after switching environments. Зміни до оточення будуть застосовані після перемикання оточень. LiteFindPlugin Find Знайти Find Next Знайти наступне Find Previous Знайти попереднє Replace Замінити File Search Пошук в файлах LiteTabWidget Open a new tab Відкрити нову вкладку List All Tabs Перелік вкладок Close Tab Закрити вкладку MarkdownBatchBrowser Markdown Exporter Markdown Batch Експортер формату Markdown All Files (*) Всі файли (*) Select the folder containing your markdown files: Select Markdown Folder Оберіть директорію з Markdown-файлами: Select Markdown Files Вибрати Markdown-файли Select the folder to contain separated markdown exports: Виберіть директорію для збереження окремих експортів Markdown: Export Merged HTML Export Html Експортувати об'єднаний HTML Export Merged PDF Export PDF Експортувати об'єднаний PDF MarkdownBatchWidget Form Форма Markdown Source Files Markdown Files Вихідні файли Markdown Import Folder... Import Folder Імпортувати директорію... Add Files... Add Files Додати файли... Move Up Посунути вгору Move Down Посунути донизу Remove Видалити Remove All Видалити все Options Параметри Export Folder: Директорія експорту: Browse... Browser Огляд... Use CSS Використовувати CSS Insert horizontal line between merged files Merge files insert split <hr> Вставляти горизонтальні лінії між об'єднаними файлами Insert page break between merged files Merge files insert page break Вставляти переходи на нову сторінку в об'єднаних файлах Export Export Util Експорт Export Separated HTML Separate Html Експортувати окремі HTML Export Separated PDF Separate PDF Експортувати окремі PDF Export Merged HTML... Merge Html Експортувати об'єднаний HTML... Export Merged PDF... Merge PDF Експортувати об'єднаний PDF... Print Preview Merged... Merge Print Preview Перегляд перед друком... Print Merged Merge Print Друк об'єднаного Log Журнал MarkdownEdit Header (h1) Header <h1> Заголовок (h1) Header (h2) Header <h2> Заголовок (h2) Header (h3) Header <h3> Заголовок (h3) Header (h4) Header <h4> Заголовок (h4) Header (h5) Header <h5> Заголовок (h5) Header (h6) Header <h6> Заголовок (h6) Bold Жирний Italic Курсив Inline Code Рядковий код Link Посилання Image Зображення Unordered List Список з позначками Ordered List Нумерований список Blockquote Цитата Horizontal Rule Горизонтальна лінія Heading Заголовок MultiFolderView Delete Folder Видалити директорію Are you sure that you want to permanently delete this folder and all of its contents? Видалити цю директорію разом із її вмістом назавжди? Failed to delete the folder! Не вдалося видалити директорію! Delete File Видалити файл Are you sure that you want to permanently delete this file? Видалити цей файл назавжди? Failed to delete the file! Не вдалося видалити файл! NavigateBar Browser Files in %1 Переглянути файли в %1 NewFileDialog New Project or File Новий проект чи файл Browse... Відкрити... GOPATH: GOPATH: Template: Template Шаблон: Type Тип Information Інформація Name: Назва: Location: Локація: Error Помилка Could not create the target directory: %1 Не можу створити цільову директорію: %1 Warning Попередження Location %1 is not empty. Use the target directory anyway? %1 не порожня. Все одно використовувати цю директорію? Overwrite File Перезаписати файл %1 already exists. Do you want to replace it? %1 вже існує. Замінити? No files could be created. Не вдалося створити жодного файлу. File template details: Деталі шаблону: Project template details: New project wizard: Шаблон нового проекту: Choose a directory for the new content: Вибрати директорію для нового вмісту: OpenEditorsWidget Open Documents Відкриті документи OptionsBrowser Options Options Page Параметри OptionsWidget Options Параметри Info Інформація [*] item request restart of LiteIDE [*] item requeset restart LiteIDE [*] - вимагає перезапуску LiteIDE OutputDockWidget Move To Пересунути в LeftSideBar RightSideBar BottomDockWidget OutputOption Form Форма Font Шрифт Family: Сімейство: Size: Розмір: Zoom: Масштаб: % Antialias Згладжування Display Вигляд Use editor color scheme Використовувати кольорову схему редактора Sets the maximum number of lines Максимальне число рядків: PackageBrowser Manage GOPATH/Modules ... Manage GOPATH... Управляти GOPATH... Reload All Перезавантажити все Use godoc View Відкрити Godoc Load Package in New Window Завантажити пакет в новому вікні Add Package to Folders Додати пакет в директорії Open Source File Відкрити файл коду Copy Name to Clipboard Copy Name To Clipboard Скопіювати ім`я до буферу обміну Go Package Browser Package Browser Перегляд пакетів Loading Go package list... Loading go package ... Завантажую список пакетів Go... PackageProject Reload Package Перезавантажити пакунок Open Explorer Here Відкрити в файловому менеджері Add Source File Додати вихідний файл File Name: Ім'я файлу: Error Помилка File %1 already exists. Файл %1 вже існує. Could not open %1 for writing. Неможливо відкрити %1 для запису. PluginsDialog Installed Plugins Install Plugins Встановлені додатки Close Закрити Name Назва Author Anchor Автор Enabled Включено Details Деталі Version Last Ver Версія File Name FileName Им'я файлу ProcessEx process exited with code %1 процес завершився із кодом %1 process crashed or was terminated процес завершився аварійно чи був завершений іззовні process exited with an unknown status процес завершився із невідомим статусом process failed to start процес не вдалося запустити process crashed or was terminated while running процес завершився аварійно чи був завершений іззовні під час виконання timed out waiting for process вийшов тамйм очікування процесу couldn't read from the process не вдалося прочитати з процесу couldn't write to the process не вдалося записати в процес an unknown error occurred сталася невідома помилка ProjectManager Project <%1> Проект <%1> Import Directory <%1> Імпортувати директорію <%1> QFileSystemModel %1 TB %1 ТБ %1 GB %1 ГБ %1 MB %1 МБ %1 KB %1 КБ %1 bytes %1 байт(ів) QJson::ParserRunnable An error occurred while parsing json: %1 Помилка розбору JSON: %1 QJsonParseError no error occurred помилки відсутні unterminated object незавершений об'єкт missing name separator unterminated array незавершений масив missing value separator illegal value недопустиме значення invalid termination by number illegal number недопустиме число invalid escape sequence недопустима управляюча послідовність invalid UTF8 string недопустимий рядок UTF8 unterminated string незавершений рядок object is missing after a comma відсутній об'єкт після коми too deeply nested document документ має надмірну вкладеність too large document занадто великий документ garbage at the end of the document мотлох в кінці документу QuickOpenAction Show and Run Commands Показ та виконання команд QuickOpenEditor Show All Opened Editors Show All Editors Список відкритих редакторів QuickOpenFileSystem File System Файлова система QuickOpenFiles Go to File Перейти до файлу Type '?' to get help on the actions you can take from here Напишіть '?' для отримання довідки з доступних дій QuickOpenFolder Browser Folder Перегляд директорій QuickOpenHelp Show All Quick Open Actions Show Quick Open Help Показати всі дії Quick Open QuickOpenLines Go to Line Перейти до рядка Open a text file first to go to a line Спершу відкрийте файл для переходу до рядка Type a line number between %1 and %2 to navigate to Вкажіть номер рядка між %1 та %2 для переходу Go to Line %1 Go to line %1 Перейти до рядка %1 QuickOpenManager Quick Open File Quick Open Файли Quick Open Editor Quick Open Редактори Quick Open Symbol Quick Open Символи Quick Open Command Quick Open Команди Show All Quick Open Actions Показати всі дії Quick Open QuickOpenMimeType Go to Symbol in File Open Symbol by Name Перейти до символа у файлі not found symbol символ не знайдено QuickOpenOption Form Форма QuickOpenFiles Quick Open Файли Match case sensitive Враховувати регістр Max files count: Максимальне число файлів: QuickOpenEditor Quick Open Редактори RecentManager Clear All History Очистити всю історію Clear Menu Очистити меню SearchEdit Search Пошук Stop Search Зупинити пошук SelectExternalDialog Debug External Application Відлагодження зовнішньої програми Application: Програма: Browse... Browser Відкрити... Arguments: Аргументи: Working directory: Робоча директорія: Select Executable Вибрати програму Select the working directory: Select Working Directory Оберіть робочу директорію: SessionRecent Sessions Сесії SideDockWidget Move To Перемістити в RightSideBar LeftDockWidgt LeftSideBar RightDockWidget OutputBar SideBar Бічна панель Show SideBar Показувати бічну панель SideWindowStyle Hide SideBar Приховати бічну панель SideBar Windows Вікна бічної панелі Output Windows Вікна виводу? Вікна виведення SplitDockWidget Move To Перемістити в Top Верх Top (Split) Верх (розділити) TopDockWidget (Split) TopDockWidget Bottom Низ Bottom (Split) Низ (розділити) BottomDockWidget (Split) BottomDockWidget Left Ліво Left (Split) Ліво (розділити) LeftDockWidget (Split) LeftDockWidget Right Право Right (Split) Право (розділити) RightDockWidget (Split) RightDockWidget Unsplit Не розділяти Split Розділити SplitWindowStyle Hide Sidebars Приховати бічні панелі Tool Windows Панелі інструментів Terminal New Open a new terminal Close Закрити Close current terminal CloseAll Close all terminal LoadEnv Current terminal load environment from LiteIDE Filter Dark Mode Login Mode (shell --login) Terminal Термінал Rename Tab Title TerminalEdit Cut Вирізати Copy Копіювати Paste Вставити Select All Виділити все Clear All Очистити все TextEditor::Internal::ColorScheme Not a color scheme file. Файл не є схемою кольору. Utils::FilterLineEdit Filter Фільтрувати Clear text Очистити фільтр VTermWidget Copy Копіювати Paste Вставити Select All Виділити все WebKitBrowser Navigation Навігація Open Html File Open Html Відкрити HTML файл WebKitBrowser Переглядач WebKit False load %1 ! Не вдалося завантажити %1! Open Html or Markdown File Open Html or Markdown Files Відкрити файл з HTML або Markdown WebKitHtmlWidgetPlugin Open Html or Markdown File Open Html or Markdown Files Відкрити файл з HTML або Markdown WelcomeBrowser New Створити Open Відкрити Open Folder Відкрити директорію Options Параметри Welcome Welcome Page Ласкаво просимо WelcomePlugin Welcome Home Ласкаво просимо ================================================ FILE: liteidex/liteide_zh.ts ================================================ AboutDialog About LiteIDE About Liteide 关于 LiteIDE Information Infomation 信息 Welcome: 欢迎: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. 欢迎使用 LiteIDE X! LiteIDE是一个轻量级的开源跨平台IDE. Project: 项目: Name: 名称: Author: 作者: Version: 版本: Build: 编译: Based on Qt Based on Qt Version 基于 Qt Source Code: 源代码: Support LiteIDE: Support 支持LiteIDE: Developers 开发者 Translations 翻译 Chinese 中文 Japanese 日文 Russian 俄文 French 法文 Traditional Chinese 繁体中文 German 德文 Ukrainian 乌克兰文 Thanks to... 感谢... License 许可协议 Close 关闭 Based on Qt %1 (%2 bit) 基于 Qt %1 (%2 位) ActionManager &File 文件(&F) &Recent 历史(&R) &Edit 编辑(&E) F&ind &Find 查找(&I) &View 查看(&V) &Tools 工具(&T) &Build 编译(&B) &Debug 调试(&D) &Help 帮助(&H) Standard Toolbar Standard ToolBar 标准工具栏 AstWidget Go To Definition 跳转到声明 View Import Document 查看Import文档 BaseDockWidget Hide 隐藏 Hide Tool Window 隐藏工具窗口 Floating Window 浮动窗口 BaseFolderView Open In New Window 在新窗口打开 Open File 打开文件 New File... 新建文件... New File Wizard... 新建文件向导... Rename File... 重命名文件... Delete File 删除文件 New Folder... 新建目录... Rename Folder... 重命名目录... Delete Folder 删除目录 Open Terminal Here 在此打开终端 Show in Explorer Open Explorer Here 在资源管理器中显示 Open Application 运行应用程序 Show in Finder 在Finder中显示 Show Containing Folder 显示包含文件夹 Open Command Prompt Here 在此打开命令提示符 Open in Integrated Terminal 打开集成终端 Open Folder... Add Folder... 打开目录... Reload Folder 重新读取目录 Close Folder 关闭目录 Close All Folders 关闭所有目录 Copy 复制 Paste 粘贴 Copy Path 复制路径 Move To Trash 移动到回收站 Create File 建立文件 A file with that name already exists! 文件已存在! Failed to create the file! 建立文件失败! Rename File 文件更名 New Name: 新名称: Failed to rename the file! 重命名文件失败! An item "%1" already exists in this location. Do you want to replace it and move old item to trash? 项目 "%1" 本地已存在,确定替换并将旧项目移到到回收站? Stop 停止 Keep Both 保持两者 Keep Both All 全部保留两者 Replace 替换 Replace All 替换所有 Are you sure that you want move to trash this item? 确定移动项目到回收站? Are you sure that you want move to trash %1 items? 确定移动 %1 个项目到回收站? Move to Trash 移动到回收站 Open With 用...打开 System Editor 系统编辑器 Create Folder 建立目录 A folder with that name already exists! 目录名已存在! Failed to create the folder! 建立目录失败! Rename Folder 目录更名 Folder Name 目录名 Failed to rename the folder! 重命名目录失败! Are you sure that you want to permanently delete this folder and all of its contents? 您确定要删除此文件夹及所有内容? Failed to delete the folder! 删除目录失败! BookmarkManager Toggle Bookmark 切换书签 Goto bookmark 跳转书签 Remove bookmark 删除书签 Remove all bookmarks for this file 删除这个文件的全部书签 Remove all bookmarks for all files 删除全部书签 Bookmarks 书签 BookmarkRecent Bookmarks 书签 BuildConfigDialog Build Configuration Build Config Dialog 编译配置 Build ID 编译 ID Build Path Build File 编译目录 GOPATH GOPATH information GOPATH 信息 Use Custom GOPATH for Build Path 编译目录使用自定义 GOPATH Inherit System GOPATH 继承 系统 GOPATH Inherit LiteIDE GOPATH 继承 LiteIDE GOPATH Custom GOPATH (one per line) 自定义 GOPATH (每行一个) Add Directory... 添加目录... Clear 清除 LiteIDE LiteIDE Config 配置 Action 动作 Custom Build Custom 自定义 Reset all to initial value 全部重置为初始值 Name 名称 Value SharedValue 共享值 Id Cmd 命令 Choose directory to add to GOPATH: 选择目录添加到 GOPATH: CreateDirDialog Create Folder 建立目录 Directory: 当前目录: Dir Name: 目录名: Create 新建 Cancel 取消 CreateFileDialog Create File Create File Dialog 新建文件 Directory: 当前目录: File Name: 文件名称: Create 新建 Create and Edit 新建并编辑 Cancel 取消 DebugWidget Add Watch 添加监视 Async Record AsyncRecord 同步记录 Variables 变量 Watch 监视 Call Stack CallStack 调用堆栈 Threads Goroutines Registers Libraries Library 动态库 Console 控制台 Watch expression (e.g. buf main.var os.Stdout): Remove Watch 移除监视 Remove All Watches 移除所有监视 DlvDebuggerOption Form delve debug pass flags: (example --check-go-version=false) delve debug pass flags:(示例 --check go version=false) DocumentBrowser Back Backward 返回 Forward 前进 Reload 刷新 Increase Font Size 增大字号 Decrease Font Size 减小字号 Reset Font Size 重置字号 DocumentBrowserFactory DocumentBrowser 文档浏览器 EditorManager Close 关闭 Move to New Window Move To New Window 移动到新窗口 Navigate Forward GoForward 前进 Close Others Close Others Tabs 关闭其他标签 Open Editor 打开文档 Close All Close All Tabs 关闭所有标签 Close Left Tabs 关闭左侧所有标签 Close Right Tabs 关闭右侧所有标签 Close Files in Same Folder Close Same Folder Files 关闭相同目录文件 Close Files in Other Folders Close Other Folder Files 关闭其他目录文件 Copy Full Path to Clipboard Copy Path to Clipboard 复制完整路径到剪贴板 Show in Explorer 在资源管理器中显示 Show in Finder 在Finder中显示 Show Containing Folder 显示包含文件夹 Open Command Prompt Here 在此打开命令提示符 Open Terminal Here 在此打开终端 Open in Integrated Terminal 打开集成终端 Navigate Backward 返回 Save changes to %1? 保存修改到 %1 ? Unsaved Modifications Save Modify 未保存修改 All Files (*) 所有文件(*) Save As 另存为 EnvManager Environment Toolbar Environment ToolBar 环境工具栏 Switching current environment Switch Current Environment 切换当前环境 Edit current environment Edit Current Environment 编辑当前环境 Reload current environment Reload Current Environment 重新加载当前环境 Select Environment 选择环境 ExportDialog Dialog 对话框 Name: 名称: Export 导出 ExportAndView 导出并查看 FakeVim::Internal Use Vim-style Editing 使用Vim样式编辑 Read .vimrc Path to .vimrc FakeVim::Internal::FakeVimHandler Unknown option: %1 Argument must be positive: %1=%2 Mark "%1" not set. %1%2% %1All Not implemented in FakeVim. Unknown option: Invalid argument: Trailing characters: Move lines into themselves. %n lines moved. File "%1" exists (add ! to override) Cannot open file "%1" for writing "%1" %2 %3L, %4C written. Cannot open file "%1" for reading "%1" %2L, %3C %n lines filtered. Cannot open file %1 Invalid regular expression: %1 Pattern not found: %1 Search hit BOTTOM, continuing at TOP. Search hit TOP, continuing at BOTTOM. Search hit BOTTOM without match for: %1 Search hit TOP without match for: %1 %n lines indented. %n lines %1ed %2 time. %n lines yanked. Already at oldest change. Already at newest change. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Type Alt-V, Alt-V to quit FakeVim mode. [New] Not an editor command: %1 FakeVimEdit Use FakeVim Editing 使用FakeVim编辑 FakeVimEditOption Form FakeVim initialization command list (# start is comment): FakeVim 初始命令列表(以#开始行为注释): Load default init command list 加载默认的初始化命令列表 FiFoTty Cannot create temporary file: %1 无法建立临时文件: %1 Cannot create FiFo %1: %2 无法建立FiFo %1: %2 Cannot open FiFo %1: %2 无法打开 FiFo %1: %2 FileBrowser Synchronize with editor 与编辑器同步 Show Hidden Files 显示隐藏文件 Set As Root Folder Set Folder To Root 设置为顶层目录 Execute File 执行文件 Reload Folder 重新读取目录 Show Details 显示详细信息 Debug File 调试文件 Open Folder in New Window 在新窗口打开目录 Add to Folders 添加到目录列表 Open Parent Open to Parent 打开上级目录 Filter 过滤 File System 文件系统 FileBrowserOption Form Terminal 终端 Command: 命令: Arguments: 参数: FileManager All Files (*) 所有文件(*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? 项目文件 '%1'已建立,是否加载? Open Project or File 打开项目或文件 Show Hidden Files 显示隐藏文件 Show Details 显示详细信息 Synchronize with editor 与编辑器同步 Split Mode 分离模式 Filter 过滤 Folders Folers 目录 All Support Files (%1) 所有支持文件(%1) Select a folder: Open Folder 选择目录: %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 文件在磁盘上已经被删除,但LiteIDE上有您的未保存修改。 您想要关闭编辑器? 回答“是”将放弃您的未保存修改。 %1 This file has been deleted from the drive. Do you want to close the editor? %1 文件在磁盘上已经被删除。 您想要关闭编辑器? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 文件已经在磁盘上已经被改变,但LiteIDE上有您的未保存修改。 您想要重新从磁盘读取? 回答“是”将放弃您的未保存修改。 %1 This file has been modified on the drive. Do you want to reload the file from disk? %1 文件已经在磁盘上已经被改变。 您想要重新从磁盘读取? Open Files 打开文件 Open Project 打开项目 LiteIDE X FileRecent Files 文件 FileSearch Match whole word Match word 全词匹配 Match case 区分大小写 Regular expression 使用正则表达式 Scan subdirectories Look in subdirs 搜索子目录 Search for: 搜索内容: Options: 选项: Browse... Browser 浏览... Filter: 过滤: Files on File System 文件系统中的文件 Search 搜索 Cancel 取消 Current Folder 当前目录 Auto Switch 自动切换 Clear 清除 Open Directory 打开目录 FileSearchManager Search Item: 搜索项目: Only golang file changes can be revert! This file change cannot be undone! 只有Golang文件修改可以恢复! New Search 新搜索 File Search 文件搜索 Search Result 搜索结果 LiteIDE X Warning! Replace text is empty. Want to remove all the search items? 警告!替换文本为空 想要删除所有搜索到的项目? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? 警告!替换文本为空白字符 想要替换所有搜索到的项目为空白? The following files have no write permissions. Do you want to change the permissions? 下面的文件没有可写权限,你想要更改可写权限? File is readonly 文件只读 FileSystemWidget Open File Open Editor 打开文件 New File... New File 新建文件... New File Wizard... New File Wizard 新建文件向导... Rename File 文件更名 Delete File Remove File 删除文件 New Folder... New Folder 新建目录... Are you sure that you want to permanently delete this file? 您确定要永久删除这个文件? Rename Folder 目录更名 Delete Folder Remove Folder 删除目录 Rename File... 重命名文件... Rename Folder... 重命名目录... Open Terminal Here 打开终端 Open Explorer Here 打开目录浏览 View Godoc Here 查看GODOC Add Folder 添加目录 Close Folder 关闭目录 Add Folder... 添加目录... Close All Folders 关闭所有目录 Create File 建立文件 A file with that name already exists! The file already exists! 文件已存在! Failed to create the file! 建立文件失败! New Name: 新名称: Failed to rename the file! 重命名文件失败! Are you sure that you want to permanently delete this folder and all of its contents? 您确定要删除此文件夹及所有内容? Failed to delete the file! Failed to remove the file! 删除文件失败! Create Folder 建立目录 A folder with that name already exists! The folder name is exists! 目录名已存在! Failed to create the folder! 建立目录失败! Folder Name 目录名 Failed to rename the folder! 重命名目录失败! Failed to delete the folder! Failed to remove the folder! 删除目录失败! Find::Internal::SearchResultWidget Search was canceled. 搜索已取消. Cancel 取消 Repeat the search with same parameters 使用相同参数重新搜索 Search again 重新搜索 Set show replace mode ui 设置为替换模式 Show Replace 显示替换 Replace with: 替换为: Replace all occurrences 替换所有出现位置 Replace 替换 Preserve case 保留大小写 Expand all items 展开所有项目 Collapse all items 折叠所有项目 Revert with: 恢复为: Revert 恢复 Revert all occurrences 恢复所有出现位置 %n matches replaced. %n 个匹配被替换. searching... %n matches found. 搜索中... 找到 %n 个匹配. searching ... 搜索中... No matches found. 未找到匹配. %n matches found. 找到 %n 个匹配. FindApiEdit Search 搜索 Stop Search 中止搜索 FindApiWidget Search 搜索 Find 查找 FindDocWidget Search 搜索 Find 查找 Find All 查找所有 Find const 查找 const Find func 查找 func Find interface 查找 interface Find pkg 查找 pkg Find struct 查找 struct Find type 查找 type Find var 查找 var Use Regexp 使用正则 Match Case 区分大小写 Match Word 全词匹配 Help 帮助 FindEditor Match case 区分大小写 Regular expression 使用正则表达式 Wrap around 全文环绕 Find Next 查找下一个 Find Previous Find Prev 查找上一个 Replace With: 替换: Replace 替换 Replace All 替换所有 Match whole word only 全词匹配 Ready 准备 Close 关闭 Show Replace 显示替换 Find What: 查找: Options: Find Option: 选项: Not found 没有找到 FolderListView Delete File 删除文件 Are you sure that you want to permanently delete this file? 您确定要永久删除这个文件? Failed to delete the file! 删除文件失败! Delete Folder 删除目录 Are you sure that you want to permanently delete this folder and all of its contents? 您确定要删除此文件夹及所有内容? Failed to delete the folder! 删除目录失败! FolderRecent Folders 目录 FolderView Delete File 删除文件 Are you sure that you want to permanently delete this file? 您确定要永久删除这个文件? Failed to delete the file! 删除文件失败! Delete Folder 删除目录 Are you sure that you want to permanently delete this folder and all of its contents? 您确定要删除此文件夹及所有内容? Failed to delete the folder! 删除目录失败! GdbDebuggerOption Form Enable --tty for program being debugged. 使用 --tty 参数调试程序. GoAddTagsDialog Add Tags To Struct Field 添加 Tags 到结构体字段 Add JSON Tag 添加 JSON Tag Options 选项 Multiple options separated by commas Multiple options are separated by commas 多个选项之间使用逗号分隔 Add XML Tag 添加 XML Tag Add Custom Tags 添加自定义 Tags Tag Name Tag 名称 Setup custom tag name 设置自定义 tag 名称 Sort sorts the tags in increasing order according to the key name 设置多个 tags 根据键名称按升序重新排列 Override current tags when adding tags 设置添加标签时覆盖当前标签 Info 信息 GoRemoveTagsDialog Remove Tags From Struct Field 从结构体字段删除 Tags Remove Tags And Options 删除 Tags 和选项 Clear All Tags 清除所有 Tags Clear All Tags Options Clear All Tag Options 清除所有 Tags 的选项 Remove JSON Tag 删除 JSON Tag Remove XML Tag 删除 XML Tag Remove Custom Tag 删除自定义 Tag Multiple tags separated by commas Multiple tags are separated by commas 多个 tags 之间使用逗号分隔 Remove JSON Options 删除 JSON 选项 Multiple options separated by commas Multiple options are separated by commas 多个选项之间使用逗号分隔 Remove XML Options 删除 XML 选项 Remove Custom Tag Options 删除自定义 Tag 选项 Setup remove custom tag and option, example tag=opt1,tag=opt2 Setup remove custom tag option, example tag=opt1,tag=opt2 设置删除自定义 tag 和选项,形如 tag=op1,tag=op2 tag=option Info 信息 GolangAst No outline available 没有大纲 Synchronize with editor 与编辑器同步 Go Class View Class View Go 类视图 Go Outline Outline Go 大纲 GolangAstOption Form QuickOpenSymbol 快速跳转符号 Show import path 显示导入包 Match case sensitive 区分大小写匹配 GolangCodeOption Form PKG automitic import prompt 包自动导入提示 PKG automatic import hints for all packages (GOPATH) GOPATH 所有包导入自动提示 PKG automatic import hints for standard package 标准包导入自动提示 Gocode Go API Auto update depends package when it's source changed. Auto update depends package when its source is changed. 自动更新依赖库当其源码改变时. Close gocode when exiting 退出时关闭gocode GolangDoc Godoc Search Go文档搜索 Go Doc Search Golang Doc Search Go 文档搜索 Go Api Index Golang Api Index Go Api 索引 Find Package: 查找包: GolangDocOption Form Go API Use default context (fast) 使用默认context(快速) Only load standard API documentation Only load standard api 只加载标准库 GolangEdit View import package use godoc 使用godoc查看导入包 View Expression Information 查看表达式信息 Jump to Declaration 跳转到声明 Find Usages 查找使用 Rename Symbol Under Cursor 重命名符号 %1 (Module/GOPATH) with GOROOT Stop 停止 Go Source Query Go源码查询 SourceQuery What Go源码查询What Callees Callers Callstack Definition Describe Freevars Implements Implements(GOPATH) Peers Referrers Pointsto Whicherrs Add Tags To Struct Field 添加结构体字段 Tags Remove Tags From Struct Field 删除结构体字段 Tags Refactor 重构 SourceQuery Go源码查询 Below files in package %1 下面的文件属于包 %1 GolangEditOption Form Mouse 鼠标 Go root source file editor setup read only GO 源码目录源文件设置为只读 Enable view expression infomation on mouse 允许显示鼠标下代码信息 Enable mouse navigation 允许鼠标导航 GolangFileSearch Golang Find Usages Golang 查找使用 GolangFmtOption Form Format Options Golang Format Golang 格式化 Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Goimports自动更新您的Go语言import行,增加缺少的pkg和移除未引用的pkg。 Enable update imports line, adding missing ones and removing unreferenced ones. 允许更新import行,增加缺少的pkg和移除未引用的pkg. Synchronous 同步 Synchronous code formatting Synchronous code formatting 同步代码格式化 Synchronous code formatting timeout in milliseconds (500ms or more): 同步代码格式化超时时间(500毫秒以上): Automatically format code when saving When the editor is saved automatically gofmt 文件保存时代码自动格式化 GolangFmtPlugin Format Code Format Code (goimports) 代码格式化 Format Code (Adjusts Imports) 代码格式化(调整导入行) GolangPackageOption Choose directory to add to GOPATH: 选择目录添加到 GOPATH: Manage GOPATH / Modules 管理 GOPATH / Modules Go Modules Custom GONOPROXY 自定义 GONOPROXY Custom GOPROXY 自定义 GOPROXY Custom GO111MODULE 自定义 GO111MODULE Custom GONOSUMDB 自定义 GONOSUMDB Custom GOPRIVATE 自定义 GOPRIVATE TextLabel GOPATH Use System GOPATH 使用系统 GOPATH Reload 重新加载 Use Custom GOPATH (one per line) 使用自定义 GOPATH (每行一个) Add Directory... 添加目录... Clear 清除 GolangPresentEdit Section (s1) 一级标题 (s1) Subsection (s2) 二级标题 (s2) Sub-subsection (s3) 三级标题 (s3) Bold 加重 Italic 斜体 Inline Code 内联代码 Switch Bullets 切换列表 Comment/Uncomment Selection 切换区域注释/反注释 Export HTML 输出HTML文档 Verify Present 校验 Present verify success Present校验成功 Present verify false Present校验失败 Export PDF 输出PDF文档 GolangSymbol Quick Open Symbol by Name 根据名称跳转到符号 GoplayBrowser Go Playground Run 运行 Stop 停止 New 新建 Load... 加载... Save... 保存... Explore Folder 浏览目录 Running... Running... 运行... Error: %1. Error: %1. 错误: %1. Success: %2. Success: %2. 成功: %2. Load File 读取文件 Select a file to load: 选择文件并加载: Save File 保存文件 New File Name: 新文件名: HtmlPreview Page Style 页面样式 Reload 刷新 Export Html 输出Html文档 Export PDF 输出PDF文档 Print Preview 打印预览 Synchronize preview and code scrollbars 同步预览和代码窗口滚动 Config 配置 Plain HTML 纯HTML Export Failed 导出失败 Automatically display preview Automatically Display Preview 自动显示预览窗口 HTML Preview Html Preview HTML预览 Could not open %1 for writing! Can not write file %1 无法写入文件 %1! ImageEditor ZoomIn 放大 ZoomOut 缩小 Reset to original size 重置为原始大小 Fit to view 适应视图 Play movie 播放动画 Prev frame 上一帧 Next frame 下一帧 Pause movie 暂停动画 ImageEditorFactory Image Viewer 图像查看器 ImportPkgTip warning, pkg not find, please enter to import : 警告,包未发现,按回车导入: JsonEdit Verify 校验 Format Json 格式化Json Compact Json 压缩Json LiteApp Event Log 事件记录 Escape 取消 Close File 关闭文件 Close All Files 关闭所有文件 Save File 保存文件 Save File As... 文件另存为... Save All Files 保存所有文件 Open Project 打开项目 Options 选项 New... 新建... Open File... 打开文件... Open Folder... 打开目录... Open Folder in New Window... 在新窗口打开目录... Close All Folders Add Folder... 关闭所有目录 New Window 新窗口 Close Window 关闭窗口 Save Project 保存项目 Close Project 关闭项目 Exit 退出 Full Screen 全屏显示 About LiteIDE 关于 LiteIDE About Plugins 关于插件 LiteAppOption Form Store [*] Store 存储 [*] Language: 语言: Use tool window shortcuts 工具窗口使用快捷键 Icon [*] 图标 [*] Reload files in session 在会话中重新加载文件 Recent Files Recent File 历史文件 Max Count: Max Recent: 最大记录数: Monitoring files for modifications 文件修改监视 Store settings to local ini file 存储设置到本地ini文件 Interface [*] 界面 [*] Style: 样式: Theme [*] 主题 [*] Fallback build-in icon library and liteapp/qrc/default 失败时回退内置图标库和 liteapp/qrc/default Load the external file icon library Load custome icon from liteapp/qrc folder 加载外部文件图标库 Automatically save documents 自动保存文档 Automatically save documents when application is idle 应用程序空闲时自动保存文档 sec Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. 当文件被更改或删除时,自动重新读取或关闭编辑器。 Session 会话 0-99 Editor Tabs 编辑器标签 10-999 Display 显示 Display [*] 显示 [*] Show splash screen on startup 启动时显示启动画面 Show welcome page on startup 启动时显示欢迎页面 Editor 编辑器 Editor tab [*] 编辑器标签 Show close buttons on each editor tab 在每个文档标签栏都显示关闭按钮 Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab 允许鼠标滚轮导航Tabs Toolbar Icon Size [*] 工具栏图标大小 [*] Editor navigate 编辑器导航 Enable mouse extra 'Back' button and 'Forward' button for go back and forward 启用鼠标“Back”和“Forward”按键支持前进和后退 Keyboard 键盘 Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands 隐藏标准命令 Reset 重置 Reset All 重置所有 Import... 导入... Export... 导出... Generic 通用 Theme: 主题: Reload session on startup Auto load last session 启动时重新加载会话 SideBarStyle 边栏样式 SplitterStyle 分离样式 Command 命令 Label 标签 Shortcuts 快捷键 NativeText 本机文本 Standard 标准键 Import Keyboard Mapping Scheme 导入键盘映射方案 Keyboard Mapping Scheme (%1) 键盘映射方案 (%1) Could not read scheme from %1! 无法加载方案%1! Export Keyboard Mapping Scheme 导出键盘映射方案 Could not write scheme to %1! 无法写入方案%1! LiteBuild Build Toolbar 编译工具栏 Build Configuration... Build Config 编译配置... Stop Action 停止执行 Clear Output Clear All 清除输出 Execute File 执行文件 Debug File 调试文件 Lock Build Path 锁定编译目录 Build Path Configuration Go Build Configuration 编译目录配置 Use godoc View 使用godoc查看 Line Wrap 自动换行 Auto Clear 自动清除 Automatic positioning cursor 自动定位光标 Setup 设置 Build Output Build 编译输出 Current environment change id "%1" 当前环境变更 id "%1" Lock Build Lock Build: %1 锁定编译 Error: %1. Error: %1. 错误: %1. Command exited with code %1. 命令退出代码 %1. Success: %1. Success: %1. 成功: %1. A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. 进程正在运行.请先停止当前命令操作. Killing current process... Killing current process... 终止当前进程... Failed to terminate the existing process! Failed to terminate the existing process! 无法终止已存在进程! Started process successfully Started process successfully 进程启动成功 Failed to start process LiteBuildOption Form Recheck Go installation when changing environments Recheck go env if enviroment changed 环境变更重新检查Go安装 Build command configuration files [*] Build command configuration files: 编译命令配置文件 [*] LiteBuildPlugin Close 关闭 Execute: Exec: 执行: Execute File Execute 执行文件 LiteDebug Stop 停止 Clear 清除 Continue 继续 Show Current Line 显示当前行 Debug Output Debug 调试输出 Start Debugging External Application... Start Debugging External Application 调试其他应用程序... Close 关闭 Start Debugging 开始调试 Step Into 逐语句 Step Over 逐过程 Step Out 跳出 Run to Line 运行到行 Insert/Remove Breakpoint 插入/删除断点 Remove All Breakpoints 删除所有断点 LiteDebugOption Form Debug 调试 Automatically insert breakpoint main.main when debugging Automatically add breakpoint main.main when debugging 调试时自动插入断点 main.main LiteDebugPlugin Debug Window Debug 调试窗口 LiteDoc LiteIDE Documentation LiteIDE Document Browser LiteIDE文档 LiteEditor Undo 撤消 Redo 重做 Cut 剪切 Copy 复制 Paste 粘贴 Select All 选择所有 Go to Doc Start 跳转到文件开头 Go to Doc End 跳转到文件结尾 Go to Line Start 跳转到行开头 Go to Line End 跳转到行结尾 Go to Previous Line 跳转到上一行 Go to Next Line 跳转到下一行 Go to Previous Character 跳转到前一字符 Go to Next Charater 跳转到后一字符 Go to Previous Word 跳转到前一单词 Go to Next Word 跳转到后一单词 Go to Line 跳转到行 File is readonly 文件只读 File is writable 文件可写 Line Wrap (MimeType) Word Wrap (MimeType) 自动换行 (MimeType) Toggle Comment 切换注释 Toggle Block Commnet 切换块注释 Auto-indent Selection 自动代码缩进 Tab To Spaces (MimeType) TAB转空格(MimeType) Line End Windows (\r\n) Windows行结束符 (\r\n) Line End Unix (\n) Unix行结束符 (\n) Visualize Whitespace (Global) 显示空白 (全局) Move Line Up 移动行(向上) Move Line Down 移动行(向下) Copy Line Up 复制行(向上) Copy Line Down 复制行(向下) Join Lines 连接行 Title Case 首字母大写 Upper Case 大写转换 Lower Case 小写转换 Swap Case 大小写互换 Tab To Spaces TAB 转空格 Spaces To Tab 空格转 TAB Advanced 高级 Goto 跳转 Convert Tab 转换 TAB Code Folding 代码折叠 Convert Case 转换大小写 Export HTML 输出HTML文档 Export Failed 导出失败 Could not open %1 for writing. 无法写入文件 %1. Export PDF 输出PDF文档 Print Document 文档打印 Print Preview... Print Preview Document 打印预览... Export HTML... 导出HTML... Export PDF... 导出PDF... Print... 打印... Go to Previous Block Go To Previous Block 跳转到上一段 Select Block 选择段 Go to Matching Brace Go To Matching Brace 跳转到括号匹配 Fold 折叠 Unfold 展开 Fold All 折叠所有 Unfold All 展开所有 Go To Line Goto Line 跳转到行 Duplicate 重复 Delete Line 删除行 Copy Line 复制行 Cut Line 剪切行 Insert Line Before 行前插入 Insert Line After 行后插入 Increase Font Size 增大字号 Decrease Font Size 减小字号 Reset Font Size 重置字号 Clean Whitespace 清除空白 Code Complete 代码完成 Settings File Setup 设置 Reload File 重新读取文件 Do you want to permanently discard unsaved modifications and reload %1? 您想要放弃未保存的修改并重新载入%1? Go to Next Block Go To Next Block 跳转到下一段 ReadOnly 只读 Line: 行: LiteEditorFileFactory Text Editor 文本编辑器 LiteEditorOption Form Load File 读取文件 Check and convert no printable char to '.' 检查并转换不可打印字符为'.' Font 字体 Font && Colors 字体和颜色 Family: 名称: Show Monospace Font 显示等宽字体 Size: 大小: Zoom: 缩放: % % Antialias 抗锯齿 Restore Default Font 重置为默认字体 Editor Color Scheme ColorStyle Scheme 编辑器颜色方案 File: 文件: Edit 编辑 Syntax Auto-completion Auto complete brackets 语法自动完成 Fuzzy code completion 模糊代码完成 Clean completion cache when saving files 保存文件时清除代码完成缓存 Clean whitespace when saving files 保存文件时清除空白 Enable scroll wheel zooming 允许鼠标滚轮缩放 Add copied text into the clipboard as HTML 将复制的文本作为HTML添加到剪贴板中 Allow vertical scrolling to the last line [*] 允许垂直滚动到最后一行 [*] Display VisualizeWhitespace 显示空白 Word wrap by default 默认自动换行 Display code fold 显示代码折叠 Display offset position 显示偏移位置 File Types 文件类型 Behavior 行为 Display EOF 显示EOF Display line numbers 显示行号 Display indent guide Display indent guide 显示缩进指示 Display right margin at column 显示右侧边线 Automatic indentation Enable automatic indentation 自动缩进 Case sensitive code completion Completer case sensitive 代码完成区分大小写 Code completion prefix length: Word Complete Prefix Length 代码完成前缀长度: Display 显示 MIME Type MIME类型 Tab Width Tab宽度 Tab To Spaces TAB转空格 File Extensions 文件扩展名 Custom Extensions 自定义扩展名 LiteEditorPlugin Edit ToolBar 编辑工具栏 Edit Navigation Bar 编辑导航栏 LiteEnvOption Form Environment definition files: 环境定义文件: Environment changes will take effect after switching environments. 环境变更后自动切换环境. LiteFindPlugin Find 查找 Find Next 查找下一个 Find Previous 查找上一个 Replace 替换 File Search 文件搜索 LiteTabWidget Open a new tab 打开新标签 List All Tabs 显示所有页面 Close Tab 关闭页面 MarkdownBatchBrowser Markdown Exporter Markdown Batch Markdown导出 All Files (*) 所有文件(*) Select the folder containing your markdown files: Select Markdown Folder 选择Markdown文件所在目录: Select Markdown Files 选择Markdown文件 Select the folder to contain separated markdown exports: 选择处理markdown文件导出目录: Export Merged HTML Export Html 导出合并HTML Export Merged PDF Export PDF 导出合并PDF MarkdownBatchWidget Form Markdown Source Files Markdown Files Markdown源文件 Import Folder... Import Folder 导入文件夹... Add Files... Add Files 添加文件... Move Up 上移 Move Down 下移 Remove 删除 Remove All 删除所有 Options 选项 Export Folder: 输出目录: Browse... Browser 浏览... Use CSS 使用CSS Insert horizontal line between merged files Merge files insert split <hr> 合并文件之间插入水平线 Insert page break between merged files Merge files insert page break 合并文件插入分页符 Export Export Util 导出 Export Separated HTML Separate Html 转出单独HTML Export Separated PDF Separate PDF 导出单独PDF Export Merged HTML... Merge Html 导出合并HTML... Export Merged PDF... Merge PDF 导出合并PDF... Print Preview Merged... Merge Print Preview 合并打印预览... Print Merged Merge Print 合并打印 Log 记录 MarkdownEdit Header (h1) Header <h1> 标题 (h1) Header (h2) Header <h2> 标题 (h2) Header (h3) Header <h3> 标题 (h3) Header (h4) Header <h4> 标题 (h4) Header (h5) Header <h5> 标题 (h5) Header (h6) Header <h6> 标题 (h6) Bold 加重 Italic 斜体 Inline Code 内联代码 Link 链接 Image 图像 Unordered List 无序列表 Ordered List 有序列表 Blockquote 引用 Horizontal Rule 水平分隔线 Heading 标题 MultiFolderView Delete Folder 删除目录 Are you sure that you want to permanently delete this folder and all of its contents? 您确定要删除此文件夹及所有内容? Failed to delete the folder! 删除目录失败! Delete File 删除文件 Are you sure that you want to permanently delete this file? 您确定要永久删除这个文件? Failed to delete the file! 删除文件失败! NavigateBar Browser Files in %1 浏览文件 %1 NewFileDialog New Project or File 新项目或文件 Browse... 浏览... GOPATH: Template: Template 模板: Type Information 信息 Name: 名称: Location: 位置: Error 错误 Could not create the target directory: %1 无法创建目标目录: %1 Warning 警告 Location %1 is not empty. Use the target directory anyway? 位置 %1 不为空.继续使用目标目录? Overwrite File 覆盖文件 %1 already exists. Do you want to replace it? %1 已存在.您要替换它吗? No files could be created. 文件无法建立. File template details: 文件模板详细信息: Project template details: New project wizard: 项目模板详细信息: Choose a directory for the new content: 选择新目录: OpenEditorsWidget Open Documents 打开文档 OptionsBrowser Options Options Page 选项 OptionsWidget Options 选项 Info 信息 [*] item request restart of LiteIDE [*] item requeset restart LiteIDE [*] 项需要重启LiteIDE OutputDockWidget Move To 移动到 LeftSideBar 左侧边栏 RightSideBar 右侧边栏 BottomDockWidget 底部停靠窗口 OutputOption Form Font 字体 Family: 名称: Size: 大小: Zoom: 缩放: % % Antialias 抗锯齿 Display 显示 Use editor color scheme 使用编辑器颜色方案 Sets the maximum number of lines 设置最大行数 PackageBrowser Manage GOPATH/Modules ... Manage GOPATH... 管理 GOPATH/Modules ... Reload All 重新加载所有 Use godoc View 使用godoc查看 Load Package in New Window 在新窗口打开包 Add Package to Folders 添加Package到目录列表 Open Source File 打开源文件 Copy Name to Clipboard Copy Name To Clipboard 复制名字到剪切板 Go Package Browser Package Browser Go Package 浏览 Loading Go package list... Loading go package ... 正在加载go package列表... PackageProject Reload Package 刷新Package Open Explorer Here 打开目录浏览 Add Source File 添加源文件 File Name: 文件名称: Error 错误 File %1 already exists. 文件 %1 已存在. Could not open %1 for writing. 无法写入文件 %1. PluginsDialog Installed Plugins Install Plugins 已安装插件 Close 关闭 Name 名称 Author Anchor 作者 Enabled 允许 Details 详细信息 Version Last Ver 版本 File Name FileName 文件名 ProcessEx process exited with code %1 进程退出代码 %1 process crashed or was terminated 进程崩溃或被终止 process exited with an unknown status 未知状态的进程退出 process failed to start 进程无法启动 process crashed or was terminated while running 进程崩溃或运行终止 timed out waiting for process 进程等待超时 couldn't read from the process 无法从进程读取 couldn't write to the process 无法写入进程 an unknown error occurred 发生未知错误 ProjectManager Project <%1> 项目 <%1> Import Directory <%1> 导入目录 <%1> QFileSystemModel %1 TB %1 GB %1 MB %1 KB %1 bytes QJson::ParserRunnable An error occurred while parsing json: %1 QJsonParseError no error occurred unterminated object missing name separator unterminated array missing value separator illegal value invalid termination by number illegal number invalid escape sequence invalid UTF8 string unterminated string object is missing after a comma too deeply nested document too large document garbage at the end of the document QuickOpenAction Show and Run Commands 显示和运行命令 QuickOpenEditor Show All Opened Editors Show All Editors 显示所有打开文档 QuickOpenFileSystem File System 文件系统 QuickOpenFiles Go to File 跳转到文件 Type '?' to get help on the actions you can take from here 键入'?'在此处获取相关操作的帮助 QuickOpenFolder Browser Folder 浏览目录 QuickOpenHelp Show All Quick Open Actions Show Quick Open Help 显示所有快速打开操作 QuickOpenLines Go to Line 跳转到行 Open a text file first to go to a line 请先打开文本文件再跳转到行 Type a line number between %1 and %2 to navigate to 键入要导航到的介于%1和%2之间的行号 Go to Line %1 Go to line %1 转到行 %1 QuickOpenManager Quick Open File 快速打开文件 Quick Open Editor 快速打开文档 Quick Open Symbol 快速跳转符号 Quick Open Command 快速打开命令 Show All Quick Open Actions 显示所有快速打开操作 QuickOpenMimeType Go to Symbol in File Open Symbol by Name 跳转到文件中的符号 not found symbol 没有找到符号 QuickOpenOption Form QuickOpenFiles 快速打开文件 Match case sensitive 区分大小写匹配 Max files count: 最大文件数: QuickOpenEditor 快速打开文档 RecentManager Clear All History 清除所有历史 Clear Menu 清除菜单 SearchEdit Search 搜索 Stop Search 中止搜索 SelectExternalDialog Debug External Application 调试外部应用程序 Application: 应用程序: Browse... Browser 浏览... Arguments: 参数: Working directory: 工作目录: Select Executable 选择可执行文件 Select the working directory: Select Working Directory 选择工作目录: SessionRecent Sessions 会话 SideDockWidget Move To 移动到 RightSideBar 右侧边栏 LeftDockWidgt 左侧停靠窗口 LeftSideBar 左侧边栏 RightDockWidget 右侧停靠窗口 OutputBar 输出栏 SideBar 边栏 Show SideBar 显示边栏 SideWindowStyle Hide SideBar 隐藏侧边栏 SideBar Windows 侧边栏窗口 Output Windows 输出窗口 SplitDockWidget Move To 移动到 Top 顶部 Top (Split) 顶部(切分) TopDockWidget (Split) 项部停靠窗口 (切分) TopDockWidget 项部停靠窗口 Bottom 底部 Bottom (Split) 底部(切分) BottomDockWidget (Split) 底部停靠窗口 (切分) BottomDockWidget 底部停靠窗口 Left 左侧 Left (Split) 左侧(切分) LeftDockWidget (Split) 左侧停靠窗口 (切分) LeftDockWidget 左侧停靠窗口 Right 右侧 Right (Split) 右侧(切分) RightDockWidget (Split) 右侧停靠窗口 (切分) RightDockWidget 右侧停靠窗口 Unsplit 不切分 Split 切分 SplitWindowStyle Hide Sidebars 隐藏侧边栏 Tool Windows 工具窗口 Terminal New 新建 Open a new terminal 新建终端 Close 关闭 Close current terminal 关闭当前终端 CloseAll 关闭所有 Close all terminal 关闭所有终端 LoadEnv 加载环境 Current terminal load environment from LiteIDE 从 LiteIDE 加载环境到当前终端 Filter 过滤 Dark Mode 暗黑模式 Login Mode (shell --login) 登录模式 (shell --login) Terminal 终端 Rename Tab Title 重命名标签 TerminalEdit Cut 剪切 Copy 复制 Paste 粘贴 Select All 选择所有 Clear All 清除所有 TextEditor::Internal::ColorScheme Not a color scheme file. 没有颜色配置文件. Utils::FilterLineEdit Filter 过滤 Clear text 清除文本 VTermWidget Copy 复制 Paste 粘贴 Select All 选择所有 WebKitBrowser Navigation 导航 Open Html File Open Html 打开Html文件 WebKitBrowser WebKit浏览器 False load %1 ! 加载失败 %1 ! Open Html or Markdown File Open Html or Markdown Files 打开HTML或者Markdown文件 WebKitHtmlWidgetPlugin Open Html or Markdown File Open Html or Markdown Files 打开HTML或者Markdown文件 WelcomeBrowser New 新建 Open 打开 Open Folder 打开目录 Options 选项 Welcome Welcome Page 起始页 WelcomePlugin Welcome Home 欢迎 ================================================ FILE: liteidex/liteide_zh_TW.ts ================================================ AboutDialog About LiteIDE About Liteide 關於 LiteIDE Information Infomation 資訊 Welcome: 歡迎: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. 歡迎使用 LiteIDE X! LiteIDE是一個簡單,開源,跨平臺的IDE. Project: 專案: Name: 名稱: Author: 作者: Version: 版本: Build: Based on Qt Based on Qt Version Source Code: Support LiteIDE: Support Developers 開發者 Translations 翻譯 Chinese 中文 Japanese 日文 Russian 俄文 French 法文 Traditional Chinese German Ukrainian Thanks to... 感謝... License 許可協議 Close 關閉 Based on Qt %1 (%2 bit) ActionManager &File 檔案(&F) &Recent &Edit 編輯 F&ind &Find 搜尋(&I) &View 檢視(&V) &Tools &Build &Debug 除錯(&D) &Help 說明(&H) Standard Toolbar Standard ToolBar 標準工具列 AstWidget Go To Definition View Import Document BaseDockWidget Hide 隱藏 Hide Tool Window Floating Window BaseFolderView Open In New Window Open File 開啟編輯器 New File... 新建文件 New File Wizard... 新建文件精靈 Rename File... Delete File 刪除文件 New Folder... 新建目錄 Rename Folder... Delete Folder 刪除目錄 Open Terminal Here 開啟終端機 Show in Explorer Open Explorer Here 開啟目錄瀏覽 Open Application Show in Finder Show Containing Folder Open Command Prompt Here Open in Integrated Terminal Open Folder... Add Folder... Reload Folder Close Folder Close All Folders Copy 複製 Paste 貼上 Copy Path Move To Trash Create File A file with that name already exists! Failed to create the file! 建立文件失敗! Rename File 文件更名 New Name: Failed to rename the file! 重命名文件失敗! An item "%1" already exists in this location. Do you want to replace it and move old item to trash? Stop 停止 Keep Both Keep Both All Replace 取代 Replace All 全部取代 Are you sure that you want move to trash this item? Are you sure that you want move to trash %1 items? Move to Trash Open With System Editor Create Folder 建立目錄 A folder with that name already exists! 目錄名稱已存在! Failed to create the folder! 建立目錄失敗! Rename Folder 目錄更名 Folder Name 目錄名稱 Failed to rename the folder! 重命名目錄失敗! Are you sure that you want to permanently delete this folder and all of its contents? Failed to delete the folder! 刪除目錄失敗! BookmarkManager Toggle Bookmark Goto bookmark Remove bookmark Remove all bookmarks for this file Remove all bookmarks for all files Bookmarks BookmarkRecent Bookmarks BuildConfigDialog Build Configuration Build Config Dialog 建置設定對話框 Build ID 建置編號 Build Path Build File 建置文件 GOPATH GOPATH information Use Custom GOPATH for Build Path Inherit System GOPATH Inherit LiteIDE GOPATH Custom GOPATH (one per line) Add Directory... Clear 清除 LiteIDE LiteIDE Config Action Custom Build Custom 建置自定項目 Reset all to initial value Name 名稱 Value SharedValue Id Cmd Choose directory to add to GOPATH: 載入GOPATH目錄 CreateDirDialog Create Folder 建立目錄 Directory: 當前目錄: Dir Name: Create 新建 Cancel 取消 CreateFileDialog Create File Create File Dialog 新建文件對話框 Directory: 當前目錄: File Name: 文件名稱: Create 新建 Create and Edit 新建並編輯 Cancel 取消 DebugWidget Add Watch Async Record AsyncRecord 非同步記錄 Variables 變數 Watch Call Stack CallStack 呼叫堆疊 Threads Goroutines Registers Libraries Library 函式庫 Console 控制台 Watch expression (e.g. buf main.var os.Stdout): Remove Watch Remove All Watches DlvDebuggerOption Form 表單 delve debug pass flags: (example --check-go-version=false) DocumentBrowser Back Backward 返回 Forward 前進 Reload 刷新 Increase Font Size Decrease Font Size Reset Font Size DocumentBrowserFactory DocumentBrowser EditorManager Close 關閉 Move to New Window Move To New Window Navigate Forward GoForward Close Others Close Others Tabs Open Editor Close All Close All Tabs Close Left Tabs Close Right Tabs Close Files in Same Folder Close Same Folder Files Close Files in Other Folders Close Other Folder Files Copy Full Path to Clipboard Copy Path to Clipboard Show in Explorer 開啟目錄瀏覽 Show in Finder Show Containing Folder Open Command Prompt Here Open Terminal Here 開啟終端機 Open in Integrated Terminal Navigate Backward Save changes to %1? Unsaved Modifications Save Modify 儲存修改內容 All Files (*) 所有文件(*) Save As 另存爲 EnvManager Environment Toolbar Environment ToolBar Switching current environment Switch Current Environment 環境變數 Edit current environment Edit Current Environment Reload current environment Reload Current Environment Select Environment ExportDialog Dialog Name: 名稱: Export ExportAndView FakeVim::Internal Use Vim-style Editing Read .vimrc Path to .vimrc FakeVim::Internal::FakeVimHandler Unknown option: %1 Argument must be positive: %1=%2 Mark "%1" not set. %1%2% %1All Not implemented in FakeVim. Unknown option: Invalid argument: Trailing characters: Move lines into themselves. %n lines moved. File "%1" exists (add ! to override) Cannot open file "%1" for writing "%1" %2 %3L, %4C written. Cannot open file "%1" for reading "%1" %2L, %3C %n lines filtered. Cannot open file %1 Invalid regular expression: %1 Pattern not found: %1 Search hit BOTTOM, continuing at TOP. Search hit TOP, continuing at BOTTOM. Search hit BOTTOM without match for: %1 Search hit TOP without match for: %1 %n lines indented. %n lines %1ed %2 time. %n lines yanked. Already at oldest change. Already at newest change. FakeVim::Internal::FakeVimHandler::Private Recursive mapping Type Alt-V, Alt-V to quit FakeVim mode. [New] Not an editor command: %1 FakeVimEdit Use FakeVim Editing FakeVimEditOption Form 表單 FakeVim initialization command list (# start is comment): Load default init command list FiFoTty Cannot create temporary file: %1 Cannot create FiFo %1: %2 Cannot open FiFo %1: %2 FileBrowser Synchronize with editor 與編輯器同步 Show Hidden Files Set As Root Folder Set Folder To Root 設置爲頂層目錄 Execute File Reload Folder Show Details Debug File Open Folder in New Window Add to Folders Open Parent Open to Parent Filter File System FileBrowserOption Form 表單 Terminal 終端機 Command: 指令: Arguments: 參數: FileManager All Files (*) 所有文件(*) LiteIDE LiteIDE Project '%1' has been created. Do you want to open it now? Project '%1' is created. Do you want to load? 專案 '%1'已建立,是否要載入? Open Project or File 開啟專案或文件 Show Hidden Files Show Details Split Mode Folders Folers All Support Files (%1) Select a folder: Open Folder %1 This file has been deleted from the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to close the editor? Answering "Yes" will discard your unsaved changes. %1 This file has been deleted from the drive. Do you want to close the editor? %1 This file has been modified on the drive, but you have unsaved modifications in your LiteIDE editor. Do you want to reload the file from disk? Answering "Yes" will discard your unsaved changes. %1 This file has been modified on the drive. Do you want to reload the file from disk? Open Files 開啟文件 Synchronize with editor 與編輯器同步 Filter Open Project 開啟專案 LiteIDE X FileRecent Files FileSearch Match whole word Match word 全詞匹配 Match case 區分大小寫 Regular expression 使用正則表達式 Scan subdirectories Look in subdirs Search for: Options: 選項: Browse... Browser 瀏覽 Filter: Files on File System Search Cancel 取消 Current Folder Auto Switch Clear 清除 Open Directory FileSearchManager Search Item: Only golang file changes can be revert! This file change cannot be undone! New Search File Search Search Result LiteIDE X Warning! Replace text is empty. Want to remove all the search items? Warning! Replace text is whitespace. Want to replace to all the search items to whitespace? The following files have no write permissions. Do you want to change the permissions? File is readonly FileSystemWidget Open File Open Editor 開啟編輯器 New File... New File 新建文件 New File Wizard... New File Wizard 新建文件精靈 Rename File 文件更名 Delete File Remove File 刪除文件 New Folder... New Folder 新建目錄 Are you sure that you want to permanently delete this file? Rename Folder 目錄更名 Delete Folder Remove Folder 刪除目錄 Rename File... Rename Folder... Open Terminal Here 開啟終端機 Open Explorer Here 開啟目錄瀏覽 View Godoc Here 查看GODOC Add Folder Close Folder Add Folder... Close All Folders Create File 建立文件 A file with that name already exists! The file already exists! Failed to create the file! 建立文件失敗! New Name: Failed to rename the file! 重命名文件失敗! Are you sure that you want to permanently delete this folder and all of its contents? Failed to delete the file! Failed to remove the file! 刪除文件失敗! Create Folder 建立目錄 A folder with that name already exists! The folder name is exists! 目錄名稱已存在! Failed to create the folder! 建立目錄失敗! Folder Name 目錄名稱 Failed to rename the folder! 重命名目錄失敗! Failed to delete the folder! Failed to remove the folder! 刪除目錄失敗! Find::Internal::SearchResultWidget Search was canceled. Cancel 取消 Repeat the search with same parameters Search again Set show replace mode ui Show Replace Replace with: Replace all occurrences Replace 取代 Preserve case Expand all items Collapse all items Revert with: Revert Revert all occurrences %n matches replaced. searching... %n matches found. searching ... No matches found. %n matches found. FindApiEdit Search Stop Search FindApiWidget Search Find 搜尋 FindDocWidget Search Find 搜尋 Find All Find const Find func Find interface Find pkg Find struct Find type Find var Use Regexp Match Case Match Word Help FindEditor Match case 區分大小寫 Regular expression 使用正則表達式 Wrap around 搜尋到結尾時從頭開始 Find Next 查找下一個 Find Previous Find Prev 查找上一個 Replace With: 取代為: Replace 取代 Replace All 全部取代 Match whole word only 全詞匹配 Ready 已完成 Close 關閉 Show Replace Find What: 查找: Options: Find Option: 選項: Not found 沒有找到 FolderListView Delete File 刪除文件 Are you sure that you want to permanently delete this file? Failed to delete the file! 刪除文件失敗! Delete Folder 刪除目錄 Are you sure that you want to permanently delete this folder and all of its contents? Failed to delete the folder! 刪除目錄失敗! FolderRecent Folders FolderView Delete File 刪除文件 Are you sure that you want to permanently delete this file? Failed to delete the file! 刪除文件失敗! Delete Folder 刪除目錄 Are you sure that you want to permanently delete this folder and all of its contents? Failed to delete the folder! 刪除目錄失敗! GdbDebuggerOption Form 表單 Enable --tty for program being debugged. GoAddTagsDialog Add Tags To Struct Field Add JSON Tag Options 選項 Multiple options separated by commas Multiple options are separated by commas Add XML Tag Add Custom Tags Tag Name Setup custom tag name Sort sorts the tags in increasing order according to the key name Override current tags when adding tags Info 資訊 GoRemoveTagsDialog Remove Tags From Struct Field Remove Tags And Options Clear All Tags Clear All Tags Options Clear All Tag Options Remove JSON Tag Remove XML Tag Remove Custom Tag Multiple tags separated by commas Multiple tags are separated by commas Remove JSON Options Multiple options separated by commas Multiple options are separated by commas Remove XML Options Remove Custom Tag Options Setup remove custom tag and option, example tag=opt1,tag=opt2 Setup remove custom tag option, example tag=opt1,tag=opt2 tag=option Info 資訊 GolangAst No outline available Synchronize with editor 與編輯器同步 Go Class View Class View Go Outline Outline GolangAstOption Form 表單 QuickOpenSymbol Show import path Match case sensitive GolangCodeOption Form 表單 PKG automitic import prompt PKG automatic import hints for all packages (GOPATH) PKG automatic import hints for standard package Gocode Go API Auto update depends package when it's source changed. Auto update depends package when its source is changed. Close gocode when exiting GolangDoc Godoc Search Go Doc Search Golang Doc Search Go Api Index Golang Api Index Find Package: GolangDocOption Form 表單 Go API Use default context (fast) Only load standard API documentation Only load standard api GolangEdit View import package use godoc View Expression Information Jump to Declaration Find Usages Rename Symbol Under Cursor %1 (Module/GOPATH) with GOROOT Stop 停止 Go Source Query SourceQuery What Callees Callers Callstack Definition Describe Freevars Implements Implements(GOPATH) Peers Referrers Pointsto Whicherrs Add Tags To Struct Field Remove Tags From Struct Field Refactor SourceQuery Below files in package %1 GolangEditOption Form 表單 Mouse Go root source file editor setup read only Enable view expression infomation on mouse Enable mouse navigation GolangFileSearch Golang Find Usages GolangFmtOption Form 表單 Format Options Golang Format Goimports updates your Go import lines, adding missing ones and removing unreferenced ones. Enable update imports line, adding missing ones and removing unreferenced ones. Synchronous Synchronous code formatting Synchronous code formatting Synchronous code formatting timeout in milliseconds (500ms or more): Automatically format code when saving When the editor is saved automatically gofmt GolangFmtPlugin Format Code Format Code (goimports) Format Code (Adjusts Imports) GolangPackageOption Choose directory to add to GOPATH: 載入GOPATH目錄 Manage GOPATH / Modules Go Modules Custom GONOPROXY Custom GOPROXY Custom GO111MODULE Custom GONOSUMDB Custom GOPRIVATE TextLabel GOPATH Use System GOPATH Reload 刷新 Use Custom GOPATH (one per line) Add Directory... Clear 清除 GolangPresentEdit Section (s1) Subsection (s2) Sub-subsection (s3) Bold Italic Inline Code Switch Bullets Comment/Uncomment Selection Export HTML 匯出HTML文檔 Verify Present Present verify success Present verify false Export PDF 匯出PDF文檔 GolangSymbol Quick Open Symbol by Name GoplayBrowser Go Playground Run Stop 停止 New 新建 Load... Save... Explore Folder Running... Running... Error: %1. Error: %1. Success: %2. Success: %2. Load File 讀取文件 Select a file to load: Save File 儲存文件 New File Name: HtmlPreview Page Style Reload 刷新 Export Html Export PDF 匯出PDF文檔 Print Preview Synchronize preview and code scrollbars Config Plain HTML Export Failed Automatically display preview Automatically Display Preview HTML Preview Html Preview Could not open %1 for writing! Can not write file %1 無法寫入文件 %1 ImageEditor ZoomIn ZoomOut Reset to original size Fit to view Play movie Prev frame Next frame Pause movie ImageEditorFactory Image Viewer ImportPkgTip warning, pkg not find, please enter to import : JsonEdit Verify Format Json Compact Json LiteApp Event Log Escape Close File Close All Files Save File 儲存文件 Save File As... Save All Files Open Project 開啟專案 Options 選項 New... Open File... Open Folder... Open Folder in New Window... Close All Folders Add Folder... New Window Close Window Save Project 儲存專案 Close Project Exit 離開 Full Screen About LiteIDE 關於 LiteIDE About Plugins LiteAppOption Form 表單 Store [*] Store Language: 語言: Icon [*] Reload files in session Recent Files Recent File 最近開啟的文件 Max Count: Max Recent: Monitoring files for modifications Store settings to local ini file Interface [*] Style: Use tool window shortcuts Theme [*] Fallback build-in icon library and liteapp/qrc/default Load the external file icon library Load custome icon from liteapp/qrc folder Automatically save documents Automatically save documents when application is idle sec Auto reload or close editor buffer,if underlying file is modified/deleted. Auto reload editor buffer from disk file,if underlying file is modified/deleted. Session 0-99 Editor Tabs 10-999 Display 顯示 Display [*] Show splash screen on startup Show welcome page on startup Editor Editor tab [*] Show close buttons on each editor tab Enable mouse wheel navigation on tabs Enable mouse wheel selected on tab Toolbar Icon Size [*] Editor navigate Enable mouse extra 'Back' button and 'Forward' button for go back and forward Keyboard Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands Reset Reset All Import... Export... Generic Theme: Reload session on startup Auto load last session SideBarStyle SplitterStyle Command Label Shortcuts NativeText Standard Import Keyboard Mapping Scheme Keyboard Mapping Scheme (%1) Could not read scheme from %1! Export Keyboard Mapping Scheme Could not write scheme to %1! LiteBuild Build Toolbar Build Configuration... Build Config 建置設定 Stop Action Clear Output Clear All Execute File Debug File Lock Build Path Lock Go Build Path Build Path Configuration Go Build Configuration Use godoc View 查看GODOC Line Wrap Auto Clear Automatic positioning cursor Setup Build Output Build 編譯輸出 Current environment change id "%1" Lock Build Lock Build: %1 Error: %1. Error: %1. Command exited with code %1. Success: %1. Success: %1. A process is currently running. Stop the current action first. A process is currently running. Stop the current action first. Killing current process... Killing current process... Failed to terminate the existing process! Failed to terminate the existing process! Started process successfully Started process successfully Failed to start process LiteBuildOption Form 表單 Recheck Go installation when changing environments Recheck go env if enviroment changed Build command configuration files [*] Build command configuration files: LiteBuildPlugin Close 關閉 Execute: Exec: Execute File Execute LiteDebug Stop 停止 Clear 清除 Continue Show Current Line 顯示當前行 Debug Output Debug 除錯輸出 Start Debugging External Application... Start Debugging External Application Close 關閉 Start Debugging Step Into Step Over Step Out Run to Line Insert/Remove Breakpoint Remove All Breakpoints LiteDebugOption Form 表單 Debug Automatically insert breakpoint main.main when debugging Automatically add breakpoint main.main when debugging LiteDebugPlugin Debug Window Debug 除錯視窗 LiteDoc LiteIDE Documentation LiteIDE Document Browser IDE文件瀏覽 LiteEditor Undo 復原 Redo 重做 Cut 剪下 Copy 複製 Paste 貼上 Select All 全部選擇 Go to Doc Start Go to Doc End Go to Line Start Go to Line End Go to Previous Line Go to Next Line Go to Previous Character Go to Next Charater Go to Previous Word Go to Next Word Go to Line File is readonly File is writable Line Wrap (MimeType) Word Wrap (MimeType) Toggle Comment Toggle Block Commnet Auto-indent Selection Tab To Spaces (MimeType) Line End Windows (\r\n) Line End Unix (\n) Visualize Whitespace (Global) Title Case Upper Case Lower Case Swap Case Tab To Spaces Spaces To Tab Advanced Goto Convert Tab Code Folding Convert Case Export HTML 匯出HTML文檔 Export Failed Could not open %1 for writing. Export PDF 匯出PDF文檔 Print Document 列印文件 Print Preview... Print Preview Document 預覽列印 Export HTML... Export PDF... Print... Go to Previous Block Go To Previous Block Select Block Go to Matching Brace Go To Matching Brace Fold Unfold Fold All Unfold All Go To Line Goto Line Duplicate Delete Line Copy Line Cut Line Insert Line Before Insert Line After Increase Font Size Decrease Font Size Reset Font Size Clean Whitespace Code Complete Move Line Up Move Line Down Copy Line Up Copy Line Down Join Lines Settings File Setup Reload File Do you want to permanently discard unsaved modifications and reload %1? Go to Next Block Go To Next Block ReadOnly Line: LiteEditorFileFactory Text Editor LiteEditorOption Form 表單 Load File 讀取文件 Check and convert no printable char to '.' Font 字型 Font && Colors Family: 字型: Show Monospace Font Size: 大小: Zoom: % Antialias 反鋸齒 Restore Default Font Editor Color Scheme ColorStyle Scheme 顏色配置主題 File: 文件: Edit 編輯 Syntax Auto-completion Auto complete brackets Fuzzy code completion Clean completion cache when saving files Clean whitespace when saving files Enable scroll wheel zooming Add copied text into the clipboard as HTML Allow vertical scrolling to the last line [*] Display VisualizeWhitespace Word wrap by default Display code fold Display offset position File Types Behavior 行爲 Display EOF Display line numbers Display indent guide Display indent guide Display right margin at column Automatic indentation Enable automatic indentation 啓用自動縮排 Case sensitive code completion Completer case sensitive Code completion prefix length: Word Complete Prefix Length Display 顯示 MIME Type Tab Width Tab To Spaces File Extensions Custom Extensions LiteEditorPlugin Edit ToolBar Edit Navigation Bar LiteEnvOption Form 表單 Environment definition files: Environment changes will take effect after switching environments. LiteFindPlugin Find 搜尋 Find Next 查找下一個 Find Previous 查找上一個 Replace 取代 File Search LiteTabWidget Open a new tab List All Tabs Close Tab MarkdownBatchBrowser Markdown Exporter Markdown Batch All Files (*) 所有文件(*) Select the folder containing your markdown files: Select Markdown Folder Select Markdown Files Select the folder to contain separated markdown exports: Export Merged HTML Export Html Export Merged PDF Export PDF 匯出PDF文檔 MarkdownBatchWidget Form 表單 Markdown Source Files Markdown Files Import Folder... Import Folder Add Files... Add Files Move Up Move Down Remove Remove All Options 選項 Export Folder: Browse... Browser 瀏覽 Use CSS Insert horizontal line between merged files Merge files insert split <hr> Insert page break between merged files Merge files insert page break Export Export Util Export Separated HTML Separate Html Export Separated PDF Separate PDF Export Merged HTML... Merge Html Export Merged PDF... Merge PDF Print Preview Merged... Merge Print Preview Print Merged Merge Print Log MarkdownEdit Header (h1) Header <h1> Header (h2) Header <h2> Header (h3) Header <h3> Header (h4) Header <h4> Header (h5) Header <h5> Header (h6) Header <h6> Bold Italic Inline Code Link Image Unordered List Ordered List Blockquote Horizontal Rule Heading MultiFolderView Delete Folder 刪除目錄 Are you sure that you want to permanently delete this folder and all of its contents? Failed to delete the folder! 刪除目錄失敗! Delete File 刪除文件 Are you sure that you want to permanently delete this file? Failed to delete the file! 刪除文件失敗! NavigateBar Browser Files in %1 NewFileDialog New Project or File 建立新專案或文件 Browse... 瀏覽 GOPATH: Template: Template 類別 Type Information 資訊 Name: 名稱: Location: 位置: Error Could not create the target directory: %1 Warning Location %1 is not empty. Use the target directory anyway? Overwrite File %1 already exists. Do you want to replace it? No files could be created. File template details: Project template details: New project wizard: 新項目精靈: Choose a directory for the new content: OpenEditorsWidget Open Documents OptionsBrowser Options Options Page 選項 OptionsWidget Options 選項 Info 資訊 [*] item request restart of LiteIDE [*] item requeset restart LiteIDE OutputDockWidget Move To LeftSideBar RightSideBar BottomDockWidget OutputOption Form 表單 Font 字型 Family: 字型: Size: 大小: Zoom: % Antialias 反鋸齒 Display 顯示 Use editor color scheme Sets the maximum number of lines PackageBrowser Manage GOPATH/Modules ... Manage GOPATH... Reload All Use godoc View 查看GODOC Load Package in New Window Add Package to Folders Open Source File Copy Name to Clipboard Copy Name To Clipboard Go Package Browser Package Browser Loading Go package list... Loading go package ... PackageProject Reload Package Open Explorer Here 開啟目錄瀏覽 Add Source File File Name: 文件名稱: Error File %1 already exists. Could not open %1 for writing. PluginsDialog Installed Plugins Install Plugins 已安裝插件 Close 關閉 Name 名稱 Author Anchor 作者 Enabled Details Version Last Ver 版本 File Name FileName 文件名稱 ProcessEx process exited with code %1 process crashed or was terminated process exited with an unknown status process failed to start process crashed or was terminated while running timed out waiting for process couldn't read from the process couldn't write to the process an unknown error occurred ProjectManager Project <%1> Import Directory <%1> QFileSystemModel %1 TB %1 GB %1 MB %1 KB %1 bytes QJson::ParserRunnable An error occurred while parsing json: %1 QJsonParseError no error occurred unterminated object missing name separator unterminated array missing value separator illegal value invalid termination by number illegal number invalid escape sequence invalid UTF8 string unterminated string object is missing after a comma too deeply nested document too large document garbage at the end of the document QuickOpenAction Show and Run Commands QuickOpenEditor Show All Opened Editors Show All Editors QuickOpenFileSystem File System QuickOpenFiles Go to File Type '?' to get help on the actions you can take from here QuickOpenFolder Browser Folder QuickOpenHelp Show All Quick Open Actions Show Quick Open Help QuickOpenLines Go to Line Open a text file first to go to a line Type a line number between %1 and %2 to navigate to Go to Line %1 Go to line %1 QuickOpenManager Quick Open File Quick Open Editor Quick Open Symbol Quick Open Command Show All Quick Open Actions QuickOpenMimeType Go to Symbol in File Open Symbol by Name not found symbol QuickOpenOption Form 表單 QuickOpenFiles Match case sensitive Max files count: QuickOpenEditor RecentManager Clear All History Clear Menu SearchEdit Search Stop Search SelectExternalDialog Debug External Application Application: Browse... Browser 瀏覽 Arguments: 參數: Working directory: Select Executable Select the working directory: Select Working Directory SessionRecent Sessions SideDockWidget Move To RightSideBar LeftDockWidgt LeftSideBar RightDockWidget OutputBar SideBar Show SideBar SideWindowStyle Hide SideBar SideBar Windows Output Windows SplitDockWidget Move To Top Top (Split) TopDockWidget (Split) TopDockWidget Bottom Bottom (Split) BottomDockWidget (Split) BottomDockWidget Left Left (Split) LeftDockWidget (Split) LeftDockWidget Right Right (Split) RightDockWidget (Split) RightDockWidget Unsplit Split SplitWindowStyle Hide Sidebars Tool Windows Terminal New 新建 Open a new terminal Close 關閉 Close current terminal CloseAll Close all terminal LoadEnv Current terminal load environment from LiteIDE Filter Dark Mode Login Mode (shell --login) Terminal 終端機 Rename Tab Title TerminalEdit Cut 剪下 Copy 複製 Paste 貼上 Select All 全部選擇 Clear All TextEditor::Internal::ColorScheme Not a color scheme file. 不是正確的顏色配置文件. Utils::FilterLineEdit Filter Clear text VTermWidget Copy 複製 Paste 貼上 Select All 全部選擇 WebKitBrowser Navigation Open Html File Open Html WebKitBrowser False load %1 ! Open Html or Markdown File Open Html or Markdown Files WebKitHtmlWidgetPlugin Open Html or Markdown File Open Html or Markdown Files WelcomeBrowser New 新建 Open Open Folder Options 選項 Welcome Welcome Page 起始頁 WelcomePlugin Welcome Home 主頁 ================================================ FILE: liteidex/liteidex.pri ================================================ !isEmpty(LITEIDE_PRI_INCLUDED):error("liteidex.pri already included") LITEIDE_PRI_INCLUDED = 1 defineReplace(qtLibraryName) { unset(LIBRARY_NAME) LIBRARY_NAME = $$1 CONFIG(debug, debug|release) { !debug_and_release|build_pass { mac:RET = $$member(LIBRARY_NAME, 0)_debug else:win32:RET = $$member(LIBRARY_NAME, 0)d } } isEmpty(RET):RET = $$LIBRARY_NAME return($$RET) } isEmpty(IDE_LIBRARY_BASENAME) { IDE_LIBRARY_BASENAME = lib } greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport DEFINES += LITEAPP_LIBRARY DEFINES += IDE_LIBRARY_BASENAME=\\\"$$IDE_LIBRARY_BASENAME\\\" isEmpty(PREFIX) { PREFIX = /usr/local } BINPREFIX = $$PREFIX/bin LIBPREFIX = $$PREFIX/lib/liteide PLUGINPREFIX = $$PREFIX/lib/liteide/plugins IDE_APP_TARGET = liteide IDE_SOURCE_TREE = $$PWD IDE_BUILD_TREE = $$IDE_SOURCE_TREE/liteide IDE_APP_PATH = $$IDE_BUILD_TREE/bin macx { IDE_APP_TARGET = "LiteIDE" IDE_LIBRARY_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/PlugIns IDE_PLUGIN_PATH = $$IDE_LIBRARY_PATH IDE_DATA_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/Resources IDE_BIN_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/MacOS contains(QT_CONFIG, ppc):CONFIG += ppc x86 copydata = 1 } else { win32 { contains(TEMPLATE, vc.*)|contains(TEMPLATE_PREFIX, vc):vcproj = 1 IDE_APP_TARGET = liteide } else { IDE_APP_TARGET = liteide } IDE_BIN_PATH = $$IDE_BUILD_TREE/bin IDE_LIBRARY_PATH = $$IDE_BUILD_TREE/$$IDE_LIBRARY_BASENAME/liteide IDE_PLUGIN_PATH = $$IDE_LIBRARY_PATH/plugins IDE_DATA_PATH = $$IDE_BUILD_TREE/share/liteide !isEqual(IDE_SOURCE_TREE, $$IDE_BUILD_TREE):copydata = 1 } #LIBS += -L$$IDE_LIBRARY_PATH #DEFINES += QT_NO_CAST_FROM_ASCII DEFINES += QT_NO_CAST_TO_ASCII !macx:DEFINES += QT_USE_FAST_OPERATOR_PLUS QT_USE_FAST_CONCATENATION unix { CONFIG(debug, debug|release):OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared CONFIG(release, debug|release):OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared CONFIG(debug, debug|release):MOC_DIR = $${OUT_PWD}/.moc/debug-shared CONFIG(release, debug|release):MOC_DIR = $${OUT_PWD}/.moc/release-shared RCC_DIR = $${OUT_PWD}/.rcc UI_DIR = $${OUT_PWD}/.uic } linux-g++-* { # Bail out on non-selfcontained libraries. Just a security measure # to prevent checking in code that does not compile on other platforms. QMAKE_LFLAGS += -Wl,--allow-shlib-undefined -Wl,--no-undefined } win32-msvc* { #Don't warn about sprintf, fopen etc being 'unsafe' DEFINES += _CRT_SECURE_NO_WARNINGS } linux* { contains(CONFIG, liteide_qtwebkit) { DEFINES += LITEIDE_QTWEBKIT } } else { greaterThan(QT_MAJOR_VERSION, 4) { } else { DEFINES += LITEIDE_QTWEBKIT } } ================================================ FILE: liteidex/liteidex.pro ================================================ include (liteidex.pri) TEMPLATE = subdirs CONFIG += ordered SUBDIRS = src TRANSLATIONS = \ liteide_zh.ts \ liteide_zh_tw.ts \ liteide_ru.ts \ liteide_ja.ts \ liteide_fr.ts \ liteide_de.ts \ liteide_uk.ts # liteide_tr.ts ================================================ FILE: liteidex/macosx_deploy.sh ================================================ #!/bin/sh cp -v ../README.md liteide/bin cp -v LICENSE.LGPL liteide/bin cp -v LGPL_EXCEPTION.TXT liteide/bin cp -r -v deploy/* liteide/bin/LiteIDE.app/Contents/Resources cp -r -v os_deploy/macosx/* liteide/bin/LiteIDE.app/Contents/Resources cp -R -v src/liteide/Info.plist liteide/bin/LiteIDE.app/Contents cp -v bin/gotools liteide/bin/LiteIDE.app/Contents/MacOS cp -v bin/gocode liteide/bin/LiteIDE.app/Contents/MacOS cp -v bin/gomodifytags liteide/bin/LiteIDE.app/Contents/MacOS ================================================ FILE: liteidex/make_tools.cmd ================================================ @echo off set GOBIN=%CD%\bin echo install gocode ... go install -v github.com/visualfc/gocode@latest echo install gotools ... go install -v github.com/visualfc/gotools@latest echo install gomodifytags ... go install -v github.com/fatih/gomodifytags@latest ================================================ FILE: liteidex/make_tools.sh ================================================ #!/bin/sh export GOBIN=$PWD/bin echo install gocode ... go install -v github.com/visualfc/gocode@latest echo install gotools ... go install -v github.com/visualfc/gotools@latest echo install gomodifytags ... go install -v github.com/fatih/gomodifytags@latest ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-arm5.env ================================================ # cross-compiler linux arm5 GOROOT=$HOME/go #GOBIN= GOARCH=arm GOARM=5 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-arm6.env ================================================ # cross-compiler linux arm6 GOROOT=$HOME/go #GOBIN= GOARCH=arm GOARM=6 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-darwin32.env ================================================ # native compiler darwin 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-darwin64.env ================================================ # native compiler darwin amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-linux32.env ================================================ # cross-compiler linux 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-linux64.env ================================================ # cross-compiler linux amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-win32.env ================================================ # cross-compiler windows 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/cross-win64.env ================================================ # cross-compiler windows amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/freebsd32.env ================================================ # native compiler darwin 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/freebsd64.env ================================================ # native compiler darwin amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/freebsd/liteenv/system.env ================================================ # native compiler darwin amd64 #GOROOT=/usr/local/go #GOBIN= #GOARCH=amd64 #GOOS=freebsd #CGO_ENABLED=1 #PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-arm5.env ================================================ # cross-compiler linux arm5 GOROOT=$HOME/go #GOBIN= GOARCH=arm GOARM=5 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-arm6.env ================================================ # cross-compiler linux arm6 GOROOT=$HOME/go #GOBIN= GOARCH=arm GOARM=6 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-darwin32.env ================================================ # cross-compiler darwin 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=darwin CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-darwin64.env ================================================ # cross-compiler darwin amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=darwin CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-freebsd32.env ================================================ # native compiler darwin 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-freebsd64.env ================================================ # native compiler darwin amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-win32.env ================================================ # cross-compiler windows 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/cross-win64.env ================================================ # cross-compiler windows amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/linux32-local.env ================================================ # native compiler linux 386 GOROOT=/usr/local/go #GOBIN= GOARCH=386 GOOS=linux CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/linux32.env ================================================ # native compiler linux 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=linux CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/linux64-local.env ================================================ # native compiler linux amd64 GOROOT=/usr/local/go #GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/linux64.env ================================================ # native compiler linux amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/liteenv/system.env ================================================ # native compiler linux 386 #GOROOT=$HOME/go #GOBIN= #GOARCH=386 #GOOS=linux #CGO_ENABLED=1 #PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/gnome-terminal LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/bin/xterm LITEIDE_EXECOPT=-e LITEIDE_SHELL=x-terminal-emulator;gnome-terminal;lxterminal;konsole;xfce4-terminal;xterm ================================================ FILE: liteidex/os_deploy/linux/qt.conf ================================================ [Paths] Plugins = ../lib/liteide/plugins ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-arm5.env ================================================ # cross-compiler linux arm5 #GOROOT=/usr/local/go #GOBIN= GOARCH=arm GOARM=5 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-arm6.env ================================================ # cross-compiler linux arm6 #GOROOT=/usr/local/go #GOBIN= GOARCH=arm GOARM=6 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-freebsd32.env ================================================ # native compiler darwin 386 #GOROOT=/usr/local/go #GOBIN= GOARCH=386 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-freebsd64.env ================================================ # native compiler darwin amd64 #GOROOT=/usr/local/go #GOBIN= GOARCH=amd64 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-linux32.env ================================================ # cross-compiler linux 386 #GOROOT=/usr/local/go #GOBIN= GOARCH=386 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-linux64.env ================================================ # cross-compiler linux amd64 #GOROOT=/usr/local/go #GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-win32.env ================================================ # cross-compiler windows 386 #GOROOT=/usr/local/go #GOBIN= GOARCH=386 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/cross-win64.env ================================================ # cross-compiler windows amd64 #GOROOT=/usr/local/go #GOBIN= GOARCH=amd64 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/darwin32-home.env ================================================ # native compiler darwin 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/darwin32-local.env ================================================ # native compiler darwin 386 GOROOT=/usr/local/go #GOBIN= GOARCH=386 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/darwin64-home.env ================================================ # native compiler darwin amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/darwin64-local.env ================================================ # native compiler darwin amd64 GOROOT=/usr/local/go #GOBIN= GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/macosx/liteenv/system.env ================================================ # native compiler darwin amd64 #GOROOT=/usr/local/go #GOBIN= #GOARCH=amd64 #GOOS=darwin #CGO_ENABLED=1 #PATH=$GOROOT/bin:$PATH:/usr/local/bin PATH=$PATH:/usr/local/bin LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-arm5.env ================================================ # cross-compiler linux arm5 GOROOT=$HOME/go #GOBIN= GOARCH=arm GOARM=5 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-arm6.env ================================================ # cross-compiler linux arm6 GOROOT=$HOME/go #GOBIN= GOARCH=arm GOARM=6 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-darwin32.env ================================================ # native compiler darwin 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-darwin64.env ================================================ # native compiler darwin amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-freebsd32.env ================================================ # native compiler darwin 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-freebsd64.env ================================================ # native compiler darwin amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=freebsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/local/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-linux32.env ================================================ # cross-compiler linux 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-linux64.env ================================================ # cross-compiler linux amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-win32.env ================================================ # cross-compiler windows 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/cross-win64.env ================================================ # cross-compiler windows amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=windows CGO_ENABLED=0 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/bin/open LITEIDE_TERMARGS=-a Terminal LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/openbsd32.env ================================================ # native compiler openbsd 386 GOROOT=$HOME/go #GOBIN= GOARCH=386 GOOS=openbsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/local/bin/open LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/openbsd64.env ================================================ # native compiler openbsd amd64 GOROOT=$HOME/go #GOBIN= GOARCH=amd64 GOOS=openbsd CGO_ENABLED=1 PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/local/bin/open LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/openbsd/liteenv/system.env ================================================ # native compiler openbsd amd64 #GOROOT=/usr/local/go #GOBIN= #GOARCH=amd64 #GOOS=freebsd #CGO_ENABLED=1 #PATH=$GOROOT/bin:$PATH LITEIDE_GDB=/usr/bin/gdb LITEIDE_MAKE=make LITEIDE_TERM=/usr/local/bin/open LITEIDE_TERMARGS= LITEIDE_EXEC=/usr/X11R6/bin/xterm LITEIDE_EXECOPT=-e ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-arm5.env ================================================ # cross-compiler linux arm5 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=arm GOARM=5 GOOS=linux CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-arm6.env ================================================ # cross-compiler linux arm6 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=arm GOARM=6 GOOS=linux CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-darwin32.env ================================================ # cross-compiler darwin 386 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=386 GOOS=darwin CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-darwin64.env ================================================ # cross-compiler darwin amd64 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=amd64 GOOS=darwin CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-freebsd32.env ================================================ # native compiler darwin 386 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=386 GOOS=freebsd CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-freebsd64.env ================================================ # native compiler darwin amd64 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=amd64 GOOS=freebsd CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-linux32.env ================================================ # cross-compiler linux 386 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=386 GOOS=linux CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/cross-linux64.env ================================================ # cross-compiler linux amd64 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=amd64 GOOS=linux CGO_ENABLED=0 PATH=%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/system.env ================================================ # native compiler windows amd64 #GOROOT=%PROGRAMFILES%\Go #GOBIN= #GOARCH=amd64 #GOOS=windows #CGO_ENABLED=1 #PATH=c:\mingw32\bin;%GOROOT%\bin;%PATH% #LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/win32-user.env ================================================ # native compiler windows 386 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=386 GOOS=windows CGO_ENABLED=1 PATH=c:\mingw32\bin;%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/win32.env ================================================ # native compiler windows 386 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=386 GOOS=windows CGO_ENABLED=1 PATH=c:\mingw32\bin;%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/win64-user.env ================================================ # native compiler windows amd64 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=amd64 GOOS=windows CGO_ENABLED=1 PATH=c:\mingw64\bin;%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb64 LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/liteenv/win64.env ================================================ # native compiler windows amd64 GOROOT=%PROGRAMFILES%\Go #GOBIN= GOARCH=amd64 GOOS=windows CGO_ENABLED=1 PATH=c:\mingw64\bin;%GOROOT%\bin;%PATH% LITEIDE_GDB=gdb64 LITEIDE_MAKE=mingw32-make LITEIDE_TERM=%COMSPEC% LITEIDE_TERMARGS= LITEIDE_EXEC=%COMSPEC% LITEIDE_EXECOPT=/C ================================================ FILE: liteidex/os_deploy/windows/qt.conf ================================================ [Paths] Plugins = plugins ================================================ FILE: liteidex/src/3rdparty/3rdparty.pro ================================================ include (../../liteidex.pri) TEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ treemodelcompleter \ qtc_texteditor \ qtc_gdbmi \ qtc_editutil \ qtc_searchresult \ qtc_itemview \ qt_browser \ qjson \ elidedlabel \ cplusplus \ fakevim \ diff_match_patch \ qjsonrpc \ libucd \ cmark \ libvterm \ ptyqt ================================================ FILE: liteidex/src/3rdparty/cmark/COPYING ================================================ Copyright (c) 2014, John MacFarlane All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----- houdini.h, houdini_href_e.c, houdini_html_e.c, houdini_html_u.c derive from https://github.com/vmg/houdini (with some modifications) Copyright (C) 2012 Vicent Martí 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. ----- buffer.h, buffer.c, chunk.h are derived from code (C) 2012 Github, Inc. 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. ----- utf8.c and utf8.c are derived from utf8proc (), (C) 2009 Public Software Group e. V., Berlin, Germany. 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. ----- The normalization code in normalize.py was derived from the markdowntest project, Copyright 2013 Karl Dubost: The MIT License (MIT) Copyright (c) 2013 Karl Dubost 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. ----- The CommonMark spec (test/spec.txt) is Copyright (C) 2014-15 John MacFarlane Released under the Creative Commons CC-BY-SA 4.0 license: . ----- The test software in test/ is Copyright (c) 2014, John MacFarlane All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: liteidex/src/3rdparty/cmark/README.md ================================================ cmark ===== [![Build Status]](https://travis-ci.org/commonmark/cmark) [![Windows Build Status]](https://ci.appveyor.com/project/jgm/cmark-0ub06) `cmark` is the C reference implementation of [CommonMark], a rationalized version of Markdown syntax with a [spec][the spec]. (For the JavaScript reference implementation, see [commonmark.js].) It provides a shared library (`libcmark`) with functions for parsing CommonMark documents to an abstract syntax tree (AST), manipulating the AST, and rendering the document to HTML, groff man, LaTeX, CommonMark, or an XML representation of the AST. It also provides a command-line program (`cmark`) for parsing and rendering CommonMark documents. Advantages of this library: - **Portable.** The library and program are written in standard C99 and have no external dependencies. They have been tested with MSVC, gcc, tcc, and clang. - **Fast.** cmark can render a Markdown version of *War and Peace* in the blink of an eye (127 milliseconds on a ten year old laptop, vs. 100-400 milliseconds for an eye blink). In our [benchmarks], cmark is 10,000 times faster than the original `Markdown.pl`, and on par with the very fastest available Markdown processors. - **Accurate.** The library passes all CommonMark conformance tests. - **Standardized.** The library can be expected to parse CommonMark the same way as any other conforming parser. So, for example, you can use `commonmark.js` on the client to preview content that will be rendered on the server using `cmark`. - **Robust.** The library has been extensively fuzz-tested using [american fuzzy lop]. The test suite includes pathological cases that bring many other Markdown parsers to a crawl (for example, thousands-deep nested bracketed text or block quotes). - **Flexible.** CommonMark input is parsed to an AST which can be manipulated programmatically prior to rendering. - **Multiple renderers.** Output in HTML, groff man, LaTeX, CommonMark, and a custom XML format is supported. And it is easy to write new renderers to support other formats. - **Free.** BSD2-licensed. It is easy to use `libcmark` in python, lua, ruby, and other dynamic languages: see the `wrappers/` subdirectory for some simple examples. There are also libraries that wrap `libcmark` for [Go](https://github.com/rhinoman/go-commonmark), [Haskell](https://hackage.haskell.org/package/cmark), [Ruby](https://github.com/gjtorikian/commonmarker), [Lua](https://github.com/jgm/cmark-lua), [Perl](https://metacpan.org/release/CommonMark), [Python](https://pypi.python.org/pypi/paka.cmark), [R](https://cran.r-project.org/package=commonmark) and [Scala](https://github.com/sparsetech/cmark-scala). Installing ---------- Building the C program (`cmark`) and shared library (`libcmark`) requires [cmake]. If you modify `scanners.re`, then you will also need [re2c] \(>= 0.14.2\), which is used to generate `scanners.c` from `scanners.re`. We have included a pre-generated `scanners.c` in the repository to reduce build dependencies. If you have GNU make, you can simply `make`, `make test`, and `make install`. This calls [cmake] to create a `Makefile` in the `build` directory, then uses that `Makefile` to create the executable and library. The binaries can be found in `build/src`. The default installation prefix is `/usr/local`. To change the installation prefix, pass the `INSTALL_PREFIX` variable if you run `make` for the first time: `make INSTALL_PREFIX=path`. For a more portable method, you can use [cmake] manually. [cmake] knows how to create build environments for many build systems. For example, on FreeBSD: mkdir build cd build cmake .. # optionally: -DCMAKE_INSTALL_PREFIX=path make # executable will be created as build/src/cmark make test make install Or, to create Xcode project files on OSX: mkdir build cd build cmake -G Xcode .. open cmark.xcodeproj The GNU Makefile also provides a few other targets for developers. To run a benchmark: make bench For more detailed benchmarks: make newbench To run a test for memory leaks using `valgrind`: make leakcheck To reformat source code using `clang-format`: make format To run a "fuzz test" against ten long randomly generated inputs: make fuzztest To do a more systematic fuzz test with [american fuzzy lop]: AFL_PATH=/path/to/afl_directory make afl Fuzzing with [libFuzzer] is also supported but, because libFuzzer is still under active development, may not work with your system-installed version of clang. Assuming LLVM has been built in `$HOME/src/llvm/build` the fuzzer can be run with: CC="$HOME/src/llvm/build/bin/clang" LIB_FUZZER_PATH="$HOME/src/llvm/lib/Fuzzer/libFuzzer.a" make libFuzzer To make a release tarball and zip archive: make archive Installing (Windows) -------------------- To compile with MSVC and NMAKE: nmake You can cross-compile a Windows binary and dll on linux if you have the `mingw32` compiler: make mingw The binaries will be in `build-mingw/windows/bin`. Usage ----- Instructions for the use of the command line program and library can be found in the man pages in the `man` subdirectory. Security -------- By default, the library will scrub raw HTML and potentially dangerous links (`javascript:`, `vbscript:`, `data:`, `file:`). To allow these, use the option `CMARK_OPT_UNSAFE` (or `--unsafe`) with the command line program. If doing so, we recommend you use a HTML sanitizer specific to your needs to protect against [XSS attacks](http://en.wikipedia.org/wiki/Cross-site_scripting). Contributing ------------ There is a [forum for discussing CommonMark](http://talk.commonmark.org); you should use it instead of github issues for questions and possibly open-ended discussions. Use the [github issue tracker](http://github.com/commonmark/CommonMark/issues) only for simple, clear, actionable issues. Authors ------- John MacFarlane wrote the original library and program. The block parsing algorithm was worked out together with David Greenspan. Vicent Marti optimized the C implementation for performance, increasing its speed tenfold. Kārlis Gaņģis helped work out a better parsing algorithm for links and emphasis, eliminating several worst-case performance issues. Nick Wellnhofer contributed many improvements, including most of the C library's API and its test harness. [benchmarks]: benchmarks.md [the spec]: http://spec.commonmark.org [CommonMark]: http://commonmark.org [cmake]: http://www.cmake.org/download/ [re2c]: http://re2c.org [commonmark.js]: https://github.com/commonmark/commonmark.js [Build Status]: https://img.shields.io/travis/commonmark/cmark/master.svg?style=flat [Windows Build Status]: https://ci.appveyor.com/api/projects/status/h3fd91vtd1xfmp69?svg=true [american fuzzy lop]: http://lcamtuf.coredump.cx/afl/ [libFuzzer]: http://llvm.org/docs/LibFuzzer.html ================================================ FILE: liteidex/src/3rdparty/cmark/changelog.txt ================================================ [0.29.0] * Update spec to 0.29. * Make rendering safe by default (#239, #273). Adds `CMARK_OPT_UNSAFE` and make `CMARK_OPT_SAFE` a no-op (for API compatibility). The new default behavior is to suppress raw HTML and potentially dangerous links. The `CMARK_OPT_UNSAFE` option has to be set explicitly to prevent this. **NOTE:** This change will require modifications in bindings for cmark and in most libraries and programs that use cmark. Borrows heavily from @kivikakk's patch in github/cmark-gfm#123. * Add sourcepos info for inlines (Yuki Izumi). * Disallow more than 32 nested balanced parens in a link (Yuki Izumi). * Resolve link references before creating setext header. A setext header line after a link reference should not create a header, according to the spec. * commonmark renderer: improve escaping. URL-escape special characters when escape mode is URL, and not otherwise. Entity-escape control characters (< 0x20) in non-literal escape modes. * render: only emit actual newline when escape mode is LITERAL. For markdown content, e.g., in other contexts we want some kind of escaping, not a literal newline. * Update code span normalization to conform with spec change. * Allow empty `<>` link destination in reference link. * Remove leftover includes of `memory.h` (#290). * A link destination can't start with `<` unless it is an angle-bracket link that also ends with `>` (#289). (If your URL really starts with `<`, URL-escape it.) * Allow internal delimiter runs to match if both have lengths that are multiples of 3. See commonmark/commonmark#528. * Include `references.h` in `parser.h` (#287). * Fix `[link]()`. * Use hand-rolled scanner for thematic break (see #284). Keep track of the last position where a thematic break failed to match on a line, to avoid rescanning unnecessarily. * Rename `ends_with_blank_line` with `S_` prefix. * Add `CMARK_NODE__LAST_LINE_CHECKED` flag (#284). Use this to avoid unnecessary recursion in `ends_with_blank_line`. * In `ends_with_blank_line`, call `S_set_last_line_blank` to avoid unnecessary repetition (#284). Once we settle whether a list item ends in a blank line, we don't need to revisit this in considering parent list items. * Disallow unescaped `(` in parenthesized link title. * Copy line/col info straight from opener/closer (Ashe Connor). We can't rely on anything in `subj` since it's been modified while parsing the subject and could represent line info from a future line. This is simple and works. * `render.c`: reset `last_breakable` after cr. Fixes jgm/pandoc#5033. * Fix a typo in `houdini_href_e.c` (Felix Yan). * commonmark writer: use `~~~` fences if info string contains backtick. This is needed for round-trip tests. * Update scanners for new info string rules. * Add XSLT stylesheet to convert cmark XML back to Commonmark (Nick Wellnhofer, #264). Initial version of an XSLT stylesheet that converts the XML format produced by `cmark -t xml` back to Commonmark. * Check for whitespace before reference title (#263). * Bump CMake to version 3 (Jonathan Müller). * Build: Remove deprecated call to `add_compiler_export_flags()` (Jonathan Müller). It is deprecated in CMake 3.0, the replacement is to set the `CXX_VISIBILITY_PRESET` (or in our case `C_VISIBILITY_PRESET`) and `VISIBILITY_INLINES_HIDDEN` properties of the target. We're already setting them by setting the CMake variables anyway, so the call can be removed. * Build: only attempt to install MSVC system libraries on Windows (Saleem Abdulrasool). Newer versions of CMake attempt to query the system for information about the VS 2017 installation. Unfortunately, this query fails on non-Windows systems when cross-compiling: `cmake_host_system_information does not recognize VS_15_DIR`. CMake will not find these system libraries on non-Windows hosts anyways, and we were silencing the warnings, so simply omit the installation when cross-compiling to Windows. * Simplify code normalization, in line with spec change. * Implement code span spec changes. These affect both parsing and writing commonmark. * Add link parsing corner cases to regressions (Ashe Connor). * Add `xml:space="preserve"` in XML output when appropriate (Nguyễn Thái Ngọc Duy). (For text, code, code_block, html_inline and html_block tags.) * Removed meta from list of block tags. Added regression test. See commonmark/CommonMark#527. * `entity_tests.py` - omit noisy success output. * `pathological_tests.py`: make tests run faster. Commented out the (already ignored) "many references" test, which times out. Reduced the iterations for a couple other tests. * `pathological_tests.py`: added test for deeply nested lists. * Optimize `S_find_first_nonspace`. We were needlessly redoing things we'd already done. Now we skip the work if the first nonspace is greater than the current offset. This fixes pathological slowdown with deeply nested lists (#255). For N = 3000, the time goes from over 17s to about 0.7s. Thanks to Martin Mitas for diagnosing the problem. * Allow spaces in link destination delimited with pointy brackets. * Adjust max length of decimal/numeric entities. See commonmark/CommonMark#487. * Fix inline raw HTML parsing. This fixes a recently added failing spec test case. Previously spaces were being allowed in unquoted attribute values; no we forbid them. * Don't allow list markers to be indented >= 4 spaces. See commonmark/CommonMark#497. * Check for empty buffer when rendering (Phil Turnbull). For empty documents, `->size` is zero so `renderer.buffer->ptr[renderer.buffer->size - 1]` will cause an out-of-bounds read. Empty buffers always point to the global `cmark_strbuf__initbuf` buffer so we read `cmark_strbuf__initbuf[-1]`. * Also run API tests with `CMARK_SHARED=OFF` (Nick Wellnhofer). * Rename roundtrip and entity tests (Nick Wellnhofer). Rename the tests to reflect that they use the library, not the executable. * Generate export header for static-only build (#247, Nick Wellnhofer). * Fuzz width parameter too (Phil Turnbull). Allow the `width` parameter to be generated too so we get better fuzz-coverage. * Don't discard empty fuzz test-cases (Phil Turnbull). We currently discard fuzz test-cases that are empty but empty inputs are valid markdown. This improves the fuzzing coverage slightly. * Fixed exit code for pathological tests. * Add allowed failures to `pathological_tests.py`. This allows us to include tests that we don't yet know how to pass. * Add timeout to `pathological_tests.py`. Tests must complete in 8 seconds or are errors. * Add more pathological tests (Martin Mitas). These tests target the issues #214, #218, #220. * Use pledge(2) on OpenBSD (Ashe Connor). * Update the Racket wrapper (Eli Barzilay). * Makefile: For afl target, don't build tests. [0.28.3] * Include GNUInstallDirs in src/CMakeLists.txt (Nick Wellnhofer, #240). This fixes build problems on some cmake versions (#241). [0.28.2] * Fixed regression in install dest for static library (#238). Due to a mistake, 0.28.1 installed libcmark.a into include/. [0.28.1] * `--smart`: open quote can never occur right after `]` or `)` (#227). * Fix quadratic behavior in `finalize` (Vicent Marti). * Don't use `CMAKE_INSTALL_LIBDIR` to create `libcmark.pc` (#236). This wasn't getting set in processing `libcmark.pc.in`, and we were getting the wrong entry in `libcmark.pc`. The new approach sets an internal `libdir` variable to `lib${LIB_SUFFIX}`. This variable is used both to set the install destination and in the libcmark.pc.in template. * Update README.md, replace `make astyle` with `make format` (Nguyễn Thái Ngọc Duy). [0.28.0] * Update spec. * Use unsigned integer when shifting (Phil Turnbull). Avoids a UBSAN warning which can be triggered when handling a long sequence of backticks. * Avoid memcpy'ing NULL pointers (Phil Turnbull). Avoids a UBSAN warning when link title is empty string. The length of the memcpy is zero so the NULL pointer is not dereferenced but it is still undefined behaviour. * DeMorgan simplification of some tests in emphasis parser. This also brings the code into closer alignment with the wording of the spec (see jgm/CommonMark#467). * Fixed undefined shift in commonmark writer (#211). Found by google/oss-fuzz: . * latex writer: fix memory overflow (#210). We got an array overflow in enumerated lists nested more than 10 deep with start number =/= 1. This commit also ensures that we don't try to set `enum_` counters that aren't defined by LaTeX (generally up to enumv). Found by google/oss-fuzz: . * Check for NULL pointer in get_link_type (Phil Turnbull). `echo '[](xx:)' | ./build/src/cmark -t latex` gave a segfault. * Move fuzzing dictionary into single file (Phil Turnbull). This allows AFL and libFuzzer to use the same dictionary * Reset bytes after UTF8 proc (Yuki Izumi, #206). * Don't scan past an EOL (Yuki Izumi). The existing negated character classes (`[^…]`) are careful to always include` \x00` in the characters excluded, but these `.` catch-alls can scan right past the terminating NUL placed at the end of the buffer by `_scan_at`. As such, buffer overruns can occur. Also, don't scan past a newline in HTML block end scanners. * Document cases where `get_` functions return `NULL` (#155). E.g. `cmark_node_get_url` on a non-link or image. * Properly handle backslashes in link destinations (#192). Only ascii punctuation characters are escapable, per the spec. * Fixed `cmark_node_get_list_start` to return 0 for bullet lists, as documented (#202). * Use `CMARK_NO_DELIM` for bullet lists (#201). * Fixed code for freeing delimiter stack (#189). * Removed abort outside of conditional (typo). * Removed coercion in error message when aborting from buffer. * Print message to stderr when we abort due to memory demands (#188). * `libcmark.pc`: use `CMAKE_INSTALL_LIBDIR` (#185, Jens Petersen). Needed for multilib distros like Fedora. * Fixed buffer overflow error in `S_parser_feed` (#184). The overflow could occur in the following condition: the buffer ends with `\r` and the next memory address contains `\n`. * Update emphasis parsing for spec change. Strong now goes inside Emph rather than the reverse, when both scopes are possible. The code is much simpler. This also avoids a spec inconsistency that cmark had previously: `***hi***` became Strong (Emph "hi")) but `***hi****` became Emph (Strong "hi")) "*" * Fixes for the LaTeX renderer (#182, Doeme) + Don't double-output the link in latex-rendering. + Prevent ligatures in dashes sensibly when rendering latex. `\-` is a hyphenation, so it doesn't get displayed at all. * Added a test for NULL when freeing `subj->last_delim`. * Cleaned up setting of lower bounds for openers. We now use a much smaller array. * Fix #178, quadratic parsing bug. Add pathological test. * Slight improvement of clarity of logic in emph matching. * Fix "multiple of 3" determination in emph/strong parsing. We need to store the length of the original delimiter run, instead of using the length of the remaining delimiters after some have been subtracted. Test case: `a***b* c*`. Thanks to Raph Levin for reporting. * Correctly initialize chunk in S_process_line (Nick Wellnhofer, #170). The `alloc` member wasn't initialized. This also allows to add an assertion in `chunk_rtrim` which doesn't work for alloced chunks. * Added 'make newbench'. * `scanners.c` generated with re2c 0.16 (68K smaller!). * `scanners.re` - fixed warnings; use `*` for fallback. * Fixed some warnings in `scanners.re`. * Update CaseFolding to latest (Kevin Wojniak, #168). * Allow balanced nested parens in link destinations (Yuki Izumi, #166) * Allocate enough bytes for backticks array. * Inlines: Ensure that the delimiter stack is freed in subject. * Fixed pathological cases with backtick code spans: - Removed recursion in scan_to_closing_backticks - Added an array of pointers to potential backtick closers to subject - This array is used to avoid traversing the subject again when we've already seen all the potential backtick closers. - Added a max bound of 1000 for backtick code span delimiters. - This helps with pathological cases like: x x ` x `` x ``` x ```` ... - Added pathological test case. Thanks to Martin Mitáš for identifying the problem and for discussion of solutions. * Remove redundant cmake_minimum_required (#163, @kainjow). * Make shared and static libraries optional (Azamat H. Hackimov). Now you can enable/disable compilation and installation targets for shared and static libraries via `-DCMARK_SHARED=ON/OFF` and `-DCMARK_STATIC=ON/OFF`. * Added support for built-in `${LIB_SUFFIX}` feature (Azamat H. Hackimov). Replaced `${LIB_INSTALL_DIR}` option with built-in `${LIB_SUFFIX}` for installing for 32/64-bit systems. Normally, CMake will set `${LIB_SUFFIX}` automatically for required enviroment. If you have any issues with it, you can override this option with `-DLIB_SUFFIX=64` or `-DLIB_SUFFIX=""` during configuration. * Add Makefile target and harness to fuzz with libFuzzer (Phil Turnbull). This can be run locally with `make libFuzzer` but the harness will be integrated into oss-fuzz for large-scale fuzzing. * Advertise `--validate-utf8` in usage information (Nguyễn Thái Ngọc Duy). * Makefile: use warnings with re2c. * README: Add link to Python wrapper, prettify languages list (Pavlo Kapyshin). * README: Add link to cmark-scala (Tim Nieradzik, #196) [0.27.1] * Set policy for CMP0063 to avoid a warning (#162). Put set_policy under cmake version test. Otherwise we get errors in older versions of cmake. * Use VERSION_GREATER to clean up cmake version test. * Improve afl target. Use afl-clang by default. Set default for path. [0.27.0] * Update spec to 0.27. * Fix warnings building with MSVC on Windows (#165, Hugh Bellamy). * Fix `CMAKE_C_VISIBILITY_PRESET` for cmake versions greater than 1.8 (e.g. 3.6.2) (#162, Hugh Bellamy). This lets us build swift-cmark on Windows, using clang-cl. * Fix for non-matching entities (#161, Yuki Izumi). * Modified `print_delimiters` (commented out) so it compiles again. * `make format`: don't change order of includes. * Changed logic for null/eol checks (#160). + only check once for "not at end of line" + check for null before we check for newline characters (the previous patch would fail for NULL + CR) * Fix by not advancing past both `\0` and `\n` (Yuki Izumi). * Add test for NUL-LF sequence (Yuki Izumi). * Fix memory leak in list parsing (Yuki Izumi). * Use `cmark_mem` to free where used to alloc (Yuki Izumi). * Allow a shortcut link before a `(` (jgm/CommonMark#427). * Allow tabs after setext header line (jgm/commonmark.js#109). * Don't let URI schemes start with spaces. * Fixed h2..h6 HTML blocks (jgm/CommonMark#430). Added regression test. * Autolink scheme can contain digits (Gábor Csárdi). * Fix nullary function declarations in cmark.h (Nick Wellnhofer). Fixes strict prototypes warnings. * COPYING: Update file name and remove duplicate section and (Peter Eisentraut). * Fix typo (Pavlo Kapyshin). [0.26.1] * Removed unnecessary typedef that caused build failure on some platforms. * Use `$(MAKE)` in Makefile instead of hardcoded `make` (#146, Tobias Kortkamp). [0.26.0] * Implement spec changes for list items: - Empty list items cannot interrupt paragraphs. - Ordered lists cannot interrupt paragraphs unless they start with 1. - Removed "two blank lines break out of a list" feature. * Fix sourcepos for blockquotes (#142). * Fix sourcepos for atx headers (#141). * Fix ATX headers and thematic breaks to allow tabs as well as spaces. * Fix `chunk_set_cstr` with suffix of current string (#139, Nick Wellnhofer). It's possible that `cmark_chunk_set_cstr` is called with a substring (suffix) of the current string. Delay freeing of the chunk content to handle this case correctly. * Export targets on installation (Jonathan Müller). This allows using them in other cmake projects. * Fix cmake warning about CMP0048 (Jonathan Müller). * commonmark renderer: Ensure we don't have a blank line before a code block when it's the first thing in a list item. * Change parsing of strong/emph in response to spec changes. `process_emphasis` now gets better results in corner cases. The change is this: when considering matches between an interior delimiter run (one that can open and can close) and another delimiter run, we require that the sum of the lengths of the two delimiter runs mod 3 is not 0. * Ported Robin Stocker's changes to link parsing in jgm/commonmark#101. This uses a separate stack for brackets, instead of putting them on the delimiter stack. This avoids the need for looking through the delimiter stack for the next bracket. * `cmark_reference_lookup`: Return NULL if reference is null string. * Fix character type detection in `commonmark.c` (Nick Wellnhofer). Fixes test failures on Windows and undefined behavior. - Implement `cmark_isalpha`. - Check for ASCII character before implicit cast to char. - Use internal ctype functions in `commonmark.c`. * Better documentation of memory-freeing responsibilities. in `cmark.h` and its man page (#124). * Use library functions to insert nodes in emphasis/link processing. Previously we did this manually, which introduces many places where errors can creep in. * Correctly handle list marker followed only by spaces. Previously when a list marker was followed only by spaces, cmark expected the following content to be indented by the same number of spaces. But in this case we should treat the line just like a blank line and set list padding accordingly. * Fixed a number of issues relating to line wrapping. - Extend `CMARK_OPT_NOBREAKS` to all renderers and add `--nobreaks`. - Do not autowrap, regardless of width parameter, if `CMARK_OPT_NOBREAKS` is set. - Fixed `CMARK_OPT_HARDBREAKS` for LaTeX and man renderers. - Ensure that no auto-wrapping occurs if `CMARK_OPT_NOBREAKS` is enabled, or if output is CommonMark and `CMARK_OPT_HARDBREAKS` is enabled. * Set stdin to binary mode on Windows (Nick Wellnhofer, #113). This fixes EOLs when reading from stdin. * Add library option to render softbreaks as spaces (Pavlo Kapyshin). Note that the `NOBREAKS` option is HTML-only * renderer: `no_linebreaks` instead of `no_wrap`. We generally want this option to prohibit any breaking in things like headers (not just wraps, but softbreaks). * Coerce `realurllen` to `int`. This is an alternate solution for pull request #132, which introduced a new warning on the comparison (Benedict Cohen). * Remove unused variable `link_text` (Mathiew Duponchelle). * Improved safety checks in buffer (Vicent Marti). * Add new interface allowing specification of custom memory allocator for nodes (Vicent Marti). Added `cmark_node_new_with_mem`, `cmark_parser_new_with_mem`, `cmark_mem` to API. * Reduce storage size for nodes by using bit flags instead of separate booleans (Vicent Marti). * config: Add `SSIZE_T` compat for Win32 (Vicent Marti). * cmake: Global handler for OOM situations (Vicent Marti). * Add tests for memory exhaustion (Vicent Marti). * Document in man page and public header that one should use the same memory allocator for every node in a tree. * Fix ctypes in Python FFI calls (Nick Wellnhofer). This didn't cause problems so far because all types are 32-bit on 32-bit systems and arguments are passed in registers on x86-64. The wrong types could cause crashes on other platforms, though. * Remove spurious failures in roundtrip tests. In the commonmark writer we separate lists, and lists and indented code, using a dummy HTML comment. So in evaluating the round-trip tests, we now strip out these comments. We also normalize HTML to avoid issues having to do with line breaks. * Add 2016 to copyright (Kevin Burke). * Added `to_commonmark` in `test/cmark.py` (for round-trip tests). * `spec_test.py` - parameterize `do_test` with converter. * `spec_tests.py`: exit code is now sum of failures and errors. This ensures that a failing exit code will be given when there are errors, not just with failures. * Fixed round trip tests. Previously they actually ran `cmark` instead of the round-trip version, since there was a bug in setting the ROUNDTRIP variable (#131). * Added new `roundtrip_tests.py`. This replaces the old use of simple shell scripts. It is much faster, and more flexible. (We will be able to do custom normalization and skip certain tests.) * Fix tests under MinGW (Nick Wellnhofer). * Fix leak in `api_test` (Mathieu Duponchelle). * Makefile: have leakcheck stop on first error instead of going through all the formats and options and probably getting the same output. * Add regression tests (Nick Wellnhofer). [0.25.2] * Open files in binary mode (#113, Nick Wellnhofer). Now that cmark supports different line endings, files must be openend in binary mode on Windows. * Reset `partially_consumed_tab` on every new line (#114, Nick Wellnhofer). * Handle buffer split across a CRLF line ending (#117). Adds an internal field to the parser struct to keep track of `last_buffer_ended_with_cr`. Added test. [0.25.1] * Release with no code changes. cmark version was mistakenly set to 0.25.1 in the 0.25.0 release (#112), so this release just ensures that this will cause no confusion later. [0.25.0] * Fixed tabs in indentation (#101). This patch fixes S_advance_offset so that it doesn't gobble a tab character when advancing less than the width of a tab. * Added partially_consumed_tab to parser. This keeps track of when we have gotten partway through a tab when consuming initial indentation. * Simplified add_line (only need parser parameter). * Properly handle partially consumed tab. E.g. in - foo bar we should consume two spaces from the second tab, including two spaces in the code block. * Properly handle tabs with blockquotes and fenced blocks. * Fixed handling of tabs in lists. * Clarified logic in S_advance_offset. * Use an assertion to check for in-range html_block_type. It's a programming error if the type is out of range. * Refactored S_processLines to make the logic easier to understand, and added documentation (Mathieu Duponchelle). * Removed unnecessary check for empty string_content. * Factored out contains_inlines. * Moved the cmake minimum version to top line of CMakeLists.txt (tinysun212). * Fix ctype(3) usage on NetBSD (Kamil Rytarowski). We need to cast value passed to isspace(3) to unsigned char to explicitly prevent possibly undefined behavior. * Compile in plain C mode with MSVC 12.0 or newer (Nick Wellnhofer). Under MSVC, we used to compile in C++ mode to get some C99 features like mixing declarations and code. With newer MSVC versions, it's possible to build in plain C mode. * Switched from "inline" to "CMARK_INLINE" (Nick Wellnhofer). Newer MSVC versions support enough of C99 to be able to compile cmark in plain C mode. Only the "inline" keyword is still unsupported. We have to use "__inline" instead. * Added include guards to config.h * config.h.in - added compatibility snprintf, vsnprintf for MSVC. * Replaced sprintf with snprintf (Marco Benelli). * config.h: include stdio.h for _vscprintf etc. * Include starg.h when needed in config.h. * Removed an unnecessary C99-ism in buffer.c. This helps compiling on systems like luarocks that don't have all the cmake configuration goodness (thanks to carlmartus). * Don't use variable length arrays (Nick Wellnhofer). They're not supported by MSVC. * Test with multiple MSVC versions under Appveyor (Nick Wellnhofer). * Fix installation dir of man-pages on NetBSD (Kamil Rytarowski). * Fixed typo in cmark.h comments (Chris Eidhof). * Clarify in man page that cmark_node_free frees a node's children too. * Fixed documentation of --width in man page. * Require re2c >= 1.14.2 (#102). * Generated scanners.c with more recent re2c. [0.24.1] * Commonmark renderer: + Use HTML comment, not two blank lines, to separate a list item from a following code block or list. This makes the output more portable, since the "two blank lines" rule is unique to CommonMark. Also, it allows us to break out of a sublist without breaking out of all levels of nesting. + `is_autolink` - handle case where link has no children, which previously caused a segfault. + Use 4-space indent for bullet lists, for increased portability. + Use 2-space + newline for line break for increased portability (#90). + Improved punctuation escaping. Previously all `)` and `.` characters after digits were escaped; now they are only escaped if they are genuinely in a position where they'd cause a list item. This is achieved by changes in `render.c`: (a) `renderer->begin_content` is only set to false after a string of digits at the beginning of the line, and (b) we never break a line before a digit. Also, `begin_content` is properly initialized to true. * Handle NULL root in `consolidate_text_nodes`. [0.24.0] * [API change] Added `cmark_node_replace(oldnode, newnode)`. * Updated spec.txt to 0.24. * Fixed edge case with escaped parens in link destination (#97). This was also checked against the #82 case with asan. * Removed unnecessary check for `fenced` in `cmark_render_html`. It's sufficient to check that the info string is empty. Indeed, those who use the API may well create a code block with an info string without explicitly setting `fenced`. * Updated format of `test/smart_punct.txt`. * Updated `test/spec.txt`, `test/smart_punct.txt`, and `spec_tests.py` to new format. * Fixed `get_containing_block` logic in `src/commonmark.c`. This did not allow for the possibility that a node might have no containing block, causing the commonmark renderer to segfault if passed an inline node with no block parent. * Fixed string representations of `CUSTOM_BLOCK`, `CUSTOM_INLINE`. The old versions `raw_inline` and `raw_block` were being used, and this led to incorrect xml output. * Use default opts in python sample wrapper. * Allow multiline setext header content, as per spec. * Don't allow spaces in link destinations, even with pointy brackets. Conforms to latest change in spec. * Updated `scheme` scanner according to spec change. We no longer use a whitelist of valid schemes. * Allow any kind of nodes as children of `CUSTOM_BLOCK` (#96). * `cmark.h`: moved typedefs for iterator into iterator section. This just moves some code around so it makes more sense to read, and in the man page. * Fixed `make_man_page.py` so it includes typedefs again. [0.23.0] * [API change] Added `CUSTOM_BLOCK` and `CUSTOM_INLINE` node types. They are never generated by the parser, and do not correspond to CommonMark elements. They are designed to be inserted by filters that postprocess the AST. For example, a filter might convert specially marked code blocks to svg diagrams in HTML and tikz diagrams in LaTeX, passing these through to the renderer as a `CUSTOM_BLOCK`. These nodes can have children, but they also have literal text to be printed by the renderer "on enter" and "on exit." Added `cmark_node_get_on_enter`, `cmark_node_set_on_enter`, `cmark_node_get_on_exit`, `cmark_node_set_on_exit` to API. * [API change] Rename `NODE_HTML` -> `NODE_HTML_BLOCK`, `NODE_INLINE_HTML` -> `NODE_HTML_INLINE`. Define aliases so the old names still work, for backwards compatibility. * [API change] Rename `CMARK_NODE_HEADER` -> `CMARK_NODE_HEADING`. Note that for backwards compatibility, we have defined aliases: `CMARK_NODE_HEADER` = `CMARK_NODE_HEADING`, `cmark_node_get_header_level` = `cmark_node_get_heading_level`, and `cmark_node_set_header_level` = `cmark_node_set_heading_level`. * [API change] Rename `CMARK_NODE_HRULE` -> `CMARK_NODE_THEMATIC_BREAK`. Defined the former as the latter for backwards compatibility. * Don't allow space between link text and link label in a reference link (spec change). * Separate parsing and rendering opts in `cmark.h` (#88). This change also changes some of these constants' numerical values, but nothing should change in the API if you use the constants themselves. It should now be clear in the man page which options affect parsing and which affect rendering. * xml renderer - Added xmlns attribute to document node (jgm/CommonMark#87). * Commonmark renderer: ensure html blocks surrounded by blanks. Otherwise we get failures of roundtrip tests. * Commonmark renderer: ensure that literal characters get escaped when they're at the beginning of a block, e.g. `> \- foo`. * LaTeX renderer - better handling of internal links. Now we render `[foo](#bar)` as `\protect\hyperlink{bar}{foo}`. * Check for NULL pointer in _scan_at (#81). * `Makefile.nmake`: be more robust when cmake is missing. Previously, when cmake was missing, the build dir would be created anyway, and subsequent attempts (even with cmake) would fail, because cmake would not be run. Depending on `build/CMakeFiles` is more robust -- this won't be created unless cmake is run. Partially addresses #85. * Fixed DOCTYPE in xml output. * commonmark.c: fix `size_t` to `int`. This fixes an MSVC warning "conversion from 'size_t' to 'int', possible loss of data" (Kevin Wojniak). * Correct string length in `cmark_parse_document` example (Lee Jeffery). * Fix non-ASCII end-of-line character check (andyuhnak). * Fix "declaration shadows a local variable" (Kevin Wojniak). * Install static library (jgm/CommonMark#381). * Fix warnings about dropping const qualifier (Kevin Wojniak). * Use full (unabbreviated) versions of constants (`CMARK_...`). * Removed outdated targets from Makefile. * Removed need for sudo in `make bench`. * Improved benchmark. Use longer test, since `time` has limited resolution. * Removed `bench.h` and timing calls in `main.c`. * Updated API docs; getters return empty strings if not set rather than NULL, as previously documented. * Added api_tests for custom nodes. * Made roundtrip test part of the test suite run by cmake. * Regenerate `scanners.c` using re2c 0.15.3. * Adjusted scanner for link url. This fixes a heap buffer overflow (#82). * Added version number (1.0) to XML namespace. We don't guarantee stability in this until 1.0 is actually released, however. * Removed obsolete `TIMER` macro. * Make `LIB_INSTALL_DIR` configurable (Mathieu Bridon, #79). * Removed out-of-date luajit wrapper. * Use `input`, not `parser->curline` to determine last line length. * Small optimizations in `_scan_at`. * Replaced hard-coded 4 with `TAB_STOP`. * Have `make format` reformat api tests as well. * Added api tests for man, latex, commonmark, and xml renderers (#51). * render.c: added `begin_content` field. This is like `begin_line` except that it doesn't trigger production of the prefix. So it can be set after an initial prefix (say `> `) is printed by the renderer, and consulted in determining whether to escape content that has a special meaning at the beginning of a line. Used in the commonmark renderer. * Python 3.5 compatibility: don't require HTMLParseError (Zhiming Wang). HTMLParseError was removed in Python 3.5. Since it could never be thrown in Python 3.5+, we simply define a placeholder when HTMLParseError cannot be imported. * Set `convert_charrefs=False` in `normalize.py` (#83). This defeats the new default as of python 3.5, and allows the script to work with python 3.5. [0.22.0] * Removed `pre` from blocktags scanner. `pre` is handled separately in rule 1 and needn't be handled in rule 6. * Added `iframe` to list of blocktags, as per spec change. * Fixed bug with `HRULE` after blank line. This previously caused cmark to break out of a list, thinking it had two consecutive blanks. * Check for empty string before trying to look at line ending. * Make sure every line fed to `S_process_line` ends with `\n` (#72). So `S_process_line` sees only unix style line endings. Ultimately we probably want a better solution, allowing the line ending style of the input file to be preserved. This solution forces output with newlines. * Improved `cmark_strbuf_normalize_whitespace` (#73). Now all characters that satisfy `cmark_isspace` are recognized as whitespace. Previously `\r` and `\t` (and others) weren't included. * Treat line ending with EOF as ending with newline (#71). * Fixed `--hardbreaks` with `\r\n` line breaks (#68). * Disallow list item starting with multiple blank lines (jgm/CommonMark#332). * Allow tabs before closing `#`s in ATX header * Removed `cmark_strbuf_printf` and `cmark_strbuf_vprintf`. These are no longer needed, and cause complications for MSVC. Also removed `HAVE_VA_COPY` and `HAVE_C99_SNPRINTF` feature tests. * Added option to disable tests (Kevin Wojniak). * Added `CMARK_INLINE` macro. * Removed need to disable MSVC warnings 4267, 4244, 4800 (Kevin Wojniak). * Fixed MSVC inline errors when cmark is included in sources that don't have the same set of disabled warnings (Kevin Wojniak). * Fix `FileNotFoundError` errors on tests when cmark is built from another project via `add_subdirectory()` (Kevin Wojniak). * Prefix `utf8proc` functions to avoid conflict with existing library (Kevin Wojniak). * Avoid name clash between Windows `.pdb` files (Nick Wellnhofer). * Improved `smart_punct.txt` (see jgm/commonmark.js#61). * Set `POSITION_INDEPENDENT_CODE` `ON` for static library (see #39). * `make bench`: allow overriding `BENCHFILE`. Previously if you did this, it would clopper `BENCHFILE` with the default bench file. * `make bench`: Use -10 priority with renice. * Improved `make_autolink`. Ensures that title is chunk with empty string rather than NULL, as with other links. * Added `clang-check` target. * Travis: split `roundtrip_test` and `leakcheck` (OGINO Masanori). * Use clang-format, llvm style, for formatting. Reformatted all source files. Added `format` target to Makefile. Removed `astyle` target. Updated `.editorconfig`. [0.21.0] * Updated to version 0.21 of spec. * Added latex renderer (#31). New exported function in API: `cmark_render_latex`. New source file: `src/latex.hs`. * Updates for new HTML block spec. Removed old `html_block_tag` scanner. Added new `html_block_start` and `html_block_start_7`, as well as `html_block_end_n` for n = 1-5. Rewrote block parser for new HTML block spec. * We no longer preprocess tabs to spaces before parsing. Instead, we keep track of both the byte offset and the (virtual) column as we parse block starts. This allows us to handle tabs without converting to spaces first. Tabs are left as tabs in the output, as per the revised spec. * Removed utf8 validation by default. We now replace null characters in the line splitting code. * Added `CMARK_OPT_VALIDATE_UTF8` option and command-line option `--validate-utf8`. This option causes cmark to check for valid UTF-8, replacing invalid sequences with the replacement character, U+FFFD. Previously this was done by default in connection with tab expansion, but we no longer do it by default with the new tab treatment. (Many applications will know that the input is valid UTF-8, so validation will not be necessary.) * Added `CMARK_OPT_SAFE` option and `--safe` command-line flag. + Added `CMARK_OPT_SAFE`. This option disables rendering of raw HTML and potentially dangerous links. + Added `--safe` option in command-line program. + Updated `cmark.3` man page. + Added `scan_dangerous_url` to scanners. + In HTML, suppress rendering of raw HTML and potentially dangerous links if `CMARK_OPT_SAFE`. Dangerous URLs are those that begin with `javascript:`, `vbscript:`, `file:`, or `data:` (except for `image/png`, `image/gif`, `image/jpeg`, or `image/webp` mime types). + Added `api_test` for `OPT_CMARK_SAFE`. + Rewrote `README.md` on security. * Limit ordered list start to 9 digits, per spec. * Added width parameter to `render_man` (API change). * Extracted common renderer code from latex, man, and commonmark renderers into a separate module, `renderer.[ch]` (#63). To write a renderer now, you only need to write a character escaping function and a node rendering function. You pass these to `cmark_render` and it handles all the plumbing (including line wrapping) for you. So far this is an internal module, but we might consider adding it to the API in the future. * commonmark writer: correctly handle email autolinks. * commonmark writer: escape `!`. * Fixed soft breaks in commonmark renderer. * Fixed scanner for link url. re2c returns the longest match, so we were getting bad results with `[link](foo\(and\(bar\)\))` which it would parse as containing a bare `\` followed by an in-parens chunk ending with the final paren. * Allow non-initial hyphens in html tag names. This allows for custom tags, see jgm/CommonMark#239. * Updated `test/smart_punct.txt`. * Implemented new treatment of hyphens with `--smart`, converting sequences of hyphens to sequences of em and en dashes that contain no hyphens. * HTML renderer: properly split info on first space char (see jgm/commonmark.js#54). * Changed version variables to functions (#60, Andrius Bentkus). This is easier to access using ffi, since some languages, like C# like to use only function interfaces for accessing library functionality. * `process_emphasis`: Fixed setting lower bound to potential openers. Renamed `potential_openers` -> `openers_bottom`. Renamed `start_delim` -> `stack_bottom`. * Added case for #59 to `pathological_test.py`. * Fixed emphasis/link parsing bug (#59). * Fixed off-by-one error in line splitting routine. This caused certain NULLs not to be replaced. * Don't rtrim in `subject_from_buffer`. This gives bad results in parsing reference links, where we might have trailing blanks (`finalize` removes the bytes parsed as a reference definition; before this change, some blank bytes might remain on the line). + Added `column` and `first_nonspace_column` fields to `parser`. + Added utility function to advance the offset, computing the virtual column too. Note that we don't need to deal with UTF-8 here at all. Only ASCII occurs in block starts. + Significant performance improvement due to the fact that we're not doing UTF-8 validation. * Fixed entity lookup table. The old one had many errors. The new one is derived from the list in the npm entities package. Since the sequences can now be longer (multi-code-point), we have bumped the length limit from 4 to 8, which also affects `houdini_html_u.c`. An example of the kind of error that was fixed: `≧̸` should be rendered as "≧̸" (U+02267 U+00338), but it was being rendered as "≧" (which is the same as `≧`). * Replace gperf-based entity lookup with binary tree lookup. The primary advantage is a big reduction in the size of the compiled library and executable (> 100K). There should be no measurable performance difference in normal documents. I detected only a slight performance hit in a file containing 1,000,000 entities. + Removed `src/html_unescape.gperf` and `src/html_unescape.h`. + Added `src/entities.h` (generated by `tools/make_entities_h.py`). + Added binary tree lookup functions to `houdini_html_u.c`, and use the data in `src/entities.h`. * Renamed `entities.h` -> `entities.inc`, and `tools/make_entities_h.py` -> `tools/make_entitis_inc.py`. * Fixed cases like ``` [ref]: url "title" ok ``` Here we should parse the first line as a reference. * `inlines.c`: Added utility functions to skip spaces and line endings. * Fixed backslashes in link destinations that are not part of escapes (jgm/commonmark#45). * `process_line`: Removed "add newline if line doesn't have one." This isn't actually needed. * Small logic fixes and a simplification in `process_emphasis`. * Added more pathological tests: + Many link closers with no openers. + Many link openers with no closers. + Many emph openers with no closers. + Many closers with no openers. + `"*a_ " * 20000`. * Fixed `process_emphasis` to handle new pathological cases. Now we have an array of pointers (`potential_openers`), keyed to the delim char. When we've failed to match a potential opener prior to point X in the delimiter stack, we reset `potential_openers` for that opener type to X, and thus avoid having to look again through all the openers we've already rejected. * `process_inlines`: remove closers from delim stack when possible. When they have no matching openers and cannot be openers themselves, we can safely remove them. This helps with a performance case: `"a_ " * 20000` (jgm/commonmark.js#43). * Roll utf8proc_charlen into utf8proc_valid (Nick Wellnhofer). Speeds up "make bench" by another percent. * `spec_tests.py`: allow `→` for tab in HTML examples. * `normalize.py`: don't collapse whitespace in pre contexts. * Use utf-8 aware re2c. * Makefile afl target: removed `-m none`, added `CMARK_OPTS`. * README: added `make afl` instructions. * Limit generated generated `cmark.3` to 72 character line width. * Travis: switched to containerized build system. * Removed `debug.h`. (It uses GNU extensions, and we don't need it anyway.) * Removed sundown from benchmarks, because the reading was anomalous. sundown had an arbitrary 16MB limit on buffers, and the benchmark input exceeded that. So who knows what we were actually testing? Added hoedown, sundown's successor, which is a better comparison. [0.20.0] * Fixed bug in list item parsing when items indented >= 4 spaces (#52). * Don't allow link labels with no non-whitespace characters (jgm/CommonMark#322). * Fixed multiple issues with numeric entities (#33, Nick Wellnhofer). * Support CR and CRLF line endings (Ben Trask). * Added test for different line endings to `api_test`. * Allow NULL value in string setters (Nick Wellnhofer). (NULL produces a 0-length string value.) Internally, URL and title are now stored as `cmark_chunk` rather than `char *`. * Fixed memory leak in `cmark_consolidate_text_nodes` (#32). * Fixed `is_autolink` in the CommonMark renderer (#50). Previously *any* link with an absolute URL was treated as an autolink. * Cope with broken `snprintf` on Windows (Nick Wellnhofer). On Windows, `snprintf` returns -1 if the output was truncated. Fall back to Windows-specific `_scprintf`. * Switched length parameter on `cmark_markdown_to_html`, `cmark_parser_feed`, and `cmark_parse_document` from `int` to `size_t` (#53, Nick Wellnhofer). * Use a custom type `bufsize_t` for all string sizes and indices. This allows to switch to 64-bit string buffers by changing a single typedef and a macro definition (Nick Wellnhofer). * Hardened the `strbuf` code, checking for integer overflows and adding range checks (Nick Wellnhofer). * Removed unused function `cmark_strbuf_attach` (Nick Wellnhofer). * Fixed all implicit 64-bit to 32-bit conversions that `-Wshorten-64-to-32` warns about (Nick Wellnhofer). * Added helper function `cmark_strbuf_safe_strlen` that converts from `size_t` to `bufsize_t` and throws an error in case of an overflow (Nick Wellnhofer). * Abort on `strbuf` out of memory errors (Nick Wellnhofer). Previously such errors were not being trapped. This involves some internal changes to the `buffer` library that do not affect the API. * Factored out `S_find_first_nonspace` in `S_proces_line`. Added fields `offset`, `first_nonspace`, `indent`, and `blank` to `cmark_parser` struct. This just removes some repetition. * Added Racket Racket (5.3+) wrapper (Eli Barzilay). * Removed `-pg` from Debug build flags (#47). * Added Ubsan build target, to check for undefined behavior. * Improved `make leakcheck`. We now return an error status if anything in the loop fails. We now check `--smart` and `--normalize` options. * Removed `wrapper3.py`, made `wrapper.py` work with python 2 and 3. Also improved the wrapper to work with Windows, and to use smart punctuation (as an example). * In `wrapper.rb`, added argument for options. * Revised luajit wrapper. * Added build status badges to README.md. * Added links to go, perl, ruby, R, and Haskell bindings to README.md. [0.19.0] * Fixed `_` emphasis parsing to conform to spec (jgm/CommonMark#317). * Updated `spec.txt`. * Compile static library with `-DCMARK_STATIC_DEFINE` (Nick Wellnhofer). * Suppress warnings about Windows runtime library files (Nick Wellnhofer). Visual Studio Express editions do not include the redistributable files. Set `CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS` to suppress warnings. * Added appyeyor: Windows continuous integration (`appveyor.yml`). * Use `os.path.join` in `test/cmark.py` for proper cross-platform paths. * Fixed `Makefile.nmake`. * Improved `make afl`: added `test/afl_dictionary`, increased timeout for hangs. * Improved README with a description of the library's strengths. * Pass-through Unicode non-characters (Nick Wellnhofer). Despite their name, Unicode non-characters are valid code points. They should be passed through by a library like libcmark. * Check return status of `utf8proc_iterate` (#27). [0.18.3] * Include patch level in soname (Nick Wellnhofer). Minor version is tied to spec version, so this allows breaking the ABI between spec releases. * Install compiler-provided system runtime libraries (Changjiang Yang). * Use `strbuf_printf` instead of `snprintf`. `snprintf` is not available on some platforms (Visual Studio 2013 and earlier). * Fixed memory access bug: "invalid read of size 1" on input `[link](<>)`. [0.18.2] * Added commonmark renderer: `cmark_render_commonmark`. In addition to options, this takes a `width` parameter. A value of 0 disables wrapping; a positive value wraps the document to the specified width. Note that width is automatically set to 0 if the `CMARK_OPT_HARDBREAKS` option is set. * The `cmark` executable now allows `-t commonmark` for output as CommonMark. A `--width` option has been added to specify wrapping width. * Added `roundtrip_test` Makefile target. This runs all the spec through the commonmark renderer, and then through the commonmark parser, and compares normalized HTML to the test. All tests pass with the current parser and renderer, giving us some confidence that the commonmark renderer is sufficiently robust. Eventually this should be pythonized and put in the cmake test routine. * Removed an unnecessary check in `blocks.c`. By the time we check for a list start, we've already checked for a horizontal rule, so we don't need to repeat that check here. Thanks to Robin Stocker for pointing out a similar redundancy in commonmark.js. * Fixed bug in `cmark_strbuf_unescape` (`buffer.c`). The old function gave incorrect results on input like `\\*`, since the next backslash would be treated as escaping the `*` instead of being escaped itself. * `scanners.re`: added `_scan_scheme`, `scan_scheme`, used in the commonmark renderer. * Check for `CMAKE_C_COMPILER` (not `CC_COMPILER`) when setting C flags. * Update code examples in documentation, adding new parser option argument, and using `CMARK_OPT_DEFAULT` (Nick Wellnhofer). * Added options parameter to `cmark_markdown_to_html`. * Removed obsolete reference to `CMARK_NODE_LINK_LABEL`. * `make leakcheck` now checks all output formats. * `test/cmark.py`: set default options for `markdown_to_html`. * Warn about buggy re2c versions (Nick Wellnhofer). [0.18.1] * Build static version of library in default build (#11). * `cmark.h`: Add missing argument to `cmark_parser_new` (#12). [0.18] * Switch to 2-clause BSD license, with agreement of contributors. * Added Profile build type, `make prof` target. * Fixed autolink scanner to conform to the spec. Backslash escapes not allowed in autolinks. * Don't rely on strnlen being available (Nick Wellnhofer). * Updated scanners for new whitespace definition. * Added `CMARK_OPT_SMART` and `--smart` option, `smart.c`, `smart.h`. * Added test for `--smart` option. * Fixed segfault with --normalize (closes #7). * Moved normalization step from XML renderer to `cmark_parser_finish`. * Added options parameter to `cmark_parse_document`, `cmark_parse_file`. * Fixed man renderer's escaping for unicode characters. * Don't require python3 to make `cmark.3` man page. * Use ASCII escapes for punctuation characters for portability. * Made `options` an int rather than a long, for consistency. * Packed `cmark_node` struct to fit into 128 bytes. This gives a small performance boost and lowers memory usage. * Repacked `delimiter` struct to avoid hole. * Fixed use-after-free bug, which arose when a paragraph containing only reference links and blank space was finalized (#9). Avoid using `parser->current` in the loop that creates new blocks, since `finalize` in `add_child` may have removed the current parser (if it contains only reference definitions). This isn't a great solution; in the long run we need to rewrite to make the logic clearer and to make it harder to make mistakes like this one. * Added 'Asan' build type. `make asan` will link against ASan; the resulting executable will do checks for memory access issues. Thanks @JordanMilne for the suggestion. * Add Makefile target to fuzz with AFL (Nick Wellnhofer) The variable `$AFL_PATH` must point to the directory containing the AFL binaries. It can be set as an environment variable or passed to make on the command line. [0.17] * Stripped out all JavaScript related code and documentation, moving it to a separate repository (). * Improved Makefile targets, so that `cmake` is run again only when necessary (Nick Wellnhofer). * Added `INSTALL_PREFIX` to the Makefile, allowing installation to a location other than `/usr/local` without invoking `cmake` manually (Nick Wellnhofer). * `make test` now guarantees that the project will be rebuilt before tests are run (Nick Wellnhofer). * Prohibited overriding of some Makefile variables (Nick Wellnhofer). * Provide version number and string, both as macros (`CMARK_VERSION`, `CMARK_VERSION_STRING`) and as symbols (`cmark_version`, `cmark_version_string`) (Nick Wellnhofer). All of these come from `cmark_version.h`, which is constructed from a template `cmark_version.h.in` and data in `CMakeLists.txt`. * Avoid calling `free` on null pointer. * Added an accessor for an iterator's root node (`cmark_iter_get_root`). * Added user data field for nodes (Nick Wellnhofer). This is intended mainly for use in bindings for dynamic languages, where it could store a pointer to a target language object (#287). But it can be used for anything. * Man renderer: properly escape multiline strings. * Added assertion to raise error if finalize is called on a closed block. * Implemented the new spec rule for emphasis and strong emphasis with `_`. * Moved the check for fence-close with the other checks for end-of-block. * Fixed a bug with loose list detection with items containings fenced code blocks (#285). * Removed recursive algorithm in `ends_with_blank_line` (#286). * Minor code reformatting: renamed parameters. [0.16] * Added xml renderer (XML representation of the CommonMark AST, which is described in `CommonMark.dtd`). * Reduced size of gperf entity table (Nick Wellnhofer). * Reworked iterators to allow deletion of nodes during iteration (Nick Wellnhofer). * Optimized `S_is_leaf`. * Added `cmark_iter_reset` to iterator API. * Added `cmark_consolidate_text_nodes` to API to combine adjacent text nodes. * Added `CMARK_OPT_NORMALIZE` to options (this combines adjacent text nodes). * Added `--normalize` option to command-line program. * Improved regex for HTML comments in inline parsing. * Python is no longer required for a basic build from the repository. ================================================ FILE: liteidex/src/3rdparty/cmark/cmark.pri ================================================ LIBS *= -l$$qtLibraryName(cmark) ================================================ FILE: liteidex/src/3rdparty/cmark/cmark.pro ================================================ TEMPLATE = lib CONFIG += staticlib TARGET = cmark include(../../liteideutils.pri) DEFINES += QT_DEPRECATED_WARNINGS INCLUDEPATH += . SOURCES += \ libcmark.cpp \ src/blocks.c \ src/buffer.c \ src/cmark.c \ src/cmark_ctype.c \ src/commonmark.c \ src/houdini_href_e.c \ src/houdini_html_e.c \ src/houdini_html_u.c \ src/html.c \ src/inlines.c \ src/iterator.c \ src/latex.c \ src/man.c \ src/node.c \ src/references.c \ src/render.c \ src/scanners.c \ src/utf8.c \ src/xml.c DISTFILES += \ src/case_fold_switch.inc \ src/entities.inc HEADERS += \ libcmark.h \ src/buffer.h \ src/chunk.h \ src/cmark.h \ src/cmark_ctype.h \ src/houdini.h \ src/inlines.h \ src/iterator.h \ src/node.h \ src/parser.h \ src/references.h \ src/render.h \ src/scanners.h \ src/utf8.h ================================================ FILE: liteidex/src/3rdparty/cmark/cmark_export.h ================================================ #ifndef CMARK_EXPORT_H #define CMARK_EXPORT_H #define CMARK_EXPORT #ifdef CMARK_STATIC_DEFINE # define CMARK_EXPORT # define CMARK_NO_EXPORT #else # ifndef CMARK_EXPORT # ifdef libcmark_EXPORTS /* We are building this library */ # define CMARK_EXPORT __attribute__((visibility("default"))) # else /* We are using this library */ # define CMARK_EXPORT __attribute__((visibility("default"))) # endif # endif # ifndef CMARK_NO_EXPORT # define CMARK_NO_EXPORT __attribute__((visibility("hidden"))) # endif #endif #ifndef CMARK_DEPRECATED # define CMARK_DEPRECATED __attribute__ ((__deprecated__)) #endif #ifndef CMARK_DEPRECATED_EXPORT # define CMARK_DEPRECATED_EXPORT CMARK_EXPORT CMARK_DEPRECATED #endif #ifndef CMARK_DEPRECATED_NO_EXPORT # define CMARK_DEPRECATED_NO_EXPORT CMARK_NO_EXPORT CMARK_DEPRECATED #endif #if 0 /* DEFINE_NO_DEPRECATED */ # ifndef CMARK_NO_DEPRECATED # define CMARK_NO_DEPRECATED # endif #endif #endif /* CMARK_EXPORT_H */ ================================================ FILE: liteidex/src/3rdparty/cmark/cmark_version.h ================================================ #ifndef CMARK_VERSION_H #define CMARK_VERSION_H #define CMARK_VERSION ((0 << 16) | (29 << 8) | 0) #define CMARK_VERSION_STRING "0.29.0" #endif ================================================ FILE: liteidex/src/3rdparty/cmark/config.h ================================================ #ifndef CMARK_CONFIG_H #define CMARK_CONFIG_H #ifdef __cplusplus extern "C" { #endif #define HAVE_STDBOOL_H #ifdef HAVE_STDBOOL_H #include #elif !defined(__cplusplus) typedef char bool; #endif #ifndef _MSC_VER #define HAVE___BUILTIN_EXPECT #endif #define HAVE___ATTRIBUTE__ #ifdef HAVE___ATTRIBUTE__ #define CMARK_ATTRIBUTE(list) __attribute__ (list) #else #define CMARK_ATTRIBUTE(list) #endif #ifndef CMARK_INLINE #if defined(_MSC_VER) && !defined(__cplusplus) #define CMARK_INLINE __inline #else #define CMARK_INLINE inline #endif #endif /* snprintf and vsnprintf fallbacks for MSVC before 2015, due to Valentin Milea http://stackoverflow.com/questions/2915672/ */ #if defined(_MSC_VER) && _MSC_VER < 1900 #include #include #define snprintf c99_snprintf #define vsnprintf c99_vsnprintf CMARK_INLINE int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int count = -1; if (size != 0) count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); if (count == -1) count = _vscprintf(format, ap); return count; } CMARK_INLINE int c99_snprintf(char *outBuf, size_t size, const char *format, ...) { int count; va_list ap; va_start(ap, format); count = c99_vsnprintf(outBuf, size, format, ap); va_end(ap); return count; } #endif #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/libcmark.cpp ================================================ #include "libcmark.h" #include "src/cmark.h" namespace cmark { QByteArray markdown_to_html(const QByteArray &data) { char *buf = cmark_markdown_to_html(data.data(),size_t(data.size()),CMARK_OPT_UNSAFE); QByteArray out(buf); free(buf); return out; } } //cmark ================================================ FILE: liteidex/src/3rdparty/cmark/libcmark.h ================================================ #ifndef LIBCMARK_H #define LIBCMARK_H #include namespace cmark { QByteArray markdown_to_html(const QByteArray &data); } inline QByteArray md2html(const QByteArray &data) { return cmark::markdown_to_html(data); } #endif // LIBCMARK_H ================================================ FILE: liteidex/src/3rdparty/cmark/src/CMakeLists.txt ================================================ if(${CMAKE_VERSION} VERSION_GREATER "3.3") cmake_policy(SET CMP0063 NEW) endif() include(GNUInstallDirs) set(LIBRARY "libcmark") set(STATICLIBRARY "libcmark_static") set(HEADERS cmark.h parser.h buffer.h node.h iterator.h chunk.h references.h utf8.h scanners.h inlines.h houdini.h cmark_ctype.h render.h ) set(LIBRARY_SOURCES cmark.c node.c iterator.c blocks.c inlines.c scanners.c scanners.re utf8.c buffer.c references.c render.c man.c xml.c html.c commonmark.c latex.c houdini_href_e.c houdini_html_e.c houdini_html_u.c cmark_ctype.c ${HEADERS} ) set(PROGRAM "cmark") set(PROGRAM_SOURCES ${LIBRARY_SOURCES} main.c ) include_directories(. ${CMAKE_CURRENT_BINARY_DIR}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmark_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/cmark_version.h) include (GenerateExportHeader) add_executable(${PROGRAM} ${PROGRAM_SOURCES}) # Disable the PUBLIC declarations when compiling the executable: set_target_properties(${PROGRAM} PROPERTIES COMPILE_FLAGS -DCMARK_STATIC_DEFINE) # Check integrity of node structure when compiled as debug: set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DCMARK_DEBUG_NODES") set(CMAKE_LINKER_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE} -pg") set(CMAKE_LINKER_PROFILE "${CMAKE_LINKER_FLAGS_RELEASE} -pg") # -fvisibility=hidden set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) if (CMARK_SHARED) add_library(${LIBRARY} SHARED ${LIBRARY_SOURCES}) # Include minor version and patch level in soname for now. set_target_properties(${LIBRARY} PROPERTIES OUTPUT_NAME "cmark" SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} VERSION ${PROJECT_VERSION}) set_property(TARGET ${LIBRARY} APPEND PROPERTY MACOSX_RPATH true) # Avoid name clash between PROGRAM and LIBRARY pdb files. set_target_properties(${LIBRARY} PROPERTIES PDB_NAME cmark_dll) generate_export_header(${LIBRARY} BASE_NAME ${PROJECT_NAME}) list(APPEND CMARK_INSTALL ${LIBRARY}) endif() if (CMARK_STATIC) add_library(${STATICLIBRARY} STATIC ${LIBRARY_SOURCES}) set_target_properties(${STATICLIBRARY} PROPERTIES COMPILE_FLAGS -DCMARK_STATIC_DEFINE POSITION_INDEPENDENT_CODE ON) if (MSVC) set_target_properties(${STATICLIBRARY} PROPERTIES OUTPUT_NAME "cmark_static" VERSION ${PROJECT_VERSION}) else() set_target_properties(${STATICLIBRARY} PROPERTIES OUTPUT_NAME "cmark" VERSION ${PROJECT_VERSION}) endif(MSVC) if (NOT CMARK_SHARED) generate_export_header(${STATICLIBRARY} BASE_NAME ${PROJECT_NAME}) endif() list(APPEND CMARK_INSTALL ${STATICLIBRARY}) endif() if (MSVC) set_property(TARGET ${PROGRAM} APPEND PROPERTY LINK_FLAGS /INCREMENTAL:NO) endif(MSVC) if(NOT MSVC OR CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) include(InstallRequiredSystemLibraries) endif() set(libdir lib${LIB_SUFFIX}) install(TARGETS ${PROGRAM} ${CMARK_INSTALL} EXPORT cmark RUNTIME DESTINATION bin LIBRARY DESTINATION ${libdir} ARCHIVE DESTINATION ${libdir} ) if(CMARK_SHARED OR CMARK_STATIC) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libcmark.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libcmark.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcmark.pc DESTINATION ${libdir}/pkgconfig) install(FILES cmark.h ${CMAKE_CURRENT_BINARY_DIR}/cmark_export.h ${CMAKE_CURRENT_BINARY_DIR}/cmark_version.h DESTINATION include ) install(EXPORT cmark DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) endif() # Feature tests include(CheckIncludeFile) include(CheckCSourceCompiles) include(CheckCSourceRuns) include(CheckSymbolExists) CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H) CHECK_C_SOURCE_COMPILES( "int main() { __builtin_expect(0,0); return 0; }" HAVE___BUILTIN_EXPECT) CHECK_C_SOURCE_COMPILES(" int f(void) __attribute__ (()); int main() { return 0; } " HAVE___ATTRIBUTE__) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) # Always compile with warnings if(MSVC) # Force to always compile with W4 if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4706 /D_CRT_SECURE_NO_WARNINGS") elseif(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=c99 -pedantic") endif() # Compile as C++ under MSVC older than 12.0 if(MSVC AND MSVC_VERSION LESS 1800) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /TP") endif() if(CMAKE_BUILD_TYPE STREQUAL "Ubsan") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined") endif() if(CMARK_LIB_FUZZER) set(FUZZ_HARNESS "cmark-fuzz") add_executable(${FUZZ_HARNESS} ../test/cmark-fuzz.c ${LIBRARY_SOURCES}) target_link_libraries(${FUZZ_HARNESS} "${CMAKE_LIB_FUZZER_PATH}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-coverage=trace-pc-guard") # cmark is written in C but the libFuzzer runtime is written in C++ which # needs to link against the C++ runtime. Explicitly link it into cmark-fuzz set_target_properties(${FUZZ_HARNESS} PROPERTIES LINK_FLAGS "-lstdc++") endif() ================================================ FILE: liteidex/src/3rdparty/cmark/src/blocks.c ================================================ /** * Block parsing implementation. * * For a high-level overview of the block parsing process, * see http://spec.commonmark.org/0.24/#phase-1-block-structure */ #include #include #include #include "cmark_ctype.h" #include "config.h" #include "parser.h" #include "cmark.h" #include "node.h" #include "references.h" #include "utf8.h" #include "scanners.h" #include "inlines.h" #include "houdini.h" #include "buffer.h" #define CODE_INDENT 4 #define TAB_STOP 4 #ifndef MIN #define MIN(x, y) ((x < y) ? x : y) #endif #define peek_at(i, n) (i)->data[n] static bool S_last_line_blank(const cmark_node *node) { return (node->flags & CMARK_NODE__LAST_LINE_BLANK) != 0; } static bool S_last_line_checked(const cmark_node *node) { return (node->flags & CMARK_NODE__LAST_LINE_CHECKED) != 0; } static CMARK_INLINE cmark_node_type S_type(const cmark_node *node) { return (cmark_node_type)node->type; } static void S_set_last_line_blank(cmark_node *node, bool is_blank) { if (is_blank) node->flags |= CMARK_NODE__LAST_LINE_BLANK; else node->flags &= ~CMARK_NODE__LAST_LINE_BLANK; } static void S_set_last_line_checked(cmark_node *node) { node->flags |= CMARK_NODE__LAST_LINE_CHECKED; } static CMARK_INLINE bool S_is_line_end_char(char c) { return (c == '\n' || c == '\r'); } static CMARK_INLINE bool S_is_space_or_tab(char c) { return (c == ' ' || c == '\t'); } static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer, size_t len, bool eof); static void S_process_line(cmark_parser *parser, const unsigned char *buffer, bufsize_t bytes); static cmark_node *make_block(cmark_mem *mem, cmark_node_type tag, int start_line, int start_column) { cmark_node *e; e = (cmark_node *)mem->calloc(1, sizeof(*e)); cmark_strbuf_init(mem, &e->content, 32); e->type = (uint16_t)tag; e->flags = CMARK_NODE__OPEN; e->start_line = start_line; e->start_column = start_column; e->end_line = start_line; return e; } // Create a root document node. static cmark_node *make_document(cmark_mem *mem) { cmark_node *e = make_block(mem, CMARK_NODE_DOCUMENT, 1, 1); return e; } cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem) { cmark_parser *parser = (cmark_parser *)mem->calloc(1, sizeof(cmark_parser)); parser->mem = mem; cmark_node *document = make_document(mem); cmark_strbuf_init(mem, &parser->curline, 256); cmark_strbuf_init(mem, &parser->linebuf, 0); parser->refmap = cmark_reference_map_new(mem); parser->root = document; parser->current = document; parser->line_number = 0; parser->offset = 0; parser->column = 0; parser->first_nonspace = 0; parser->first_nonspace_column = 0; parser->thematic_break_kill_pos = 0; parser->indent = 0; parser->blank = false; parser->partially_consumed_tab = false; parser->last_line_length = 0; parser->options = options; parser->last_buffer_ended_with_cr = false; return parser; } cmark_parser *cmark_parser_new(int options) { extern cmark_mem DEFAULT_MEM_ALLOCATOR; return cmark_parser_new_with_mem(options, &DEFAULT_MEM_ALLOCATOR); } void cmark_parser_free(cmark_parser *parser) { cmark_mem *mem = parser->mem; cmark_strbuf_free(&parser->curline); cmark_strbuf_free(&parser->linebuf); cmark_reference_map_free(parser->refmap); mem->free(parser); } static cmark_node *finalize(cmark_parser *parser, cmark_node *b); // Returns true if line has only space characters, else false. static bool is_blank(cmark_strbuf *s, bufsize_t offset) { while (offset < s->size) { switch (s->ptr[offset]) { case '\r': case '\n': return true; case ' ': offset++; break; case '\t': offset++; break; default: return false; } } return true; } static CMARK_INLINE bool can_contain(cmark_node_type parent_type, cmark_node_type child_type) { return (parent_type == CMARK_NODE_DOCUMENT || parent_type == CMARK_NODE_BLOCK_QUOTE || parent_type == CMARK_NODE_ITEM || (parent_type == CMARK_NODE_LIST && child_type == CMARK_NODE_ITEM)); } static CMARK_INLINE bool accepts_lines(cmark_node_type block_type) { return (block_type == CMARK_NODE_PARAGRAPH || block_type == CMARK_NODE_HEADING || block_type == CMARK_NODE_CODE_BLOCK); } static CMARK_INLINE bool contains_inlines(cmark_node_type block_type) { return (block_type == CMARK_NODE_PARAGRAPH || block_type == CMARK_NODE_HEADING); } static void add_line(cmark_node *node, cmark_chunk *ch, cmark_parser *parser) { int chars_to_tab; int i; assert(node->flags & CMARK_NODE__OPEN); if (parser->partially_consumed_tab) { parser->offset += 1; // skip over tab // add space characters: chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); for (i = 0; i < chars_to_tab; i++) { cmark_strbuf_putc(&node->content, ' '); } } cmark_strbuf_put(&node->content, ch->data + parser->offset, ch->len - parser->offset); } static void remove_trailing_blank_lines(cmark_strbuf *ln) { bufsize_t i; unsigned char c; for (i = ln->size - 1; i >= 0; --i) { c = ln->ptr[i]; if (c != ' ' && c != '\t' && !S_is_line_end_char(c)) break; } if (i < 0) { cmark_strbuf_clear(ln); return; } for (; i < ln->size; ++i) { c = ln->ptr[i]; if (!S_is_line_end_char(c)) continue; cmark_strbuf_truncate(ln, i); break; } } // Check to see if a node ends with a blank line, descending // if needed into lists and sublists. static bool S_ends_with_blank_line(cmark_node *node) { if (S_last_line_checked(node)) { return(S_last_line_blank(node)); } else if ((S_type(node) == CMARK_NODE_LIST || S_type(node) == CMARK_NODE_ITEM) && node->last_child) { S_set_last_line_checked(node); return(S_ends_with_blank_line(node->last_child)); } else { S_set_last_line_checked(node); return (S_last_line_blank(node)); } } // returns true if content remains after link defs are resolved. static bool resolve_reference_link_definitions( cmark_parser *parser, cmark_node *b) { bufsize_t pos; cmark_strbuf *node_content = &b->content; cmark_chunk chunk = {node_content->ptr, node_content->size, 0}; while (chunk.len && chunk.data[0] == '[' && (pos = cmark_parse_reference_inline(parser->mem, &chunk, parser->refmap))) { chunk.data += pos; chunk.len -= pos; } cmark_strbuf_drop(node_content, (node_content->size - chunk.len)); return !is_blank(&b->content, 0); } static cmark_node *finalize(cmark_parser *parser, cmark_node *b) { bufsize_t pos; cmark_node *item; cmark_node *subitem; cmark_node *parent; bool has_content; parent = b->parent; assert(b->flags & CMARK_NODE__OPEN); // shouldn't call finalize on closed blocks b->flags &= ~CMARK_NODE__OPEN; if (parser->curline.size == 0) { // end of input - line number has not been incremented b->end_line = parser->line_number; b->end_column = parser->last_line_length; } else if (S_type(b) == CMARK_NODE_DOCUMENT || (S_type(b) == CMARK_NODE_CODE_BLOCK && b->as.code.fenced) || (S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext)) { b->end_line = parser->line_number; b->end_column = parser->curline.size; if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\n') b->end_column -= 1; if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\r') b->end_column -= 1; } else { b->end_line = parser->line_number - 1; b->end_column = parser->last_line_length; } cmark_strbuf *node_content = &b->content; switch (S_type(b)) { case CMARK_NODE_PARAGRAPH: { has_content = resolve_reference_link_definitions(parser, b); if (!has_content) { // remove blank node (former reference def) cmark_node_free(b); } break; } case CMARK_NODE_CODE_BLOCK: if (!b->as.code.fenced) { // indented code remove_trailing_blank_lines(node_content); cmark_strbuf_putc(node_content, '\n'); } else { // first line of contents becomes info for (pos = 0; pos < node_content->size; ++pos) { if (S_is_line_end_char(node_content->ptr[pos])) break; } assert(pos < node_content->size); cmark_strbuf tmp = CMARK_BUF_INIT(parser->mem); houdini_unescape_html_f(&tmp, node_content->ptr, pos); cmark_strbuf_trim(&tmp); cmark_strbuf_unescape(&tmp); b->as.code.info = cmark_chunk_buf_detach(&tmp); if (node_content->ptr[pos] == '\r') pos += 1; if (node_content->ptr[pos] == '\n') pos += 1; cmark_strbuf_drop(node_content, pos); } b->as.code.literal = cmark_chunk_buf_detach(node_content); break; case CMARK_NODE_HTML_BLOCK: b->as.literal = cmark_chunk_buf_detach(node_content); break; case CMARK_NODE_LIST: // determine tight/loose status b->as.list.tight = true; // tight by default item = b->first_child; while (item) { // check for non-final non-empty list item ending with blank line: if (S_last_line_blank(item) && item->next) { b->as.list.tight = false; break; } // recurse into children of list item, to see if there are // spaces between them: subitem = item->first_child; while (subitem) { if ((item->next || subitem->next) && S_ends_with_blank_line(subitem)) { b->as.list.tight = false; break; } subitem = subitem->next; } if (!(b->as.list.tight)) { break; } item = item->next; } break; default: break; } return parent; } // Add a node as child of another. Return pointer to child. static cmark_node *add_child(cmark_parser *parser, cmark_node *parent, cmark_node_type block_type, int start_column) { assert(parent); // if 'parent' isn't the kind of node that can accept this child, // then back up til we hit a node that can. while (!can_contain(S_type(parent), block_type)) { parent = finalize(parser, parent); } cmark_node *child = make_block(parser->mem, block_type, parser->line_number, start_column); child->parent = parent; if (parent->last_child) { parent->last_child->next = child; child->prev = parent->last_child; } else { parent->first_child = child; child->prev = NULL; } parent->last_child = child; return child; } // Walk through node and all children, recursively, parsing // string content into inline content where appropriate. static void process_inlines(cmark_mem *mem, cmark_node *root, cmark_reference_map *refmap, int options) { cmark_iter *iter = cmark_iter_new(root); cmark_node *cur; cmark_event_type ev_type; while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { cur = cmark_iter_get_node(iter); if (ev_type == CMARK_EVENT_ENTER) { if (contains_inlines(S_type(cur))) { cmark_parse_inlines(mem, cur, refmap, options); } } } cmark_iter_free(iter); } // Attempts to parse a list item marker (bullet or enumerated). // On success, returns length of the marker, and populates // data with the details. On failure, returns 0. static bufsize_t parse_list_marker(cmark_mem *mem, cmark_chunk *input, bufsize_t pos, bool interrupts_paragraph, cmark_list **dataptr) { unsigned char c; bufsize_t startpos; cmark_list *data; bufsize_t i; startpos = pos; c = peek_at(input, pos); if (c == '*' || c == '-' || c == '+') { pos++; if (!cmark_isspace(peek_at(input, pos))) { return 0; } if (interrupts_paragraph) { i = pos; // require non-blank content after list marker: while (S_is_space_or_tab(peek_at(input, i))) { i++; } if (peek_at(input, i) == '\n') { return 0; } } data = (cmark_list *)mem->calloc(1, sizeof(*data)); data->marker_offset = 0; // will be adjusted later data->list_type = CMARK_BULLET_LIST; data->bullet_char = c; data->start = 0; data->delimiter = CMARK_NO_DELIM; data->tight = false; } else if (cmark_isdigit(c)) { int start = 0; int digits = 0; do { start = (10 * start) + (peek_at(input, pos) - '0'); pos++; digits++; // We limit to 9 digits to avoid overflow, // assuming max int is 2^31 - 1 // This also seems to be the limit for 'start' in some browsers. } while (digits < 9 && cmark_isdigit(peek_at(input, pos))); if (interrupts_paragraph && start != 1) { return 0; } c = peek_at(input, pos); if (c == '.' || c == ')') { pos++; if (!cmark_isspace(peek_at(input, pos))) { return 0; } if (interrupts_paragraph) { // require non-blank content after list marker: i = pos; while (S_is_space_or_tab(peek_at(input, i))) { i++; } if (S_is_line_end_char(peek_at(input, i))) { return 0; } } data = (cmark_list *)mem->calloc(1, sizeof(*data)); data->marker_offset = 0; // will be adjusted later data->list_type = CMARK_ORDERED_LIST; data->bullet_char = 0; data->start = start; data->delimiter = (c == '.' ? CMARK_PERIOD_DELIM : CMARK_PAREN_DELIM); data->tight = false; } else { return 0; } } else { return 0; } *dataptr = data; return (pos - startpos); } // Return 1 if list item belongs in list, else 0. static int lists_match(cmark_list *list_data, cmark_list *item_data) { return (list_data->list_type == item_data->list_type && list_data->delimiter == item_data->delimiter && // list_data->marker_offset == item_data.marker_offset && list_data->bullet_char == item_data->bullet_char); } static cmark_node *finalize_document(cmark_parser *parser) { while (parser->current != parser->root) { parser->current = finalize(parser, parser->current); } finalize(parser, parser->root); process_inlines(parser->mem, parser->root, parser->refmap, parser->options); return parser->root; } cmark_node *cmark_parse_file(FILE *f, int options) { unsigned char buffer[4096]; cmark_parser *parser = cmark_parser_new(options); size_t bytes; cmark_node *document; while ((bytes = fread(buffer, 1, sizeof(buffer), f)) > 0) { bool eof = bytes < sizeof(buffer); S_parser_feed(parser, buffer, bytes, eof); if (eof) { break; } } document = cmark_parser_finish(parser); cmark_parser_free(parser); return document; } cmark_node *cmark_parse_document(const char *buffer, size_t len, int options) { cmark_parser *parser = cmark_parser_new(options); cmark_node *document; S_parser_feed(parser, (const unsigned char *)buffer, len, true); document = cmark_parser_finish(parser); cmark_parser_free(parser); return document; } void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len) { S_parser_feed(parser, (const unsigned char *)buffer, len, false); } static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer, size_t len, bool eof) { const unsigned char *end = buffer + len; static const uint8_t repl[] = {239, 191, 189}; if (parser->last_buffer_ended_with_cr && *buffer == '\n') { // skip NL if last buffer ended with CR ; see #117 buffer++; } parser->last_buffer_ended_with_cr = false; while (buffer < end) { const unsigned char *eol; bufsize_t chunk_len; bool process = false; for (eol = buffer; eol < end; ++eol) { if (S_is_line_end_char(*eol)) { process = true; break; } if (*eol == '\0' && eol < end) { break; } } if (eol >= end && eof) { process = true; } chunk_len = (eol - buffer); if (process) { if (parser->linebuf.size > 0) { cmark_strbuf_put(&parser->linebuf, buffer, chunk_len); S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size); cmark_strbuf_clear(&parser->linebuf); } else { S_process_line(parser, buffer, chunk_len); } } else { if (eol < end && *eol == '\0') { // omit NULL byte cmark_strbuf_put(&parser->linebuf, buffer, chunk_len); // add replacement character cmark_strbuf_put(&parser->linebuf, repl, 3); } else { cmark_strbuf_put(&parser->linebuf, buffer, chunk_len); } } buffer += chunk_len; if (buffer < end) { if (*buffer == '\0') { // skip over NULL buffer++; } else { // skip over line ending characters if (*buffer == '\r') { buffer++; if (buffer == end) parser->last_buffer_ended_with_cr = true; } if (buffer < end && *buffer == '\n') buffer++; } } } } static void chop_trailing_hashtags(cmark_chunk *ch) { bufsize_t n, orig_n; cmark_chunk_rtrim(ch); orig_n = n = ch->len - 1; // if string ends in space followed by #s, remove these: while (n >= 0 && peek_at(ch, n) == '#') n--; // Check for a space before the final #s: if (n != orig_n && n >= 0 && S_is_space_or_tab(peek_at(ch, n))) { ch->len = n; cmark_chunk_rtrim(ch); } } // Check for thematic break. On failure, return 0 and update // thematic_break_kill_pos with the index at which the // parse fails. On success, return length of match. // "...three or more hyphens, asterisks, // or underscores on a line by themselves. If you wish, you may use // spaces between the hyphens or asterisks." static int S_scan_thematic_break(cmark_parser *parser, cmark_chunk *input, bufsize_t offset) { bufsize_t i; char c; char nextc = '\0'; int count; i = offset; c = peek_at(input, i); if (!(c == '*' || c == '_' || c == '-')) { parser->thematic_break_kill_pos = i; return 0; } count = 1; while ((nextc = peek_at(input, ++i))) { if (nextc == c) { count++; } else if (nextc != ' ' && nextc != '\t') { break; } } if (count >= 3 && (nextc == '\r' || nextc == '\n')) { return (i - offset) + 1; } else { parser->thematic_break_kill_pos = i; return 0; } } // Find first nonspace character from current offset, setting // parser->first_nonspace, parser->first_nonspace_column, // parser->indent, and parser->blank. Does not advance parser->offset. static void S_find_first_nonspace(cmark_parser *parser, cmark_chunk *input) { char c; int chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); if (parser->first_nonspace <= parser->offset) { parser->first_nonspace = parser->offset; parser->first_nonspace_column = parser->column; while ((c = peek_at(input, parser->first_nonspace))) { if (c == ' ') { parser->first_nonspace += 1; parser->first_nonspace_column += 1; chars_to_tab = chars_to_tab - 1; if (chars_to_tab == 0) { chars_to_tab = TAB_STOP; } } else if (c == '\t') { parser->first_nonspace += 1; parser->first_nonspace_column += chars_to_tab; chars_to_tab = TAB_STOP; } else { break; } } } parser->indent = parser->first_nonspace_column - parser->column; parser->blank = S_is_line_end_char(peek_at(input, parser->first_nonspace)); } // Advance parser->offset and parser->column. parser->offset is the // byte position in input; parser->column is a virtual column number // that takes into account tabs. (Multibyte characters are not taken // into account, because the Markdown line prefixes we are interested in // analyzing are entirely ASCII.) The count parameter indicates // how far to advance the offset. If columns is true, then count // indicates a number of columns; otherwise, a number of bytes. // If advancing a certain number of columns partially consumes // a tab character, parser->partially_consumed_tab is set to true. static void S_advance_offset(cmark_parser *parser, cmark_chunk *input, bufsize_t count, bool columns) { char c; int chars_to_tab; int chars_to_advance; while (count > 0 && (c = peek_at(input, parser->offset))) { if (c == '\t') { chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); if (columns) { parser->partially_consumed_tab = chars_to_tab > count; chars_to_advance = MIN(count, chars_to_tab); parser->column += chars_to_advance; parser->offset += (parser->partially_consumed_tab ? 0 : 1); count -= chars_to_advance; } else { parser->partially_consumed_tab = false; parser->column += chars_to_tab; parser->offset += 1; count -= 1; } } else { parser->partially_consumed_tab = false; parser->offset += 1; parser->column += 1; // assume ascii; block starts are ascii count -= 1; } } } static bool S_last_child_is_open(cmark_node *container) { return container->last_child && (container->last_child->flags & CMARK_NODE__OPEN); } static bool parse_block_quote_prefix(cmark_parser *parser, cmark_chunk *input) { bool res = false; bufsize_t matched = 0; matched = parser->indent <= 3 && peek_at(input, parser->first_nonspace) == '>'; if (matched) { S_advance_offset(parser, input, parser->indent + 1, true); if (S_is_space_or_tab(peek_at(input, parser->offset))) { S_advance_offset(parser, input, 1, true); } res = true; } return res; } static bool parse_node_item_prefix(cmark_parser *parser, cmark_chunk *input, cmark_node *container) { bool res = false; if (parser->indent >= container->as.list.marker_offset + container->as.list.padding) { S_advance_offset(parser, input, container->as.list.marker_offset + container->as.list.padding, true); res = true; } else if (parser->blank && container->first_child != NULL) { // if container->first_child is NULL, then the opening line // of the list item was blank after the list marker; in this // case, we are done with the list item. S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false); res = true; } return res; } static bool parse_code_block_prefix(cmark_parser *parser, cmark_chunk *input, cmark_node *container, bool *should_continue) { bool res = false; if (!container->as.code.fenced) { // indented if (parser->indent >= CODE_INDENT) { S_advance_offset(parser, input, CODE_INDENT, true); res = true; } else if (parser->blank) { S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false); res = true; } } else { // fenced bufsize_t matched = 0; if (parser->indent <= 3 && (peek_at(input, parser->first_nonspace) == container->as.code.fence_char)) { matched = scan_close_code_fence(input, parser->first_nonspace); } if (matched >= container->as.code.fence_length) { // closing fence - and since we're at // the end of a line, we can stop processing it: *should_continue = false; S_advance_offset(parser, input, matched, false); parser->current = finalize(parser, container); } else { // skip opt. spaces of fence parser->offset int i = container->as.code.fence_offset; while (i > 0 && S_is_space_or_tab(peek_at(input, parser->offset))) { S_advance_offset(parser, input, 1, true); i--; } res = true; } } return res; } static bool parse_html_block_prefix(cmark_parser *parser, cmark_node *container) { bool res = false; int html_block_type = container->as.html_block_type; assert(html_block_type >= 1 && html_block_type <= 7); switch (html_block_type) { case 1: case 2: case 3: case 4: case 5: // these types of blocks can accept blanks res = true; break; case 6: case 7: res = !parser->blank; break; } return res; } /** * For each containing node, try to parse the associated line start. * * Will not close unmatched blocks, as we may have a lazy continuation * line -> http://spec.commonmark.org/0.24/#lazy-continuation-line * * Returns: The last matching node, or NULL */ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input, bool *all_matched) { bool should_continue = true; *all_matched = false; cmark_node *container = parser->root; cmark_node_type cont_type; while (S_last_child_is_open(container)) { container = container->last_child; cont_type = S_type(container); S_find_first_nonspace(parser, input); switch (cont_type) { case CMARK_NODE_BLOCK_QUOTE: if (!parse_block_quote_prefix(parser, input)) goto done; break; case CMARK_NODE_ITEM: if (!parse_node_item_prefix(parser, input, container)) goto done; break; case CMARK_NODE_CODE_BLOCK: if (!parse_code_block_prefix(parser, input, container, &should_continue)) goto done; break; case CMARK_NODE_HEADING: // a heading can never contain more than one line goto done; case CMARK_NODE_HTML_BLOCK: if (!parse_html_block_prefix(parser, container)) goto done; break; case CMARK_NODE_PARAGRAPH: if (parser->blank) goto done; break; default: break; } } *all_matched = true; done: if (!*all_matched) { container = container->parent; // back up to last matching node } if (!should_continue) { container = NULL; } return container; } static void open_new_blocks(cmark_parser *parser, cmark_node **container, cmark_chunk *input, bool all_matched) { bool indented; cmark_list *data = NULL; bool maybe_lazy = S_type(parser->current) == CMARK_NODE_PARAGRAPH; cmark_node_type cont_type = S_type(*container); bufsize_t matched = 0; int lev = 0; bool save_partially_consumed_tab; bool has_content; int save_offset; int save_column; while (cont_type != CMARK_NODE_CODE_BLOCK && cont_type != CMARK_NODE_HTML_BLOCK) { S_find_first_nonspace(parser, input); indented = parser->indent >= CODE_INDENT; if (!indented && peek_at(input, parser->first_nonspace) == '>') { bufsize_t blockquote_startpos = parser->first_nonspace; S_advance_offset(parser, input, parser->first_nonspace + 1 - parser->offset, false); // optional following character if (S_is_space_or_tab(peek_at(input, parser->offset))) { S_advance_offset(parser, input, 1, true); } *container = add_child(parser, *container, CMARK_NODE_BLOCK_QUOTE, blockquote_startpos + 1); } else if (!indented && (matched = scan_atx_heading_start( input, parser->first_nonspace))) { bufsize_t hashpos; int level = 0; bufsize_t heading_startpos = parser->first_nonspace; S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false); *container = add_child(parser, *container, CMARK_NODE_HEADING, heading_startpos + 1); hashpos = cmark_chunk_strchr(input, '#', parser->first_nonspace); while (peek_at(input, hashpos) == '#') { level++; hashpos++; } (*container)->as.heading.level = level; (*container)->as.heading.setext = false; (*container)->internal_offset = matched; } else if (!indented && (matched = scan_open_code_fence( input, parser->first_nonspace))) { *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK, parser->first_nonspace + 1); (*container)->as.code.fenced = true; (*container)->as.code.fence_char = peek_at(input, parser->first_nonspace); (*container)->as.code.fence_length = (matched > 255) ? 255 : matched; (*container)->as.code.fence_offset = (int8_t)(parser->first_nonspace - parser->offset); (*container)->as.code.info = cmark_chunk_literal(""); S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false); } else if (!indented && ((matched = scan_html_block_start( input, parser->first_nonspace)) || (cont_type != CMARK_NODE_PARAGRAPH && (matched = scan_html_block_start_7( input, parser->first_nonspace))))) { *container = add_child(parser, *container, CMARK_NODE_HTML_BLOCK, parser->first_nonspace + 1); (*container)->as.html_block_type = matched; // note, we don't adjust parser->offset because the tag is part of the // text } else if (!indented && cont_type == CMARK_NODE_PARAGRAPH && (lev = scan_setext_heading_line(input, parser->first_nonspace))) { // finalize paragraph, resolving reference links has_content = resolve_reference_link_definitions(parser, *container); if (has_content) { (*container)->type = (uint16_t)CMARK_NODE_HEADING; (*container)->as.heading.level = lev; (*container)->as.heading.setext = true; S_advance_offset(parser, input, input->len - 1 - parser->offset, false); } } else if (!indented && !(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) && (parser->thematic_break_kill_pos <= parser->first_nonspace) && (matched = S_scan_thematic_break(parser, input, parser->first_nonspace))) { // it's only now that we know the line is not part of a setext heading: *container = add_child(parser, *container, CMARK_NODE_THEMATIC_BREAK, parser->first_nonspace + 1); S_advance_offset(parser, input, input->len - 1 - parser->offset, false); } else if ((!indented || cont_type == CMARK_NODE_LIST) && parser->indent < 4 && (matched = parse_list_marker( parser->mem, input, parser->first_nonspace, (*container)->type == CMARK_NODE_PARAGRAPH, &data))) { // Note that we can have new list items starting with >= 4 // spaces indent, as long as the list container is still open. int i = 0; // compute padding: S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false); save_partially_consumed_tab = parser->partially_consumed_tab; save_offset = parser->offset; save_column = parser->column; while (parser->column - save_column <= 5 && S_is_space_or_tab(peek_at(input, parser->offset))) { S_advance_offset(parser, input, 1, true); } i = parser->column - save_column; if (i >= 5 || i < 1 || // only spaces after list marker: S_is_line_end_char(peek_at(input, parser->offset))) { data->padding = matched + 1; parser->offset = save_offset; parser->column = save_column; parser->partially_consumed_tab = save_partially_consumed_tab; if (i > 0) { S_advance_offset(parser, input, 1, true); } } else { data->padding = matched + i; } // check container; if it's a list, see if this list item // can continue the list; otherwise, create a list container. data->marker_offset = parser->indent; if (cont_type != CMARK_NODE_LIST || !lists_match(&((*container)->as.list), data)) { *container = add_child(parser, *container, CMARK_NODE_LIST, parser->first_nonspace + 1); memcpy(&((*container)->as.list), data, sizeof(*data)); } // add the list item *container = add_child(parser, *container, CMARK_NODE_ITEM, parser->first_nonspace + 1); /* TODO: static */ memcpy(&((*container)->as.list), data, sizeof(*data)); parser->mem->free(data); } else if (indented && !maybe_lazy && !parser->blank) { S_advance_offset(parser, input, CODE_INDENT, true); *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK, parser->offset + 1); (*container)->as.code.fenced = false; (*container)->as.code.fence_char = 0; (*container)->as.code.fence_length = 0; (*container)->as.code.fence_offset = 0; (*container)->as.code.info = cmark_chunk_literal(""); } else { break; } if (accepts_lines(S_type(*container))) { // if it's a line container, it can't contain other containers break; } cont_type = S_type(*container); maybe_lazy = false; } } static void add_text_to_container(cmark_parser *parser, cmark_node *container, cmark_node *last_matched_container, cmark_chunk *input) { cmark_node *tmp; // what remains at parser->offset is a text line. add the text to the // appropriate container. S_find_first_nonspace(parser, input); if (parser->blank && container->last_child) S_set_last_line_blank(container->last_child, true); // block quote lines are never blank as they start with > // and we don't count blanks in fenced code for purposes of tight/loose // lists or breaking out of lists. we also don't set last_line_blank // on an empty list item. const cmark_node_type ctype = S_type(container); const bool last_line_blank = (parser->blank && ctype != CMARK_NODE_BLOCK_QUOTE && ctype != CMARK_NODE_HEADING && ctype != CMARK_NODE_THEMATIC_BREAK && !(ctype == CMARK_NODE_CODE_BLOCK && container->as.code.fenced) && !(ctype == CMARK_NODE_ITEM && container->first_child == NULL && container->start_line == parser->line_number)); S_set_last_line_blank(container, last_line_blank); tmp = container; while (tmp->parent) { S_set_last_line_blank(tmp->parent, false); tmp = tmp->parent; } // If the last line processed belonged to a paragraph node, // and we didn't match all of the line prefixes for the open containers, // and we didn't start any new containers, // and the line isn't blank, // then treat this as a "lazy continuation line" and add it to // the open paragraph. if (parser->current != last_matched_container && container == last_matched_container && !parser->blank && S_type(parser->current) == CMARK_NODE_PARAGRAPH) { add_line(parser->current, input, parser); } else { // not a lazy continuation // Finalize any blocks that were not matched and set cur to container: while (parser->current != last_matched_container) { parser->current = finalize(parser, parser->current); assert(parser->current != NULL); } if (S_type(container) == CMARK_NODE_CODE_BLOCK) { add_line(container, input, parser); } else if (S_type(container) == CMARK_NODE_HTML_BLOCK) { add_line(container, input, parser); int matches_end_condition; switch (container->as.html_block_type) { case 1: // , , matches_end_condition = scan_html_block_end_1(input, parser->first_nonspace); break; case 2: // --> matches_end_condition = scan_html_block_end_2(input, parser->first_nonspace); break; case 3: // ?> matches_end_condition = scan_html_block_end_3(input, parser->first_nonspace); break; case 4: // > matches_end_condition = scan_html_block_end_4(input, parser->first_nonspace); break; case 5: // ]]> matches_end_condition = scan_html_block_end_5(input, parser->first_nonspace); break; default: matches_end_condition = 0; break; } if (matches_end_condition) { container = finalize(parser, container); assert(parser->current != NULL); } } else if (parser->blank) { // ??? do nothing } else if (accepts_lines(S_type(container))) { if (S_type(container) == CMARK_NODE_HEADING && container->as.heading.setext == false) { chop_trailing_hashtags(input); } S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false); add_line(container, input, parser); } else { // create paragraph container for line container = add_child(parser, container, CMARK_NODE_PARAGRAPH, parser->first_nonspace + 1); S_advance_offset(parser, input, parser->first_nonspace - parser->offset, false); add_line(container, input, parser); } parser->current = container; } } /* See http://spec.commonmark.org/0.24/#phase-1-block-structure */ static void S_process_line(cmark_parser *parser, const unsigned char *buffer, bufsize_t bytes) { cmark_node *last_matched_container; bool all_matched = true; cmark_node *container; cmark_chunk input; if (parser->options & CMARK_OPT_VALIDATE_UTF8) cmark_utf8proc_check(&parser->curline, buffer, bytes); else cmark_strbuf_put(&parser->curline, buffer, bytes); bytes = parser->curline.size; // ensure line ends with a newline: if (bytes == 0 || !S_is_line_end_char(parser->curline.ptr[bytes - 1])) cmark_strbuf_putc(&parser->curline, '\n'); parser->offset = 0; parser->column = 0; parser->first_nonspace = 0; parser->first_nonspace_column = 0; parser->thematic_break_kill_pos = 0; parser->indent = 0; parser->blank = false; parser->partially_consumed_tab = false; input.data = parser->curline.ptr; input.len = parser->curline.size; input.alloc = 0; parser->line_number++; last_matched_container = check_open_blocks(parser, &input, &all_matched); if (!last_matched_container) goto finished; container = last_matched_container; open_new_blocks(parser, &container, &input, all_matched); add_text_to_container(parser, container, last_matched_container, &input); finished: parser->last_line_length = input.len; if (parser->last_line_length && input.data[parser->last_line_length - 1] == '\n') parser->last_line_length -= 1; if (parser->last_line_length && input.data[parser->last_line_length - 1] == '\r') parser->last_line_length -= 1; cmark_strbuf_clear(&parser->curline); } cmark_node *cmark_parser_finish(cmark_parser *parser) { if (parser->linebuf.size) { S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size); cmark_strbuf_clear(&parser->linebuf); } finalize_document(parser); cmark_consolidate_text_nodes(parser->root); cmark_strbuf_free(&parser->curline); #if CMARK_DEBUG_NODES if (cmark_node_check(parser->root, stderr)) { abort(); } #endif return parser->root; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/buffer.c ================================================ #include #include #include #include #include #include #include #include #include "config.h" #include "cmark_ctype.h" #include "buffer.h" /* Used as default value for cmark_strbuf->ptr so that people can always * assume ptr is non-NULL and zero terminated even for new cmark_strbufs. */ unsigned char cmark_strbuf__initbuf[1]; #ifndef MIN #define MIN(x, y) ((x < y) ? x : y) #endif void cmark_strbuf_init(cmark_mem *mem, cmark_strbuf *buf, bufsize_t initial_size) { buf->mem = mem; buf->asize = 0; buf->size = 0; buf->ptr = cmark_strbuf__initbuf; if (initial_size > 0) cmark_strbuf_grow(buf, initial_size); } static CMARK_INLINE void S_strbuf_grow_by(cmark_strbuf *buf, bufsize_t add) { cmark_strbuf_grow(buf, buf->size + add); } void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) { assert(target_size > 0); if (target_size < buf->asize) return; if (target_size > (bufsize_t)(INT32_MAX / 2)) { fprintf(stderr, "[cmark] cmark_strbuf_grow requests buffer with size > %d, aborting\n", (INT32_MAX / 2)); abort(); } /* Oversize the buffer by 50% to guarantee amortized linear time * complexity on append operations. */ bufsize_t new_size = target_size + target_size / 2; new_size += 1; new_size = (new_size + 7) & ~7; buf->ptr = (unsigned char *)buf->mem->realloc(buf->asize ? buf->ptr : NULL, new_size); buf->asize = new_size; } bufsize_t cmark_strbuf_len(const cmark_strbuf *buf) { return buf->size; } void cmark_strbuf_free(cmark_strbuf *buf) { if (!buf) return; if (buf->ptr != cmark_strbuf__initbuf) buf->mem->free(buf->ptr); cmark_strbuf_init(buf->mem, buf, 0); } void cmark_strbuf_clear(cmark_strbuf *buf) { buf->size = 0; if (buf->asize > 0) buf->ptr[0] = '\0'; } void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, bufsize_t len) { if (len <= 0 || data == NULL) { cmark_strbuf_clear(buf); } else { if (data != buf->ptr) { if (len >= buf->asize) cmark_strbuf_grow(buf, len); memmove(buf->ptr, data, len); } buf->size = len; buf->ptr[buf->size] = '\0'; } } void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) { cmark_strbuf_set(buf, (const unsigned char *)string, string ? strlen(string) : 0); } void cmark_strbuf_putc(cmark_strbuf *buf, int c) { S_strbuf_grow_by(buf, 1); buf->ptr[buf->size++] = (unsigned char)(c & 0xFF); buf->ptr[buf->size] = '\0'; } void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, bufsize_t len) { if (len <= 0) return; S_strbuf_grow_by(buf, len); memmove(buf->ptr + buf->size, data, len); buf->size += len; buf->ptr[buf->size] = '\0'; } void cmark_strbuf_puts(cmark_strbuf *buf, const char *string) { cmark_strbuf_put(buf, (const unsigned char *)string, strlen(string)); } void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, const cmark_strbuf *buf) { bufsize_t copylen; assert(buf); if (!data || datasize <= 0) return; data[0] = '\0'; if (buf->size == 0 || buf->asize <= 0) return; copylen = buf->size; if (copylen > datasize - 1) copylen = datasize - 1; memmove(data, buf->ptr, copylen); data[copylen] = '\0'; } void cmark_strbuf_swap(cmark_strbuf *buf_a, cmark_strbuf *buf_b) { cmark_strbuf t = *buf_a; *buf_a = *buf_b; *buf_b = t; } unsigned char *cmark_strbuf_detach(cmark_strbuf *buf) { unsigned char *data = buf->ptr; if (buf->asize == 0) { /* return an empty string */ return (unsigned char *)buf->mem->calloc(1, 1); } cmark_strbuf_init(buf->mem, buf, 0); return data; } int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b) { int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size)); return (result != 0) ? result : (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; } bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos) { if (pos >= buf->size) return -1; if (pos < 0) pos = 0; const unsigned char *p = (unsigned char *)memchr(buf->ptr + pos, c, buf->size - pos); if (!p) return -1; return (bufsize_t)(p - (const unsigned char *)buf->ptr); } bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos) { if (pos < 0 || buf->size == 0) return -1; if (pos >= buf->size) pos = buf->size - 1; bufsize_t i; for (i = pos; i >= 0; i--) { if (buf->ptr[i] == (unsigned char)c) return i; } return -1; } void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len) { if (len < 0) len = 0; if (len < buf->size) { buf->size = len; buf->ptr[buf->size] = '\0'; } } void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n) { if (n > 0) { if (n > buf->size) n = buf->size; buf->size = buf->size - n; if (buf->size) memmove(buf->ptr, buf->ptr + n, buf->size); buf->ptr[buf->size] = '\0'; } } void cmark_strbuf_rtrim(cmark_strbuf *buf) { if (!buf->size) return; while (buf->size > 0) { if (!cmark_isspace(buf->ptr[buf->size - 1])) break; buf->size--; } buf->ptr[buf->size] = '\0'; } void cmark_strbuf_trim(cmark_strbuf *buf) { bufsize_t i = 0; if (!buf->size) return; while (i < buf->size && cmark_isspace(buf->ptr[i])) i++; cmark_strbuf_drop(buf, i); cmark_strbuf_rtrim(buf); } // Destructively modify string, collapsing consecutive // space and newline characters into a single space. void cmark_strbuf_normalize_whitespace(cmark_strbuf *s) { bool last_char_was_space = false; bufsize_t r, w; for (r = 0, w = 0; r < s->size; ++r) { if (cmark_isspace(s->ptr[r])) { if (!last_char_was_space) { s->ptr[w++] = ' '; last_char_was_space = true; } } else { s->ptr[w++] = s->ptr[r]; last_char_was_space = false; } } cmark_strbuf_truncate(s, w); } // Destructively unescape a string: remove backslashes before punctuation chars. extern void cmark_strbuf_unescape(cmark_strbuf *buf) { bufsize_t r, w; for (r = 0, w = 0; r < buf->size; ++r) { if (buf->ptr[r] == '\\' && cmark_ispunct(buf->ptr[r + 1])) r++; buf->ptr[w++] = buf->ptr[r]; } cmark_strbuf_truncate(buf, w); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/buffer.h ================================================ #ifndef CMARK_BUFFER_H #define CMARK_BUFFER_H #include #include #include #include #include #include "config.h" #include "cmark.h" #ifdef __cplusplus extern "C" { #endif typedef int32_t bufsize_t; typedef struct { cmark_mem *mem; unsigned char *ptr; bufsize_t asize, size; } cmark_strbuf; extern unsigned char cmark_strbuf__initbuf[]; #define CMARK_BUF_INIT(mem) \ { mem, cmark_strbuf__initbuf, 0, 0 } /** * Initialize a cmark_strbuf structure. * * For the cases where CMARK_BUF_INIT cannot be used to do static * initialization. */ void cmark_strbuf_init(cmark_mem *mem, cmark_strbuf *buf, bufsize_t initial_size); /** * Grow the buffer to hold at least `target_size` bytes. */ void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size); void cmark_strbuf_free(cmark_strbuf *buf); void cmark_strbuf_swap(cmark_strbuf *buf_a, cmark_strbuf *buf_b); bufsize_t cmark_strbuf_len(const cmark_strbuf *buf); int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b); unsigned char *cmark_strbuf_detach(cmark_strbuf *buf); void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, const cmark_strbuf *buf); static CMARK_INLINE const char *cmark_strbuf_cstr(const cmark_strbuf *buf) { return (char *)buf->ptr; } #define cmark_strbuf_at(buf, n) ((buf)->ptr[n]) void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, bufsize_t len); void cmark_strbuf_sets(cmark_strbuf *buf, const char *string); void cmark_strbuf_putc(cmark_strbuf *buf, int c); void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, bufsize_t len); void cmark_strbuf_puts(cmark_strbuf *buf, const char *string); void cmark_strbuf_clear(cmark_strbuf *buf); bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos); bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos); void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n); void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len); void cmark_strbuf_rtrim(cmark_strbuf *buf); void cmark_strbuf_trim(cmark_strbuf *buf); void cmark_strbuf_normalize_whitespace(cmark_strbuf *s); void cmark_strbuf_unescape(cmark_strbuf *s); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/case_fold_switch.inc ================================================ switch (c) { case 0x0041: bufpush(0x0061); break; case 0x0042: bufpush(0x0062); break; case 0x0043: bufpush(0x0063); break; case 0x0044: bufpush(0x0064); break; case 0x0045: bufpush(0x0065); break; case 0x0046: bufpush(0x0066); break; case 0x0047: bufpush(0x0067); break; case 0x0048: bufpush(0x0068); break; case 0x0049: bufpush(0x0069); break; case 0x004A: bufpush(0x006A); break; case 0x004B: bufpush(0x006B); break; case 0x004C: bufpush(0x006C); break; case 0x004D: bufpush(0x006D); break; case 0x004E: bufpush(0x006E); break; case 0x004F: bufpush(0x006F); break; case 0x0050: bufpush(0x0070); break; case 0x0051: bufpush(0x0071); break; case 0x0052: bufpush(0x0072); break; case 0x0053: bufpush(0x0073); break; case 0x0054: bufpush(0x0074); break; case 0x0055: bufpush(0x0075); break; case 0x0056: bufpush(0x0076); break; case 0x0057: bufpush(0x0077); break; case 0x0058: bufpush(0x0078); break; case 0x0059: bufpush(0x0079); break; case 0x005A: bufpush(0x007A); break; case 0x00B5: bufpush(0x03BC); break; case 0x00C0: bufpush(0x00E0); break; case 0x00C1: bufpush(0x00E1); break; case 0x00C2: bufpush(0x00E2); break; case 0x00C3: bufpush(0x00E3); break; case 0x00C4: bufpush(0x00E4); break; case 0x00C5: bufpush(0x00E5); break; case 0x00C6: bufpush(0x00E6); break; case 0x00C7: bufpush(0x00E7); break; case 0x00C8: bufpush(0x00E8); break; case 0x00C9: bufpush(0x00E9); break; case 0x00CA: bufpush(0x00EA); break; case 0x00CB: bufpush(0x00EB); break; case 0x00CC: bufpush(0x00EC); break; case 0x00CD: bufpush(0x00ED); break; case 0x00CE: bufpush(0x00EE); break; case 0x00CF: bufpush(0x00EF); break; case 0x00D0: bufpush(0x00F0); break; case 0x00D1: bufpush(0x00F1); break; case 0x00D2: bufpush(0x00F2); break; case 0x00D3: bufpush(0x00F3); break; case 0x00D4: bufpush(0x00F4); break; case 0x00D5: bufpush(0x00F5); break; case 0x00D6: bufpush(0x00F6); break; case 0x00D8: bufpush(0x00F8); break; case 0x00D9: bufpush(0x00F9); break; case 0x00DA: bufpush(0x00FA); break; case 0x00DB: bufpush(0x00FB); break; case 0x00DC: bufpush(0x00FC); break; case 0x00DD: bufpush(0x00FD); break; case 0x00DE: bufpush(0x00FE); break; case 0x00DF: bufpush(0x0073); bufpush(0x0073); break; case 0x0100: bufpush(0x0101); break; case 0x0102: bufpush(0x0103); break; case 0x0104: bufpush(0x0105); break; case 0x0106: bufpush(0x0107); break; case 0x0108: bufpush(0x0109); break; case 0x010A: bufpush(0x010B); break; case 0x010C: bufpush(0x010D); break; case 0x010E: bufpush(0x010F); break; case 0x0110: bufpush(0x0111); break; case 0x0112: bufpush(0x0113); break; case 0x0114: bufpush(0x0115); break; case 0x0116: bufpush(0x0117); break; case 0x0118: bufpush(0x0119); break; case 0x011A: bufpush(0x011B); break; case 0x011C: bufpush(0x011D); break; case 0x011E: bufpush(0x011F); break; case 0x0120: bufpush(0x0121); break; case 0x0122: bufpush(0x0123); break; case 0x0124: bufpush(0x0125); break; case 0x0126: bufpush(0x0127); break; case 0x0128: bufpush(0x0129); break; case 0x012A: bufpush(0x012B); break; case 0x012C: bufpush(0x012D); break; case 0x012E: bufpush(0x012F); break; case 0x0130: bufpush(0x0069); bufpush(0x0307); break; case 0x0132: bufpush(0x0133); break; case 0x0134: bufpush(0x0135); break; case 0x0136: bufpush(0x0137); break; case 0x0139: bufpush(0x013A); break; case 0x013B: bufpush(0x013C); break; case 0x013D: bufpush(0x013E); break; case 0x013F: bufpush(0x0140); break; case 0x0141: bufpush(0x0142); break; case 0x0143: bufpush(0x0144); break; case 0x0145: bufpush(0x0146); break; case 0x0147: bufpush(0x0148); break; case 0x0149: bufpush(0x02BC); bufpush(0x006E); break; case 0x014A: bufpush(0x014B); break; case 0x014C: bufpush(0x014D); break; case 0x014E: bufpush(0x014F); break; case 0x0150: bufpush(0x0151); break; case 0x0152: bufpush(0x0153); break; case 0x0154: bufpush(0x0155); break; case 0x0156: bufpush(0x0157); break; case 0x0158: bufpush(0x0159); break; case 0x015A: bufpush(0x015B); break; case 0x015C: bufpush(0x015D); break; case 0x015E: bufpush(0x015F); break; case 0x0160: bufpush(0x0161); break; case 0x0162: bufpush(0x0163); break; case 0x0164: bufpush(0x0165); break; case 0x0166: bufpush(0x0167); break; case 0x0168: bufpush(0x0169); break; case 0x016A: bufpush(0x016B); break; case 0x016C: bufpush(0x016D); break; case 0x016E: bufpush(0x016F); break; case 0x0170: bufpush(0x0171); break; case 0x0172: bufpush(0x0173); break; case 0x0174: bufpush(0x0175); break; case 0x0176: bufpush(0x0177); break; case 0x0178: bufpush(0x00FF); break; case 0x0179: bufpush(0x017A); break; case 0x017B: bufpush(0x017C); break; case 0x017D: bufpush(0x017E); break; case 0x017F: bufpush(0x0073); break; case 0x0181: bufpush(0x0253); break; case 0x0182: bufpush(0x0183); break; case 0x0184: bufpush(0x0185); break; case 0x0186: bufpush(0x0254); break; case 0x0187: bufpush(0x0188); break; case 0x0189: bufpush(0x0256); break; case 0x018A: bufpush(0x0257); break; case 0x018B: bufpush(0x018C); break; case 0x018E: bufpush(0x01DD); break; case 0x018F: bufpush(0x0259); break; case 0x0190: bufpush(0x025B); break; case 0x0191: bufpush(0x0192); break; case 0x0193: bufpush(0x0260); break; case 0x0194: bufpush(0x0263); break; case 0x0196: bufpush(0x0269); break; case 0x0197: bufpush(0x0268); break; case 0x0198: bufpush(0x0199); break; case 0x019C: bufpush(0x026F); break; case 0x019D: bufpush(0x0272); break; case 0x019F: bufpush(0x0275); break; case 0x01A0: bufpush(0x01A1); break; case 0x01A2: bufpush(0x01A3); break; case 0x01A4: bufpush(0x01A5); break; case 0x01A6: bufpush(0x0280); break; case 0x01A7: bufpush(0x01A8); break; case 0x01A9: bufpush(0x0283); break; case 0x01AC: bufpush(0x01AD); break; case 0x01AE: bufpush(0x0288); break; case 0x01AF: bufpush(0x01B0); break; case 0x01B1: bufpush(0x028A); break; case 0x01B2: bufpush(0x028B); break; case 0x01B3: bufpush(0x01B4); break; case 0x01B5: bufpush(0x01B6); break; case 0x01B7: bufpush(0x0292); break; case 0x01B8: bufpush(0x01B9); break; case 0x01BC: bufpush(0x01BD); break; case 0x01C4: bufpush(0x01C6); break; case 0x01C5: bufpush(0x01C6); break; case 0x01C7: bufpush(0x01C9); break; case 0x01C8: bufpush(0x01C9); break; case 0x01CA: bufpush(0x01CC); break; case 0x01CB: bufpush(0x01CC); break; case 0x01CD: bufpush(0x01CE); break; case 0x01CF: bufpush(0x01D0); break; case 0x01D1: bufpush(0x01D2); break; case 0x01D3: bufpush(0x01D4); break; case 0x01D5: bufpush(0x01D6); break; case 0x01D7: bufpush(0x01D8); break; case 0x01D9: bufpush(0x01DA); break; case 0x01DB: bufpush(0x01DC); break; case 0x01DE: bufpush(0x01DF); break; case 0x01E0: bufpush(0x01E1); break; case 0x01E2: bufpush(0x01E3); break; case 0x01E4: bufpush(0x01E5); break; case 0x01E6: bufpush(0x01E7); break; case 0x01E8: bufpush(0x01E9); break; case 0x01EA: bufpush(0x01EB); break; case 0x01EC: bufpush(0x01ED); break; case 0x01EE: bufpush(0x01EF); break; case 0x01F0: bufpush(0x006A); bufpush(0x030C); break; case 0x01F1: bufpush(0x01F3); break; case 0x01F2: bufpush(0x01F3); break; case 0x01F4: bufpush(0x01F5); break; case 0x01F6: bufpush(0x0195); break; case 0x01F7: bufpush(0x01BF); break; case 0x01F8: bufpush(0x01F9); break; case 0x01FA: bufpush(0x01FB); break; case 0x01FC: bufpush(0x01FD); break; case 0x01FE: bufpush(0x01FF); break; case 0x0200: bufpush(0x0201); break; case 0x0202: bufpush(0x0203); break; case 0x0204: bufpush(0x0205); break; case 0x0206: bufpush(0x0207); break; case 0x0208: bufpush(0x0209); break; case 0x020A: bufpush(0x020B); break; case 0x020C: bufpush(0x020D); break; case 0x020E: bufpush(0x020F); break; case 0x0210: bufpush(0x0211); break; case 0x0212: bufpush(0x0213); break; case 0x0214: bufpush(0x0215); break; case 0x0216: bufpush(0x0217); break; case 0x0218: bufpush(0x0219); break; case 0x021A: bufpush(0x021B); break; case 0x021C: bufpush(0x021D); break; case 0x021E: bufpush(0x021F); break; case 0x0220: bufpush(0x019E); break; case 0x0222: bufpush(0x0223); break; case 0x0224: bufpush(0x0225); break; case 0x0226: bufpush(0x0227); break; case 0x0228: bufpush(0x0229); break; case 0x022A: bufpush(0x022B); break; case 0x022C: bufpush(0x022D); break; case 0x022E: bufpush(0x022F); break; case 0x0230: bufpush(0x0231); break; case 0x0232: bufpush(0x0233); break; case 0x023A: bufpush(0x2C65); break; case 0x023B: bufpush(0x023C); break; case 0x023D: bufpush(0x019A); break; case 0x023E: bufpush(0x2C66); break; case 0x0241: bufpush(0x0242); break; case 0x0243: bufpush(0x0180); break; case 0x0244: bufpush(0x0289); break; case 0x0245: bufpush(0x028C); break; case 0x0246: bufpush(0x0247); break; case 0x0248: bufpush(0x0249); break; case 0x024A: bufpush(0x024B); break; case 0x024C: bufpush(0x024D); break; case 0x024E: bufpush(0x024F); break; case 0x0345: bufpush(0x03B9); break; case 0x0370: bufpush(0x0371); break; case 0x0372: bufpush(0x0373); break; case 0x0376: bufpush(0x0377); break; case 0x037F: bufpush(0x03F3); break; case 0x0386: bufpush(0x03AC); break; case 0x0388: bufpush(0x03AD); break; case 0x0389: bufpush(0x03AE); break; case 0x038A: bufpush(0x03AF); break; case 0x038C: bufpush(0x03CC); break; case 0x038E: bufpush(0x03CD); break; case 0x038F: bufpush(0x03CE); break; case 0x0390: bufpush(0x03B9); bufpush(0x0308); bufpush(0x0301); break; case 0x0391: bufpush(0x03B1); break; case 0x0392: bufpush(0x03B2); break; case 0x0393: bufpush(0x03B3); break; case 0x0394: bufpush(0x03B4); break; case 0x0395: bufpush(0x03B5); break; case 0x0396: bufpush(0x03B6); break; case 0x0397: bufpush(0x03B7); break; case 0x0398: bufpush(0x03B8); break; case 0x0399: bufpush(0x03B9); break; case 0x039A: bufpush(0x03BA); break; case 0x039B: bufpush(0x03BB); break; case 0x039C: bufpush(0x03BC); break; case 0x039D: bufpush(0x03BD); break; case 0x039E: bufpush(0x03BE); break; case 0x039F: bufpush(0x03BF); break; case 0x03A0: bufpush(0x03C0); break; case 0x03A1: bufpush(0x03C1); break; case 0x03A3: bufpush(0x03C3); break; case 0x03A4: bufpush(0x03C4); break; case 0x03A5: bufpush(0x03C5); break; case 0x03A6: bufpush(0x03C6); break; case 0x03A7: bufpush(0x03C7); break; case 0x03A8: bufpush(0x03C8); break; case 0x03A9: bufpush(0x03C9); break; case 0x03AA: bufpush(0x03CA); break; case 0x03AB: bufpush(0x03CB); break; case 0x03B0: bufpush(0x03C5); bufpush(0x0308); bufpush(0x0301); break; case 0x03C2: bufpush(0x03C3); break; case 0x03CF: bufpush(0x03D7); break; case 0x03D0: bufpush(0x03B2); break; case 0x03D1: bufpush(0x03B8); break; case 0x03D5: bufpush(0x03C6); break; case 0x03D6: bufpush(0x03C0); break; case 0x03D8: bufpush(0x03D9); break; case 0x03DA: bufpush(0x03DB); break; case 0x03DC: bufpush(0x03DD); break; case 0x03DE: bufpush(0x03DF); break; case 0x03E0: bufpush(0x03E1); break; case 0x03E2: bufpush(0x03E3); break; case 0x03E4: bufpush(0x03E5); break; case 0x03E6: bufpush(0x03E7); break; case 0x03E8: bufpush(0x03E9); break; case 0x03EA: bufpush(0x03EB); break; case 0x03EC: bufpush(0x03ED); break; case 0x03EE: bufpush(0x03EF); break; case 0x03F0: bufpush(0x03BA); break; case 0x03F1: bufpush(0x03C1); break; case 0x03F4: bufpush(0x03B8); break; case 0x03F5: bufpush(0x03B5); break; case 0x03F7: bufpush(0x03F8); break; case 0x03F9: bufpush(0x03F2); break; case 0x03FA: bufpush(0x03FB); break; case 0x03FD: bufpush(0x037B); break; case 0x03FE: bufpush(0x037C); break; case 0x03FF: bufpush(0x037D); break; case 0x0400: bufpush(0x0450); break; case 0x0401: bufpush(0x0451); break; case 0x0402: bufpush(0x0452); break; case 0x0403: bufpush(0x0453); break; case 0x0404: bufpush(0x0454); break; case 0x0405: bufpush(0x0455); break; case 0x0406: bufpush(0x0456); break; case 0x0407: bufpush(0x0457); break; case 0x0408: bufpush(0x0458); break; case 0x0409: bufpush(0x0459); break; case 0x040A: bufpush(0x045A); break; case 0x040B: bufpush(0x045B); break; case 0x040C: bufpush(0x045C); break; case 0x040D: bufpush(0x045D); break; case 0x040E: bufpush(0x045E); break; case 0x040F: bufpush(0x045F); break; case 0x0410: bufpush(0x0430); break; case 0x0411: bufpush(0x0431); break; case 0x0412: bufpush(0x0432); break; case 0x0413: bufpush(0x0433); break; case 0x0414: bufpush(0x0434); break; case 0x0415: bufpush(0x0435); break; case 0x0416: bufpush(0x0436); break; case 0x0417: bufpush(0x0437); break; case 0x0418: bufpush(0x0438); break; case 0x0419: bufpush(0x0439); break; case 0x041A: bufpush(0x043A); break; case 0x041B: bufpush(0x043B); break; case 0x041C: bufpush(0x043C); break; case 0x041D: bufpush(0x043D); break; case 0x041E: bufpush(0x043E); break; case 0x041F: bufpush(0x043F); break; case 0x0420: bufpush(0x0440); break; case 0x0421: bufpush(0x0441); break; case 0x0422: bufpush(0x0442); break; case 0x0423: bufpush(0x0443); break; case 0x0424: bufpush(0x0444); break; case 0x0425: bufpush(0x0445); break; case 0x0426: bufpush(0x0446); break; case 0x0427: bufpush(0x0447); break; case 0x0428: bufpush(0x0448); break; case 0x0429: bufpush(0x0449); break; case 0x042A: bufpush(0x044A); break; case 0x042B: bufpush(0x044B); break; case 0x042C: bufpush(0x044C); break; case 0x042D: bufpush(0x044D); break; case 0x042E: bufpush(0x044E); break; case 0x042F: bufpush(0x044F); break; case 0x0460: bufpush(0x0461); break; case 0x0462: bufpush(0x0463); break; case 0x0464: bufpush(0x0465); break; case 0x0466: bufpush(0x0467); break; case 0x0468: bufpush(0x0469); break; case 0x046A: bufpush(0x046B); break; case 0x046C: bufpush(0x046D); break; case 0x046E: bufpush(0x046F); break; case 0x0470: bufpush(0x0471); break; case 0x0472: bufpush(0x0473); break; case 0x0474: bufpush(0x0475); break; case 0x0476: bufpush(0x0477); break; case 0x0478: bufpush(0x0479); break; case 0x047A: bufpush(0x047B); break; case 0x047C: bufpush(0x047D); break; case 0x047E: bufpush(0x047F); break; case 0x0480: bufpush(0x0481); break; case 0x048A: bufpush(0x048B); break; case 0x048C: bufpush(0x048D); break; case 0x048E: bufpush(0x048F); break; case 0x0490: bufpush(0x0491); break; case 0x0492: bufpush(0x0493); break; case 0x0494: bufpush(0x0495); break; case 0x0496: bufpush(0x0497); break; case 0x0498: bufpush(0x0499); break; case 0x049A: bufpush(0x049B); break; case 0x049C: bufpush(0x049D); break; case 0x049E: bufpush(0x049F); break; case 0x04A0: bufpush(0x04A1); break; case 0x04A2: bufpush(0x04A3); break; case 0x04A4: bufpush(0x04A5); break; case 0x04A6: bufpush(0x04A7); break; case 0x04A8: bufpush(0x04A9); break; case 0x04AA: bufpush(0x04AB); break; case 0x04AC: bufpush(0x04AD); break; case 0x04AE: bufpush(0x04AF); break; case 0x04B0: bufpush(0x04B1); break; case 0x04B2: bufpush(0x04B3); break; case 0x04B4: bufpush(0x04B5); break; case 0x04B6: bufpush(0x04B7); break; case 0x04B8: bufpush(0x04B9); break; case 0x04BA: bufpush(0x04BB); break; case 0x04BC: bufpush(0x04BD); break; case 0x04BE: bufpush(0x04BF); break; case 0x04C0: bufpush(0x04CF); break; case 0x04C1: bufpush(0x04C2); break; case 0x04C3: bufpush(0x04C4); break; case 0x04C5: bufpush(0x04C6); break; case 0x04C7: bufpush(0x04C8); break; case 0x04C9: bufpush(0x04CA); break; case 0x04CB: bufpush(0x04CC); break; case 0x04CD: bufpush(0x04CE); break; case 0x04D0: bufpush(0x04D1); break; case 0x04D2: bufpush(0x04D3); break; case 0x04D4: bufpush(0x04D5); break; case 0x04D6: bufpush(0x04D7); break; case 0x04D8: bufpush(0x04D9); break; case 0x04DA: bufpush(0x04DB); break; case 0x04DC: bufpush(0x04DD); break; case 0x04DE: bufpush(0x04DF); break; case 0x04E0: bufpush(0x04E1); break; case 0x04E2: bufpush(0x04E3); break; case 0x04E4: bufpush(0x04E5); break; case 0x04E6: bufpush(0x04E7); break; case 0x04E8: bufpush(0x04E9); break; case 0x04EA: bufpush(0x04EB); break; case 0x04EC: bufpush(0x04ED); break; case 0x04EE: bufpush(0x04EF); break; case 0x04F0: bufpush(0x04F1); break; case 0x04F2: bufpush(0x04F3); break; case 0x04F4: bufpush(0x04F5); break; case 0x04F6: bufpush(0x04F7); break; case 0x04F8: bufpush(0x04F9); break; case 0x04FA: bufpush(0x04FB); break; case 0x04FC: bufpush(0x04FD); break; case 0x04FE: bufpush(0x04FF); break; case 0x0500: bufpush(0x0501); break; case 0x0502: bufpush(0x0503); break; case 0x0504: bufpush(0x0505); break; case 0x0506: bufpush(0x0507); break; case 0x0508: bufpush(0x0509); break; case 0x050A: bufpush(0x050B); break; case 0x050C: bufpush(0x050D); break; case 0x050E: bufpush(0x050F); break; case 0x0510: bufpush(0x0511); break; case 0x0512: bufpush(0x0513); break; case 0x0514: bufpush(0x0515); break; case 0x0516: bufpush(0x0517); break; case 0x0518: bufpush(0x0519); break; case 0x051A: bufpush(0x051B); break; case 0x051C: bufpush(0x051D); break; case 0x051E: bufpush(0x051F); break; case 0x0520: bufpush(0x0521); break; case 0x0522: bufpush(0x0523); break; case 0x0524: bufpush(0x0525); break; case 0x0526: bufpush(0x0527); break; case 0x0528: bufpush(0x0529); break; case 0x052A: bufpush(0x052B); break; case 0x052C: bufpush(0x052D); break; case 0x052E: bufpush(0x052F); break; case 0x0531: bufpush(0x0561); break; case 0x0532: bufpush(0x0562); break; case 0x0533: bufpush(0x0563); break; case 0x0534: bufpush(0x0564); break; case 0x0535: bufpush(0x0565); break; case 0x0536: bufpush(0x0566); break; case 0x0537: bufpush(0x0567); break; case 0x0538: bufpush(0x0568); break; case 0x0539: bufpush(0x0569); break; case 0x053A: bufpush(0x056A); break; case 0x053B: bufpush(0x056B); break; case 0x053C: bufpush(0x056C); break; case 0x053D: bufpush(0x056D); break; case 0x053E: bufpush(0x056E); break; case 0x053F: bufpush(0x056F); break; case 0x0540: bufpush(0x0570); break; case 0x0541: bufpush(0x0571); break; case 0x0542: bufpush(0x0572); break; case 0x0543: bufpush(0x0573); break; case 0x0544: bufpush(0x0574); break; case 0x0545: bufpush(0x0575); break; case 0x0546: bufpush(0x0576); break; case 0x0547: bufpush(0x0577); break; case 0x0548: bufpush(0x0578); break; case 0x0549: bufpush(0x0579); break; case 0x054A: bufpush(0x057A); break; case 0x054B: bufpush(0x057B); break; case 0x054C: bufpush(0x057C); break; case 0x054D: bufpush(0x057D); break; case 0x054E: bufpush(0x057E); break; case 0x054F: bufpush(0x057F); break; case 0x0550: bufpush(0x0580); break; case 0x0551: bufpush(0x0581); break; case 0x0552: bufpush(0x0582); break; case 0x0553: bufpush(0x0583); break; case 0x0554: bufpush(0x0584); break; case 0x0555: bufpush(0x0585); break; case 0x0556: bufpush(0x0586); break; case 0x0587: bufpush(0x0565); bufpush(0x0582); break; case 0x10A0: bufpush(0x2D00); break; case 0x10A1: bufpush(0x2D01); break; case 0x10A2: bufpush(0x2D02); break; case 0x10A3: bufpush(0x2D03); break; case 0x10A4: bufpush(0x2D04); break; case 0x10A5: bufpush(0x2D05); break; case 0x10A6: bufpush(0x2D06); break; case 0x10A7: bufpush(0x2D07); break; case 0x10A8: bufpush(0x2D08); break; case 0x10A9: bufpush(0x2D09); break; case 0x10AA: bufpush(0x2D0A); break; case 0x10AB: bufpush(0x2D0B); break; case 0x10AC: bufpush(0x2D0C); break; case 0x10AD: bufpush(0x2D0D); break; case 0x10AE: bufpush(0x2D0E); break; case 0x10AF: bufpush(0x2D0F); break; case 0x10B0: bufpush(0x2D10); break; case 0x10B1: bufpush(0x2D11); break; case 0x10B2: bufpush(0x2D12); break; case 0x10B3: bufpush(0x2D13); break; case 0x10B4: bufpush(0x2D14); break; case 0x10B5: bufpush(0x2D15); break; case 0x10B6: bufpush(0x2D16); break; case 0x10B7: bufpush(0x2D17); break; case 0x10B8: bufpush(0x2D18); break; case 0x10B9: bufpush(0x2D19); break; case 0x10BA: bufpush(0x2D1A); break; case 0x10BB: bufpush(0x2D1B); break; case 0x10BC: bufpush(0x2D1C); break; case 0x10BD: bufpush(0x2D1D); break; case 0x10BE: bufpush(0x2D1E); break; case 0x10BF: bufpush(0x2D1F); break; case 0x10C0: bufpush(0x2D20); break; case 0x10C1: bufpush(0x2D21); break; case 0x10C2: bufpush(0x2D22); break; case 0x10C3: bufpush(0x2D23); break; case 0x10C4: bufpush(0x2D24); break; case 0x10C5: bufpush(0x2D25); break; case 0x10C7: bufpush(0x2D27); break; case 0x10CD: bufpush(0x2D2D); break; case 0x13F8: bufpush(0x13F0); break; case 0x13F9: bufpush(0x13F1); break; case 0x13FA: bufpush(0x13F2); break; case 0x13FB: bufpush(0x13F3); break; case 0x13FC: bufpush(0x13F4); break; case 0x13FD: bufpush(0x13F5); break; case 0x1C80: bufpush(0x0432); break; case 0x1C81: bufpush(0x0434); break; case 0x1C82: bufpush(0x043E); break; case 0x1C83: bufpush(0x0441); break; case 0x1C84: bufpush(0x0442); break; case 0x1C85: bufpush(0x0442); break; case 0x1C86: bufpush(0x044A); break; case 0x1C87: bufpush(0x0463); break; case 0x1C88: bufpush(0xA64B); break; case 0x1E00: bufpush(0x1E01); break; case 0x1E02: bufpush(0x1E03); break; case 0x1E04: bufpush(0x1E05); break; case 0x1E06: bufpush(0x1E07); break; case 0x1E08: bufpush(0x1E09); break; case 0x1E0A: bufpush(0x1E0B); break; case 0x1E0C: bufpush(0x1E0D); break; case 0x1E0E: bufpush(0x1E0F); break; case 0x1E10: bufpush(0x1E11); break; case 0x1E12: bufpush(0x1E13); break; case 0x1E14: bufpush(0x1E15); break; case 0x1E16: bufpush(0x1E17); break; case 0x1E18: bufpush(0x1E19); break; case 0x1E1A: bufpush(0x1E1B); break; case 0x1E1C: bufpush(0x1E1D); break; case 0x1E1E: bufpush(0x1E1F); break; case 0x1E20: bufpush(0x1E21); break; case 0x1E22: bufpush(0x1E23); break; case 0x1E24: bufpush(0x1E25); break; case 0x1E26: bufpush(0x1E27); break; case 0x1E28: bufpush(0x1E29); break; case 0x1E2A: bufpush(0x1E2B); break; case 0x1E2C: bufpush(0x1E2D); break; case 0x1E2E: bufpush(0x1E2F); break; case 0x1E30: bufpush(0x1E31); break; case 0x1E32: bufpush(0x1E33); break; case 0x1E34: bufpush(0x1E35); break; case 0x1E36: bufpush(0x1E37); break; case 0x1E38: bufpush(0x1E39); break; case 0x1E3A: bufpush(0x1E3B); break; case 0x1E3C: bufpush(0x1E3D); break; case 0x1E3E: bufpush(0x1E3F); break; case 0x1E40: bufpush(0x1E41); break; case 0x1E42: bufpush(0x1E43); break; case 0x1E44: bufpush(0x1E45); break; case 0x1E46: bufpush(0x1E47); break; case 0x1E48: bufpush(0x1E49); break; case 0x1E4A: bufpush(0x1E4B); break; case 0x1E4C: bufpush(0x1E4D); break; case 0x1E4E: bufpush(0x1E4F); break; case 0x1E50: bufpush(0x1E51); break; case 0x1E52: bufpush(0x1E53); break; case 0x1E54: bufpush(0x1E55); break; case 0x1E56: bufpush(0x1E57); break; case 0x1E58: bufpush(0x1E59); break; case 0x1E5A: bufpush(0x1E5B); break; case 0x1E5C: bufpush(0x1E5D); break; case 0x1E5E: bufpush(0x1E5F); break; case 0x1E60: bufpush(0x1E61); break; case 0x1E62: bufpush(0x1E63); break; case 0x1E64: bufpush(0x1E65); break; case 0x1E66: bufpush(0x1E67); break; case 0x1E68: bufpush(0x1E69); break; case 0x1E6A: bufpush(0x1E6B); break; case 0x1E6C: bufpush(0x1E6D); break; case 0x1E6E: bufpush(0x1E6F); break; case 0x1E70: bufpush(0x1E71); break; case 0x1E72: bufpush(0x1E73); break; case 0x1E74: bufpush(0x1E75); break; case 0x1E76: bufpush(0x1E77); break; case 0x1E78: bufpush(0x1E79); break; case 0x1E7A: bufpush(0x1E7B); break; case 0x1E7C: bufpush(0x1E7D); break; case 0x1E7E: bufpush(0x1E7F); break; case 0x1E80: bufpush(0x1E81); break; case 0x1E82: bufpush(0x1E83); break; case 0x1E84: bufpush(0x1E85); break; case 0x1E86: bufpush(0x1E87); break; case 0x1E88: bufpush(0x1E89); break; case 0x1E8A: bufpush(0x1E8B); break; case 0x1E8C: bufpush(0x1E8D); break; case 0x1E8E: bufpush(0x1E8F); break; case 0x1E90: bufpush(0x1E91); break; case 0x1E92: bufpush(0x1E93); break; case 0x1E94: bufpush(0x1E95); break; case 0x1E96: bufpush(0x0068); bufpush(0x0331); break; case 0x1E97: bufpush(0x0074); bufpush(0x0308); break; case 0x1E98: bufpush(0x0077); bufpush(0x030A); break; case 0x1E99: bufpush(0x0079); bufpush(0x030A); break; case 0x1E9A: bufpush(0x0061); bufpush(0x02BE); break; case 0x1E9B: bufpush(0x1E61); break; case 0x1E9E: bufpush(0x0073); bufpush(0x0073); break; case 0x1EA0: bufpush(0x1EA1); break; case 0x1EA2: bufpush(0x1EA3); break; case 0x1EA4: bufpush(0x1EA5); break; case 0x1EA6: bufpush(0x1EA7); break; case 0x1EA8: bufpush(0x1EA9); break; case 0x1EAA: bufpush(0x1EAB); break; case 0x1EAC: bufpush(0x1EAD); break; case 0x1EAE: bufpush(0x1EAF); break; case 0x1EB0: bufpush(0x1EB1); break; case 0x1EB2: bufpush(0x1EB3); break; case 0x1EB4: bufpush(0x1EB5); break; case 0x1EB6: bufpush(0x1EB7); break; case 0x1EB8: bufpush(0x1EB9); break; case 0x1EBA: bufpush(0x1EBB); break; case 0x1EBC: bufpush(0x1EBD); break; case 0x1EBE: bufpush(0x1EBF); break; case 0x1EC0: bufpush(0x1EC1); break; case 0x1EC2: bufpush(0x1EC3); break; case 0x1EC4: bufpush(0x1EC5); break; case 0x1EC6: bufpush(0x1EC7); break; case 0x1EC8: bufpush(0x1EC9); break; case 0x1ECA: bufpush(0x1ECB); break; case 0x1ECC: bufpush(0x1ECD); break; case 0x1ECE: bufpush(0x1ECF); break; case 0x1ED0: bufpush(0x1ED1); break; case 0x1ED2: bufpush(0x1ED3); break; case 0x1ED4: bufpush(0x1ED5); break; case 0x1ED6: bufpush(0x1ED7); break; case 0x1ED8: bufpush(0x1ED9); break; case 0x1EDA: bufpush(0x1EDB); break; case 0x1EDC: bufpush(0x1EDD); break; case 0x1EDE: bufpush(0x1EDF); break; case 0x1EE0: bufpush(0x1EE1); break; case 0x1EE2: bufpush(0x1EE3); break; case 0x1EE4: bufpush(0x1EE5); break; case 0x1EE6: bufpush(0x1EE7); break; case 0x1EE8: bufpush(0x1EE9); break; case 0x1EEA: bufpush(0x1EEB); break; case 0x1EEC: bufpush(0x1EED); break; case 0x1EEE: bufpush(0x1EEF); break; case 0x1EF0: bufpush(0x1EF1); break; case 0x1EF2: bufpush(0x1EF3); break; case 0x1EF4: bufpush(0x1EF5); break; case 0x1EF6: bufpush(0x1EF7); break; case 0x1EF8: bufpush(0x1EF9); break; case 0x1EFA: bufpush(0x1EFB); break; case 0x1EFC: bufpush(0x1EFD); break; case 0x1EFE: bufpush(0x1EFF); break; case 0x1F08: bufpush(0x1F00); break; case 0x1F09: bufpush(0x1F01); break; case 0x1F0A: bufpush(0x1F02); break; case 0x1F0B: bufpush(0x1F03); break; case 0x1F0C: bufpush(0x1F04); break; case 0x1F0D: bufpush(0x1F05); break; case 0x1F0E: bufpush(0x1F06); break; case 0x1F0F: bufpush(0x1F07); break; case 0x1F18: bufpush(0x1F10); break; case 0x1F19: bufpush(0x1F11); break; case 0x1F1A: bufpush(0x1F12); break; case 0x1F1B: bufpush(0x1F13); break; case 0x1F1C: bufpush(0x1F14); break; case 0x1F1D: bufpush(0x1F15); break; case 0x1F28: bufpush(0x1F20); break; case 0x1F29: bufpush(0x1F21); break; case 0x1F2A: bufpush(0x1F22); break; case 0x1F2B: bufpush(0x1F23); break; case 0x1F2C: bufpush(0x1F24); break; case 0x1F2D: bufpush(0x1F25); break; case 0x1F2E: bufpush(0x1F26); break; case 0x1F2F: bufpush(0x1F27); break; case 0x1F38: bufpush(0x1F30); break; case 0x1F39: bufpush(0x1F31); break; case 0x1F3A: bufpush(0x1F32); break; case 0x1F3B: bufpush(0x1F33); break; case 0x1F3C: bufpush(0x1F34); break; case 0x1F3D: bufpush(0x1F35); break; case 0x1F3E: bufpush(0x1F36); break; case 0x1F3F: bufpush(0x1F37); break; case 0x1F48: bufpush(0x1F40); break; case 0x1F49: bufpush(0x1F41); break; case 0x1F4A: bufpush(0x1F42); break; case 0x1F4B: bufpush(0x1F43); break; case 0x1F4C: bufpush(0x1F44); break; case 0x1F4D: bufpush(0x1F45); break; case 0x1F50: bufpush(0x03C5); bufpush(0x0313); break; case 0x1F52: bufpush(0x03C5); bufpush(0x0313); bufpush(0x0300); break; case 0x1F54: bufpush(0x03C5); bufpush(0x0313); bufpush(0x0301); break; case 0x1F56: bufpush(0x03C5); bufpush(0x0313); bufpush(0x0342); break; case 0x1F59: bufpush(0x1F51); break; case 0x1F5B: bufpush(0x1F53); break; case 0x1F5D: bufpush(0x1F55); break; case 0x1F5F: bufpush(0x1F57); break; case 0x1F68: bufpush(0x1F60); break; case 0x1F69: bufpush(0x1F61); break; case 0x1F6A: bufpush(0x1F62); break; case 0x1F6B: bufpush(0x1F63); break; case 0x1F6C: bufpush(0x1F64); break; case 0x1F6D: bufpush(0x1F65); break; case 0x1F6E: bufpush(0x1F66); break; case 0x1F6F: bufpush(0x1F67); break; case 0x1F80: bufpush(0x1F00); bufpush(0x03B9); break; case 0x1F81: bufpush(0x1F01); bufpush(0x03B9); break; case 0x1F82: bufpush(0x1F02); bufpush(0x03B9); break; case 0x1F83: bufpush(0x1F03); bufpush(0x03B9); break; case 0x1F84: bufpush(0x1F04); bufpush(0x03B9); break; case 0x1F85: bufpush(0x1F05); bufpush(0x03B9); break; case 0x1F86: bufpush(0x1F06); bufpush(0x03B9); break; case 0x1F87: bufpush(0x1F07); bufpush(0x03B9); break; case 0x1F88: bufpush(0x1F00); bufpush(0x03B9); break; case 0x1F89: bufpush(0x1F01); bufpush(0x03B9); break; case 0x1F8A: bufpush(0x1F02); bufpush(0x03B9); break; case 0x1F8B: bufpush(0x1F03); bufpush(0x03B9); break; case 0x1F8C: bufpush(0x1F04); bufpush(0x03B9); break; case 0x1F8D: bufpush(0x1F05); bufpush(0x03B9); break; case 0x1F8E: bufpush(0x1F06); bufpush(0x03B9); break; case 0x1F8F: bufpush(0x1F07); bufpush(0x03B9); break; case 0x1F90: bufpush(0x1F20); bufpush(0x03B9); break; case 0x1F91: bufpush(0x1F21); bufpush(0x03B9); break; case 0x1F92: bufpush(0x1F22); bufpush(0x03B9); break; case 0x1F93: bufpush(0x1F23); bufpush(0x03B9); break; case 0x1F94: bufpush(0x1F24); bufpush(0x03B9); break; case 0x1F95: bufpush(0x1F25); bufpush(0x03B9); break; case 0x1F96: bufpush(0x1F26); bufpush(0x03B9); break; case 0x1F97: bufpush(0x1F27); bufpush(0x03B9); break; case 0x1F98: bufpush(0x1F20); bufpush(0x03B9); break; case 0x1F99: bufpush(0x1F21); bufpush(0x03B9); break; case 0x1F9A: bufpush(0x1F22); bufpush(0x03B9); break; case 0x1F9B: bufpush(0x1F23); bufpush(0x03B9); break; case 0x1F9C: bufpush(0x1F24); bufpush(0x03B9); break; case 0x1F9D: bufpush(0x1F25); bufpush(0x03B9); break; case 0x1F9E: bufpush(0x1F26); bufpush(0x03B9); break; case 0x1F9F: bufpush(0x1F27); bufpush(0x03B9); break; case 0x1FA0: bufpush(0x1F60); bufpush(0x03B9); break; case 0x1FA1: bufpush(0x1F61); bufpush(0x03B9); break; case 0x1FA2: bufpush(0x1F62); bufpush(0x03B9); break; case 0x1FA3: bufpush(0x1F63); bufpush(0x03B9); break; case 0x1FA4: bufpush(0x1F64); bufpush(0x03B9); break; case 0x1FA5: bufpush(0x1F65); bufpush(0x03B9); break; case 0x1FA6: bufpush(0x1F66); bufpush(0x03B9); break; case 0x1FA7: bufpush(0x1F67); bufpush(0x03B9); break; case 0x1FA8: bufpush(0x1F60); bufpush(0x03B9); break; case 0x1FA9: bufpush(0x1F61); bufpush(0x03B9); break; case 0x1FAA: bufpush(0x1F62); bufpush(0x03B9); break; case 0x1FAB: bufpush(0x1F63); bufpush(0x03B9); break; case 0x1FAC: bufpush(0x1F64); bufpush(0x03B9); break; case 0x1FAD: bufpush(0x1F65); bufpush(0x03B9); break; case 0x1FAE: bufpush(0x1F66); bufpush(0x03B9); break; case 0x1FAF: bufpush(0x1F67); bufpush(0x03B9); break; case 0x1FB2: bufpush(0x1F70); bufpush(0x03B9); break; case 0x1FB3: bufpush(0x03B1); bufpush(0x03B9); break; case 0x1FB4: bufpush(0x03AC); bufpush(0x03B9); break; case 0x1FB6: bufpush(0x03B1); bufpush(0x0342); break; case 0x1FB7: bufpush(0x03B1); bufpush(0x0342); bufpush(0x03B9); break; case 0x1FB8: bufpush(0x1FB0); break; case 0x1FB9: bufpush(0x1FB1); break; case 0x1FBA: bufpush(0x1F70); break; case 0x1FBB: bufpush(0x1F71); break; case 0x1FBC: bufpush(0x03B1); bufpush(0x03B9); break; case 0x1FBE: bufpush(0x03B9); break; case 0x1FC2: bufpush(0x1F74); bufpush(0x03B9); break; case 0x1FC3: bufpush(0x03B7); bufpush(0x03B9); break; case 0x1FC4: bufpush(0x03AE); bufpush(0x03B9); break; case 0x1FC6: bufpush(0x03B7); bufpush(0x0342); break; case 0x1FC7: bufpush(0x03B7); bufpush(0x0342); bufpush(0x03B9); break; case 0x1FC8: bufpush(0x1F72); break; case 0x1FC9: bufpush(0x1F73); break; case 0x1FCA: bufpush(0x1F74); break; case 0x1FCB: bufpush(0x1F75); break; case 0x1FCC: bufpush(0x03B7); bufpush(0x03B9); break; case 0x1FD2: bufpush(0x03B9); bufpush(0x0308); bufpush(0x0300); break; case 0x1FD3: bufpush(0x03B9); bufpush(0x0308); bufpush(0x0301); break; case 0x1FD6: bufpush(0x03B9); bufpush(0x0342); break; case 0x1FD7: bufpush(0x03B9); bufpush(0x0308); bufpush(0x0342); break; case 0x1FD8: bufpush(0x1FD0); break; case 0x1FD9: bufpush(0x1FD1); break; case 0x1FDA: bufpush(0x1F76); break; case 0x1FDB: bufpush(0x1F77); break; case 0x1FE2: bufpush(0x03C5); bufpush(0x0308); bufpush(0x0300); break; case 0x1FE3: bufpush(0x03C5); bufpush(0x0308); bufpush(0x0301); break; case 0x1FE4: bufpush(0x03C1); bufpush(0x0313); break; case 0x1FE6: bufpush(0x03C5); bufpush(0x0342); break; case 0x1FE7: bufpush(0x03C5); bufpush(0x0308); bufpush(0x0342); break; case 0x1FE8: bufpush(0x1FE0); break; case 0x1FE9: bufpush(0x1FE1); break; case 0x1FEA: bufpush(0x1F7A); break; case 0x1FEB: bufpush(0x1F7B); break; case 0x1FEC: bufpush(0x1FE5); break; case 0x1FF2: bufpush(0x1F7C); bufpush(0x03B9); break; case 0x1FF3: bufpush(0x03C9); bufpush(0x03B9); break; case 0x1FF4: bufpush(0x03CE); bufpush(0x03B9); break; case 0x1FF6: bufpush(0x03C9); bufpush(0x0342); break; case 0x1FF7: bufpush(0x03C9); bufpush(0x0342); bufpush(0x03B9); break; case 0x1FF8: bufpush(0x1F78); break; case 0x1FF9: bufpush(0x1F79); break; case 0x1FFA: bufpush(0x1F7C); break; case 0x1FFB: bufpush(0x1F7D); break; case 0x1FFC: bufpush(0x03C9); bufpush(0x03B9); break; case 0x2126: bufpush(0x03C9); break; case 0x212A: bufpush(0x006B); break; case 0x212B: bufpush(0x00E5); break; case 0x2132: bufpush(0x214E); break; case 0x2160: bufpush(0x2170); break; case 0x2161: bufpush(0x2171); break; case 0x2162: bufpush(0x2172); break; case 0x2163: bufpush(0x2173); break; case 0x2164: bufpush(0x2174); break; case 0x2165: bufpush(0x2175); break; case 0x2166: bufpush(0x2176); break; case 0x2167: bufpush(0x2177); break; case 0x2168: bufpush(0x2178); break; case 0x2169: bufpush(0x2179); break; case 0x216A: bufpush(0x217A); break; case 0x216B: bufpush(0x217B); break; case 0x216C: bufpush(0x217C); break; case 0x216D: bufpush(0x217D); break; case 0x216E: bufpush(0x217E); break; case 0x216F: bufpush(0x217F); break; case 0x2183: bufpush(0x2184); break; case 0x24B6: bufpush(0x24D0); break; case 0x24B7: bufpush(0x24D1); break; case 0x24B8: bufpush(0x24D2); break; case 0x24B9: bufpush(0x24D3); break; case 0x24BA: bufpush(0x24D4); break; case 0x24BB: bufpush(0x24D5); break; case 0x24BC: bufpush(0x24D6); break; case 0x24BD: bufpush(0x24D7); break; case 0x24BE: bufpush(0x24D8); break; case 0x24BF: bufpush(0x24D9); break; case 0x24C0: bufpush(0x24DA); break; case 0x24C1: bufpush(0x24DB); break; case 0x24C2: bufpush(0x24DC); break; case 0x24C3: bufpush(0x24DD); break; case 0x24C4: bufpush(0x24DE); break; case 0x24C5: bufpush(0x24DF); break; case 0x24C6: bufpush(0x24E0); break; case 0x24C7: bufpush(0x24E1); break; case 0x24C8: bufpush(0x24E2); break; case 0x24C9: bufpush(0x24E3); break; case 0x24CA: bufpush(0x24E4); break; case 0x24CB: bufpush(0x24E5); break; case 0x24CC: bufpush(0x24E6); break; case 0x24CD: bufpush(0x24E7); break; case 0x24CE: bufpush(0x24E8); break; case 0x24CF: bufpush(0x24E9); break; case 0x2C00: bufpush(0x2C30); break; case 0x2C01: bufpush(0x2C31); break; case 0x2C02: bufpush(0x2C32); break; case 0x2C03: bufpush(0x2C33); break; case 0x2C04: bufpush(0x2C34); break; case 0x2C05: bufpush(0x2C35); break; case 0x2C06: bufpush(0x2C36); break; case 0x2C07: bufpush(0x2C37); break; case 0x2C08: bufpush(0x2C38); break; case 0x2C09: bufpush(0x2C39); break; case 0x2C0A: bufpush(0x2C3A); break; case 0x2C0B: bufpush(0x2C3B); break; case 0x2C0C: bufpush(0x2C3C); break; case 0x2C0D: bufpush(0x2C3D); break; case 0x2C0E: bufpush(0x2C3E); break; case 0x2C0F: bufpush(0x2C3F); break; case 0x2C10: bufpush(0x2C40); break; case 0x2C11: bufpush(0x2C41); break; case 0x2C12: bufpush(0x2C42); break; case 0x2C13: bufpush(0x2C43); break; case 0x2C14: bufpush(0x2C44); break; case 0x2C15: bufpush(0x2C45); break; case 0x2C16: bufpush(0x2C46); break; case 0x2C17: bufpush(0x2C47); break; case 0x2C18: bufpush(0x2C48); break; case 0x2C19: bufpush(0x2C49); break; case 0x2C1A: bufpush(0x2C4A); break; case 0x2C1B: bufpush(0x2C4B); break; case 0x2C1C: bufpush(0x2C4C); break; case 0x2C1D: bufpush(0x2C4D); break; case 0x2C1E: bufpush(0x2C4E); break; case 0x2C1F: bufpush(0x2C4F); break; case 0x2C20: bufpush(0x2C50); break; case 0x2C21: bufpush(0x2C51); break; case 0x2C22: bufpush(0x2C52); break; case 0x2C23: bufpush(0x2C53); break; case 0x2C24: bufpush(0x2C54); break; case 0x2C25: bufpush(0x2C55); break; case 0x2C26: bufpush(0x2C56); break; case 0x2C27: bufpush(0x2C57); break; case 0x2C28: bufpush(0x2C58); break; case 0x2C29: bufpush(0x2C59); break; case 0x2C2A: bufpush(0x2C5A); break; case 0x2C2B: bufpush(0x2C5B); break; case 0x2C2C: bufpush(0x2C5C); break; case 0x2C2D: bufpush(0x2C5D); break; case 0x2C2E: bufpush(0x2C5E); break; case 0x2C60: bufpush(0x2C61); break; case 0x2C62: bufpush(0x026B); break; case 0x2C63: bufpush(0x1D7D); break; case 0x2C64: bufpush(0x027D); break; case 0x2C67: bufpush(0x2C68); break; case 0x2C69: bufpush(0x2C6A); break; case 0x2C6B: bufpush(0x2C6C); break; case 0x2C6D: bufpush(0x0251); break; case 0x2C6E: bufpush(0x0271); break; case 0x2C6F: bufpush(0x0250); break; case 0x2C70: bufpush(0x0252); break; case 0x2C72: bufpush(0x2C73); break; case 0x2C75: bufpush(0x2C76); break; case 0x2C7E: bufpush(0x023F); break; case 0x2C7F: bufpush(0x0240); break; case 0x2C80: bufpush(0x2C81); break; case 0x2C82: bufpush(0x2C83); break; case 0x2C84: bufpush(0x2C85); break; case 0x2C86: bufpush(0x2C87); break; case 0x2C88: bufpush(0x2C89); break; case 0x2C8A: bufpush(0x2C8B); break; case 0x2C8C: bufpush(0x2C8D); break; case 0x2C8E: bufpush(0x2C8F); break; case 0x2C90: bufpush(0x2C91); break; case 0x2C92: bufpush(0x2C93); break; case 0x2C94: bufpush(0x2C95); break; case 0x2C96: bufpush(0x2C97); break; case 0x2C98: bufpush(0x2C99); break; case 0x2C9A: bufpush(0x2C9B); break; case 0x2C9C: bufpush(0x2C9D); break; case 0x2C9E: bufpush(0x2C9F); break; case 0x2CA0: bufpush(0x2CA1); break; case 0x2CA2: bufpush(0x2CA3); break; case 0x2CA4: bufpush(0x2CA5); break; case 0x2CA6: bufpush(0x2CA7); break; case 0x2CA8: bufpush(0x2CA9); break; case 0x2CAA: bufpush(0x2CAB); break; case 0x2CAC: bufpush(0x2CAD); break; case 0x2CAE: bufpush(0x2CAF); break; case 0x2CB0: bufpush(0x2CB1); break; case 0x2CB2: bufpush(0x2CB3); break; case 0x2CB4: bufpush(0x2CB5); break; case 0x2CB6: bufpush(0x2CB7); break; case 0x2CB8: bufpush(0x2CB9); break; case 0x2CBA: bufpush(0x2CBB); break; case 0x2CBC: bufpush(0x2CBD); break; case 0x2CBE: bufpush(0x2CBF); break; case 0x2CC0: bufpush(0x2CC1); break; case 0x2CC2: bufpush(0x2CC3); break; case 0x2CC4: bufpush(0x2CC5); break; case 0x2CC6: bufpush(0x2CC7); break; case 0x2CC8: bufpush(0x2CC9); break; case 0x2CCA: bufpush(0x2CCB); break; case 0x2CCC: bufpush(0x2CCD); break; case 0x2CCE: bufpush(0x2CCF); break; case 0x2CD0: bufpush(0x2CD1); break; case 0x2CD2: bufpush(0x2CD3); break; case 0x2CD4: bufpush(0x2CD5); break; case 0x2CD6: bufpush(0x2CD7); break; case 0x2CD8: bufpush(0x2CD9); break; case 0x2CDA: bufpush(0x2CDB); break; case 0x2CDC: bufpush(0x2CDD); break; case 0x2CDE: bufpush(0x2CDF); break; case 0x2CE0: bufpush(0x2CE1); break; case 0x2CE2: bufpush(0x2CE3); break; case 0x2CEB: bufpush(0x2CEC); break; case 0x2CED: bufpush(0x2CEE); break; case 0x2CF2: bufpush(0x2CF3); break; case 0xA640: bufpush(0xA641); break; case 0xA642: bufpush(0xA643); break; case 0xA644: bufpush(0xA645); break; case 0xA646: bufpush(0xA647); break; case 0xA648: bufpush(0xA649); break; case 0xA64A: bufpush(0xA64B); break; case 0xA64C: bufpush(0xA64D); break; case 0xA64E: bufpush(0xA64F); break; case 0xA650: bufpush(0xA651); break; case 0xA652: bufpush(0xA653); break; case 0xA654: bufpush(0xA655); break; case 0xA656: bufpush(0xA657); break; case 0xA658: bufpush(0xA659); break; case 0xA65A: bufpush(0xA65B); break; case 0xA65C: bufpush(0xA65D); break; case 0xA65E: bufpush(0xA65F); break; case 0xA660: bufpush(0xA661); break; case 0xA662: bufpush(0xA663); break; case 0xA664: bufpush(0xA665); break; case 0xA666: bufpush(0xA667); break; case 0xA668: bufpush(0xA669); break; case 0xA66A: bufpush(0xA66B); break; case 0xA66C: bufpush(0xA66D); break; case 0xA680: bufpush(0xA681); break; case 0xA682: bufpush(0xA683); break; case 0xA684: bufpush(0xA685); break; case 0xA686: bufpush(0xA687); break; case 0xA688: bufpush(0xA689); break; case 0xA68A: bufpush(0xA68B); break; case 0xA68C: bufpush(0xA68D); break; case 0xA68E: bufpush(0xA68F); break; case 0xA690: bufpush(0xA691); break; case 0xA692: bufpush(0xA693); break; case 0xA694: bufpush(0xA695); break; case 0xA696: bufpush(0xA697); break; case 0xA698: bufpush(0xA699); break; case 0xA69A: bufpush(0xA69B); break; case 0xA722: bufpush(0xA723); break; case 0xA724: bufpush(0xA725); break; case 0xA726: bufpush(0xA727); break; case 0xA728: bufpush(0xA729); break; case 0xA72A: bufpush(0xA72B); break; case 0xA72C: bufpush(0xA72D); break; case 0xA72E: bufpush(0xA72F); break; case 0xA732: bufpush(0xA733); break; case 0xA734: bufpush(0xA735); break; case 0xA736: bufpush(0xA737); break; case 0xA738: bufpush(0xA739); break; case 0xA73A: bufpush(0xA73B); break; case 0xA73C: bufpush(0xA73D); break; case 0xA73E: bufpush(0xA73F); break; case 0xA740: bufpush(0xA741); break; case 0xA742: bufpush(0xA743); break; case 0xA744: bufpush(0xA745); break; case 0xA746: bufpush(0xA747); break; case 0xA748: bufpush(0xA749); break; case 0xA74A: bufpush(0xA74B); break; case 0xA74C: bufpush(0xA74D); break; case 0xA74E: bufpush(0xA74F); break; case 0xA750: bufpush(0xA751); break; case 0xA752: bufpush(0xA753); break; case 0xA754: bufpush(0xA755); break; case 0xA756: bufpush(0xA757); break; case 0xA758: bufpush(0xA759); break; case 0xA75A: bufpush(0xA75B); break; case 0xA75C: bufpush(0xA75D); break; case 0xA75E: bufpush(0xA75F); break; case 0xA760: bufpush(0xA761); break; case 0xA762: bufpush(0xA763); break; case 0xA764: bufpush(0xA765); break; case 0xA766: bufpush(0xA767); break; case 0xA768: bufpush(0xA769); break; case 0xA76A: bufpush(0xA76B); break; case 0xA76C: bufpush(0xA76D); break; case 0xA76E: bufpush(0xA76F); break; case 0xA779: bufpush(0xA77A); break; case 0xA77B: bufpush(0xA77C); break; case 0xA77D: bufpush(0x1D79); break; case 0xA77E: bufpush(0xA77F); break; case 0xA780: bufpush(0xA781); break; case 0xA782: bufpush(0xA783); break; case 0xA784: bufpush(0xA785); break; case 0xA786: bufpush(0xA787); break; case 0xA78B: bufpush(0xA78C); break; case 0xA78D: bufpush(0x0265); break; case 0xA790: bufpush(0xA791); break; case 0xA792: bufpush(0xA793); break; case 0xA796: bufpush(0xA797); break; case 0xA798: bufpush(0xA799); break; case 0xA79A: bufpush(0xA79B); break; case 0xA79C: bufpush(0xA79D); break; case 0xA79E: bufpush(0xA79F); break; case 0xA7A0: bufpush(0xA7A1); break; case 0xA7A2: bufpush(0xA7A3); break; case 0xA7A4: bufpush(0xA7A5); break; case 0xA7A6: bufpush(0xA7A7); break; case 0xA7A8: bufpush(0xA7A9); break; case 0xA7AA: bufpush(0x0266); break; case 0xA7AB: bufpush(0x025C); break; case 0xA7AC: bufpush(0x0261); break; case 0xA7AD: bufpush(0x026C); break; case 0xA7AE: bufpush(0x026A); break; case 0xA7B0: bufpush(0x029E); break; case 0xA7B1: bufpush(0x0287); break; case 0xA7B2: bufpush(0x029D); break; case 0xA7B3: bufpush(0xAB53); break; case 0xA7B4: bufpush(0xA7B5); break; case 0xA7B6: bufpush(0xA7B7); break; case 0xAB70: bufpush(0x13A0); break; case 0xAB71: bufpush(0x13A1); break; case 0xAB72: bufpush(0x13A2); break; case 0xAB73: bufpush(0x13A3); break; case 0xAB74: bufpush(0x13A4); break; case 0xAB75: bufpush(0x13A5); break; case 0xAB76: bufpush(0x13A6); break; case 0xAB77: bufpush(0x13A7); break; case 0xAB78: bufpush(0x13A8); break; case 0xAB79: bufpush(0x13A9); break; case 0xAB7A: bufpush(0x13AA); break; case 0xAB7B: bufpush(0x13AB); break; case 0xAB7C: bufpush(0x13AC); break; case 0xAB7D: bufpush(0x13AD); break; case 0xAB7E: bufpush(0x13AE); break; case 0xAB7F: bufpush(0x13AF); break; case 0xAB80: bufpush(0x13B0); break; case 0xAB81: bufpush(0x13B1); break; case 0xAB82: bufpush(0x13B2); break; case 0xAB83: bufpush(0x13B3); break; case 0xAB84: bufpush(0x13B4); break; case 0xAB85: bufpush(0x13B5); break; case 0xAB86: bufpush(0x13B6); break; case 0xAB87: bufpush(0x13B7); break; case 0xAB88: bufpush(0x13B8); break; case 0xAB89: bufpush(0x13B9); break; case 0xAB8A: bufpush(0x13BA); break; case 0xAB8B: bufpush(0x13BB); break; case 0xAB8C: bufpush(0x13BC); break; case 0xAB8D: bufpush(0x13BD); break; case 0xAB8E: bufpush(0x13BE); break; case 0xAB8F: bufpush(0x13BF); break; case 0xAB90: bufpush(0x13C0); break; case 0xAB91: bufpush(0x13C1); break; case 0xAB92: bufpush(0x13C2); break; case 0xAB93: bufpush(0x13C3); break; case 0xAB94: bufpush(0x13C4); break; case 0xAB95: bufpush(0x13C5); break; case 0xAB96: bufpush(0x13C6); break; case 0xAB97: bufpush(0x13C7); break; case 0xAB98: bufpush(0x13C8); break; case 0xAB99: bufpush(0x13C9); break; case 0xAB9A: bufpush(0x13CA); break; case 0xAB9B: bufpush(0x13CB); break; case 0xAB9C: bufpush(0x13CC); break; case 0xAB9D: bufpush(0x13CD); break; case 0xAB9E: bufpush(0x13CE); break; case 0xAB9F: bufpush(0x13CF); break; case 0xABA0: bufpush(0x13D0); break; case 0xABA1: bufpush(0x13D1); break; case 0xABA2: bufpush(0x13D2); break; case 0xABA3: bufpush(0x13D3); break; case 0xABA4: bufpush(0x13D4); break; case 0xABA5: bufpush(0x13D5); break; case 0xABA6: bufpush(0x13D6); break; case 0xABA7: bufpush(0x13D7); break; case 0xABA8: bufpush(0x13D8); break; case 0xABA9: bufpush(0x13D9); break; case 0xABAA: bufpush(0x13DA); break; case 0xABAB: bufpush(0x13DB); break; case 0xABAC: bufpush(0x13DC); break; case 0xABAD: bufpush(0x13DD); break; case 0xABAE: bufpush(0x13DE); break; case 0xABAF: bufpush(0x13DF); break; case 0xABB0: bufpush(0x13E0); break; case 0xABB1: bufpush(0x13E1); break; case 0xABB2: bufpush(0x13E2); break; case 0xABB3: bufpush(0x13E3); break; case 0xABB4: bufpush(0x13E4); break; case 0xABB5: bufpush(0x13E5); break; case 0xABB6: bufpush(0x13E6); break; case 0xABB7: bufpush(0x13E7); break; case 0xABB8: bufpush(0x13E8); break; case 0xABB9: bufpush(0x13E9); break; case 0xABBA: bufpush(0x13EA); break; case 0xABBB: bufpush(0x13EB); break; case 0xABBC: bufpush(0x13EC); break; case 0xABBD: bufpush(0x13ED); break; case 0xABBE: bufpush(0x13EE); break; case 0xABBF: bufpush(0x13EF); break; case 0xFB00: bufpush(0x0066); bufpush(0x0066); break; case 0xFB01: bufpush(0x0066); bufpush(0x0069); break; case 0xFB02: bufpush(0x0066); bufpush(0x006C); break; case 0xFB03: bufpush(0x0066); bufpush(0x0066); bufpush(0x0069); break; case 0xFB04: bufpush(0x0066); bufpush(0x0066); bufpush(0x006C); break; case 0xFB05: bufpush(0x0073); bufpush(0x0074); break; case 0xFB06: bufpush(0x0073); bufpush(0x0074); break; case 0xFB13: bufpush(0x0574); bufpush(0x0576); break; case 0xFB14: bufpush(0x0574); bufpush(0x0565); break; case 0xFB15: bufpush(0x0574); bufpush(0x056B); break; case 0xFB16: bufpush(0x057E); bufpush(0x0576); break; case 0xFB17: bufpush(0x0574); bufpush(0x056D); break; case 0xFF21: bufpush(0xFF41); break; case 0xFF22: bufpush(0xFF42); break; case 0xFF23: bufpush(0xFF43); break; case 0xFF24: bufpush(0xFF44); break; case 0xFF25: bufpush(0xFF45); break; case 0xFF26: bufpush(0xFF46); break; case 0xFF27: bufpush(0xFF47); break; case 0xFF28: bufpush(0xFF48); break; case 0xFF29: bufpush(0xFF49); break; case 0xFF2A: bufpush(0xFF4A); break; case 0xFF2B: bufpush(0xFF4B); break; case 0xFF2C: bufpush(0xFF4C); break; case 0xFF2D: bufpush(0xFF4D); break; case 0xFF2E: bufpush(0xFF4E); break; case 0xFF2F: bufpush(0xFF4F); break; case 0xFF30: bufpush(0xFF50); break; case 0xFF31: bufpush(0xFF51); break; case 0xFF32: bufpush(0xFF52); break; case 0xFF33: bufpush(0xFF53); break; case 0xFF34: bufpush(0xFF54); break; case 0xFF35: bufpush(0xFF55); break; case 0xFF36: bufpush(0xFF56); break; case 0xFF37: bufpush(0xFF57); break; case 0xFF38: bufpush(0xFF58); break; case 0xFF39: bufpush(0xFF59); break; case 0xFF3A: bufpush(0xFF5A); break; case 0x10400: bufpush(0x10428); break; case 0x10401: bufpush(0x10429); break; case 0x10402: bufpush(0x1042A); break; case 0x10403: bufpush(0x1042B); break; case 0x10404: bufpush(0x1042C); break; case 0x10405: bufpush(0x1042D); break; case 0x10406: bufpush(0x1042E); break; case 0x10407: bufpush(0x1042F); break; case 0x10408: bufpush(0x10430); break; case 0x10409: bufpush(0x10431); break; case 0x1040A: bufpush(0x10432); break; case 0x1040B: bufpush(0x10433); break; case 0x1040C: bufpush(0x10434); break; case 0x1040D: bufpush(0x10435); break; case 0x1040E: bufpush(0x10436); break; case 0x1040F: bufpush(0x10437); break; case 0x10410: bufpush(0x10438); break; case 0x10411: bufpush(0x10439); break; case 0x10412: bufpush(0x1043A); break; case 0x10413: bufpush(0x1043B); break; case 0x10414: bufpush(0x1043C); break; case 0x10415: bufpush(0x1043D); break; case 0x10416: bufpush(0x1043E); break; case 0x10417: bufpush(0x1043F); break; case 0x10418: bufpush(0x10440); break; case 0x10419: bufpush(0x10441); break; case 0x1041A: bufpush(0x10442); break; case 0x1041B: bufpush(0x10443); break; case 0x1041C: bufpush(0x10444); break; case 0x1041D: bufpush(0x10445); break; case 0x1041E: bufpush(0x10446); break; case 0x1041F: bufpush(0x10447); break; case 0x10420: bufpush(0x10448); break; case 0x10421: bufpush(0x10449); break; case 0x10422: bufpush(0x1044A); break; case 0x10423: bufpush(0x1044B); break; case 0x10424: bufpush(0x1044C); break; case 0x10425: bufpush(0x1044D); break; case 0x10426: bufpush(0x1044E); break; case 0x10427: bufpush(0x1044F); break; case 0x104B0: bufpush(0x104D8); break; case 0x104B1: bufpush(0x104D9); break; case 0x104B2: bufpush(0x104DA); break; case 0x104B3: bufpush(0x104DB); break; case 0x104B4: bufpush(0x104DC); break; case 0x104B5: bufpush(0x104DD); break; case 0x104B6: bufpush(0x104DE); break; case 0x104B7: bufpush(0x104DF); break; case 0x104B8: bufpush(0x104E0); break; case 0x104B9: bufpush(0x104E1); break; case 0x104BA: bufpush(0x104E2); break; case 0x104BB: bufpush(0x104E3); break; case 0x104BC: bufpush(0x104E4); break; case 0x104BD: bufpush(0x104E5); break; case 0x104BE: bufpush(0x104E6); break; case 0x104BF: bufpush(0x104E7); break; case 0x104C0: bufpush(0x104E8); break; case 0x104C1: bufpush(0x104E9); break; case 0x104C2: bufpush(0x104EA); break; case 0x104C3: bufpush(0x104EB); break; case 0x104C4: bufpush(0x104EC); break; case 0x104C5: bufpush(0x104ED); break; case 0x104C6: bufpush(0x104EE); break; case 0x104C7: bufpush(0x104EF); break; case 0x104C8: bufpush(0x104F0); break; case 0x104C9: bufpush(0x104F1); break; case 0x104CA: bufpush(0x104F2); break; case 0x104CB: bufpush(0x104F3); break; case 0x104CC: bufpush(0x104F4); break; case 0x104CD: bufpush(0x104F5); break; case 0x104CE: bufpush(0x104F6); break; case 0x104CF: bufpush(0x104F7); break; case 0x104D0: bufpush(0x104F8); break; case 0x104D1: bufpush(0x104F9); break; case 0x104D2: bufpush(0x104FA); break; case 0x104D3: bufpush(0x104FB); break; case 0x10C80: bufpush(0x10CC0); break; case 0x10C81: bufpush(0x10CC1); break; case 0x10C82: bufpush(0x10CC2); break; case 0x10C83: bufpush(0x10CC3); break; case 0x10C84: bufpush(0x10CC4); break; case 0x10C85: bufpush(0x10CC5); break; case 0x10C86: bufpush(0x10CC6); break; case 0x10C87: bufpush(0x10CC7); break; case 0x10C88: bufpush(0x10CC8); break; case 0x10C89: bufpush(0x10CC9); break; case 0x10C8A: bufpush(0x10CCA); break; case 0x10C8B: bufpush(0x10CCB); break; case 0x10C8C: bufpush(0x10CCC); break; case 0x10C8D: bufpush(0x10CCD); break; case 0x10C8E: bufpush(0x10CCE); break; case 0x10C8F: bufpush(0x10CCF); break; case 0x10C90: bufpush(0x10CD0); break; case 0x10C91: bufpush(0x10CD1); break; case 0x10C92: bufpush(0x10CD2); break; case 0x10C93: bufpush(0x10CD3); break; case 0x10C94: bufpush(0x10CD4); break; case 0x10C95: bufpush(0x10CD5); break; case 0x10C96: bufpush(0x10CD6); break; case 0x10C97: bufpush(0x10CD7); break; case 0x10C98: bufpush(0x10CD8); break; case 0x10C99: bufpush(0x10CD9); break; case 0x10C9A: bufpush(0x10CDA); break; case 0x10C9B: bufpush(0x10CDB); break; case 0x10C9C: bufpush(0x10CDC); break; case 0x10C9D: bufpush(0x10CDD); break; case 0x10C9E: bufpush(0x10CDE); break; case 0x10C9F: bufpush(0x10CDF); break; case 0x10CA0: bufpush(0x10CE0); break; case 0x10CA1: bufpush(0x10CE1); break; case 0x10CA2: bufpush(0x10CE2); break; case 0x10CA3: bufpush(0x10CE3); break; case 0x10CA4: bufpush(0x10CE4); break; case 0x10CA5: bufpush(0x10CE5); break; case 0x10CA6: bufpush(0x10CE6); break; case 0x10CA7: bufpush(0x10CE7); break; case 0x10CA8: bufpush(0x10CE8); break; case 0x10CA9: bufpush(0x10CE9); break; case 0x10CAA: bufpush(0x10CEA); break; case 0x10CAB: bufpush(0x10CEB); break; case 0x10CAC: bufpush(0x10CEC); break; case 0x10CAD: bufpush(0x10CED); break; case 0x10CAE: bufpush(0x10CEE); break; case 0x10CAF: bufpush(0x10CEF); break; case 0x10CB0: bufpush(0x10CF0); break; case 0x10CB1: bufpush(0x10CF1); break; case 0x10CB2: bufpush(0x10CF2); break; case 0x118A0: bufpush(0x118C0); break; case 0x118A1: bufpush(0x118C1); break; case 0x118A2: bufpush(0x118C2); break; case 0x118A3: bufpush(0x118C3); break; case 0x118A4: bufpush(0x118C4); break; case 0x118A5: bufpush(0x118C5); break; case 0x118A6: bufpush(0x118C6); break; case 0x118A7: bufpush(0x118C7); break; case 0x118A8: bufpush(0x118C8); break; case 0x118A9: bufpush(0x118C9); break; case 0x118AA: bufpush(0x118CA); break; case 0x118AB: bufpush(0x118CB); break; case 0x118AC: bufpush(0x118CC); break; case 0x118AD: bufpush(0x118CD); break; case 0x118AE: bufpush(0x118CE); break; case 0x118AF: bufpush(0x118CF); break; case 0x118B0: bufpush(0x118D0); break; case 0x118B1: bufpush(0x118D1); break; case 0x118B2: bufpush(0x118D2); break; case 0x118B3: bufpush(0x118D3); break; case 0x118B4: bufpush(0x118D4); break; case 0x118B5: bufpush(0x118D5); break; case 0x118B6: bufpush(0x118D6); break; case 0x118B7: bufpush(0x118D7); break; case 0x118B8: bufpush(0x118D8); break; case 0x118B9: bufpush(0x118D9); break; case 0x118BA: bufpush(0x118DA); break; case 0x118BB: bufpush(0x118DB); break; case 0x118BC: bufpush(0x118DC); break; case 0x118BD: bufpush(0x118DD); break; case 0x118BE: bufpush(0x118DE); break; case 0x118BF: bufpush(0x118DF); break; case 0x1E900: bufpush(0x1E922); break; case 0x1E901: bufpush(0x1E923); break; case 0x1E902: bufpush(0x1E924); break; case 0x1E903: bufpush(0x1E925); break; case 0x1E904: bufpush(0x1E926); break; case 0x1E905: bufpush(0x1E927); break; case 0x1E906: bufpush(0x1E928); break; case 0x1E907: bufpush(0x1E929); break; case 0x1E908: bufpush(0x1E92A); break; case 0x1E909: bufpush(0x1E92B); break; case 0x1E90A: bufpush(0x1E92C); break; case 0x1E90B: bufpush(0x1E92D); break; case 0x1E90C: bufpush(0x1E92E); break; case 0x1E90D: bufpush(0x1E92F); break; case 0x1E90E: bufpush(0x1E930); break; case 0x1E90F: bufpush(0x1E931); break; case 0x1E910: bufpush(0x1E932); break; case 0x1E911: bufpush(0x1E933); break; case 0x1E912: bufpush(0x1E934); break; case 0x1E913: bufpush(0x1E935); break; case 0x1E914: bufpush(0x1E936); break; case 0x1E915: bufpush(0x1E937); break; case 0x1E916: bufpush(0x1E938); break; case 0x1E917: bufpush(0x1E939); break; case 0x1E918: bufpush(0x1E93A); break; case 0x1E919: bufpush(0x1E93B); break; case 0x1E91A: bufpush(0x1E93C); break; case 0x1E91B: bufpush(0x1E93D); break; case 0x1E91C: bufpush(0x1E93E); break; case 0x1E91D: bufpush(0x1E93F); break; case 0x1E91E: bufpush(0x1E940); break; case 0x1E91F: bufpush(0x1E941); break; case 0x1E920: bufpush(0x1E942); break; case 0x1E921: bufpush(0x1E943); break; default: bufpush(c); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/chunk.h ================================================ #ifndef CMARK_CHUNK_H #define CMARK_CHUNK_H #include #include #include #include "cmark.h" #include "buffer.h" #include "cmark_ctype.h" #define CMARK_CHUNK_EMPTY \ { NULL, 0, 0 } typedef struct { unsigned char *data; bufsize_t len; bufsize_t alloc; // also implies a NULL-terminated string } cmark_chunk; static CMARK_INLINE void cmark_chunk_free(cmark_mem *mem, cmark_chunk *c) { if (c->alloc) mem->free(c->data); c->data = NULL; c->alloc = 0; c->len = 0; } static CMARK_INLINE void cmark_chunk_ltrim(cmark_chunk *c) { assert(!c->alloc); while (c->len && cmark_isspace(c->data[0])) { c->data++; c->len--; } } static CMARK_INLINE void cmark_chunk_rtrim(cmark_chunk *c) { assert(!c->alloc); while (c->len > 0) { if (!cmark_isspace(c->data[c->len - 1])) break; c->len--; } } static CMARK_INLINE void cmark_chunk_trim(cmark_chunk *c) { cmark_chunk_ltrim(c); cmark_chunk_rtrim(c); } static CMARK_INLINE bufsize_t cmark_chunk_strchr(cmark_chunk *ch, int c, bufsize_t offset) { const unsigned char *p = (unsigned char *)memchr(ch->data + offset, c, ch->len - offset); return p ? (bufsize_t)(p - ch->data) : ch->len; } static CMARK_INLINE const char *cmark_chunk_to_cstr(cmark_mem *mem, cmark_chunk *c) { unsigned char *str; if (c->alloc) { return (char *)c->data; } str = (unsigned char *)mem->calloc(c->len + 1, 1); if (c->len > 0) { memcpy(str, c->data, c->len); } str[c->len] = 0; c->data = str; c->alloc = 1; return (char *)str; } static CMARK_INLINE void cmark_chunk_set_cstr(cmark_mem *mem, cmark_chunk *c, const char *str) { unsigned char *old = c->alloc ? c->data : NULL; if (str == NULL) { c->len = 0; c->data = NULL; c->alloc = 0; } else { c->len = (bufsize_t)strlen(str); c->data = (unsigned char *)mem->calloc(c->len + 1, 1); c->alloc = 1; memcpy(c->data, str, c->len + 1); } if (old != NULL) { mem->free(old); } } static CMARK_INLINE cmark_chunk cmark_chunk_literal(const char *data) { bufsize_t len = data ? (bufsize_t)strlen(data) : 0; cmark_chunk c = {(unsigned char *)data, len, 0}; return c; } static CMARK_INLINE cmark_chunk cmark_chunk_dup(const cmark_chunk *ch, bufsize_t pos, bufsize_t len) { cmark_chunk c = {ch->data + pos, len, 0}; return c; } static CMARK_INLINE cmark_chunk cmark_chunk_buf_detach(cmark_strbuf *buf) { cmark_chunk c; c.len = buf->size; c.data = cmark_strbuf_detach(buf); c.alloc = 1; return c; } #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/cmark.c ================================================ #include #include #include #include "node.h" #include "houdini.h" #include "cmark.h" #include "buffer.h" int cmark_version() { return CMARK_VERSION; } const char *cmark_version_string() { return CMARK_VERSION_STRING; } static void *xcalloc(size_t nmem, size_t size) { void *ptr = calloc(nmem, size); if (!ptr) { fprintf(stderr, "[cmark] calloc returned null pointer, aborting\n"); abort(); } return ptr; } static void *xrealloc(void *ptr, size_t size) { void *new_ptr = realloc(ptr, size); if (!new_ptr) { fprintf(stderr, "[cmark] realloc returned null pointer, aborting\n"); abort(); } return new_ptr; } cmark_mem DEFAULT_MEM_ALLOCATOR = {xcalloc, xrealloc, free}; char *cmark_markdown_to_html(const char *text, size_t len, int options) { cmark_node *doc; char *result; doc = cmark_parse_document(text, len, options); result = cmark_render_html(doc, options); cmark_node_free(doc); return result; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/cmark.h ================================================ #ifndef CMARK_H #define CMARK_H #include #include #include #ifdef __cplusplus extern "C" { #endif /** # NAME * * **cmark** - CommonMark parsing, manipulating, and rendering */ /** # DESCRIPTION * * ## Simple Interface */ /** Convert 'text' (assumed to be a UTF-8 encoded string with length * 'len') from CommonMark Markdown to HTML, returning a null-terminated, * UTF-8-encoded string. It is the caller's responsibility * to free the returned buffer. */ CMARK_EXPORT char *cmark_markdown_to_html(const char *text, size_t len, int options); /** ## Node Structure */ typedef enum { /* Error status */ CMARK_NODE_NONE, /* Block */ CMARK_NODE_DOCUMENT, CMARK_NODE_BLOCK_QUOTE, CMARK_NODE_LIST, CMARK_NODE_ITEM, CMARK_NODE_CODE_BLOCK, CMARK_NODE_HTML_BLOCK, CMARK_NODE_CUSTOM_BLOCK, CMARK_NODE_PARAGRAPH, CMARK_NODE_HEADING, CMARK_NODE_THEMATIC_BREAK, CMARK_NODE_FIRST_BLOCK = CMARK_NODE_DOCUMENT, CMARK_NODE_LAST_BLOCK = CMARK_NODE_THEMATIC_BREAK, /* Inline */ CMARK_NODE_TEXT, CMARK_NODE_SOFTBREAK, CMARK_NODE_LINEBREAK, CMARK_NODE_CODE, CMARK_NODE_HTML_INLINE, CMARK_NODE_CUSTOM_INLINE, CMARK_NODE_EMPH, CMARK_NODE_STRONG, CMARK_NODE_LINK, CMARK_NODE_IMAGE, CMARK_NODE_FIRST_INLINE = CMARK_NODE_TEXT, CMARK_NODE_LAST_INLINE = CMARK_NODE_IMAGE, } cmark_node_type; /* For backwards compatibility: */ #define CMARK_NODE_HEADER CMARK_NODE_HEADING #define CMARK_NODE_HRULE CMARK_NODE_THEMATIC_BREAK #define CMARK_NODE_HTML CMARK_NODE_HTML_BLOCK #define CMARK_NODE_INLINE_HTML CMARK_NODE_HTML_INLINE typedef enum { CMARK_NO_LIST, CMARK_BULLET_LIST, CMARK_ORDERED_LIST } cmark_list_type; typedef enum { CMARK_NO_DELIM, CMARK_PERIOD_DELIM, CMARK_PAREN_DELIM } cmark_delim_type; typedef struct cmark_node cmark_node; typedef struct cmark_parser cmark_parser; typedef struct cmark_iter cmark_iter; /** * ## Custom memory allocator support */ /** Defines the memory allocation functions to be used by CMark * when parsing and allocating a document tree */ typedef struct cmark_mem { void *(*calloc)(size_t, size_t); void *(*realloc)(void *, size_t); void (*free)(void *); } cmark_mem; /** * ## Creating and Destroying Nodes */ /** Creates a new node of type 'type'. Note that the node may have * other required properties, which it is the caller's responsibility * to assign. */ CMARK_EXPORT cmark_node *cmark_node_new(cmark_node_type type); /** Same as `cmark_node_new`, but explicitly listing the memory * allocator used to allocate the node. Note: be sure to use the same * allocator for every node in a tree, or bad things can happen. */ CMARK_EXPORT cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem); /** Frees the memory allocated for a node and any children. */ CMARK_EXPORT void cmark_node_free(cmark_node *node); /** * ## Tree Traversal */ /** Returns the next node in the sequence after 'node', or NULL if * there is none. */ CMARK_EXPORT cmark_node *cmark_node_next(cmark_node *node); /** Returns the previous node in the sequence after 'node', or NULL if * there is none. */ CMARK_EXPORT cmark_node *cmark_node_previous(cmark_node *node); /** Returns the parent of 'node', or NULL if there is none. */ CMARK_EXPORT cmark_node *cmark_node_parent(cmark_node *node); /** Returns the first child of 'node', or NULL if 'node' has no children. */ CMARK_EXPORT cmark_node *cmark_node_first_child(cmark_node *node); /** Returns the last child of 'node', or NULL if 'node' has no children. */ CMARK_EXPORT cmark_node *cmark_node_last_child(cmark_node *node); /** * ## Iterator * * An iterator will walk through a tree of nodes, starting from a root * node, returning one node at a time, together with information about * whether the node is being entered or exited. The iterator will * first descend to a child node, if there is one. When there is no * child, the iterator will go to the next sibling. When there is no * next sibling, the iterator will return to the parent (but with * a 'cmark_event_type' of `CMARK_EVENT_EXIT`). The iterator will * return `CMARK_EVENT_DONE` when it reaches the root node again. * One natural application is an HTML renderer, where an `ENTER` event * outputs an open tag and an `EXIT` event outputs a close tag. * An iterator might also be used to transform an AST in some systematic * way, for example, turning all level-3 headings into regular paragraphs. * * void * usage_example(cmark_node *root) { * cmark_event_type ev_type; * cmark_iter *iter = cmark_iter_new(root); * * while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { * cmark_node *cur = cmark_iter_get_node(iter); * // Do something with `cur` and `ev_type` * } * * cmark_iter_free(iter); * } * * Iterators will never return `EXIT` events for leaf nodes, which are nodes * of type: * * * CMARK_NODE_HTML_BLOCK * * CMARK_NODE_THEMATIC_BREAK * * CMARK_NODE_CODE_BLOCK * * CMARK_NODE_TEXT * * CMARK_NODE_SOFTBREAK * * CMARK_NODE_LINEBREAK * * CMARK_NODE_CODE * * CMARK_NODE_HTML_INLINE * * Nodes must only be modified after an `EXIT` event, or an `ENTER` event for * leaf nodes. */ typedef enum { CMARK_EVENT_NONE, CMARK_EVENT_DONE, CMARK_EVENT_ENTER, CMARK_EVENT_EXIT } cmark_event_type; /** Creates a new iterator starting at 'root'. The current node and event * type are undefined until 'cmark_iter_next' is called for the first time. * The memory allocated for the iterator should be released using * 'cmark_iter_free' when it is no longer needed. */ CMARK_EXPORT cmark_iter *cmark_iter_new(cmark_node *root); /** Frees the memory allocated for an iterator. */ CMARK_EXPORT void cmark_iter_free(cmark_iter *iter); /** Advances to the next node and returns the event type (`CMARK_EVENT_ENTER`, * `CMARK_EVENT_EXIT` or `CMARK_EVENT_DONE`). */ CMARK_EXPORT cmark_event_type cmark_iter_next(cmark_iter *iter); /** Returns the current node. */ CMARK_EXPORT cmark_node *cmark_iter_get_node(cmark_iter *iter); /** Returns the current event type. */ CMARK_EXPORT cmark_event_type cmark_iter_get_event_type(cmark_iter *iter); /** Returns the root node. */ CMARK_EXPORT cmark_node *cmark_iter_get_root(cmark_iter *iter); /** Resets the iterator so that the current node is 'current' and * the event type is 'event_type'. The new current node must be a * descendant of the root node or the root node itself. */ CMARK_EXPORT void cmark_iter_reset(cmark_iter *iter, cmark_node *current, cmark_event_type event_type); /** * ## Accessors */ /** Returns the user data of 'node'. */ CMARK_EXPORT void *cmark_node_get_user_data(cmark_node *node); /** Sets arbitrary user data for 'node'. Returns 1 on success, * 0 on failure. */ CMARK_EXPORT int cmark_node_set_user_data(cmark_node *node, void *user_data); /** Returns the type of 'node', or `CMARK_NODE_NONE` on error. */ CMARK_EXPORT cmark_node_type cmark_node_get_type(cmark_node *node); /** Like 'cmark_node_get_type', but returns a string representation of the type, or `""`. */ CMARK_EXPORT const char *cmark_node_get_type_string(cmark_node *node); /** Returns the string contents of 'node', or an empty string if none is set. Returns NULL if called on a node that does not have string content. */ CMARK_EXPORT const char *cmark_node_get_literal(cmark_node *node); /** Sets the string contents of 'node'. Returns 1 on success, * 0 on failure. */ CMARK_EXPORT int cmark_node_set_literal(cmark_node *node, const char *content); /** Returns the heading level of 'node', or 0 if 'node' is not a heading. */ CMARK_EXPORT int cmark_node_get_heading_level(cmark_node *node); /* For backwards compatibility */ #define cmark_node_get_header_level cmark_node_get_heading_level #define cmark_node_set_header_level cmark_node_set_heading_level /** Sets the heading level of 'node', returning 1 on success and 0 on error. */ CMARK_EXPORT int cmark_node_set_heading_level(cmark_node *node, int level); /** Returns the list type of 'node', or `CMARK_NO_LIST` if 'node' * is not a list. */ CMARK_EXPORT cmark_list_type cmark_node_get_list_type(cmark_node *node); /** Sets the list type of 'node', returning 1 on success and 0 on error. */ CMARK_EXPORT int cmark_node_set_list_type(cmark_node *node, cmark_list_type type); /** Returns the list delimiter type of 'node', or `CMARK_NO_DELIM` if 'node' * is not a list. */ CMARK_EXPORT cmark_delim_type cmark_node_get_list_delim(cmark_node *node); /** Sets the list delimiter type of 'node', returning 1 on success and 0 * on error. */ CMARK_EXPORT int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim); /** Returns starting number of 'node', if it is an ordered list, otherwise 0. */ CMARK_EXPORT int cmark_node_get_list_start(cmark_node *node); /** Sets starting number of 'node', if it is an ordered list. Returns 1 * on success, 0 on failure. */ CMARK_EXPORT int cmark_node_set_list_start(cmark_node *node, int start); /** Returns 1 if 'node' is a tight list, 0 otherwise. */ CMARK_EXPORT int cmark_node_get_list_tight(cmark_node *node); /** Sets the "tightness" of a list. Returns 1 on success, 0 on failure. */ CMARK_EXPORT int cmark_node_set_list_tight(cmark_node *node, int tight); /** Returns the info string from a fenced code block. */ CMARK_EXPORT const char *cmark_node_get_fence_info(cmark_node *node); /** Sets the info string in a fenced code block, returning 1 on * success and 0 on failure. */ CMARK_EXPORT int cmark_node_set_fence_info(cmark_node *node, const char *info); /** Returns the URL of a link or image 'node', or an empty string if no URL is set. Returns NULL if called on a node that is not a link or image. */ CMARK_EXPORT const char *cmark_node_get_url(cmark_node *node); /** Sets the URL of a link or image 'node'. Returns 1 on success, * 0 on failure. */ CMARK_EXPORT int cmark_node_set_url(cmark_node *node, const char *url); /** Returns the title of a link or image 'node', or an empty string if no title is set. Returns NULL if called on a node that is not a link or image. */ CMARK_EXPORT const char *cmark_node_get_title(cmark_node *node); /** Sets the title of a link or image 'node'. Returns 1 on success, * 0 on failure. */ CMARK_EXPORT int cmark_node_set_title(cmark_node *node, const char *title); /** Returns the literal "on enter" text for a custom 'node', or an empty string if no on_enter is set. Returns NULL if called on a non-custom node. */ CMARK_EXPORT const char *cmark_node_get_on_enter(cmark_node *node); /** Sets the literal text to render "on enter" for a custom 'node'. Any children of the node will be rendered after this text. Returns 1 on success 0 on failure. */ CMARK_EXPORT int cmark_node_set_on_enter(cmark_node *node, const char *on_enter); /** Returns the literal "on exit" text for a custom 'node', or an empty string if no on_exit is set. Returns NULL if called on a non-custom node. */ CMARK_EXPORT const char *cmark_node_get_on_exit(cmark_node *node); /** Sets the literal text to render "on exit" for a custom 'node'. Any children of the node will be rendered before this text. Returns 1 on success 0 on failure. */ CMARK_EXPORT int cmark_node_set_on_exit(cmark_node *node, const char *on_exit); /** Returns the line on which 'node' begins. */ CMARK_EXPORT int cmark_node_get_start_line(cmark_node *node); /** Returns the column at which 'node' begins. */ CMARK_EXPORT int cmark_node_get_start_column(cmark_node *node); /** Returns the line on which 'node' ends. */ CMARK_EXPORT int cmark_node_get_end_line(cmark_node *node); /** Returns the column at which 'node' ends. */ CMARK_EXPORT int cmark_node_get_end_column(cmark_node *node); /** * ## Tree Manipulation */ /** Unlinks a 'node', removing it from the tree, but not freeing its * memory. (Use 'cmark_node_free' for that.) */ CMARK_EXPORT void cmark_node_unlink(cmark_node *node); /** Inserts 'sibling' before 'node'. Returns 1 on success, 0 on failure. */ CMARK_EXPORT int cmark_node_insert_before(cmark_node *node, cmark_node *sibling); /** Inserts 'sibling' after 'node'. Returns 1 on success, 0 on failure. */ CMARK_EXPORT int cmark_node_insert_after(cmark_node *node, cmark_node *sibling); /** Replaces 'oldnode' with 'newnode' and unlinks 'oldnode' (but does * not free its memory). * Returns 1 on success, 0 on failure. */ CMARK_EXPORT int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode); /** Adds 'child' to the beginning of the children of 'node'. * Returns 1 on success, 0 on failure. */ CMARK_EXPORT int cmark_node_prepend_child(cmark_node *node, cmark_node *child); /** Adds 'child' to the end of the children of 'node'. * Returns 1 on success, 0 on failure. */ CMARK_EXPORT int cmark_node_append_child(cmark_node *node, cmark_node *child); /** Consolidates adjacent text nodes. */ CMARK_EXPORT void cmark_consolidate_text_nodes(cmark_node *root); /** * ## Parsing * * Simple interface: * * cmark_node *document = cmark_parse_document("Hello *world*", 13, * CMARK_OPT_DEFAULT); * * Streaming interface: * * cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); * FILE *fp = fopen("myfile.md", "rb"); * while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { * cmark_parser_feed(parser, buffer, bytes); * if (bytes < sizeof(buffer)) { * break; * } * } * document = cmark_parser_finish(parser); * cmark_parser_free(parser); */ /** Creates a new parser object. */ CMARK_EXPORT cmark_parser *cmark_parser_new(int options); /** Creates a new parser object with the given memory allocator */ CMARK_EXPORT cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem); /** Frees memory allocated for a parser object. */ CMARK_EXPORT void cmark_parser_free(cmark_parser *parser); /** Feeds a string of length 'len' to 'parser'. */ CMARK_EXPORT void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len); /** Finish parsing and return a pointer to a tree of nodes. */ CMARK_EXPORT cmark_node *cmark_parser_finish(cmark_parser *parser); /** Parse a CommonMark document in 'buffer' of length 'len'. * Returns a pointer to a tree of nodes. The memory allocated for * the node tree should be released using 'cmark_node_free' * when it is no longer needed. */ CMARK_EXPORT cmark_node *cmark_parse_document(const char *buffer, size_t len, int options); /** Parse a CommonMark document in file 'f', returning a pointer to * a tree of nodes. The memory allocated for the node tree should be * released using 'cmark_node_free' when it is no longer needed. */ CMARK_EXPORT cmark_node *cmark_parse_file(FILE *f, int options); /** * ## Rendering */ /** Render a 'node' tree as XML. It is the caller's responsibility * to free the returned buffer. */ CMARK_EXPORT char *cmark_render_xml(cmark_node *root, int options); /** Render a 'node' tree as an HTML fragment. It is up to the user * to add an appropriate header and footer. It is the caller's * responsibility to free the returned buffer. */ CMARK_EXPORT char *cmark_render_html(cmark_node *root, int options); /** Render a 'node' tree as a groff man page, without the header. * It is the caller's responsibility to free the returned buffer. */ CMARK_EXPORT char *cmark_render_man(cmark_node *root, int options, int width); /** Render a 'node' tree as a commonmark document. * It is the caller's responsibility to free the returned buffer. */ CMARK_EXPORT char *cmark_render_commonmark(cmark_node *root, int options, int width); /** Render a 'node' tree as a LaTeX document. * It is the caller's responsibility to free the returned buffer. */ CMARK_EXPORT char *cmark_render_latex(cmark_node *root, int options, int width); /** * ## Options */ /** Default options. */ #define CMARK_OPT_DEFAULT 0 /** * ### Options affecting rendering */ /** Include a `data-sourcepos` attribute on all block elements. */ #define CMARK_OPT_SOURCEPOS (1 << 1) /** Render `softbreak` elements as hard line breaks. */ #define CMARK_OPT_HARDBREAKS (1 << 2) /** `CMARK_OPT_SAFE` is defined here for API compatibility, but it no longer has any effect. "Safe" mode is now the default: set `CMARK_OPT_UNSAFE` to disable it. */ #define CMARK_OPT_SAFE (1 << 3) /** Render raw HTML and unsafe links (`javascript:`, `vbscript:`, * `file:`, and `data:`, except for `image/png`, `image/gif`, * `image/jpeg`, or `image/webp` mime types). By default, * raw HTML is replaced by a placeholder HTML comment. Unsafe * links are replaced by empty strings. */ #define CMARK_OPT_UNSAFE (1 << 17) /** Render `softbreak` elements as spaces. */ #define CMARK_OPT_NOBREAKS (1 << 4) /** * ### Options affecting parsing */ /** Legacy option (no effect). */ #define CMARK_OPT_NORMALIZE (1 << 8) /** Validate UTF-8 in the input before parsing, replacing illegal * sequences with the replacement character U+FFFD. */ #define CMARK_OPT_VALIDATE_UTF8 (1 << 9) /** Convert straight quotes to curly, --- to em dashes, -- to en dashes. */ #define CMARK_OPT_SMART (1 << 10) /** * ## Version information */ /** The library version as integer for runtime checks. Also available as * macro CMARK_VERSION for compile time checks. * * * Bits 16-23 contain the major version. * * Bits 8-15 contain the minor version. * * Bits 0-7 contain the patchlevel. * * In hexadecimal format, the number 0x010203 represents version 1.2.3. */ CMARK_EXPORT int cmark_version(void); /** The library version string for runtime checks. Also available as * macro CMARK_VERSION_STRING for compile time checks. */ CMARK_EXPORT const char *cmark_version_string(void); /** # AUTHORS * * John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer. */ #ifndef CMARK_NO_SHORT_NAMES #define NODE_DOCUMENT CMARK_NODE_DOCUMENT #define NODE_BLOCK_QUOTE CMARK_NODE_BLOCK_QUOTE #define NODE_LIST CMARK_NODE_LIST #define NODE_ITEM CMARK_NODE_ITEM #define NODE_CODE_BLOCK CMARK_NODE_CODE_BLOCK #define NODE_HTML_BLOCK CMARK_NODE_HTML_BLOCK #define NODE_CUSTOM_BLOCK CMARK_NODE_CUSTOM_BLOCK #define NODE_PARAGRAPH CMARK_NODE_PARAGRAPH #define NODE_HEADING CMARK_NODE_HEADING #define NODE_HEADER CMARK_NODE_HEADER #define NODE_THEMATIC_BREAK CMARK_NODE_THEMATIC_BREAK #define NODE_HRULE CMARK_NODE_HRULE #define NODE_TEXT CMARK_NODE_TEXT #define NODE_SOFTBREAK CMARK_NODE_SOFTBREAK #define NODE_LINEBREAK CMARK_NODE_LINEBREAK #define NODE_CODE CMARK_NODE_CODE #define NODE_HTML_INLINE CMARK_NODE_HTML_INLINE #define NODE_CUSTOM_INLINE CMARK_NODE_CUSTOM_INLINE #define NODE_EMPH CMARK_NODE_EMPH #define NODE_STRONG CMARK_NODE_STRONG #define NODE_LINK CMARK_NODE_LINK #define NODE_IMAGE CMARK_NODE_IMAGE #define BULLET_LIST CMARK_BULLET_LIST #define ORDERED_LIST CMARK_ORDERED_LIST #define PERIOD_DELIM CMARK_PERIOD_DELIM #define PAREN_DELIM CMARK_PAREN_DELIM #endif #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/cmark_ctype.c ================================================ #include #include "cmark_ctype.h" /** 1 = space, 2 = punct, 3 = digit, 4 = alpha, 0 = other */ static const uint8_t cmark_ctype_class[256] = { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 3 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, /* 4 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 5 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, /* 6 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 7 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0, /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /** * Returns 1 if c is a "whitespace" character as defined by the spec. */ int cmark_isspace(char c) { return cmark_ctype_class[(uint8_t)c] == 1; } /** * Returns 1 if c is an ascii punctuation character. */ int cmark_ispunct(char c) { return cmark_ctype_class[(uint8_t)c] == 2; } int cmark_isalnum(char c) { uint8_t result; result = cmark_ctype_class[(uint8_t)c]; return (result == 3 || result == 4); } int cmark_isdigit(char c) { return cmark_ctype_class[(uint8_t)c] == 3; } int cmark_isalpha(char c) { return cmark_ctype_class[(uint8_t)c] == 4; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/cmark_ctype.h ================================================ #ifndef CMARK_CMARK_CTYPE_H #define CMARK_CMARK_CTYPE_H #ifdef __cplusplus extern "C" { #endif /** Locale-independent versions of functions from ctype.h. * We want cmark to behave the same no matter what the system locale. */ int cmark_isspace(char c); int cmark_ispunct(char c); int cmark_isalnum(char c); int cmark_isdigit(char c); int cmark_isalpha(char c); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/cmark_version.h.in ================================================ #ifndef CMARK_VERSION_H #define CMARK_VERSION_H #define CMARK_VERSION ((@PROJECT_VERSION_MAJOR@ << 16) | (@PROJECT_VERSION_MINOR@ << 8) | @PROJECT_VERSION_PATCH@) #define CMARK_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@" #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/commonmark.c ================================================ #include #include #include #include #include #include "config.h" #include "cmark.h" #include "node.h" #include "buffer.h" #include "utf8.h" #include "scanners.h" #include "render.h" #define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping) #define LIT(s) renderer->out(renderer, s, false, LITERAL) #define CR() renderer->cr(renderer) #define BLANKLINE() renderer->blankline(renderer) #define ENCODED_SIZE 20 #define LISTMARKER_SIZE 20 // Functions to convert cmark_nodes to commonmark strings. static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c, unsigned char nextc) { bool needs_escaping = false; bool follows_digit = renderer->buffer->size > 0 && cmark_isdigit(renderer->buffer->ptr[renderer->buffer->size - 1]); char encoded[ENCODED_SIZE]; needs_escaping = c < 0x80 && escape != LITERAL && ((escape == NORMAL && (c < 0x20 || c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' || c == '>' || c == '\\' || c == '`' || c == '!' || (c == '&' && cmark_isalpha(nextc)) || (c == '!' && nextc == '[') || (renderer->begin_content && (c == '-' || c == '+' || c == '=') && // begin_content doesn't get set to false til we've passed digits // at the beginning of line, so... !follows_digit) || (renderer->begin_content && (c == '.' || c == ')') && follows_digit && (nextc == 0 || cmark_isspace(nextc))))) || (escape == URL && (c == '`' || c == '<' || c == '>' || cmark_isspace(c) || c == '\\' || c == ')' || c == '(')) || (escape == TITLE && (c == '`' || c == '<' || c == '>' || c == '"' || c == '\\'))); if (needs_escaping) { if (escape == URL && cmark_isspace(c)) { // use percent encoding for spaces snprintf(encoded, ENCODED_SIZE, "%%%2X", c); cmark_strbuf_puts(renderer->buffer, encoded); renderer->column += 3; } else if (cmark_ispunct(c)) { cmark_render_ascii(renderer, "\\"); cmark_render_code_point(renderer, c); } else { // render as entity snprintf(encoded, ENCODED_SIZE, "&#%d;", c); cmark_strbuf_puts(renderer->buffer, encoded); renderer->column += strlen(encoded); } } else { cmark_render_code_point(renderer, c); } } static int longest_backtick_sequence(const char *code) { int longest = 0; int current = 0; size_t i = 0; size_t code_len = strlen(code); while (i <= code_len) { if (code[i] == '`') { current++; } else { if (current > longest) { longest = current; } current = 0; } i++; } return longest; } static int shortest_unused_backtick_sequence(const char *code) { // note: if the shortest sequence is >= 32, this returns 32 // so as not to overflow the bit array. uint32_t used = 1; int current = 0; size_t i = 0; size_t code_len = strlen(code); while (i <= code_len) { if (code[i] == '`') { current++; } else { if (current > 0 && current < 32) { used |= (1U << current); } current = 0; } i++; } // return number of first bit that is 0: i = 0; while (i < 32 && used & 1) { used = used >> 1; i++; } return (int)i; } static bool is_autolink(cmark_node *node) { cmark_chunk *title; cmark_chunk *url; cmark_node *link_text; char *realurl; int realurllen; if (node->type != CMARK_NODE_LINK) { return false; } url = &node->as.link.url; if (url->len == 0 || scan_scheme(url, 0) == 0) { return false; } title = &node->as.link.title; // if it has a title, we can't treat it as an autolink: if (title->len > 0) { return false; } link_text = node->first_child; if (link_text == NULL) { return false; } cmark_consolidate_text_nodes(link_text); realurl = (char *)url->data; realurllen = url->len; if (strncmp(realurl, "mailto:", 7) == 0) { realurl += 7; realurllen -= 7; } return (realurllen == link_text->as.literal.len && strncmp(realurl, (char *)link_text->as.literal.data, link_text->as.literal.len) == 0); } // if node is a block node, returns node. // otherwise returns first block-level node that is an ancestor of node. // if there is no block-level ancestor, returns NULL. static cmark_node *get_containing_block(cmark_node *node) { while (node) { if (node->type >= CMARK_NODE_FIRST_BLOCK && node->type <= CMARK_NODE_LAST_BLOCK) { return node; } else { node = node->parent; } } return NULL; } static int S_render_node(cmark_renderer *renderer, cmark_node *node, cmark_event_type ev_type, int options) { cmark_node *tmp; int list_number; cmark_delim_type list_delim; int numticks; bool extra_spaces; int i; bool entering = (ev_type == CMARK_EVENT_ENTER); const char *info, *code, *title; char fencechar[2] = {'\0', '\0'}; size_t info_len, code_len; char listmarker[LISTMARKER_SIZE]; char *emph_delim; bool first_in_list_item; bufsize_t marker_width; bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options) && !(CMARK_OPT_HARDBREAKS & options); // Don't adjust tight list status til we've started the list. // Otherwise we loose the blank line between a paragraph and // a following list. if (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) { tmp = get_containing_block(node); renderer->in_tight_list_item = tmp && // tmp might be NULL if there is no containing block ((tmp->type == CMARK_NODE_ITEM && cmark_node_get_list_tight(tmp->parent)) || (tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM && cmark_node_get_list_tight(tmp->parent->parent))); } switch (node->type) { case CMARK_NODE_DOCUMENT: break; case CMARK_NODE_BLOCK_QUOTE: if (entering) { LIT("> "); renderer->begin_content = true; cmark_strbuf_puts(renderer->prefix, "> "); } else { cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 2); BLANKLINE(); } break; case CMARK_NODE_LIST: if (!entering && node->next && (node->next->type == CMARK_NODE_CODE_BLOCK || node->next->type == CMARK_NODE_LIST)) { // this ensures that a following indented code block or list will be // inteprereted correctly. CR(); LIT(""); BLANKLINE(); } break; case CMARK_NODE_ITEM: if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) { marker_width = 4; } else { list_number = cmark_node_get_list_start(node->parent); list_delim = cmark_node_get_list_delim(node->parent); tmp = node; while (tmp->prev) { tmp = tmp->prev; list_number += 1; } // we ensure a width of at least 4 so // we get nice transition from single digits // to double snprintf(listmarker, LISTMARKER_SIZE, "%d%s%s", list_number, list_delim == CMARK_PAREN_DELIM ? ")" : ".", list_number < 10 ? " " : " "); marker_width = strlen(listmarker); } if (entering) { if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) { LIT(" - "); renderer->begin_content = true; } else { LIT(listmarker); renderer->begin_content = true; } for (i = marker_width; i--;) { cmark_strbuf_putc(renderer->prefix, ' '); } } else { cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - marker_width); CR(); } break; case CMARK_NODE_HEADING: if (entering) { for (i = cmark_node_get_heading_level(node); i > 0; i--) { LIT("#"); } LIT(" "); renderer->begin_content = true; renderer->no_linebreaks = true; } else { renderer->no_linebreaks = false; BLANKLINE(); } break; case CMARK_NODE_CODE_BLOCK: first_in_list_item = node->prev == NULL && node->parent && node->parent->type == CMARK_NODE_ITEM; if (!first_in_list_item) { BLANKLINE(); } info = cmark_node_get_fence_info(node); info_len = strlen(info); fencechar[0] = strchr(info, '`') == NULL ? '`' : '~'; code = cmark_node_get_literal(node); code_len = strlen(code); // use indented form if no info, and code doesn't // begin or end with a blank line, and code isn't // first thing in a list item if (info_len == 0 && (code_len > 2 && !cmark_isspace(code[0]) && !(cmark_isspace(code[code_len - 1]) && cmark_isspace(code[code_len - 2]))) && !first_in_list_item) { LIT(" "); cmark_strbuf_puts(renderer->prefix, " "); OUT(cmark_node_get_literal(node), false, LITERAL); cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4); } else { numticks = longest_backtick_sequence(code) + 1; if (numticks < 3) { numticks = 3; } for (i = 0; i < numticks; i++) { LIT(fencechar); } LIT(" "); OUT(info, false, LITERAL); CR(); OUT(cmark_node_get_literal(node), false, LITERAL); CR(); for (i = 0; i < numticks; i++) { LIT(fencechar); } } BLANKLINE(); break; case CMARK_NODE_HTML_BLOCK: BLANKLINE(); OUT(cmark_node_get_literal(node), false, LITERAL); BLANKLINE(); break; case CMARK_NODE_CUSTOM_BLOCK: BLANKLINE(); OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), false, LITERAL); BLANKLINE(); break; case CMARK_NODE_THEMATIC_BREAK: BLANKLINE(); LIT("-----"); BLANKLINE(); break; case CMARK_NODE_PARAGRAPH: if (!entering) { BLANKLINE(); } break; case CMARK_NODE_TEXT: OUT(cmark_node_get_literal(node), allow_wrap, NORMAL); break; case CMARK_NODE_LINEBREAK: if (!(CMARK_OPT_HARDBREAKS & options)) { LIT(" "); } CR(); break; case CMARK_NODE_SOFTBREAK: if (CMARK_OPT_HARDBREAKS & options) { LIT(" "); CR(); } else if (!renderer->no_linebreaks && renderer->width == 0 && !(CMARK_OPT_HARDBREAKS & options) && !(CMARK_OPT_NOBREAKS & options)) { CR(); } else { OUT(" ", allow_wrap, LITERAL); } break; case CMARK_NODE_CODE: code = cmark_node_get_literal(node); code_len = strlen(code); numticks = shortest_unused_backtick_sequence(code); extra_spaces = code_len == 0 || code[0] == '`' || code[code_len - 1] == '`' || code[0] == ' ' || code[code_len - 1] == ' '; for (i = 0; i < numticks; i++) { LIT("`"); } if (extra_spaces) { LIT(" "); } OUT(cmark_node_get_literal(node), allow_wrap, LITERAL); if (extra_spaces) { LIT(" "); } for (i = 0; i < numticks; i++) { LIT("`"); } break; case CMARK_NODE_HTML_INLINE: OUT(cmark_node_get_literal(node), false, LITERAL); break; case CMARK_NODE_CUSTOM_INLINE: OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), false, LITERAL); break; case CMARK_NODE_STRONG: if (entering) { LIT("**"); } else { LIT("**"); } break; case CMARK_NODE_EMPH: // If we have EMPH(EMPH(x)), we need to use *_x_* // because **x** is STRONG(x): if (node->parent && node->parent->type == CMARK_NODE_EMPH && node->next == NULL && node->prev == NULL) { emph_delim = "_"; } else { emph_delim = "*"; } if (entering) { LIT(emph_delim); } else { LIT(emph_delim); } break; case CMARK_NODE_LINK: if (is_autolink(node)) { if (entering) { LIT("<"); if (strncmp(cmark_node_get_url(node), "mailto:", 7) == 0) { LIT((const char *)cmark_node_get_url(node) + 7); } else { LIT((const char *)cmark_node_get_url(node)); } LIT(">"); // return signal to skip contents of node... return 0; } } else { if (entering) { LIT("["); } else { LIT("]("); OUT(cmark_node_get_url(node), false, URL); title = cmark_node_get_title(node); if (strlen(title) > 0) { LIT(" \""); OUT(title, false, TITLE); LIT("\""); } LIT(")"); } } break; case CMARK_NODE_IMAGE: if (entering) { LIT("!["); } else { LIT("]("); OUT(cmark_node_get_url(node), false, URL); title = cmark_node_get_title(node); if (strlen(title) > 0) { OUT(" \"", allow_wrap, LITERAL); OUT(title, false, TITLE); LIT("\""); } LIT(")"); } break; default: assert(false); break; } return 1; } char *cmark_render_commonmark(cmark_node *root, int options, int width) { if (options & CMARK_OPT_HARDBREAKS) { // disable breaking on width, since it has // a different meaning with OPT_HARDBREAKS width = 0; } return cmark_render(root, options, width, outc, S_render_node); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/config.h.in ================================================ #ifndef CMARK_CONFIG_H #define CMARK_CONFIG_H #ifdef __cplusplus extern "C" { #endif #cmakedefine HAVE_STDBOOL_H #ifdef HAVE_STDBOOL_H #include #elif !defined(__cplusplus) typedef char bool; #endif #cmakedefine HAVE___BUILTIN_EXPECT #cmakedefine HAVE___ATTRIBUTE__ #ifdef HAVE___ATTRIBUTE__ #define CMARK_ATTRIBUTE(list) __attribute__ (list) #else #define CMARK_ATTRIBUTE(list) #endif #ifndef CMARK_INLINE #if defined(_MSC_VER) && !defined(__cplusplus) #define CMARK_INLINE __inline #else #define CMARK_INLINE inline #endif #endif /* snprintf and vsnprintf fallbacks for MSVC before 2015, due to Valentin Milea http://stackoverflow.com/questions/2915672/ */ #if defined(_MSC_VER) && _MSC_VER < 1900 #include #include #define snprintf c99_snprintf #define vsnprintf c99_vsnprintf CMARK_INLINE int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int count = -1; if (size != 0) count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); if (count == -1) count = _vscprintf(format, ap); return count; } CMARK_INLINE int c99_snprintf(char *outBuf, size_t size, const char *format, ...) { int count; va_list ap; va_start(ap, format); count = c99_vsnprintf(outBuf, size, format, ap); va_end(ap); return count; } #endif #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/entities.inc ================================================ /* Autogenerated by tools/make_headers_inc.py */ struct cmark_entity_node { unsigned char *entity; unsigned char bytes[8]; }; #define CMARK_ENTITY_MIN_LENGTH 2 #define CMARK_ENTITY_MAX_LENGTH 32 #define CMARK_NUM_ENTITIES 2125 static const struct cmark_entity_node cmark_entities[] = { {(unsigned char*)"AElig", {195, 134, 0}}, {(unsigned char*)"AMP", {38, 0}}, {(unsigned char*)"Aacute", {195, 129, 0}}, {(unsigned char*)"Abreve", {196, 130, 0}}, {(unsigned char*)"Acirc", {195, 130, 0}}, {(unsigned char*)"Acy", {208, 144, 0}}, {(unsigned char*)"Afr", {240, 157, 148, 132, 0}}, {(unsigned char*)"Agrave", {195, 128, 0}}, {(unsigned char*)"Alpha", {206, 145, 0}}, {(unsigned char*)"Amacr", {196, 128, 0}}, {(unsigned char*)"And", {226, 169, 147, 0}}, {(unsigned char*)"Aogon", {196, 132, 0}}, {(unsigned char*)"Aopf", {240, 157, 148, 184, 0}}, {(unsigned char*)"ApplyFunction", {226, 129, 161, 0}}, {(unsigned char*)"Aring", {195, 133, 0}}, {(unsigned char*)"Ascr", {240, 157, 146, 156, 0}}, {(unsigned char*)"Assign", {226, 137, 148, 0}}, {(unsigned char*)"Atilde", {195, 131, 0}}, {(unsigned char*)"Auml", {195, 132, 0}}, {(unsigned char*)"Backslash", {226, 136, 150, 0}}, {(unsigned char*)"Barv", {226, 171, 167, 0}}, {(unsigned char*)"Barwed", {226, 140, 134, 0}}, {(unsigned char*)"Bcy", {208, 145, 0}}, {(unsigned char*)"Because", {226, 136, 181, 0}}, {(unsigned char*)"Bernoullis", {226, 132, 172, 0}}, {(unsigned char*)"Beta", {206, 146, 0}}, {(unsigned char*)"Bfr", {240, 157, 148, 133, 0}}, {(unsigned char*)"Bopf", {240, 157, 148, 185, 0}}, {(unsigned char*)"Breve", {203, 152, 0}}, {(unsigned char*)"Bscr", {226, 132, 172, 0}}, {(unsigned char*)"Bumpeq", {226, 137, 142, 0}}, {(unsigned char*)"CHcy", {208, 167, 0}}, {(unsigned char*)"COPY", {194, 169, 0}}, {(unsigned char*)"Cacute", {196, 134, 0}}, {(unsigned char*)"Cap", {226, 139, 146, 0}}, {(unsigned char*)"CapitalDifferentialD", {226, 133, 133, 0}}, {(unsigned char*)"Cayleys", {226, 132, 173, 0}}, {(unsigned char*)"Ccaron", {196, 140, 0}}, {(unsigned char*)"Ccedil", {195, 135, 0}}, {(unsigned char*)"Ccirc", {196, 136, 0}}, {(unsigned char*)"Cconint", {226, 136, 176, 0}}, {(unsigned char*)"Cdot", {196, 138, 0}}, {(unsigned char*)"Cedilla", {194, 184, 0}}, {(unsigned char*)"CenterDot", {194, 183, 0}}, {(unsigned char*)"Cfr", {226, 132, 173, 0}}, {(unsigned char*)"Chi", {206, 167, 0}}, {(unsigned char*)"CircleDot", {226, 138, 153, 0}}, {(unsigned char*)"CircleMinus", {226, 138, 150, 0}}, {(unsigned char*)"CirclePlus", {226, 138, 149, 0}}, {(unsigned char*)"CircleTimes", {226, 138, 151, 0}}, {(unsigned char*)"ClockwiseContourIntegral", {226, 136, 178, 0}}, {(unsigned char*)"CloseCurlyDoubleQuote", {226, 128, 157, 0}}, {(unsigned char*)"CloseCurlyQuote", {226, 128, 153, 0}}, {(unsigned char*)"Colon", {226, 136, 183, 0}}, {(unsigned char*)"Colone", {226, 169, 180, 0}}, {(unsigned char*)"Congruent", {226, 137, 161, 0}}, {(unsigned char*)"Conint", {226, 136, 175, 0}}, {(unsigned char*)"ContourIntegral", {226, 136, 174, 0}}, {(unsigned char*)"Copf", {226, 132, 130, 0}}, {(unsigned char*)"Coproduct", {226, 136, 144, 0}}, {(unsigned char*)"CounterClockwiseContourIntegral", {226, 136, 179, 0}}, {(unsigned char*)"Cross", {226, 168, 175, 0}}, {(unsigned char*)"Cscr", {240, 157, 146, 158, 0}}, {(unsigned char*)"Cup", {226, 139, 147, 0}}, {(unsigned char*)"CupCap", {226, 137, 141, 0}}, {(unsigned char*)"DD", {226, 133, 133, 0}}, {(unsigned char*)"DDotrahd", {226, 164, 145, 0}}, {(unsigned char*)"DJcy", {208, 130, 0}}, {(unsigned char*)"DScy", {208, 133, 0}}, {(unsigned char*)"DZcy", {208, 143, 0}}, {(unsigned char*)"Dagger", {226, 128, 161, 0}}, {(unsigned char*)"Darr", {226, 134, 161, 0}}, {(unsigned char*)"Dashv", {226, 171, 164, 0}}, {(unsigned char*)"Dcaron", {196, 142, 0}}, {(unsigned char*)"Dcy", {208, 148, 0}}, {(unsigned char*)"Del", {226, 136, 135, 0}}, {(unsigned char*)"Delta", {206, 148, 0}}, {(unsigned char*)"Dfr", {240, 157, 148, 135, 0}}, {(unsigned char*)"DiacriticalAcute", {194, 180, 0}}, {(unsigned char*)"DiacriticalDot", {203, 153, 0}}, {(unsigned char*)"DiacriticalDoubleAcute", {203, 157, 0}}, {(unsigned char*)"DiacriticalGrave", {96, 0}}, {(unsigned char*)"DiacriticalTilde", {203, 156, 0}}, {(unsigned char*)"Diamond", {226, 139, 132, 0}}, {(unsigned char*)"DifferentialD", {226, 133, 134, 0}}, {(unsigned char*)"Dopf", {240, 157, 148, 187, 0}}, {(unsigned char*)"Dot", {194, 168, 0}}, {(unsigned char*)"DotDot", {226, 131, 156, 0}}, {(unsigned char*)"DotEqual", {226, 137, 144, 0}}, {(unsigned char*)"DoubleContourIntegral", {226, 136, 175, 0}}, {(unsigned char*)"DoubleDot", {194, 168, 0}}, {(unsigned char*)"DoubleDownArrow", {226, 135, 147, 0}}, {(unsigned char*)"DoubleLeftArrow", {226, 135, 144, 0}}, {(unsigned char*)"DoubleLeftRightArrow", {226, 135, 148, 0}}, {(unsigned char*)"DoubleLeftTee", {226, 171, 164, 0}}, {(unsigned char*)"DoubleLongLeftArrow", {226, 159, 184, 0}}, {(unsigned char*)"DoubleLongLeftRightArrow", {226, 159, 186, 0}}, {(unsigned char*)"DoubleLongRightArrow", {226, 159, 185, 0}}, {(unsigned char*)"DoubleRightArrow", {226, 135, 146, 0}}, {(unsigned char*)"DoubleRightTee", {226, 138, 168, 0}}, {(unsigned char*)"DoubleUpArrow", {226, 135, 145, 0}}, {(unsigned char*)"DoubleUpDownArrow", {226, 135, 149, 0}}, {(unsigned char*)"DoubleVerticalBar", {226, 136, 165, 0}}, {(unsigned char*)"DownArrow", {226, 134, 147, 0}}, {(unsigned char*)"DownArrowBar", {226, 164, 147, 0}}, {(unsigned char*)"DownArrowUpArrow", {226, 135, 181, 0}}, {(unsigned char*)"DownBreve", {204, 145, 0}}, {(unsigned char*)"DownLeftRightVector", {226, 165, 144, 0}}, {(unsigned char*)"DownLeftTeeVector", {226, 165, 158, 0}}, {(unsigned char*)"DownLeftVector", {226, 134, 189, 0}}, {(unsigned char*)"DownLeftVectorBar", {226, 165, 150, 0}}, {(unsigned char*)"DownRightTeeVector", {226, 165, 159, 0}}, {(unsigned char*)"DownRightVector", {226, 135, 129, 0}}, {(unsigned char*)"DownRightVectorBar", {226, 165, 151, 0}}, {(unsigned char*)"DownTee", {226, 138, 164, 0}}, {(unsigned char*)"DownTeeArrow", {226, 134, 167, 0}}, {(unsigned char*)"Downarrow", {226, 135, 147, 0}}, {(unsigned char*)"Dscr", {240, 157, 146, 159, 0}}, {(unsigned char*)"Dstrok", {196, 144, 0}}, {(unsigned char*)"ENG", {197, 138, 0}}, {(unsigned char*)"ETH", {195, 144, 0}}, {(unsigned char*)"Eacute", {195, 137, 0}}, {(unsigned char*)"Ecaron", {196, 154, 0}}, {(unsigned char*)"Ecirc", {195, 138, 0}}, {(unsigned char*)"Ecy", {208, 173, 0}}, {(unsigned char*)"Edot", {196, 150, 0}}, {(unsigned char*)"Efr", {240, 157, 148, 136, 0}}, {(unsigned char*)"Egrave", {195, 136, 0}}, {(unsigned char*)"Element", {226, 136, 136, 0}}, {(unsigned char*)"Emacr", {196, 146, 0}}, {(unsigned char*)"EmptySmallSquare", {226, 151, 187, 0}}, {(unsigned char*)"EmptyVerySmallSquare", {226, 150, 171, 0}}, {(unsigned char*)"Eogon", {196, 152, 0}}, {(unsigned char*)"Eopf", {240, 157, 148, 188, 0}}, {(unsigned char*)"Epsilon", {206, 149, 0}}, {(unsigned char*)"Equal", {226, 169, 181, 0}}, {(unsigned char*)"EqualTilde", {226, 137, 130, 0}}, {(unsigned char*)"Equilibrium", {226, 135, 140, 0}}, {(unsigned char*)"Escr", {226, 132, 176, 0}}, {(unsigned char*)"Esim", {226, 169, 179, 0}}, {(unsigned char*)"Eta", {206, 151, 0}}, {(unsigned char*)"Euml", {195, 139, 0}}, {(unsigned char*)"Exists", {226, 136, 131, 0}}, {(unsigned char*)"ExponentialE", {226, 133, 135, 0}}, {(unsigned char*)"Fcy", {208, 164, 0}}, {(unsigned char*)"Ffr", {240, 157, 148, 137, 0}}, {(unsigned char*)"FilledSmallSquare", {226, 151, 188, 0}}, {(unsigned char*)"FilledVerySmallSquare", {226, 150, 170, 0}}, {(unsigned char*)"Fopf", {240, 157, 148, 189, 0}}, {(unsigned char*)"ForAll", {226, 136, 128, 0}}, {(unsigned char*)"Fouriertrf", {226, 132, 177, 0}}, {(unsigned char*)"Fscr", {226, 132, 177, 0}}, {(unsigned char*)"GJcy", {208, 131, 0}}, {(unsigned char*)"GT", {62, 0}}, {(unsigned char*)"Gamma", {206, 147, 0}}, {(unsigned char*)"Gammad", {207, 156, 0}}, {(unsigned char*)"Gbreve", {196, 158, 0}}, {(unsigned char*)"Gcedil", {196, 162, 0}}, {(unsigned char*)"Gcirc", {196, 156, 0}}, {(unsigned char*)"Gcy", {208, 147, 0}}, {(unsigned char*)"Gdot", {196, 160, 0}}, {(unsigned char*)"Gfr", {240, 157, 148, 138, 0}}, {(unsigned char*)"Gg", {226, 139, 153, 0}}, {(unsigned char*)"Gopf", {240, 157, 148, 190, 0}}, {(unsigned char*)"GreaterEqual", {226, 137, 165, 0}}, {(unsigned char*)"GreaterEqualLess", {226, 139, 155, 0}}, {(unsigned char*)"GreaterFullEqual", {226, 137, 167, 0}}, {(unsigned char*)"GreaterGreater", {226, 170, 162, 0}}, {(unsigned char*)"GreaterLess", {226, 137, 183, 0}}, {(unsigned char*)"GreaterSlantEqual", {226, 169, 190, 0}}, {(unsigned char*)"GreaterTilde", {226, 137, 179, 0}}, {(unsigned char*)"Gscr", {240, 157, 146, 162, 0}}, {(unsigned char*)"Gt", {226, 137, 171, 0}}, {(unsigned char*)"HARDcy", {208, 170, 0}}, {(unsigned char*)"Hacek", {203, 135, 0}}, {(unsigned char*)"Hat", {94, 0}}, {(unsigned char*)"Hcirc", {196, 164, 0}}, {(unsigned char*)"Hfr", {226, 132, 140, 0}}, {(unsigned char*)"HilbertSpace", {226, 132, 139, 0}}, {(unsigned char*)"Hopf", {226, 132, 141, 0}}, {(unsigned char*)"HorizontalLine", {226, 148, 128, 0}}, {(unsigned char*)"Hscr", {226, 132, 139, 0}}, {(unsigned char*)"Hstrok", {196, 166, 0}}, {(unsigned char*)"HumpDownHump", {226, 137, 142, 0}}, {(unsigned char*)"HumpEqual", {226, 137, 143, 0}}, {(unsigned char*)"IEcy", {208, 149, 0}}, {(unsigned char*)"IJlig", {196, 178, 0}}, {(unsigned char*)"IOcy", {208, 129, 0}}, {(unsigned char*)"Iacute", {195, 141, 0}}, {(unsigned char*)"Icirc", {195, 142, 0}}, {(unsigned char*)"Icy", {208, 152, 0}}, {(unsigned char*)"Idot", {196, 176, 0}}, {(unsigned char*)"Ifr", {226, 132, 145, 0}}, {(unsigned char*)"Igrave", {195, 140, 0}}, {(unsigned char*)"Im", {226, 132, 145, 0}}, {(unsigned char*)"Imacr", {196, 170, 0}}, {(unsigned char*)"ImaginaryI", {226, 133, 136, 0}}, {(unsigned char*)"Implies", {226, 135, 146, 0}}, {(unsigned char*)"Int", {226, 136, 172, 0}}, {(unsigned char*)"Integral", {226, 136, 171, 0}}, {(unsigned char*)"Intersection", {226, 139, 130, 0}}, {(unsigned char*)"InvisibleComma", {226, 129, 163, 0}}, {(unsigned char*)"InvisibleTimes", {226, 129, 162, 0}}, {(unsigned char*)"Iogon", {196, 174, 0}}, {(unsigned char*)"Iopf", {240, 157, 149, 128, 0}}, {(unsigned char*)"Iota", {206, 153, 0}}, {(unsigned char*)"Iscr", {226, 132, 144, 0}}, {(unsigned char*)"Itilde", {196, 168, 0}}, {(unsigned char*)"Iukcy", {208, 134, 0}}, {(unsigned char*)"Iuml", {195, 143, 0}}, {(unsigned char*)"Jcirc", {196, 180, 0}}, {(unsigned char*)"Jcy", {208, 153, 0}}, {(unsigned char*)"Jfr", {240, 157, 148, 141, 0}}, {(unsigned char*)"Jopf", {240, 157, 149, 129, 0}}, {(unsigned char*)"Jscr", {240, 157, 146, 165, 0}}, {(unsigned char*)"Jsercy", {208, 136, 0}}, {(unsigned char*)"Jukcy", {208, 132, 0}}, {(unsigned char*)"KHcy", {208, 165, 0}}, {(unsigned char*)"KJcy", {208, 140, 0}}, {(unsigned char*)"Kappa", {206, 154, 0}}, {(unsigned char*)"Kcedil", {196, 182, 0}}, {(unsigned char*)"Kcy", {208, 154, 0}}, {(unsigned char*)"Kfr", {240, 157, 148, 142, 0}}, {(unsigned char*)"Kopf", {240, 157, 149, 130, 0}}, {(unsigned char*)"Kscr", {240, 157, 146, 166, 0}}, {(unsigned char*)"LJcy", {208, 137, 0}}, {(unsigned char*)"LT", {60, 0}}, {(unsigned char*)"Lacute", {196, 185, 0}}, {(unsigned char*)"Lambda", {206, 155, 0}}, {(unsigned char*)"Lang", {226, 159, 170, 0}}, {(unsigned char*)"Laplacetrf", {226, 132, 146, 0}}, {(unsigned char*)"Larr", {226, 134, 158, 0}}, {(unsigned char*)"Lcaron", {196, 189, 0}}, {(unsigned char*)"Lcedil", {196, 187, 0}}, {(unsigned char*)"Lcy", {208, 155, 0}}, {(unsigned char*)"LeftAngleBracket", {226, 159, 168, 0}}, {(unsigned char*)"LeftArrow", {226, 134, 144, 0}}, {(unsigned char*)"LeftArrowBar", {226, 135, 164, 0}}, {(unsigned char*)"LeftArrowRightArrow", {226, 135, 134, 0}}, {(unsigned char*)"LeftCeiling", {226, 140, 136, 0}}, {(unsigned char*)"LeftDoubleBracket", {226, 159, 166, 0}}, {(unsigned char*)"LeftDownTeeVector", {226, 165, 161, 0}}, {(unsigned char*)"LeftDownVector", {226, 135, 131, 0}}, {(unsigned char*)"LeftDownVectorBar", {226, 165, 153, 0}}, {(unsigned char*)"LeftFloor", {226, 140, 138, 0}}, {(unsigned char*)"LeftRightArrow", {226, 134, 148, 0}}, {(unsigned char*)"LeftRightVector", {226, 165, 142, 0}}, {(unsigned char*)"LeftTee", {226, 138, 163, 0}}, {(unsigned char*)"LeftTeeArrow", {226, 134, 164, 0}}, {(unsigned char*)"LeftTeeVector", {226, 165, 154, 0}}, {(unsigned char*)"LeftTriangle", {226, 138, 178, 0}}, {(unsigned char*)"LeftTriangleBar", {226, 167, 143, 0}}, {(unsigned char*)"LeftTriangleEqual", {226, 138, 180, 0}}, {(unsigned char*)"LeftUpDownVector", {226, 165, 145, 0}}, {(unsigned char*)"LeftUpTeeVector", {226, 165, 160, 0}}, {(unsigned char*)"LeftUpVector", {226, 134, 191, 0}}, {(unsigned char*)"LeftUpVectorBar", {226, 165, 152, 0}}, {(unsigned char*)"LeftVector", {226, 134, 188, 0}}, {(unsigned char*)"LeftVectorBar", {226, 165, 146, 0}}, {(unsigned char*)"Leftarrow", {226, 135, 144, 0}}, {(unsigned char*)"Leftrightarrow", {226, 135, 148, 0}}, {(unsigned char*)"LessEqualGreater", {226, 139, 154, 0}}, {(unsigned char*)"LessFullEqual", {226, 137, 166, 0}}, {(unsigned char*)"LessGreater", {226, 137, 182, 0}}, {(unsigned char*)"LessLess", {226, 170, 161, 0}}, {(unsigned char*)"LessSlantEqual", {226, 169, 189, 0}}, {(unsigned char*)"LessTilde", {226, 137, 178, 0}}, {(unsigned char*)"Lfr", {240, 157, 148, 143, 0}}, {(unsigned char*)"Ll", {226, 139, 152, 0}}, {(unsigned char*)"Lleftarrow", {226, 135, 154, 0}}, {(unsigned char*)"Lmidot", {196, 191, 0}}, {(unsigned char*)"LongLeftArrow", {226, 159, 181, 0}}, {(unsigned char*)"LongLeftRightArrow", {226, 159, 183, 0}}, {(unsigned char*)"LongRightArrow", {226, 159, 182, 0}}, {(unsigned char*)"Longleftarrow", {226, 159, 184, 0}}, {(unsigned char*)"Longleftrightarrow", {226, 159, 186, 0}}, {(unsigned char*)"Longrightarrow", {226, 159, 185, 0}}, {(unsigned char*)"Lopf", {240, 157, 149, 131, 0}}, {(unsigned char*)"LowerLeftArrow", {226, 134, 153, 0}}, {(unsigned char*)"LowerRightArrow", {226, 134, 152, 0}}, {(unsigned char*)"Lscr", {226, 132, 146, 0}}, {(unsigned char*)"Lsh", {226, 134, 176, 0}}, {(unsigned char*)"Lstrok", {197, 129, 0}}, {(unsigned char*)"Lt", {226, 137, 170, 0}}, {(unsigned char*)"Map", {226, 164, 133, 0}}, {(unsigned char*)"Mcy", {208, 156, 0}}, {(unsigned char*)"MediumSpace", {226, 129, 159, 0}}, {(unsigned char*)"Mellintrf", {226, 132, 179, 0}}, {(unsigned char*)"Mfr", {240, 157, 148, 144, 0}}, {(unsigned char*)"MinusPlus", {226, 136, 147, 0}}, {(unsigned char*)"Mopf", {240, 157, 149, 132, 0}}, {(unsigned char*)"Mscr", {226, 132, 179, 0}}, {(unsigned char*)"Mu", {206, 156, 0}}, {(unsigned char*)"NJcy", {208, 138, 0}}, {(unsigned char*)"Nacute", {197, 131, 0}}, {(unsigned char*)"Ncaron", {197, 135, 0}}, {(unsigned char*)"Ncedil", {197, 133, 0}}, {(unsigned char*)"Ncy", {208, 157, 0}}, {(unsigned char*)"NegativeMediumSpace", {226, 128, 139, 0}}, {(unsigned char*)"NegativeThickSpace", {226, 128, 139, 0}}, {(unsigned char*)"NegativeThinSpace", {226, 128, 139, 0}}, {(unsigned char*)"NegativeVeryThinSpace", {226, 128, 139, 0}}, {(unsigned char*)"NestedGreaterGreater", {226, 137, 171, 0}}, {(unsigned char*)"NestedLessLess", {226, 137, 170, 0}}, {(unsigned char*)"NewLine", {10, 0}}, {(unsigned char*)"Nfr", {240, 157, 148, 145, 0}}, {(unsigned char*)"NoBreak", {226, 129, 160, 0}}, {(unsigned char*)"NonBreakingSpace", {194, 160, 0}}, {(unsigned char*)"Nopf", {226, 132, 149, 0}}, {(unsigned char*)"Not", {226, 171, 172, 0}}, {(unsigned char*)"NotCongruent", {226, 137, 162, 0}}, {(unsigned char*)"NotCupCap", {226, 137, 173, 0}}, {(unsigned char*)"NotDoubleVerticalBar", {226, 136, 166, 0}}, {(unsigned char*)"NotElement", {226, 136, 137, 0}}, {(unsigned char*)"NotEqual", {226, 137, 160, 0}}, {(unsigned char*)"NotEqualTilde", {226, 137, 130, 204, 184, 0}}, {(unsigned char*)"NotExists", {226, 136, 132, 0}}, {(unsigned char*)"NotGreater", {226, 137, 175, 0}}, {(unsigned char*)"NotGreaterEqual", {226, 137, 177, 0}}, {(unsigned char*)"NotGreaterFullEqual", {226, 137, 167, 204, 184, 0}}, {(unsigned char*)"NotGreaterGreater", {226, 137, 171, 204, 184, 0}}, {(unsigned char*)"NotGreaterLess", {226, 137, 185, 0}}, {(unsigned char*)"NotGreaterSlantEqual", {226, 169, 190, 204, 184, 0}}, {(unsigned char*)"NotGreaterTilde", {226, 137, 181, 0}}, {(unsigned char*)"NotHumpDownHump", {226, 137, 142, 204, 184, 0}}, {(unsigned char*)"NotHumpEqual", {226, 137, 143, 204, 184, 0}}, {(unsigned char*)"NotLeftTriangle", {226, 139, 170, 0}}, {(unsigned char*)"NotLeftTriangleBar", {226, 167, 143, 204, 184, 0}}, {(unsigned char*)"NotLeftTriangleEqual", {226, 139, 172, 0}}, {(unsigned char*)"NotLess", {226, 137, 174, 0}}, {(unsigned char*)"NotLessEqual", {226, 137, 176, 0}}, {(unsigned char*)"NotLessGreater", {226, 137, 184, 0}}, {(unsigned char*)"NotLessLess", {226, 137, 170, 204, 184, 0}}, {(unsigned char*)"NotLessSlantEqual", {226, 169, 189, 204, 184, 0}}, {(unsigned char*)"NotLessTilde", {226, 137, 180, 0}}, {(unsigned char*)"NotNestedGreaterGreater", {226, 170, 162, 204, 184, 0}}, {(unsigned char*)"NotNestedLessLess", {226, 170, 161, 204, 184, 0}}, {(unsigned char*)"NotPrecedes", {226, 138, 128, 0}}, {(unsigned char*)"NotPrecedesEqual", {226, 170, 175, 204, 184, 0}}, {(unsigned char*)"NotPrecedesSlantEqual", {226, 139, 160, 0}}, {(unsigned char*)"NotReverseElement", {226, 136, 140, 0}}, {(unsigned char*)"NotRightTriangle", {226, 139, 171, 0}}, {(unsigned char*)"NotRightTriangleBar", {226, 167, 144, 204, 184, 0}}, {(unsigned char*)"NotRightTriangleEqual", {226, 139, 173, 0}}, {(unsigned char*)"NotSquareSubset", {226, 138, 143, 204, 184, 0}}, {(unsigned char*)"NotSquareSubsetEqual", {226, 139, 162, 0}}, {(unsigned char*)"NotSquareSuperset", {226, 138, 144, 204, 184, 0}}, {(unsigned char*)"NotSquareSupersetEqual", {226, 139, 163, 0}}, {(unsigned char*)"NotSubset", {226, 138, 130, 226, 131, 146, 0}}, {(unsigned char*)"NotSubsetEqual", {226, 138, 136, 0}}, {(unsigned char*)"NotSucceeds", {226, 138, 129, 0}}, {(unsigned char*)"NotSucceedsEqual", {226, 170, 176, 204, 184, 0}}, {(unsigned char*)"NotSucceedsSlantEqual", {226, 139, 161, 0}}, {(unsigned char*)"NotSucceedsTilde", {226, 137, 191, 204, 184, 0}}, {(unsigned char*)"NotSuperset", {226, 138, 131, 226, 131, 146, 0}}, {(unsigned char*)"NotSupersetEqual", {226, 138, 137, 0}}, {(unsigned char*)"NotTilde", {226, 137, 129, 0}}, {(unsigned char*)"NotTildeEqual", {226, 137, 132, 0}}, {(unsigned char*)"NotTildeFullEqual", {226, 137, 135, 0}}, {(unsigned char*)"NotTildeTilde", {226, 137, 137, 0}}, {(unsigned char*)"NotVerticalBar", {226, 136, 164, 0}}, {(unsigned char*)"Nscr", {240, 157, 146, 169, 0}}, {(unsigned char*)"Ntilde", {195, 145, 0}}, {(unsigned char*)"Nu", {206, 157, 0}}, {(unsigned char*)"OElig", {197, 146, 0}}, {(unsigned char*)"Oacute", {195, 147, 0}}, {(unsigned char*)"Ocirc", {195, 148, 0}}, {(unsigned char*)"Ocy", {208, 158, 0}}, {(unsigned char*)"Odblac", {197, 144, 0}}, {(unsigned char*)"Ofr", {240, 157, 148, 146, 0}}, {(unsigned char*)"Ograve", {195, 146, 0}}, {(unsigned char*)"Omacr", {197, 140, 0}}, {(unsigned char*)"Omega", {206, 169, 0}}, {(unsigned char*)"Omicron", {206, 159, 0}}, {(unsigned char*)"Oopf", {240, 157, 149, 134, 0}}, {(unsigned char*)"OpenCurlyDoubleQuote", {226, 128, 156, 0}}, {(unsigned char*)"OpenCurlyQuote", {226, 128, 152, 0}}, {(unsigned char*)"Or", {226, 169, 148, 0}}, {(unsigned char*)"Oscr", {240, 157, 146, 170, 0}}, {(unsigned char*)"Oslash", {195, 152, 0}}, {(unsigned char*)"Otilde", {195, 149, 0}}, {(unsigned char*)"Otimes", {226, 168, 183, 0}}, {(unsigned char*)"Ouml", {195, 150, 0}}, {(unsigned char*)"OverBar", {226, 128, 190, 0}}, {(unsigned char*)"OverBrace", {226, 143, 158, 0}}, {(unsigned char*)"OverBracket", {226, 142, 180, 0}}, {(unsigned char*)"OverParenthesis", {226, 143, 156, 0}}, {(unsigned char*)"PartialD", {226, 136, 130, 0}}, {(unsigned char*)"Pcy", {208, 159, 0}}, {(unsigned char*)"Pfr", {240, 157, 148, 147, 0}}, {(unsigned char*)"Phi", {206, 166, 0}}, {(unsigned char*)"Pi", {206, 160, 0}}, {(unsigned char*)"PlusMinus", {194, 177, 0}}, {(unsigned char*)"Poincareplane", {226, 132, 140, 0}}, {(unsigned char*)"Popf", {226, 132, 153, 0}}, {(unsigned char*)"Pr", {226, 170, 187, 0}}, {(unsigned char*)"Precedes", {226, 137, 186, 0}}, {(unsigned char*)"PrecedesEqual", {226, 170, 175, 0}}, {(unsigned char*)"PrecedesSlantEqual", {226, 137, 188, 0}}, {(unsigned char*)"PrecedesTilde", {226, 137, 190, 0}}, {(unsigned char*)"Prime", {226, 128, 179, 0}}, {(unsigned char*)"Product", {226, 136, 143, 0}}, {(unsigned char*)"Proportion", {226, 136, 183, 0}}, {(unsigned char*)"Proportional", {226, 136, 157, 0}}, {(unsigned char*)"Pscr", {240, 157, 146, 171, 0}}, {(unsigned char*)"Psi", {206, 168, 0}}, {(unsigned char*)"QUOT", {34, 0}}, {(unsigned char*)"Qfr", {240, 157, 148, 148, 0}}, {(unsigned char*)"Qopf", {226, 132, 154, 0}}, {(unsigned char*)"Qscr", {240, 157, 146, 172, 0}}, {(unsigned char*)"RBarr", {226, 164, 144, 0}}, {(unsigned char*)"REG", {194, 174, 0}}, {(unsigned char*)"Racute", {197, 148, 0}}, {(unsigned char*)"Rang", {226, 159, 171, 0}}, {(unsigned char*)"Rarr", {226, 134, 160, 0}}, {(unsigned char*)"Rarrtl", {226, 164, 150, 0}}, {(unsigned char*)"Rcaron", {197, 152, 0}}, {(unsigned char*)"Rcedil", {197, 150, 0}}, {(unsigned char*)"Rcy", {208, 160, 0}}, {(unsigned char*)"Re", {226, 132, 156, 0}}, {(unsigned char*)"ReverseElement", {226, 136, 139, 0}}, {(unsigned char*)"ReverseEquilibrium", {226, 135, 139, 0}}, {(unsigned char*)"ReverseUpEquilibrium", {226, 165, 175, 0}}, {(unsigned char*)"Rfr", {226, 132, 156, 0}}, {(unsigned char*)"Rho", {206, 161, 0}}, {(unsigned char*)"RightAngleBracket", {226, 159, 169, 0}}, {(unsigned char*)"RightArrow", {226, 134, 146, 0}}, {(unsigned char*)"RightArrowBar", {226, 135, 165, 0}}, {(unsigned char*)"RightArrowLeftArrow", {226, 135, 132, 0}}, {(unsigned char*)"RightCeiling", {226, 140, 137, 0}}, {(unsigned char*)"RightDoubleBracket", {226, 159, 167, 0}}, {(unsigned char*)"RightDownTeeVector", {226, 165, 157, 0}}, {(unsigned char*)"RightDownVector", {226, 135, 130, 0}}, {(unsigned char*)"RightDownVectorBar", {226, 165, 149, 0}}, {(unsigned char*)"RightFloor", {226, 140, 139, 0}}, {(unsigned char*)"RightTee", {226, 138, 162, 0}}, {(unsigned char*)"RightTeeArrow", {226, 134, 166, 0}}, {(unsigned char*)"RightTeeVector", {226, 165, 155, 0}}, {(unsigned char*)"RightTriangle", {226, 138, 179, 0}}, {(unsigned char*)"RightTriangleBar", {226, 167, 144, 0}}, {(unsigned char*)"RightTriangleEqual", {226, 138, 181, 0}}, {(unsigned char*)"RightUpDownVector", {226, 165, 143, 0}}, {(unsigned char*)"RightUpTeeVector", {226, 165, 156, 0}}, {(unsigned char*)"RightUpVector", {226, 134, 190, 0}}, {(unsigned char*)"RightUpVectorBar", {226, 165, 148, 0}}, {(unsigned char*)"RightVector", {226, 135, 128, 0}}, {(unsigned char*)"RightVectorBar", {226, 165, 147, 0}}, {(unsigned char*)"Rightarrow", {226, 135, 146, 0}}, {(unsigned char*)"Ropf", {226, 132, 157, 0}}, {(unsigned char*)"RoundImplies", {226, 165, 176, 0}}, {(unsigned char*)"Rrightarrow", {226, 135, 155, 0}}, {(unsigned char*)"Rscr", {226, 132, 155, 0}}, {(unsigned char*)"Rsh", {226, 134, 177, 0}}, {(unsigned char*)"RuleDelayed", {226, 167, 180, 0}}, {(unsigned char*)"SHCHcy", {208, 169, 0}}, {(unsigned char*)"SHcy", {208, 168, 0}}, {(unsigned char*)"SOFTcy", {208, 172, 0}}, {(unsigned char*)"Sacute", {197, 154, 0}}, {(unsigned char*)"Sc", {226, 170, 188, 0}}, {(unsigned char*)"Scaron", {197, 160, 0}}, {(unsigned char*)"Scedil", {197, 158, 0}}, {(unsigned char*)"Scirc", {197, 156, 0}}, {(unsigned char*)"Scy", {208, 161, 0}}, {(unsigned char*)"Sfr", {240, 157, 148, 150, 0}}, {(unsigned char*)"ShortDownArrow", {226, 134, 147, 0}}, {(unsigned char*)"ShortLeftArrow", {226, 134, 144, 0}}, {(unsigned char*)"ShortRightArrow", {226, 134, 146, 0}}, {(unsigned char*)"ShortUpArrow", {226, 134, 145, 0}}, {(unsigned char*)"Sigma", {206, 163, 0}}, {(unsigned char*)"SmallCircle", {226, 136, 152, 0}}, {(unsigned char*)"Sopf", {240, 157, 149, 138, 0}}, {(unsigned char*)"Sqrt", {226, 136, 154, 0}}, {(unsigned char*)"Square", {226, 150, 161, 0}}, {(unsigned char*)"SquareIntersection", {226, 138, 147, 0}}, {(unsigned char*)"SquareSubset", {226, 138, 143, 0}}, {(unsigned char*)"SquareSubsetEqual", {226, 138, 145, 0}}, {(unsigned char*)"SquareSuperset", {226, 138, 144, 0}}, {(unsigned char*)"SquareSupersetEqual", {226, 138, 146, 0}}, {(unsigned char*)"SquareUnion", {226, 138, 148, 0}}, {(unsigned char*)"Sscr", {240, 157, 146, 174, 0}}, {(unsigned char*)"Star", {226, 139, 134, 0}}, {(unsigned char*)"Sub", {226, 139, 144, 0}}, {(unsigned char*)"Subset", {226, 139, 144, 0}}, {(unsigned char*)"SubsetEqual", {226, 138, 134, 0}}, {(unsigned char*)"Succeeds", {226, 137, 187, 0}}, {(unsigned char*)"SucceedsEqual", {226, 170, 176, 0}}, {(unsigned char*)"SucceedsSlantEqual", {226, 137, 189, 0}}, {(unsigned char*)"SucceedsTilde", {226, 137, 191, 0}}, {(unsigned char*)"SuchThat", {226, 136, 139, 0}}, {(unsigned char*)"Sum", {226, 136, 145, 0}}, {(unsigned char*)"Sup", {226, 139, 145, 0}}, {(unsigned char*)"Superset", {226, 138, 131, 0}}, {(unsigned char*)"SupersetEqual", {226, 138, 135, 0}}, {(unsigned char*)"Supset", {226, 139, 145, 0}}, {(unsigned char*)"THORN", {195, 158, 0}}, {(unsigned char*)"TRADE", {226, 132, 162, 0}}, {(unsigned char*)"TSHcy", {208, 139, 0}}, {(unsigned char*)"TScy", {208, 166, 0}}, {(unsigned char*)"Tab", {9, 0}}, {(unsigned char*)"Tau", {206, 164, 0}}, {(unsigned char*)"Tcaron", {197, 164, 0}}, {(unsigned char*)"Tcedil", {197, 162, 0}}, {(unsigned char*)"Tcy", {208, 162, 0}}, {(unsigned char*)"Tfr", {240, 157, 148, 151, 0}}, {(unsigned char*)"Therefore", {226, 136, 180, 0}}, {(unsigned char*)"Theta", {206, 152, 0}}, {(unsigned char*)"ThickSpace", {226, 129, 159, 226, 128, 138, 0}}, {(unsigned char*)"ThinSpace", {226, 128, 137, 0}}, {(unsigned char*)"Tilde", {226, 136, 188, 0}}, {(unsigned char*)"TildeEqual", {226, 137, 131, 0}}, {(unsigned char*)"TildeFullEqual", {226, 137, 133, 0}}, {(unsigned char*)"TildeTilde", {226, 137, 136, 0}}, {(unsigned char*)"Topf", {240, 157, 149, 139, 0}}, {(unsigned char*)"TripleDot", {226, 131, 155, 0}}, {(unsigned char*)"Tscr", {240, 157, 146, 175, 0}}, {(unsigned char*)"Tstrok", {197, 166, 0}}, {(unsigned char*)"Uacute", {195, 154, 0}}, {(unsigned char*)"Uarr", {226, 134, 159, 0}}, {(unsigned char*)"Uarrocir", {226, 165, 137, 0}}, {(unsigned char*)"Ubrcy", {208, 142, 0}}, {(unsigned char*)"Ubreve", {197, 172, 0}}, {(unsigned char*)"Ucirc", {195, 155, 0}}, {(unsigned char*)"Ucy", {208, 163, 0}}, {(unsigned char*)"Udblac", {197, 176, 0}}, {(unsigned char*)"Ufr", {240, 157, 148, 152, 0}}, {(unsigned char*)"Ugrave", {195, 153, 0}}, {(unsigned char*)"Umacr", {197, 170, 0}}, {(unsigned char*)"UnderBar", {95, 0}}, {(unsigned char*)"UnderBrace", {226, 143, 159, 0}}, {(unsigned char*)"UnderBracket", {226, 142, 181, 0}}, {(unsigned char*)"UnderParenthesis", {226, 143, 157, 0}}, {(unsigned char*)"Union", {226, 139, 131, 0}}, {(unsigned char*)"UnionPlus", {226, 138, 142, 0}}, {(unsigned char*)"Uogon", {197, 178, 0}}, {(unsigned char*)"Uopf", {240, 157, 149, 140, 0}}, {(unsigned char*)"UpArrow", {226, 134, 145, 0}}, {(unsigned char*)"UpArrowBar", {226, 164, 146, 0}}, {(unsigned char*)"UpArrowDownArrow", {226, 135, 133, 0}}, {(unsigned char*)"UpDownArrow", {226, 134, 149, 0}}, {(unsigned char*)"UpEquilibrium", {226, 165, 174, 0}}, {(unsigned char*)"UpTee", {226, 138, 165, 0}}, {(unsigned char*)"UpTeeArrow", {226, 134, 165, 0}}, {(unsigned char*)"Uparrow", {226, 135, 145, 0}}, {(unsigned char*)"Updownarrow", {226, 135, 149, 0}}, {(unsigned char*)"UpperLeftArrow", {226, 134, 150, 0}}, {(unsigned char*)"UpperRightArrow", {226, 134, 151, 0}}, {(unsigned char*)"Upsi", {207, 146, 0}}, {(unsigned char*)"Upsilon", {206, 165, 0}}, {(unsigned char*)"Uring", {197, 174, 0}}, {(unsigned char*)"Uscr", {240, 157, 146, 176, 0}}, {(unsigned char*)"Utilde", {197, 168, 0}}, {(unsigned char*)"Uuml", {195, 156, 0}}, {(unsigned char*)"VDash", {226, 138, 171, 0}}, {(unsigned char*)"Vbar", {226, 171, 171, 0}}, {(unsigned char*)"Vcy", {208, 146, 0}}, {(unsigned char*)"Vdash", {226, 138, 169, 0}}, {(unsigned char*)"Vdashl", {226, 171, 166, 0}}, {(unsigned char*)"Vee", {226, 139, 129, 0}}, {(unsigned char*)"Verbar", {226, 128, 150, 0}}, {(unsigned char*)"Vert", {226, 128, 150, 0}}, {(unsigned char*)"VerticalBar", {226, 136, 163, 0}}, {(unsigned char*)"VerticalLine", {124, 0}}, {(unsigned char*)"VerticalSeparator", {226, 157, 152, 0}}, {(unsigned char*)"VerticalTilde", {226, 137, 128, 0}}, {(unsigned char*)"VeryThinSpace", {226, 128, 138, 0}}, {(unsigned char*)"Vfr", {240, 157, 148, 153, 0}}, {(unsigned char*)"Vopf", {240, 157, 149, 141, 0}}, {(unsigned char*)"Vscr", {240, 157, 146, 177, 0}}, {(unsigned char*)"Vvdash", {226, 138, 170, 0}}, {(unsigned char*)"Wcirc", {197, 180, 0}}, {(unsigned char*)"Wedge", {226, 139, 128, 0}}, {(unsigned char*)"Wfr", {240, 157, 148, 154, 0}}, {(unsigned char*)"Wopf", {240, 157, 149, 142, 0}}, {(unsigned char*)"Wscr", {240, 157, 146, 178, 0}}, {(unsigned char*)"Xfr", {240, 157, 148, 155, 0}}, {(unsigned char*)"Xi", {206, 158, 0}}, {(unsigned char*)"Xopf", {240, 157, 149, 143, 0}}, {(unsigned char*)"Xscr", {240, 157, 146, 179, 0}}, {(unsigned char*)"YAcy", {208, 175, 0}}, {(unsigned char*)"YIcy", {208, 135, 0}}, {(unsigned char*)"YUcy", {208, 174, 0}}, {(unsigned char*)"Yacute", {195, 157, 0}}, {(unsigned char*)"Ycirc", {197, 182, 0}}, {(unsigned char*)"Ycy", {208, 171, 0}}, {(unsigned char*)"Yfr", {240, 157, 148, 156, 0}}, {(unsigned char*)"Yopf", {240, 157, 149, 144, 0}}, {(unsigned char*)"Yscr", {240, 157, 146, 180, 0}}, {(unsigned char*)"Yuml", {197, 184, 0}}, {(unsigned char*)"ZHcy", {208, 150, 0}}, {(unsigned char*)"Zacute", {197, 185, 0}}, {(unsigned char*)"Zcaron", {197, 189, 0}}, {(unsigned char*)"Zcy", {208, 151, 0}}, {(unsigned char*)"Zdot", {197, 187, 0}}, {(unsigned char*)"ZeroWidthSpace", {226, 128, 139, 0}}, {(unsigned char*)"Zeta", {206, 150, 0}}, {(unsigned char*)"Zfr", {226, 132, 168, 0}}, {(unsigned char*)"Zopf", {226, 132, 164, 0}}, {(unsigned char*)"Zscr", {240, 157, 146, 181, 0}}, {(unsigned char*)"aacute", {195, 161, 0}}, {(unsigned char*)"abreve", {196, 131, 0}}, {(unsigned char*)"ac", {226, 136, 190, 0}}, {(unsigned char*)"acE", {226, 136, 190, 204, 179, 0}}, {(unsigned char*)"acd", {226, 136, 191, 0}}, {(unsigned char*)"acirc", {195, 162, 0}}, {(unsigned char*)"acute", {194, 180, 0}}, {(unsigned char*)"acy", {208, 176, 0}}, {(unsigned char*)"aelig", {195, 166, 0}}, {(unsigned char*)"af", {226, 129, 161, 0}}, {(unsigned char*)"afr", {240, 157, 148, 158, 0}}, {(unsigned char*)"agrave", {195, 160, 0}}, {(unsigned char*)"alefsym", {226, 132, 181, 0}}, {(unsigned char*)"aleph", {226, 132, 181, 0}}, {(unsigned char*)"alpha", {206, 177, 0}}, {(unsigned char*)"amacr", {196, 129, 0}}, {(unsigned char*)"amalg", {226, 168, 191, 0}}, {(unsigned char*)"amp", {38, 0}}, {(unsigned char*)"and", {226, 136, 167, 0}}, {(unsigned char*)"andand", {226, 169, 149, 0}}, {(unsigned char*)"andd", {226, 169, 156, 0}}, {(unsigned char*)"andslope", {226, 169, 152, 0}}, {(unsigned char*)"andv", {226, 169, 154, 0}}, {(unsigned char*)"ang", {226, 136, 160, 0}}, {(unsigned char*)"ange", {226, 166, 164, 0}}, {(unsigned char*)"angle", {226, 136, 160, 0}}, {(unsigned char*)"angmsd", {226, 136, 161, 0}}, {(unsigned char*)"angmsdaa", {226, 166, 168, 0}}, {(unsigned char*)"angmsdab", {226, 166, 169, 0}}, {(unsigned char*)"angmsdac", {226, 166, 170, 0}}, {(unsigned char*)"angmsdad", {226, 166, 171, 0}}, {(unsigned char*)"angmsdae", {226, 166, 172, 0}}, {(unsigned char*)"angmsdaf", {226, 166, 173, 0}}, {(unsigned char*)"angmsdag", {226, 166, 174, 0}}, {(unsigned char*)"angmsdah", {226, 166, 175, 0}}, {(unsigned char*)"angrt", {226, 136, 159, 0}}, {(unsigned char*)"angrtvb", {226, 138, 190, 0}}, {(unsigned char*)"angrtvbd", {226, 166, 157, 0}}, {(unsigned char*)"angsph", {226, 136, 162, 0}}, {(unsigned char*)"angst", {195, 133, 0}}, {(unsigned char*)"angzarr", {226, 141, 188, 0}}, {(unsigned char*)"aogon", {196, 133, 0}}, {(unsigned char*)"aopf", {240, 157, 149, 146, 0}}, {(unsigned char*)"ap", {226, 137, 136, 0}}, {(unsigned char*)"apE", {226, 169, 176, 0}}, {(unsigned char*)"apacir", {226, 169, 175, 0}}, {(unsigned char*)"ape", {226, 137, 138, 0}}, {(unsigned char*)"apid", {226, 137, 139, 0}}, {(unsigned char*)"apos", {39, 0}}, {(unsigned char*)"approx", {226, 137, 136, 0}}, {(unsigned char*)"approxeq", {226, 137, 138, 0}}, {(unsigned char*)"aring", {195, 165, 0}}, {(unsigned char*)"ascr", {240, 157, 146, 182, 0}}, {(unsigned char*)"ast", {42, 0}}, {(unsigned char*)"asymp", {226, 137, 136, 0}}, {(unsigned char*)"asympeq", {226, 137, 141, 0}}, {(unsigned char*)"atilde", {195, 163, 0}}, {(unsigned char*)"auml", {195, 164, 0}}, {(unsigned char*)"awconint", {226, 136, 179, 0}}, {(unsigned char*)"awint", {226, 168, 145, 0}}, {(unsigned char*)"bNot", {226, 171, 173, 0}}, {(unsigned char*)"backcong", {226, 137, 140, 0}}, {(unsigned char*)"backepsilon", {207, 182, 0}}, {(unsigned char*)"backprime", {226, 128, 181, 0}}, {(unsigned char*)"backsim", {226, 136, 189, 0}}, {(unsigned char*)"backsimeq", {226, 139, 141, 0}}, {(unsigned char*)"barvee", {226, 138, 189, 0}}, {(unsigned char*)"barwed", {226, 140, 133, 0}}, {(unsigned char*)"barwedge", {226, 140, 133, 0}}, {(unsigned char*)"bbrk", {226, 142, 181, 0}}, {(unsigned char*)"bbrktbrk", {226, 142, 182, 0}}, {(unsigned char*)"bcong", {226, 137, 140, 0}}, {(unsigned char*)"bcy", {208, 177, 0}}, {(unsigned char*)"bdquo", {226, 128, 158, 0}}, {(unsigned char*)"becaus", {226, 136, 181, 0}}, {(unsigned char*)"because", {226, 136, 181, 0}}, {(unsigned char*)"bemptyv", {226, 166, 176, 0}}, {(unsigned char*)"bepsi", {207, 182, 0}}, {(unsigned char*)"bernou", {226, 132, 172, 0}}, {(unsigned char*)"beta", {206, 178, 0}}, {(unsigned char*)"beth", {226, 132, 182, 0}}, {(unsigned char*)"between", {226, 137, 172, 0}}, {(unsigned char*)"bfr", {240, 157, 148, 159, 0}}, {(unsigned char*)"bigcap", {226, 139, 130, 0}}, {(unsigned char*)"bigcirc", {226, 151, 175, 0}}, {(unsigned char*)"bigcup", {226, 139, 131, 0}}, {(unsigned char*)"bigodot", {226, 168, 128, 0}}, {(unsigned char*)"bigoplus", {226, 168, 129, 0}}, {(unsigned char*)"bigotimes", {226, 168, 130, 0}}, {(unsigned char*)"bigsqcup", {226, 168, 134, 0}}, {(unsigned char*)"bigstar", {226, 152, 133, 0}}, {(unsigned char*)"bigtriangledown", {226, 150, 189, 0}}, {(unsigned char*)"bigtriangleup", {226, 150, 179, 0}}, {(unsigned char*)"biguplus", {226, 168, 132, 0}}, {(unsigned char*)"bigvee", {226, 139, 129, 0}}, {(unsigned char*)"bigwedge", {226, 139, 128, 0}}, {(unsigned char*)"bkarow", {226, 164, 141, 0}}, {(unsigned char*)"blacklozenge", {226, 167, 171, 0}}, {(unsigned char*)"blacksquare", {226, 150, 170, 0}}, {(unsigned char*)"blacktriangle", {226, 150, 180, 0}}, {(unsigned char*)"blacktriangledown", {226, 150, 190, 0}}, {(unsigned char*)"blacktriangleleft", {226, 151, 130, 0}}, {(unsigned char*)"blacktriangleright", {226, 150, 184, 0}}, {(unsigned char*)"blank", {226, 144, 163, 0}}, {(unsigned char*)"blk12", {226, 150, 146, 0}}, {(unsigned char*)"blk14", {226, 150, 145, 0}}, {(unsigned char*)"blk34", {226, 150, 147, 0}}, {(unsigned char*)"block", {226, 150, 136, 0}}, {(unsigned char*)"bne", {61, 226, 131, 165, 0}}, {(unsigned char*)"bnequiv", {226, 137, 161, 226, 131, 165, 0}}, {(unsigned char*)"bnot", {226, 140, 144, 0}}, {(unsigned char*)"bopf", {240, 157, 149, 147, 0}}, {(unsigned char*)"bot", {226, 138, 165, 0}}, {(unsigned char*)"bottom", {226, 138, 165, 0}}, {(unsigned char*)"bowtie", {226, 139, 136, 0}}, {(unsigned char*)"boxDL", {226, 149, 151, 0}}, {(unsigned char*)"boxDR", {226, 149, 148, 0}}, {(unsigned char*)"boxDl", {226, 149, 150, 0}}, {(unsigned char*)"boxDr", {226, 149, 147, 0}}, {(unsigned char*)"boxH", {226, 149, 144, 0}}, {(unsigned char*)"boxHD", {226, 149, 166, 0}}, {(unsigned char*)"boxHU", {226, 149, 169, 0}}, {(unsigned char*)"boxHd", {226, 149, 164, 0}}, {(unsigned char*)"boxHu", {226, 149, 167, 0}}, {(unsigned char*)"boxUL", {226, 149, 157, 0}}, {(unsigned char*)"boxUR", {226, 149, 154, 0}}, {(unsigned char*)"boxUl", {226, 149, 156, 0}}, {(unsigned char*)"boxUr", {226, 149, 153, 0}}, {(unsigned char*)"boxV", {226, 149, 145, 0}}, {(unsigned char*)"boxVH", {226, 149, 172, 0}}, {(unsigned char*)"boxVL", {226, 149, 163, 0}}, {(unsigned char*)"boxVR", {226, 149, 160, 0}}, {(unsigned char*)"boxVh", {226, 149, 171, 0}}, {(unsigned char*)"boxVl", {226, 149, 162, 0}}, {(unsigned char*)"boxVr", {226, 149, 159, 0}}, {(unsigned char*)"boxbox", {226, 167, 137, 0}}, {(unsigned char*)"boxdL", {226, 149, 149, 0}}, {(unsigned char*)"boxdR", {226, 149, 146, 0}}, {(unsigned char*)"boxdl", {226, 148, 144, 0}}, {(unsigned char*)"boxdr", {226, 148, 140, 0}}, {(unsigned char*)"boxh", {226, 148, 128, 0}}, {(unsigned char*)"boxhD", {226, 149, 165, 0}}, {(unsigned char*)"boxhU", {226, 149, 168, 0}}, {(unsigned char*)"boxhd", {226, 148, 172, 0}}, {(unsigned char*)"boxhu", {226, 148, 180, 0}}, {(unsigned char*)"boxminus", {226, 138, 159, 0}}, {(unsigned char*)"boxplus", {226, 138, 158, 0}}, {(unsigned char*)"boxtimes", {226, 138, 160, 0}}, {(unsigned char*)"boxuL", {226, 149, 155, 0}}, {(unsigned char*)"boxuR", {226, 149, 152, 0}}, {(unsigned char*)"boxul", {226, 148, 152, 0}}, {(unsigned char*)"boxur", {226, 148, 148, 0}}, {(unsigned char*)"boxv", {226, 148, 130, 0}}, {(unsigned char*)"boxvH", {226, 149, 170, 0}}, {(unsigned char*)"boxvL", {226, 149, 161, 0}}, {(unsigned char*)"boxvR", {226, 149, 158, 0}}, {(unsigned char*)"boxvh", {226, 148, 188, 0}}, {(unsigned char*)"boxvl", {226, 148, 164, 0}}, {(unsigned char*)"boxvr", {226, 148, 156, 0}}, {(unsigned char*)"bprime", {226, 128, 181, 0}}, {(unsigned char*)"breve", {203, 152, 0}}, {(unsigned char*)"brvbar", {194, 166, 0}}, {(unsigned char*)"bscr", {240, 157, 146, 183, 0}}, {(unsigned char*)"bsemi", {226, 129, 143, 0}}, {(unsigned char*)"bsim", {226, 136, 189, 0}}, {(unsigned char*)"bsime", {226, 139, 141, 0}}, {(unsigned char*)"bsol", {92, 0}}, {(unsigned char*)"bsolb", {226, 167, 133, 0}}, {(unsigned char*)"bsolhsub", {226, 159, 136, 0}}, {(unsigned char*)"bull", {226, 128, 162, 0}}, {(unsigned char*)"bullet", {226, 128, 162, 0}}, {(unsigned char*)"bump", {226, 137, 142, 0}}, {(unsigned char*)"bumpE", {226, 170, 174, 0}}, {(unsigned char*)"bumpe", {226, 137, 143, 0}}, {(unsigned char*)"bumpeq", {226, 137, 143, 0}}, {(unsigned char*)"cacute", {196, 135, 0}}, {(unsigned char*)"cap", {226, 136, 169, 0}}, {(unsigned char*)"capand", {226, 169, 132, 0}}, {(unsigned char*)"capbrcup", {226, 169, 137, 0}}, {(unsigned char*)"capcap", {226, 169, 139, 0}}, {(unsigned char*)"capcup", {226, 169, 135, 0}}, {(unsigned char*)"capdot", {226, 169, 128, 0}}, {(unsigned char*)"caps", {226, 136, 169, 239, 184, 128, 0}}, {(unsigned char*)"caret", {226, 129, 129, 0}}, {(unsigned char*)"caron", {203, 135, 0}}, {(unsigned char*)"ccaps", {226, 169, 141, 0}}, {(unsigned char*)"ccaron", {196, 141, 0}}, {(unsigned char*)"ccedil", {195, 167, 0}}, {(unsigned char*)"ccirc", {196, 137, 0}}, {(unsigned char*)"ccups", {226, 169, 140, 0}}, {(unsigned char*)"ccupssm", {226, 169, 144, 0}}, {(unsigned char*)"cdot", {196, 139, 0}}, {(unsigned char*)"cedil", {194, 184, 0}}, {(unsigned char*)"cemptyv", {226, 166, 178, 0}}, {(unsigned char*)"cent", {194, 162, 0}}, {(unsigned char*)"centerdot", {194, 183, 0}}, {(unsigned char*)"cfr", {240, 157, 148, 160, 0}}, {(unsigned char*)"chcy", {209, 135, 0}}, {(unsigned char*)"check", {226, 156, 147, 0}}, {(unsigned char*)"checkmark", {226, 156, 147, 0}}, {(unsigned char*)"chi", {207, 135, 0}}, {(unsigned char*)"cir", {226, 151, 139, 0}}, {(unsigned char*)"cirE", {226, 167, 131, 0}}, {(unsigned char*)"circ", {203, 134, 0}}, {(unsigned char*)"circeq", {226, 137, 151, 0}}, {(unsigned char*)"circlearrowleft", {226, 134, 186, 0}}, {(unsigned char*)"circlearrowright", {226, 134, 187, 0}}, {(unsigned char*)"circledR", {194, 174, 0}}, {(unsigned char*)"circledS", {226, 147, 136, 0}}, {(unsigned char*)"circledast", {226, 138, 155, 0}}, {(unsigned char*)"circledcirc", {226, 138, 154, 0}}, {(unsigned char*)"circleddash", {226, 138, 157, 0}}, {(unsigned char*)"cire", {226, 137, 151, 0}}, {(unsigned char*)"cirfnint", {226, 168, 144, 0}}, {(unsigned char*)"cirmid", {226, 171, 175, 0}}, {(unsigned char*)"cirscir", {226, 167, 130, 0}}, {(unsigned char*)"clubs", {226, 153, 163, 0}}, {(unsigned char*)"clubsuit", {226, 153, 163, 0}}, {(unsigned char*)"colon", {58, 0}}, {(unsigned char*)"colone", {226, 137, 148, 0}}, {(unsigned char*)"coloneq", {226, 137, 148, 0}}, {(unsigned char*)"comma", {44, 0}}, {(unsigned char*)"commat", {64, 0}}, {(unsigned char*)"comp", {226, 136, 129, 0}}, {(unsigned char*)"compfn", {226, 136, 152, 0}}, {(unsigned char*)"complement", {226, 136, 129, 0}}, {(unsigned char*)"complexes", {226, 132, 130, 0}}, {(unsigned char*)"cong", {226, 137, 133, 0}}, {(unsigned char*)"congdot", {226, 169, 173, 0}}, {(unsigned char*)"conint", {226, 136, 174, 0}}, {(unsigned char*)"copf", {240, 157, 149, 148, 0}}, {(unsigned char*)"coprod", {226, 136, 144, 0}}, {(unsigned char*)"copy", {194, 169, 0}}, {(unsigned char*)"copysr", {226, 132, 151, 0}}, {(unsigned char*)"crarr", {226, 134, 181, 0}}, {(unsigned char*)"cross", {226, 156, 151, 0}}, {(unsigned char*)"cscr", {240, 157, 146, 184, 0}}, {(unsigned char*)"csub", {226, 171, 143, 0}}, {(unsigned char*)"csube", {226, 171, 145, 0}}, {(unsigned char*)"csup", {226, 171, 144, 0}}, {(unsigned char*)"csupe", {226, 171, 146, 0}}, {(unsigned char*)"ctdot", {226, 139, 175, 0}}, {(unsigned char*)"cudarrl", {226, 164, 184, 0}}, {(unsigned char*)"cudarrr", {226, 164, 181, 0}}, {(unsigned char*)"cuepr", {226, 139, 158, 0}}, {(unsigned char*)"cuesc", {226, 139, 159, 0}}, {(unsigned char*)"cularr", {226, 134, 182, 0}}, {(unsigned char*)"cularrp", {226, 164, 189, 0}}, {(unsigned char*)"cup", {226, 136, 170, 0}}, {(unsigned char*)"cupbrcap", {226, 169, 136, 0}}, {(unsigned char*)"cupcap", {226, 169, 134, 0}}, {(unsigned char*)"cupcup", {226, 169, 138, 0}}, {(unsigned char*)"cupdot", {226, 138, 141, 0}}, {(unsigned char*)"cupor", {226, 169, 133, 0}}, {(unsigned char*)"cups", {226, 136, 170, 239, 184, 128, 0}}, {(unsigned char*)"curarr", {226, 134, 183, 0}}, {(unsigned char*)"curarrm", {226, 164, 188, 0}}, {(unsigned char*)"curlyeqprec", {226, 139, 158, 0}}, {(unsigned char*)"curlyeqsucc", {226, 139, 159, 0}}, {(unsigned char*)"curlyvee", {226, 139, 142, 0}}, {(unsigned char*)"curlywedge", {226, 139, 143, 0}}, {(unsigned char*)"curren", {194, 164, 0}}, {(unsigned char*)"curvearrowleft", {226, 134, 182, 0}}, {(unsigned char*)"curvearrowright", {226, 134, 183, 0}}, {(unsigned char*)"cuvee", {226, 139, 142, 0}}, {(unsigned char*)"cuwed", {226, 139, 143, 0}}, {(unsigned char*)"cwconint", {226, 136, 178, 0}}, {(unsigned char*)"cwint", {226, 136, 177, 0}}, {(unsigned char*)"cylcty", {226, 140, 173, 0}}, {(unsigned char*)"dArr", {226, 135, 147, 0}}, {(unsigned char*)"dHar", {226, 165, 165, 0}}, {(unsigned char*)"dagger", {226, 128, 160, 0}}, {(unsigned char*)"daleth", {226, 132, 184, 0}}, {(unsigned char*)"darr", {226, 134, 147, 0}}, {(unsigned char*)"dash", {226, 128, 144, 0}}, {(unsigned char*)"dashv", {226, 138, 163, 0}}, {(unsigned char*)"dbkarow", {226, 164, 143, 0}}, {(unsigned char*)"dblac", {203, 157, 0}}, {(unsigned char*)"dcaron", {196, 143, 0}}, {(unsigned char*)"dcy", {208, 180, 0}}, {(unsigned char*)"dd", {226, 133, 134, 0}}, {(unsigned char*)"ddagger", {226, 128, 161, 0}}, {(unsigned char*)"ddarr", {226, 135, 138, 0}}, {(unsigned char*)"ddotseq", {226, 169, 183, 0}}, {(unsigned char*)"deg", {194, 176, 0}}, {(unsigned char*)"delta", {206, 180, 0}}, {(unsigned char*)"demptyv", {226, 166, 177, 0}}, {(unsigned char*)"dfisht", {226, 165, 191, 0}}, {(unsigned char*)"dfr", {240, 157, 148, 161, 0}}, {(unsigned char*)"dharl", {226, 135, 131, 0}}, {(unsigned char*)"dharr", {226, 135, 130, 0}}, {(unsigned char*)"diam", {226, 139, 132, 0}}, {(unsigned char*)"diamond", {226, 139, 132, 0}}, {(unsigned char*)"diamondsuit", {226, 153, 166, 0}}, {(unsigned char*)"diams", {226, 153, 166, 0}}, {(unsigned char*)"die", {194, 168, 0}}, {(unsigned char*)"digamma", {207, 157, 0}}, {(unsigned char*)"disin", {226, 139, 178, 0}}, {(unsigned char*)"div", {195, 183, 0}}, {(unsigned char*)"divide", {195, 183, 0}}, {(unsigned char*)"divideontimes", {226, 139, 135, 0}}, {(unsigned char*)"divonx", {226, 139, 135, 0}}, {(unsigned char*)"djcy", {209, 146, 0}}, {(unsigned char*)"dlcorn", {226, 140, 158, 0}}, {(unsigned char*)"dlcrop", {226, 140, 141, 0}}, {(unsigned char*)"dollar", {36, 0}}, {(unsigned char*)"dopf", {240, 157, 149, 149, 0}}, {(unsigned char*)"dot", {203, 153, 0}}, {(unsigned char*)"doteq", {226, 137, 144, 0}}, {(unsigned char*)"doteqdot", {226, 137, 145, 0}}, {(unsigned char*)"dotminus", {226, 136, 184, 0}}, {(unsigned char*)"dotplus", {226, 136, 148, 0}}, {(unsigned char*)"dotsquare", {226, 138, 161, 0}}, {(unsigned char*)"doublebarwedge", {226, 140, 134, 0}}, {(unsigned char*)"downarrow", {226, 134, 147, 0}}, {(unsigned char*)"downdownarrows", {226, 135, 138, 0}}, {(unsigned char*)"downharpoonleft", {226, 135, 131, 0}}, {(unsigned char*)"downharpoonright", {226, 135, 130, 0}}, {(unsigned char*)"drbkarow", {226, 164, 144, 0}}, {(unsigned char*)"drcorn", {226, 140, 159, 0}}, {(unsigned char*)"drcrop", {226, 140, 140, 0}}, {(unsigned char*)"dscr", {240, 157, 146, 185, 0}}, {(unsigned char*)"dscy", {209, 149, 0}}, {(unsigned char*)"dsol", {226, 167, 182, 0}}, {(unsigned char*)"dstrok", {196, 145, 0}}, {(unsigned char*)"dtdot", {226, 139, 177, 0}}, {(unsigned char*)"dtri", {226, 150, 191, 0}}, {(unsigned char*)"dtrif", {226, 150, 190, 0}}, {(unsigned char*)"duarr", {226, 135, 181, 0}}, {(unsigned char*)"duhar", {226, 165, 175, 0}}, {(unsigned char*)"dwangle", {226, 166, 166, 0}}, {(unsigned char*)"dzcy", {209, 159, 0}}, {(unsigned char*)"dzigrarr", {226, 159, 191, 0}}, {(unsigned char*)"eDDot", {226, 169, 183, 0}}, {(unsigned char*)"eDot", {226, 137, 145, 0}}, {(unsigned char*)"eacute", {195, 169, 0}}, {(unsigned char*)"easter", {226, 169, 174, 0}}, {(unsigned char*)"ecaron", {196, 155, 0}}, {(unsigned char*)"ecir", {226, 137, 150, 0}}, {(unsigned char*)"ecirc", {195, 170, 0}}, {(unsigned char*)"ecolon", {226, 137, 149, 0}}, {(unsigned char*)"ecy", {209, 141, 0}}, {(unsigned char*)"edot", {196, 151, 0}}, {(unsigned char*)"ee", {226, 133, 135, 0}}, {(unsigned char*)"efDot", {226, 137, 146, 0}}, {(unsigned char*)"efr", {240, 157, 148, 162, 0}}, {(unsigned char*)"eg", {226, 170, 154, 0}}, {(unsigned char*)"egrave", {195, 168, 0}}, {(unsigned char*)"egs", {226, 170, 150, 0}}, {(unsigned char*)"egsdot", {226, 170, 152, 0}}, {(unsigned char*)"el", {226, 170, 153, 0}}, {(unsigned char*)"elinters", {226, 143, 167, 0}}, {(unsigned char*)"ell", {226, 132, 147, 0}}, {(unsigned char*)"els", {226, 170, 149, 0}}, {(unsigned char*)"elsdot", {226, 170, 151, 0}}, {(unsigned char*)"emacr", {196, 147, 0}}, {(unsigned char*)"empty", {226, 136, 133, 0}}, {(unsigned char*)"emptyset", {226, 136, 133, 0}}, {(unsigned char*)"emptyv", {226, 136, 133, 0}}, {(unsigned char*)"emsp", {226, 128, 131, 0}}, {(unsigned char*)"emsp13", {226, 128, 132, 0}}, {(unsigned char*)"emsp14", {226, 128, 133, 0}}, {(unsigned char*)"eng", {197, 139, 0}}, {(unsigned char*)"ensp", {226, 128, 130, 0}}, {(unsigned char*)"eogon", {196, 153, 0}}, {(unsigned char*)"eopf", {240, 157, 149, 150, 0}}, {(unsigned char*)"epar", {226, 139, 149, 0}}, {(unsigned char*)"eparsl", {226, 167, 163, 0}}, {(unsigned char*)"eplus", {226, 169, 177, 0}}, {(unsigned char*)"epsi", {206, 181, 0}}, {(unsigned char*)"epsilon", {206, 181, 0}}, {(unsigned char*)"epsiv", {207, 181, 0}}, {(unsigned char*)"eqcirc", {226, 137, 150, 0}}, {(unsigned char*)"eqcolon", {226, 137, 149, 0}}, {(unsigned char*)"eqsim", {226, 137, 130, 0}}, {(unsigned char*)"eqslantgtr", {226, 170, 150, 0}}, {(unsigned char*)"eqslantless", {226, 170, 149, 0}}, {(unsigned char*)"equals", {61, 0}}, {(unsigned char*)"equest", {226, 137, 159, 0}}, {(unsigned char*)"equiv", {226, 137, 161, 0}}, {(unsigned char*)"equivDD", {226, 169, 184, 0}}, {(unsigned char*)"eqvparsl", {226, 167, 165, 0}}, {(unsigned char*)"erDot", {226, 137, 147, 0}}, {(unsigned char*)"erarr", {226, 165, 177, 0}}, {(unsigned char*)"escr", {226, 132, 175, 0}}, {(unsigned char*)"esdot", {226, 137, 144, 0}}, {(unsigned char*)"esim", {226, 137, 130, 0}}, {(unsigned char*)"eta", {206, 183, 0}}, {(unsigned char*)"eth", {195, 176, 0}}, {(unsigned char*)"euml", {195, 171, 0}}, {(unsigned char*)"euro", {226, 130, 172, 0}}, {(unsigned char*)"excl", {33, 0}}, {(unsigned char*)"exist", {226, 136, 131, 0}}, {(unsigned char*)"expectation", {226, 132, 176, 0}}, {(unsigned char*)"exponentiale", {226, 133, 135, 0}}, {(unsigned char*)"fallingdotseq", {226, 137, 146, 0}}, {(unsigned char*)"fcy", {209, 132, 0}}, {(unsigned char*)"female", {226, 153, 128, 0}}, {(unsigned char*)"ffilig", {239, 172, 131, 0}}, {(unsigned char*)"fflig", {239, 172, 128, 0}}, {(unsigned char*)"ffllig", {239, 172, 132, 0}}, {(unsigned char*)"ffr", {240, 157, 148, 163, 0}}, {(unsigned char*)"filig", {239, 172, 129, 0}}, {(unsigned char*)"fjlig", {102, 106, 0}}, {(unsigned char*)"flat", {226, 153, 173, 0}}, {(unsigned char*)"fllig", {239, 172, 130, 0}}, {(unsigned char*)"fltns", {226, 150, 177, 0}}, {(unsigned char*)"fnof", {198, 146, 0}}, {(unsigned char*)"fopf", {240, 157, 149, 151, 0}}, {(unsigned char*)"forall", {226, 136, 128, 0}}, {(unsigned char*)"fork", {226, 139, 148, 0}}, {(unsigned char*)"forkv", {226, 171, 153, 0}}, {(unsigned char*)"fpartint", {226, 168, 141, 0}}, {(unsigned char*)"frac12", {194, 189, 0}}, {(unsigned char*)"frac13", {226, 133, 147, 0}}, {(unsigned char*)"frac14", {194, 188, 0}}, {(unsigned char*)"frac15", {226, 133, 149, 0}}, {(unsigned char*)"frac16", {226, 133, 153, 0}}, {(unsigned char*)"frac18", {226, 133, 155, 0}}, {(unsigned char*)"frac23", {226, 133, 148, 0}}, {(unsigned char*)"frac25", {226, 133, 150, 0}}, {(unsigned char*)"frac34", {194, 190, 0}}, {(unsigned char*)"frac35", {226, 133, 151, 0}}, {(unsigned char*)"frac38", {226, 133, 156, 0}}, {(unsigned char*)"frac45", {226, 133, 152, 0}}, {(unsigned char*)"frac56", {226, 133, 154, 0}}, {(unsigned char*)"frac58", {226, 133, 157, 0}}, {(unsigned char*)"frac78", {226, 133, 158, 0}}, {(unsigned char*)"frasl", {226, 129, 132, 0}}, {(unsigned char*)"frown", {226, 140, 162, 0}}, {(unsigned char*)"fscr", {240, 157, 146, 187, 0}}, {(unsigned char*)"gE", {226, 137, 167, 0}}, {(unsigned char*)"gEl", {226, 170, 140, 0}}, {(unsigned char*)"gacute", {199, 181, 0}}, {(unsigned char*)"gamma", {206, 179, 0}}, {(unsigned char*)"gammad", {207, 157, 0}}, {(unsigned char*)"gap", {226, 170, 134, 0}}, {(unsigned char*)"gbreve", {196, 159, 0}}, {(unsigned char*)"gcirc", {196, 157, 0}}, {(unsigned char*)"gcy", {208, 179, 0}}, {(unsigned char*)"gdot", {196, 161, 0}}, {(unsigned char*)"ge", {226, 137, 165, 0}}, {(unsigned char*)"gel", {226, 139, 155, 0}}, {(unsigned char*)"geq", {226, 137, 165, 0}}, {(unsigned char*)"geqq", {226, 137, 167, 0}}, {(unsigned char*)"geqslant", {226, 169, 190, 0}}, {(unsigned char*)"ges", {226, 169, 190, 0}}, {(unsigned char*)"gescc", {226, 170, 169, 0}}, {(unsigned char*)"gesdot", {226, 170, 128, 0}}, {(unsigned char*)"gesdoto", {226, 170, 130, 0}}, {(unsigned char*)"gesdotol", {226, 170, 132, 0}}, {(unsigned char*)"gesl", {226, 139, 155, 239, 184, 128, 0}}, {(unsigned char*)"gesles", {226, 170, 148, 0}}, {(unsigned char*)"gfr", {240, 157, 148, 164, 0}}, {(unsigned char*)"gg", {226, 137, 171, 0}}, {(unsigned char*)"ggg", {226, 139, 153, 0}}, {(unsigned char*)"gimel", {226, 132, 183, 0}}, {(unsigned char*)"gjcy", {209, 147, 0}}, {(unsigned char*)"gl", {226, 137, 183, 0}}, {(unsigned char*)"glE", {226, 170, 146, 0}}, {(unsigned char*)"gla", {226, 170, 165, 0}}, {(unsigned char*)"glj", {226, 170, 164, 0}}, {(unsigned char*)"gnE", {226, 137, 169, 0}}, {(unsigned char*)"gnap", {226, 170, 138, 0}}, {(unsigned char*)"gnapprox", {226, 170, 138, 0}}, {(unsigned char*)"gne", {226, 170, 136, 0}}, {(unsigned char*)"gneq", {226, 170, 136, 0}}, {(unsigned char*)"gneqq", {226, 137, 169, 0}}, {(unsigned char*)"gnsim", {226, 139, 167, 0}}, {(unsigned char*)"gopf", {240, 157, 149, 152, 0}}, {(unsigned char*)"grave", {96, 0}}, {(unsigned char*)"gscr", {226, 132, 138, 0}}, {(unsigned char*)"gsim", {226, 137, 179, 0}}, {(unsigned char*)"gsime", {226, 170, 142, 0}}, {(unsigned char*)"gsiml", {226, 170, 144, 0}}, {(unsigned char*)"gt", {62, 0}}, {(unsigned char*)"gtcc", {226, 170, 167, 0}}, {(unsigned char*)"gtcir", {226, 169, 186, 0}}, {(unsigned char*)"gtdot", {226, 139, 151, 0}}, {(unsigned char*)"gtlPar", {226, 166, 149, 0}}, {(unsigned char*)"gtquest", {226, 169, 188, 0}}, {(unsigned char*)"gtrapprox", {226, 170, 134, 0}}, {(unsigned char*)"gtrarr", {226, 165, 184, 0}}, {(unsigned char*)"gtrdot", {226, 139, 151, 0}}, {(unsigned char*)"gtreqless", {226, 139, 155, 0}}, {(unsigned char*)"gtreqqless", {226, 170, 140, 0}}, {(unsigned char*)"gtrless", {226, 137, 183, 0}}, {(unsigned char*)"gtrsim", {226, 137, 179, 0}}, {(unsigned char*)"gvertneqq", {226, 137, 169, 239, 184, 128, 0}}, {(unsigned char*)"gvnE", {226, 137, 169, 239, 184, 128, 0}}, {(unsigned char*)"hArr", {226, 135, 148, 0}}, {(unsigned char*)"hairsp", {226, 128, 138, 0}}, {(unsigned char*)"half", {194, 189, 0}}, {(unsigned char*)"hamilt", {226, 132, 139, 0}}, {(unsigned char*)"hardcy", {209, 138, 0}}, {(unsigned char*)"harr", {226, 134, 148, 0}}, {(unsigned char*)"harrcir", {226, 165, 136, 0}}, {(unsigned char*)"harrw", {226, 134, 173, 0}}, {(unsigned char*)"hbar", {226, 132, 143, 0}}, {(unsigned char*)"hcirc", {196, 165, 0}}, {(unsigned char*)"hearts", {226, 153, 165, 0}}, {(unsigned char*)"heartsuit", {226, 153, 165, 0}}, {(unsigned char*)"hellip", {226, 128, 166, 0}}, {(unsigned char*)"hercon", {226, 138, 185, 0}}, {(unsigned char*)"hfr", {240, 157, 148, 165, 0}}, {(unsigned char*)"hksearow", {226, 164, 165, 0}}, {(unsigned char*)"hkswarow", {226, 164, 166, 0}}, {(unsigned char*)"hoarr", {226, 135, 191, 0}}, {(unsigned char*)"homtht", {226, 136, 187, 0}}, {(unsigned char*)"hookleftarrow", {226, 134, 169, 0}}, {(unsigned char*)"hookrightarrow", {226, 134, 170, 0}}, {(unsigned char*)"hopf", {240, 157, 149, 153, 0}}, {(unsigned char*)"horbar", {226, 128, 149, 0}}, {(unsigned char*)"hscr", {240, 157, 146, 189, 0}}, {(unsigned char*)"hslash", {226, 132, 143, 0}}, {(unsigned char*)"hstrok", {196, 167, 0}}, {(unsigned char*)"hybull", {226, 129, 131, 0}}, {(unsigned char*)"hyphen", {226, 128, 144, 0}}, {(unsigned char*)"iacute", {195, 173, 0}}, {(unsigned char*)"ic", {226, 129, 163, 0}}, {(unsigned char*)"icirc", {195, 174, 0}}, {(unsigned char*)"icy", {208, 184, 0}}, {(unsigned char*)"iecy", {208, 181, 0}}, {(unsigned char*)"iexcl", {194, 161, 0}}, {(unsigned char*)"iff", {226, 135, 148, 0}}, {(unsigned char*)"ifr", {240, 157, 148, 166, 0}}, {(unsigned char*)"igrave", {195, 172, 0}}, {(unsigned char*)"ii", {226, 133, 136, 0}}, {(unsigned char*)"iiiint", {226, 168, 140, 0}}, {(unsigned char*)"iiint", {226, 136, 173, 0}}, {(unsigned char*)"iinfin", {226, 167, 156, 0}}, {(unsigned char*)"iiota", {226, 132, 169, 0}}, {(unsigned char*)"ijlig", {196, 179, 0}}, {(unsigned char*)"imacr", {196, 171, 0}}, {(unsigned char*)"image", {226, 132, 145, 0}}, {(unsigned char*)"imagline", {226, 132, 144, 0}}, {(unsigned char*)"imagpart", {226, 132, 145, 0}}, {(unsigned char*)"imath", {196, 177, 0}}, {(unsigned char*)"imof", {226, 138, 183, 0}}, {(unsigned char*)"imped", {198, 181, 0}}, {(unsigned char*)"in", {226, 136, 136, 0}}, {(unsigned char*)"incare", {226, 132, 133, 0}}, {(unsigned char*)"infin", {226, 136, 158, 0}}, {(unsigned char*)"infintie", {226, 167, 157, 0}}, {(unsigned char*)"inodot", {196, 177, 0}}, {(unsigned char*)"int", {226, 136, 171, 0}}, {(unsigned char*)"intcal", {226, 138, 186, 0}}, {(unsigned char*)"integers", {226, 132, 164, 0}}, {(unsigned char*)"intercal", {226, 138, 186, 0}}, {(unsigned char*)"intlarhk", {226, 168, 151, 0}}, {(unsigned char*)"intprod", {226, 168, 188, 0}}, {(unsigned char*)"iocy", {209, 145, 0}}, {(unsigned char*)"iogon", {196, 175, 0}}, {(unsigned char*)"iopf", {240, 157, 149, 154, 0}}, {(unsigned char*)"iota", {206, 185, 0}}, {(unsigned char*)"iprod", {226, 168, 188, 0}}, {(unsigned char*)"iquest", {194, 191, 0}}, {(unsigned char*)"iscr", {240, 157, 146, 190, 0}}, {(unsigned char*)"isin", {226, 136, 136, 0}}, {(unsigned char*)"isinE", {226, 139, 185, 0}}, {(unsigned char*)"isindot", {226, 139, 181, 0}}, {(unsigned char*)"isins", {226, 139, 180, 0}}, {(unsigned char*)"isinsv", {226, 139, 179, 0}}, {(unsigned char*)"isinv", {226, 136, 136, 0}}, {(unsigned char*)"it", {226, 129, 162, 0}}, {(unsigned char*)"itilde", {196, 169, 0}}, {(unsigned char*)"iukcy", {209, 150, 0}}, {(unsigned char*)"iuml", {195, 175, 0}}, {(unsigned char*)"jcirc", {196, 181, 0}}, {(unsigned char*)"jcy", {208, 185, 0}}, {(unsigned char*)"jfr", {240, 157, 148, 167, 0}}, {(unsigned char*)"jmath", {200, 183, 0}}, {(unsigned char*)"jopf", {240, 157, 149, 155, 0}}, {(unsigned char*)"jscr", {240, 157, 146, 191, 0}}, {(unsigned char*)"jsercy", {209, 152, 0}}, {(unsigned char*)"jukcy", {209, 148, 0}}, {(unsigned char*)"kappa", {206, 186, 0}}, {(unsigned char*)"kappav", {207, 176, 0}}, {(unsigned char*)"kcedil", {196, 183, 0}}, {(unsigned char*)"kcy", {208, 186, 0}}, {(unsigned char*)"kfr", {240, 157, 148, 168, 0}}, {(unsigned char*)"kgreen", {196, 184, 0}}, {(unsigned char*)"khcy", {209, 133, 0}}, {(unsigned char*)"kjcy", {209, 156, 0}}, {(unsigned char*)"kopf", {240, 157, 149, 156, 0}}, {(unsigned char*)"kscr", {240, 157, 147, 128, 0}}, {(unsigned char*)"lAarr", {226, 135, 154, 0}}, {(unsigned char*)"lArr", {226, 135, 144, 0}}, {(unsigned char*)"lAtail", {226, 164, 155, 0}}, {(unsigned char*)"lBarr", {226, 164, 142, 0}}, {(unsigned char*)"lE", {226, 137, 166, 0}}, {(unsigned char*)"lEg", {226, 170, 139, 0}}, {(unsigned char*)"lHar", {226, 165, 162, 0}}, {(unsigned char*)"lacute", {196, 186, 0}}, {(unsigned char*)"laemptyv", {226, 166, 180, 0}}, {(unsigned char*)"lagran", {226, 132, 146, 0}}, {(unsigned char*)"lambda", {206, 187, 0}}, {(unsigned char*)"lang", {226, 159, 168, 0}}, {(unsigned char*)"langd", {226, 166, 145, 0}}, {(unsigned char*)"langle", {226, 159, 168, 0}}, {(unsigned char*)"lap", {226, 170, 133, 0}}, {(unsigned char*)"laquo", {194, 171, 0}}, {(unsigned char*)"larr", {226, 134, 144, 0}}, {(unsigned char*)"larrb", {226, 135, 164, 0}}, {(unsigned char*)"larrbfs", {226, 164, 159, 0}}, {(unsigned char*)"larrfs", {226, 164, 157, 0}}, {(unsigned char*)"larrhk", {226, 134, 169, 0}}, {(unsigned char*)"larrlp", {226, 134, 171, 0}}, {(unsigned char*)"larrpl", {226, 164, 185, 0}}, {(unsigned char*)"larrsim", {226, 165, 179, 0}}, {(unsigned char*)"larrtl", {226, 134, 162, 0}}, {(unsigned char*)"lat", {226, 170, 171, 0}}, {(unsigned char*)"latail", {226, 164, 153, 0}}, {(unsigned char*)"late", {226, 170, 173, 0}}, {(unsigned char*)"lates", {226, 170, 173, 239, 184, 128, 0}}, {(unsigned char*)"lbarr", {226, 164, 140, 0}}, {(unsigned char*)"lbbrk", {226, 157, 178, 0}}, {(unsigned char*)"lbrace", {123, 0}}, {(unsigned char*)"lbrack", {91, 0}}, {(unsigned char*)"lbrke", {226, 166, 139, 0}}, {(unsigned char*)"lbrksld", {226, 166, 143, 0}}, {(unsigned char*)"lbrkslu", {226, 166, 141, 0}}, {(unsigned char*)"lcaron", {196, 190, 0}}, {(unsigned char*)"lcedil", {196, 188, 0}}, {(unsigned char*)"lceil", {226, 140, 136, 0}}, {(unsigned char*)"lcub", {123, 0}}, {(unsigned char*)"lcy", {208, 187, 0}}, {(unsigned char*)"ldca", {226, 164, 182, 0}}, {(unsigned char*)"ldquo", {226, 128, 156, 0}}, {(unsigned char*)"ldquor", {226, 128, 158, 0}}, {(unsigned char*)"ldrdhar", {226, 165, 167, 0}}, {(unsigned char*)"ldrushar", {226, 165, 139, 0}}, {(unsigned char*)"ldsh", {226, 134, 178, 0}}, {(unsigned char*)"le", {226, 137, 164, 0}}, {(unsigned char*)"leftarrow", {226, 134, 144, 0}}, {(unsigned char*)"leftarrowtail", {226, 134, 162, 0}}, {(unsigned char*)"leftharpoondown", {226, 134, 189, 0}}, {(unsigned char*)"leftharpoonup", {226, 134, 188, 0}}, {(unsigned char*)"leftleftarrows", {226, 135, 135, 0}}, {(unsigned char*)"leftrightarrow", {226, 134, 148, 0}}, {(unsigned char*)"leftrightarrows", {226, 135, 134, 0}}, {(unsigned char*)"leftrightharpoons", {226, 135, 139, 0}}, {(unsigned char*)"leftrightsquigarrow", {226, 134, 173, 0}}, {(unsigned char*)"leftthreetimes", {226, 139, 139, 0}}, {(unsigned char*)"leg", {226, 139, 154, 0}}, {(unsigned char*)"leq", {226, 137, 164, 0}}, {(unsigned char*)"leqq", {226, 137, 166, 0}}, {(unsigned char*)"leqslant", {226, 169, 189, 0}}, {(unsigned char*)"les", {226, 169, 189, 0}}, {(unsigned char*)"lescc", {226, 170, 168, 0}}, {(unsigned char*)"lesdot", {226, 169, 191, 0}}, {(unsigned char*)"lesdoto", {226, 170, 129, 0}}, {(unsigned char*)"lesdotor", {226, 170, 131, 0}}, {(unsigned char*)"lesg", {226, 139, 154, 239, 184, 128, 0}}, {(unsigned char*)"lesges", {226, 170, 147, 0}}, {(unsigned char*)"lessapprox", {226, 170, 133, 0}}, {(unsigned char*)"lessdot", {226, 139, 150, 0}}, {(unsigned char*)"lesseqgtr", {226, 139, 154, 0}}, {(unsigned char*)"lesseqqgtr", {226, 170, 139, 0}}, {(unsigned char*)"lessgtr", {226, 137, 182, 0}}, {(unsigned char*)"lesssim", {226, 137, 178, 0}}, {(unsigned char*)"lfisht", {226, 165, 188, 0}}, {(unsigned char*)"lfloor", {226, 140, 138, 0}}, {(unsigned char*)"lfr", {240, 157, 148, 169, 0}}, {(unsigned char*)"lg", {226, 137, 182, 0}}, {(unsigned char*)"lgE", {226, 170, 145, 0}}, {(unsigned char*)"lhard", {226, 134, 189, 0}}, {(unsigned char*)"lharu", {226, 134, 188, 0}}, {(unsigned char*)"lharul", {226, 165, 170, 0}}, {(unsigned char*)"lhblk", {226, 150, 132, 0}}, {(unsigned char*)"ljcy", {209, 153, 0}}, {(unsigned char*)"ll", {226, 137, 170, 0}}, {(unsigned char*)"llarr", {226, 135, 135, 0}}, {(unsigned char*)"llcorner", {226, 140, 158, 0}}, {(unsigned char*)"llhard", {226, 165, 171, 0}}, {(unsigned char*)"lltri", {226, 151, 186, 0}}, {(unsigned char*)"lmidot", {197, 128, 0}}, {(unsigned char*)"lmoust", {226, 142, 176, 0}}, {(unsigned char*)"lmoustache", {226, 142, 176, 0}}, {(unsigned char*)"lnE", {226, 137, 168, 0}}, {(unsigned char*)"lnap", {226, 170, 137, 0}}, {(unsigned char*)"lnapprox", {226, 170, 137, 0}}, {(unsigned char*)"lne", {226, 170, 135, 0}}, {(unsigned char*)"lneq", {226, 170, 135, 0}}, {(unsigned char*)"lneqq", {226, 137, 168, 0}}, {(unsigned char*)"lnsim", {226, 139, 166, 0}}, {(unsigned char*)"loang", {226, 159, 172, 0}}, {(unsigned char*)"loarr", {226, 135, 189, 0}}, {(unsigned char*)"lobrk", {226, 159, 166, 0}}, {(unsigned char*)"longleftarrow", {226, 159, 181, 0}}, {(unsigned char*)"longleftrightarrow", {226, 159, 183, 0}}, {(unsigned char*)"longmapsto", {226, 159, 188, 0}}, {(unsigned char*)"longrightarrow", {226, 159, 182, 0}}, {(unsigned char*)"looparrowleft", {226, 134, 171, 0}}, {(unsigned char*)"looparrowright", {226, 134, 172, 0}}, {(unsigned char*)"lopar", {226, 166, 133, 0}}, {(unsigned char*)"lopf", {240, 157, 149, 157, 0}}, {(unsigned char*)"loplus", {226, 168, 173, 0}}, {(unsigned char*)"lotimes", {226, 168, 180, 0}}, {(unsigned char*)"lowast", {226, 136, 151, 0}}, {(unsigned char*)"lowbar", {95, 0}}, {(unsigned char*)"loz", {226, 151, 138, 0}}, {(unsigned char*)"lozenge", {226, 151, 138, 0}}, {(unsigned char*)"lozf", {226, 167, 171, 0}}, {(unsigned char*)"lpar", {40, 0}}, {(unsigned char*)"lparlt", {226, 166, 147, 0}}, {(unsigned char*)"lrarr", {226, 135, 134, 0}}, {(unsigned char*)"lrcorner", {226, 140, 159, 0}}, {(unsigned char*)"lrhar", {226, 135, 139, 0}}, {(unsigned char*)"lrhard", {226, 165, 173, 0}}, {(unsigned char*)"lrm", {226, 128, 142, 0}}, {(unsigned char*)"lrtri", {226, 138, 191, 0}}, {(unsigned char*)"lsaquo", {226, 128, 185, 0}}, {(unsigned char*)"lscr", {240, 157, 147, 129, 0}}, {(unsigned char*)"lsh", {226, 134, 176, 0}}, {(unsigned char*)"lsim", {226, 137, 178, 0}}, {(unsigned char*)"lsime", {226, 170, 141, 0}}, {(unsigned char*)"lsimg", {226, 170, 143, 0}}, {(unsigned char*)"lsqb", {91, 0}}, {(unsigned char*)"lsquo", {226, 128, 152, 0}}, {(unsigned char*)"lsquor", {226, 128, 154, 0}}, {(unsigned char*)"lstrok", {197, 130, 0}}, {(unsigned char*)"lt", {60, 0}}, {(unsigned char*)"ltcc", {226, 170, 166, 0}}, {(unsigned char*)"ltcir", {226, 169, 185, 0}}, {(unsigned char*)"ltdot", {226, 139, 150, 0}}, {(unsigned char*)"lthree", {226, 139, 139, 0}}, {(unsigned char*)"ltimes", {226, 139, 137, 0}}, {(unsigned char*)"ltlarr", {226, 165, 182, 0}}, {(unsigned char*)"ltquest", {226, 169, 187, 0}}, {(unsigned char*)"ltrPar", {226, 166, 150, 0}}, {(unsigned char*)"ltri", {226, 151, 131, 0}}, {(unsigned char*)"ltrie", {226, 138, 180, 0}}, {(unsigned char*)"ltrif", {226, 151, 130, 0}}, {(unsigned char*)"lurdshar", {226, 165, 138, 0}}, {(unsigned char*)"luruhar", {226, 165, 166, 0}}, {(unsigned char*)"lvertneqq", {226, 137, 168, 239, 184, 128, 0}}, {(unsigned char*)"lvnE", {226, 137, 168, 239, 184, 128, 0}}, {(unsigned char*)"mDDot", {226, 136, 186, 0}}, {(unsigned char*)"macr", {194, 175, 0}}, {(unsigned char*)"male", {226, 153, 130, 0}}, {(unsigned char*)"malt", {226, 156, 160, 0}}, {(unsigned char*)"maltese", {226, 156, 160, 0}}, {(unsigned char*)"map", {226, 134, 166, 0}}, {(unsigned char*)"mapsto", {226, 134, 166, 0}}, {(unsigned char*)"mapstodown", {226, 134, 167, 0}}, {(unsigned char*)"mapstoleft", {226, 134, 164, 0}}, {(unsigned char*)"mapstoup", {226, 134, 165, 0}}, {(unsigned char*)"marker", {226, 150, 174, 0}}, {(unsigned char*)"mcomma", {226, 168, 169, 0}}, {(unsigned char*)"mcy", {208, 188, 0}}, {(unsigned char*)"mdash", {226, 128, 148, 0}}, {(unsigned char*)"measuredangle", {226, 136, 161, 0}}, {(unsigned char*)"mfr", {240, 157, 148, 170, 0}}, {(unsigned char*)"mho", {226, 132, 167, 0}}, {(unsigned char*)"micro", {194, 181, 0}}, {(unsigned char*)"mid", {226, 136, 163, 0}}, {(unsigned char*)"midast", {42, 0}}, {(unsigned char*)"midcir", {226, 171, 176, 0}}, {(unsigned char*)"middot", {194, 183, 0}}, {(unsigned char*)"minus", {226, 136, 146, 0}}, {(unsigned char*)"minusb", {226, 138, 159, 0}}, {(unsigned char*)"minusd", {226, 136, 184, 0}}, {(unsigned char*)"minusdu", {226, 168, 170, 0}}, {(unsigned char*)"mlcp", {226, 171, 155, 0}}, {(unsigned char*)"mldr", {226, 128, 166, 0}}, {(unsigned char*)"mnplus", {226, 136, 147, 0}}, {(unsigned char*)"models", {226, 138, 167, 0}}, {(unsigned char*)"mopf", {240, 157, 149, 158, 0}}, {(unsigned char*)"mp", {226, 136, 147, 0}}, {(unsigned char*)"mscr", {240, 157, 147, 130, 0}}, {(unsigned char*)"mstpos", {226, 136, 190, 0}}, {(unsigned char*)"mu", {206, 188, 0}}, {(unsigned char*)"multimap", {226, 138, 184, 0}}, {(unsigned char*)"mumap", {226, 138, 184, 0}}, {(unsigned char*)"nGg", {226, 139, 153, 204, 184, 0}}, {(unsigned char*)"nGt", {226, 137, 171, 226, 131, 146, 0}}, {(unsigned char*)"nGtv", {226, 137, 171, 204, 184, 0}}, {(unsigned char*)"nLeftarrow", {226, 135, 141, 0}}, {(unsigned char*)"nLeftrightarrow", {226, 135, 142, 0}}, {(unsigned char*)"nLl", {226, 139, 152, 204, 184, 0}}, {(unsigned char*)"nLt", {226, 137, 170, 226, 131, 146, 0}}, {(unsigned char*)"nLtv", {226, 137, 170, 204, 184, 0}}, {(unsigned char*)"nRightarrow", {226, 135, 143, 0}}, {(unsigned char*)"nVDash", {226, 138, 175, 0}}, {(unsigned char*)"nVdash", {226, 138, 174, 0}}, {(unsigned char*)"nabla", {226, 136, 135, 0}}, {(unsigned char*)"nacute", {197, 132, 0}}, {(unsigned char*)"nang", {226, 136, 160, 226, 131, 146, 0}}, {(unsigned char*)"nap", {226, 137, 137, 0}}, {(unsigned char*)"napE", {226, 169, 176, 204, 184, 0}}, {(unsigned char*)"napid", {226, 137, 139, 204, 184, 0}}, {(unsigned char*)"napos", {197, 137, 0}}, {(unsigned char*)"napprox", {226, 137, 137, 0}}, {(unsigned char*)"natur", {226, 153, 174, 0}}, {(unsigned char*)"natural", {226, 153, 174, 0}}, {(unsigned char*)"naturals", {226, 132, 149, 0}}, {(unsigned char*)"nbsp", {194, 160, 0}}, {(unsigned char*)"nbump", {226, 137, 142, 204, 184, 0}}, {(unsigned char*)"nbumpe", {226, 137, 143, 204, 184, 0}}, {(unsigned char*)"ncap", {226, 169, 131, 0}}, {(unsigned char*)"ncaron", {197, 136, 0}}, {(unsigned char*)"ncedil", {197, 134, 0}}, {(unsigned char*)"ncong", {226, 137, 135, 0}}, {(unsigned char*)"ncongdot", {226, 169, 173, 204, 184, 0}}, {(unsigned char*)"ncup", {226, 169, 130, 0}}, {(unsigned char*)"ncy", {208, 189, 0}}, {(unsigned char*)"ndash", {226, 128, 147, 0}}, {(unsigned char*)"ne", {226, 137, 160, 0}}, {(unsigned char*)"neArr", {226, 135, 151, 0}}, {(unsigned char*)"nearhk", {226, 164, 164, 0}}, {(unsigned char*)"nearr", {226, 134, 151, 0}}, {(unsigned char*)"nearrow", {226, 134, 151, 0}}, {(unsigned char*)"nedot", {226, 137, 144, 204, 184, 0}}, {(unsigned char*)"nequiv", {226, 137, 162, 0}}, {(unsigned char*)"nesear", {226, 164, 168, 0}}, {(unsigned char*)"nesim", {226, 137, 130, 204, 184, 0}}, {(unsigned char*)"nexist", {226, 136, 132, 0}}, {(unsigned char*)"nexists", {226, 136, 132, 0}}, {(unsigned char*)"nfr", {240, 157, 148, 171, 0}}, {(unsigned char*)"ngE", {226, 137, 167, 204, 184, 0}}, {(unsigned char*)"nge", {226, 137, 177, 0}}, {(unsigned char*)"ngeq", {226, 137, 177, 0}}, {(unsigned char*)"ngeqq", {226, 137, 167, 204, 184, 0}}, {(unsigned char*)"ngeqslant", {226, 169, 190, 204, 184, 0}}, {(unsigned char*)"nges", {226, 169, 190, 204, 184, 0}}, {(unsigned char*)"ngsim", {226, 137, 181, 0}}, {(unsigned char*)"ngt", {226, 137, 175, 0}}, {(unsigned char*)"ngtr", {226, 137, 175, 0}}, {(unsigned char*)"nhArr", {226, 135, 142, 0}}, {(unsigned char*)"nharr", {226, 134, 174, 0}}, {(unsigned char*)"nhpar", {226, 171, 178, 0}}, {(unsigned char*)"ni", {226, 136, 139, 0}}, {(unsigned char*)"nis", {226, 139, 188, 0}}, {(unsigned char*)"nisd", {226, 139, 186, 0}}, {(unsigned char*)"niv", {226, 136, 139, 0}}, {(unsigned char*)"njcy", {209, 154, 0}}, {(unsigned char*)"nlArr", {226, 135, 141, 0}}, {(unsigned char*)"nlE", {226, 137, 166, 204, 184, 0}}, {(unsigned char*)"nlarr", {226, 134, 154, 0}}, {(unsigned char*)"nldr", {226, 128, 165, 0}}, {(unsigned char*)"nle", {226, 137, 176, 0}}, {(unsigned char*)"nleftarrow", {226, 134, 154, 0}}, {(unsigned char*)"nleftrightarrow", {226, 134, 174, 0}}, {(unsigned char*)"nleq", {226, 137, 176, 0}}, {(unsigned char*)"nleqq", {226, 137, 166, 204, 184, 0}}, {(unsigned char*)"nleqslant", {226, 169, 189, 204, 184, 0}}, {(unsigned char*)"nles", {226, 169, 189, 204, 184, 0}}, {(unsigned char*)"nless", {226, 137, 174, 0}}, {(unsigned char*)"nlsim", {226, 137, 180, 0}}, {(unsigned char*)"nlt", {226, 137, 174, 0}}, {(unsigned char*)"nltri", {226, 139, 170, 0}}, {(unsigned char*)"nltrie", {226, 139, 172, 0}}, {(unsigned char*)"nmid", {226, 136, 164, 0}}, {(unsigned char*)"nopf", {240, 157, 149, 159, 0}}, {(unsigned char*)"not", {194, 172, 0}}, {(unsigned char*)"notin", {226, 136, 137, 0}}, {(unsigned char*)"notinE", {226, 139, 185, 204, 184, 0}}, {(unsigned char*)"notindot", {226, 139, 181, 204, 184, 0}}, {(unsigned char*)"notinva", {226, 136, 137, 0}}, {(unsigned char*)"notinvb", {226, 139, 183, 0}}, {(unsigned char*)"notinvc", {226, 139, 182, 0}}, {(unsigned char*)"notni", {226, 136, 140, 0}}, {(unsigned char*)"notniva", {226, 136, 140, 0}}, {(unsigned char*)"notnivb", {226, 139, 190, 0}}, {(unsigned char*)"notnivc", {226, 139, 189, 0}}, {(unsigned char*)"npar", {226, 136, 166, 0}}, {(unsigned char*)"nparallel", {226, 136, 166, 0}}, {(unsigned char*)"nparsl", {226, 171, 189, 226, 131, 165, 0}}, {(unsigned char*)"npart", {226, 136, 130, 204, 184, 0}}, {(unsigned char*)"npolint", {226, 168, 148, 0}}, {(unsigned char*)"npr", {226, 138, 128, 0}}, {(unsigned char*)"nprcue", {226, 139, 160, 0}}, {(unsigned char*)"npre", {226, 170, 175, 204, 184, 0}}, {(unsigned char*)"nprec", {226, 138, 128, 0}}, {(unsigned char*)"npreceq", {226, 170, 175, 204, 184, 0}}, {(unsigned char*)"nrArr", {226, 135, 143, 0}}, {(unsigned char*)"nrarr", {226, 134, 155, 0}}, {(unsigned char*)"nrarrc", {226, 164, 179, 204, 184, 0}}, {(unsigned char*)"nrarrw", {226, 134, 157, 204, 184, 0}}, {(unsigned char*)"nrightarrow", {226, 134, 155, 0}}, {(unsigned char*)"nrtri", {226, 139, 171, 0}}, {(unsigned char*)"nrtrie", {226, 139, 173, 0}}, {(unsigned char*)"nsc", {226, 138, 129, 0}}, {(unsigned char*)"nsccue", {226, 139, 161, 0}}, {(unsigned char*)"nsce", {226, 170, 176, 204, 184, 0}}, {(unsigned char*)"nscr", {240, 157, 147, 131, 0}}, {(unsigned char*)"nshortmid", {226, 136, 164, 0}}, {(unsigned char*)"nshortparallel", {226, 136, 166, 0}}, {(unsigned char*)"nsim", {226, 137, 129, 0}}, {(unsigned char*)"nsime", {226, 137, 132, 0}}, {(unsigned char*)"nsimeq", {226, 137, 132, 0}}, {(unsigned char*)"nsmid", {226, 136, 164, 0}}, {(unsigned char*)"nspar", {226, 136, 166, 0}}, {(unsigned char*)"nsqsube", {226, 139, 162, 0}}, {(unsigned char*)"nsqsupe", {226, 139, 163, 0}}, {(unsigned char*)"nsub", {226, 138, 132, 0}}, {(unsigned char*)"nsubE", {226, 171, 133, 204, 184, 0}}, {(unsigned char*)"nsube", {226, 138, 136, 0}}, {(unsigned char*)"nsubset", {226, 138, 130, 226, 131, 146, 0}}, {(unsigned char*)"nsubseteq", {226, 138, 136, 0}}, {(unsigned char*)"nsubseteqq", {226, 171, 133, 204, 184, 0}}, {(unsigned char*)"nsucc", {226, 138, 129, 0}}, {(unsigned char*)"nsucceq", {226, 170, 176, 204, 184, 0}}, {(unsigned char*)"nsup", {226, 138, 133, 0}}, {(unsigned char*)"nsupE", {226, 171, 134, 204, 184, 0}}, {(unsigned char*)"nsupe", {226, 138, 137, 0}}, {(unsigned char*)"nsupset", {226, 138, 131, 226, 131, 146, 0}}, {(unsigned char*)"nsupseteq", {226, 138, 137, 0}}, {(unsigned char*)"nsupseteqq", {226, 171, 134, 204, 184, 0}}, {(unsigned char*)"ntgl", {226, 137, 185, 0}}, {(unsigned char*)"ntilde", {195, 177, 0}}, {(unsigned char*)"ntlg", {226, 137, 184, 0}}, {(unsigned char*)"ntriangleleft", {226, 139, 170, 0}}, {(unsigned char*)"ntrianglelefteq", {226, 139, 172, 0}}, {(unsigned char*)"ntriangleright", {226, 139, 171, 0}}, {(unsigned char*)"ntrianglerighteq", {226, 139, 173, 0}}, {(unsigned char*)"nu", {206, 189, 0}}, {(unsigned char*)"num", {35, 0}}, {(unsigned char*)"numero", {226, 132, 150, 0}}, {(unsigned char*)"numsp", {226, 128, 135, 0}}, {(unsigned char*)"nvDash", {226, 138, 173, 0}}, {(unsigned char*)"nvHarr", {226, 164, 132, 0}}, {(unsigned char*)"nvap", {226, 137, 141, 226, 131, 146, 0}}, {(unsigned char*)"nvdash", {226, 138, 172, 0}}, {(unsigned char*)"nvge", {226, 137, 165, 226, 131, 146, 0}}, {(unsigned char*)"nvgt", {62, 226, 131, 146, 0}}, {(unsigned char*)"nvinfin", {226, 167, 158, 0}}, {(unsigned char*)"nvlArr", {226, 164, 130, 0}}, {(unsigned char*)"nvle", {226, 137, 164, 226, 131, 146, 0}}, {(unsigned char*)"nvlt", {60, 226, 131, 146, 0}}, {(unsigned char*)"nvltrie", {226, 138, 180, 226, 131, 146, 0}}, {(unsigned char*)"nvrArr", {226, 164, 131, 0}}, {(unsigned char*)"nvrtrie", {226, 138, 181, 226, 131, 146, 0}}, {(unsigned char*)"nvsim", {226, 136, 188, 226, 131, 146, 0}}, {(unsigned char*)"nwArr", {226, 135, 150, 0}}, {(unsigned char*)"nwarhk", {226, 164, 163, 0}}, {(unsigned char*)"nwarr", {226, 134, 150, 0}}, {(unsigned char*)"nwarrow", {226, 134, 150, 0}}, {(unsigned char*)"nwnear", {226, 164, 167, 0}}, {(unsigned char*)"oS", {226, 147, 136, 0}}, {(unsigned char*)"oacute", {195, 179, 0}}, {(unsigned char*)"oast", {226, 138, 155, 0}}, {(unsigned char*)"ocir", {226, 138, 154, 0}}, {(unsigned char*)"ocirc", {195, 180, 0}}, {(unsigned char*)"ocy", {208, 190, 0}}, {(unsigned char*)"odash", {226, 138, 157, 0}}, {(unsigned char*)"odblac", {197, 145, 0}}, {(unsigned char*)"odiv", {226, 168, 184, 0}}, {(unsigned char*)"odot", {226, 138, 153, 0}}, {(unsigned char*)"odsold", {226, 166, 188, 0}}, {(unsigned char*)"oelig", {197, 147, 0}}, {(unsigned char*)"ofcir", {226, 166, 191, 0}}, {(unsigned char*)"ofr", {240, 157, 148, 172, 0}}, {(unsigned char*)"ogon", {203, 155, 0}}, {(unsigned char*)"ograve", {195, 178, 0}}, {(unsigned char*)"ogt", {226, 167, 129, 0}}, {(unsigned char*)"ohbar", {226, 166, 181, 0}}, {(unsigned char*)"ohm", {206, 169, 0}}, {(unsigned char*)"oint", {226, 136, 174, 0}}, {(unsigned char*)"olarr", {226, 134, 186, 0}}, {(unsigned char*)"olcir", {226, 166, 190, 0}}, {(unsigned char*)"olcross", {226, 166, 187, 0}}, {(unsigned char*)"oline", {226, 128, 190, 0}}, {(unsigned char*)"olt", {226, 167, 128, 0}}, {(unsigned char*)"omacr", {197, 141, 0}}, {(unsigned char*)"omega", {207, 137, 0}}, {(unsigned char*)"omicron", {206, 191, 0}}, {(unsigned char*)"omid", {226, 166, 182, 0}}, {(unsigned char*)"ominus", {226, 138, 150, 0}}, {(unsigned char*)"oopf", {240, 157, 149, 160, 0}}, {(unsigned char*)"opar", {226, 166, 183, 0}}, {(unsigned char*)"operp", {226, 166, 185, 0}}, {(unsigned char*)"oplus", {226, 138, 149, 0}}, {(unsigned char*)"or", {226, 136, 168, 0}}, {(unsigned char*)"orarr", {226, 134, 187, 0}}, {(unsigned char*)"ord", {226, 169, 157, 0}}, {(unsigned char*)"order", {226, 132, 180, 0}}, {(unsigned char*)"orderof", {226, 132, 180, 0}}, {(unsigned char*)"ordf", {194, 170, 0}}, {(unsigned char*)"ordm", {194, 186, 0}}, {(unsigned char*)"origof", {226, 138, 182, 0}}, {(unsigned char*)"oror", {226, 169, 150, 0}}, {(unsigned char*)"orslope", {226, 169, 151, 0}}, {(unsigned char*)"orv", {226, 169, 155, 0}}, {(unsigned char*)"oscr", {226, 132, 180, 0}}, {(unsigned char*)"oslash", {195, 184, 0}}, {(unsigned char*)"osol", {226, 138, 152, 0}}, {(unsigned char*)"otilde", {195, 181, 0}}, {(unsigned char*)"otimes", {226, 138, 151, 0}}, {(unsigned char*)"otimesas", {226, 168, 182, 0}}, {(unsigned char*)"ouml", {195, 182, 0}}, {(unsigned char*)"ovbar", {226, 140, 189, 0}}, {(unsigned char*)"par", {226, 136, 165, 0}}, {(unsigned char*)"para", {194, 182, 0}}, {(unsigned char*)"parallel", {226, 136, 165, 0}}, {(unsigned char*)"parsim", {226, 171, 179, 0}}, {(unsigned char*)"parsl", {226, 171, 189, 0}}, {(unsigned char*)"part", {226, 136, 130, 0}}, {(unsigned char*)"pcy", {208, 191, 0}}, {(unsigned char*)"percnt", {37, 0}}, {(unsigned char*)"period", {46, 0}}, {(unsigned char*)"permil", {226, 128, 176, 0}}, {(unsigned char*)"perp", {226, 138, 165, 0}}, {(unsigned char*)"pertenk", {226, 128, 177, 0}}, {(unsigned char*)"pfr", {240, 157, 148, 173, 0}}, {(unsigned char*)"phi", {207, 134, 0}}, {(unsigned char*)"phiv", {207, 149, 0}}, {(unsigned char*)"phmmat", {226, 132, 179, 0}}, {(unsigned char*)"phone", {226, 152, 142, 0}}, {(unsigned char*)"pi", {207, 128, 0}}, {(unsigned char*)"pitchfork", {226, 139, 148, 0}}, {(unsigned char*)"piv", {207, 150, 0}}, {(unsigned char*)"planck", {226, 132, 143, 0}}, {(unsigned char*)"planckh", {226, 132, 142, 0}}, {(unsigned char*)"plankv", {226, 132, 143, 0}}, {(unsigned char*)"plus", {43, 0}}, {(unsigned char*)"plusacir", {226, 168, 163, 0}}, {(unsigned char*)"plusb", {226, 138, 158, 0}}, {(unsigned char*)"pluscir", {226, 168, 162, 0}}, {(unsigned char*)"plusdo", {226, 136, 148, 0}}, {(unsigned char*)"plusdu", {226, 168, 165, 0}}, {(unsigned char*)"pluse", {226, 169, 178, 0}}, {(unsigned char*)"plusmn", {194, 177, 0}}, {(unsigned char*)"plussim", {226, 168, 166, 0}}, {(unsigned char*)"plustwo", {226, 168, 167, 0}}, {(unsigned char*)"pm", {194, 177, 0}}, {(unsigned char*)"pointint", {226, 168, 149, 0}}, {(unsigned char*)"popf", {240, 157, 149, 161, 0}}, {(unsigned char*)"pound", {194, 163, 0}}, {(unsigned char*)"pr", {226, 137, 186, 0}}, {(unsigned char*)"prE", {226, 170, 179, 0}}, {(unsigned char*)"prap", {226, 170, 183, 0}}, {(unsigned char*)"prcue", {226, 137, 188, 0}}, {(unsigned char*)"pre", {226, 170, 175, 0}}, {(unsigned char*)"prec", {226, 137, 186, 0}}, {(unsigned char*)"precapprox", {226, 170, 183, 0}}, {(unsigned char*)"preccurlyeq", {226, 137, 188, 0}}, {(unsigned char*)"preceq", {226, 170, 175, 0}}, {(unsigned char*)"precnapprox", {226, 170, 185, 0}}, {(unsigned char*)"precneqq", {226, 170, 181, 0}}, {(unsigned char*)"precnsim", {226, 139, 168, 0}}, {(unsigned char*)"precsim", {226, 137, 190, 0}}, {(unsigned char*)"prime", {226, 128, 178, 0}}, {(unsigned char*)"primes", {226, 132, 153, 0}}, {(unsigned char*)"prnE", {226, 170, 181, 0}}, {(unsigned char*)"prnap", {226, 170, 185, 0}}, {(unsigned char*)"prnsim", {226, 139, 168, 0}}, {(unsigned char*)"prod", {226, 136, 143, 0}}, {(unsigned char*)"profalar", {226, 140, 174, 0}}, {(unsigned char*)"profline", {226, 140, 146, 0}}, {(unsigned char*)"profsurf", {226, 140, 147, 0}}, {(unsigned char*)"prop", {226, 136, 157, 0}}, {(unsigned char*)"propto", {226, 136, 157, 0}}, {(unsigned char*)"prsim", {226, 137, 190, 0}}, {(unsigned char*)"prurel", {226, 138, 176, 0}}, {(unsigned char*)"pscr", {240, 157, 147, 133, 0}}, {(unsigned char*)"psi", {207, 136, 0}}, {(unsigned char*)"puncsp", {226, 128, 136, 0}}, {(unsigned char*)"qfr", {240, 157, 148, 174, 0}}, {(unsigned char*)"qint", {226, 168, 140, 0}}, {(unsigned char*)"qopf", {240, 157, 149, 162, 0}}, {(unsigned char*)"qprime", {226, 129, 151, 0}}, {(unsigned char*)"qscr", {240, 157, 147, 134, 0}}, {(unsigned char*)"quaternions", {226, 132, 141, 0}}, {(unsigned char*)"quatint", {226, 168, 150, 0}}, {(unsigned char*)"quest", {63, 0}}, {(unsigned char*)"questeq", {226, 137, 159, 0}}, {(unsigned char*)"quot", {34, 0}}, {(unsigned char*)"rAarr", {226, 135, 155, 0}}, {(unsigned char*)"rArr", {226, 135, 146, 0}}, {(unsigned char*)"rAtail", {226, 164, 156, 0}}, {(unsigned char*)"rBarr", {226, 164, 143, 0}}, {(unsigned char*)"rHar", {226, 165, 164, 0}}, {(unsigned char*)"race", {226, 136, 189, 204, 177, 0}}, {(unsigned char*)"racute", {197, 149, 0}}, {(unsigned char*)"radic", {226, 136, 154, 0}}, {(unsigned char*)"raemptyv", {226, 166, 179, 0}}, {(unsigned char*)"rang", {226, 159, 169, 0}}, {(unsigned char*)"rangd", {226, 166, 146, 0}}, {(unsigned char*)"range", {226, 166, 165, 0}}, {(unsigned char*)"rangle", {226, 159, 169, 0}}, {(unsigned char*)"raquo", {194, 187, 0}}, {(unsigned char*)"rarr", {226, 134, 146, 0}}, {(unsigned char*)"rarrap", {226, 165, 181, 0}}, {(unsigned char*)"rarrb", {226, 135, 165, 0}}, {(unsigned char*)"rarrbfs", {226, 164, 160, 0}}, {(unsigned char*)"rarrc", {226, 164, 179, 0}}, {(unsigned char*)"rarrfs", {226, 164, 158, 0}}, {(unsigned char*)"rarrhk", {226, 134, 170, 0}}, {(unsigned char*)"rarrlp", {226, 134, 172, 0}}, {(unsigned char*)"rarrpl", {226, 165, 133, 0}}, {(unsigned char*)"rarrsim", {226, 165, 180, 0}}, {(unsigned char*)"rarrtl", {226, 134, 163, 0}}, {(unsigned char*)"rarrw", {226, 134, 157, 0}}, {(unsigned char*)"ratail", {226, 164, 154, 0}}, {(unsigned char*)"ratio", {226, 136, 182, 0}}, {(unsigned char*)"rationals", {226, 132, 154, 0}}, {(unsigned char*)"rbarr", {226, 164, 141, 0}}, {(unsigned char*)"rbbrk", {226, 157, 179, 0}}, {(unsigned char*)"rbrace", {125, 0}}, {(unsigned char*)"rbrack", {93, 0}}, {(unsigned char*)"rbrke", {226, 166, 140, 0}}, {(unsigned char*)"rbrksld", {226, 166, 142, 0}}, {(unsigned char*)"rbrkslu", {226, 166, 144, 0}}, {(unsigned char*)"rcaron", {197, 153, 0}}, {(unsigned char*)"rcedil", {197, 151, 0}}, {(unsigned char*)"rceil", {226, 140, 137, 0}}, {(unsigned char*)"rcub", {125, 0}}, {(unsigned char*)"rcy", {209, 128, 0}}, {(unsigned char*)"rdca", {226, 164, 183, 0}}, {(unsigned char*)"rdldhar", {226, 165, 169, 0}}, {(unsigned char*)"rdquo", {226, 128, 157, 0}}, {(unsigned char*)"rdquor", {226, 128, 157, 0}}, {(unsigned char*)"rdsh", {226, 134, 179, 0}}, {(unsigned char*)"real", {226, 132, 156, 0}}, {(unsigned char*)"realine", {226, 132, 155, 0}}, {(unsigned char*)"realpart", {226, 132, 156, 0}}, {(unsigned char*)"reals", {226, 132, 157, 0}}, {(unsigned char*)"rect", {226, 150, 173, 0}}, {(unsigned char*)"reg", {194, 174, 0}}, {(unsigned char*)"rfisht", {226, 165, 189, 0}}, {(unsigned char*)"rfloor", {226, 140, 139, 0}}, {(unsigned char*)"rfr", {240, 157, 148, 175, 0}}, {(unsigned char*)"rhard", {226, 135, 129, 0}}, {(unsigned char*)"rharu", {226, 135, 128, 0}}, {(unsigned char*)"rharul", {226, 165, 172, 0}}, {(unsigned char*)"rho", {207, 129, 0}}, {(unsigned char*)"rhov", {207, 177, 0}}, {(unsigned char*)"rightarrow", {226, 134, 146, 0}}, {(unsigned char*)"rightarrowtail", {226, 134, 163, 0}}, {(unsigned char*)"rightharpoondown", {226, 135, 129, 0}}, {(unsigned char*)"rightharpoonup", {226, 135, 128, 0}}, {(unsigned char*)"rightleftarrows", {226, 135, 132, 0}}, {(unsigned char*)"rightleftharpoons", {226, 135, 140, 0}}, {(unsigned char*)"rightrightarrows", {226, 135, 137, 0}}, {(unsigned char*)"rightsquigarrow", {226, 134, 157, 0}}, {(unsigned char*)"rightthreetimes", {226, 139, 140, 0}}, {(unsigned char*)"ring", {203, 154, 0}}, {(unsigned char*)"risingdotseq", {226, 137, 147, 0}}, {(unsigned char*)"rlarr", {226, 135, 132, 0}}, {(unsigned char*)"rlhar", {226, 135, 140, 0}}, {(unsigned char*)"rlm", {226, 128, 143, 0}}, {(unsigned char*)"rmoust", {226, 142, 177, 0}}, {(unsigned char*)"rmoustache", {226, 142, 177, 0}}, {(unsigned char*)"rnmid", {226, 171, 174, 0}}, {(unsigned char*)"roang", {226, 159, 173, 0}}, {(unsigned char*)"roarr", {226, 135, 190, 0}}, {(unsigned char*)"robrk", {226, 159, 167, 0}}, {(unsigned char*)"ropar", {226, 166, 134, 0}}, {(unsigned char*)"ropf", {240, 157, 149, 163, 0}}, {(unsigned char*)"roplus", {226, 168, 174, 0}}, {(unsigned char*)"rotimes", {226, 168, 181, 0}}, {(unsigned char*)"rpar", {41, 0}}, {(unsigned char*)"rpargt", {226, 166, 148, 0}}, {(unsigned char*)"rppolint", {226, 168, 146, 0}}, {(unsigned char*)"rrarr", {226, 135, 137, 0}}, {(unsigned char*)"rsaquo", {226, 128, 186, 0}}, {(unsigned char*)"rscr", {240, 157, 147, 135, 0}}, {(unsigned char*)"rsh", {226, 134, 177, 0}}, {(unsigned char*)"rsqb", {93, 0}}, {(unsigned char*)"rsquo", {226, 128, 153, 0}}, {(unsigned char*)"rsquor", {226, 128, 153, 0}}, {(unsigned char*)"rthree", {226, 139, 140, 0}}, {(unsigned char*)"rtimes", {226, 139, 138, 0}}, {(unsigned char*)"rtri", {226, 150, 185, 0}}, {(unsigned char*)"rtrie", {226, 138, 181, 0}}, {(unsigned char*)"rtrif", {226, 150, 184, 0}}, {(unsigned char*)"rtriltri", {226, 167, 142, 0}}, {(unsigned char*)"ruluhar", {226, 165, 168, 0}}, {(unsigned char*)"rx", {226, 132, 158, 0}}, {(unsigned char*)"sacute", {197, 155, 0}}, {(unsigned char*)"sbquo", {226, 128, 154, 0}}, {(unsigned char*)"sc", {226, 137, 187, 0}}, {(unsigned char*)"scE", {226, 170, 180, 0}}, {(unsigned char*)"scap", {226, 170, 184, 0}}, {(unsigned char*)"scaron", {197, 161, 0}}, {(unsigned char*)"sccue", {226, 137, 189, 0}}, {(unsigned char*)"sce", {226, 170, 176, 0}}, {(unsigned char*)"scedil", {197, 159, 0}}, {(unsigned char*)"scirc", {197, 157, 0}}, {(unsigned char*)"scnE", {226, 170, 182, 0}}, {(unsigned char*)"scnap", {226, 170, 186, 0}}, {(unsigned char*)"scnsim", {226, 139, 169, 0}}, {(unsigned char*)"scpolint", {226, 168, 147, 0}}, {(unsigned char*)"scsim", {226, 137, 191, 0}}, {(unsigned char*)"scy", {209, 129, 0}}, {(unsigned char*)"sdot", {226, 139, 133, 0}}, {(unsigned char*)"sdotb", {226, 138, 161, 0}}, {(unsigned char*)"sdote", {226, 169, 166, 0}}, {(unsigned char*)"seArr", {226, 135, 152, 0}}, {(unsigned char*)"searhk", {226, 164, 165, 0}}, {(unsigned char*)"searr", {226, 134, 152, 0}}, {(unsigned char*)"searrow", {226, 134, 152, 0}}, {(unsigned char*)"sect", {194, 167, 0}}, {(unsigned char*)"semi", {59, 0}}, {(unsigned char*)"seswar", {226, 164, 169, 0}}, {(unsigned char*)"setminus", {226, 136, 150, 0}}, {(unsigned char*)"setmn", {226, 136, 150, 0}}, {(unsigned char*)"sext", {226, 156, 182, 0}}, {(unsigned char*)"sfr", {240, 157, 148, 176, 0}}, {(unsigned char*)"sfrown", {226, 140, 162, 0}}, {(unsigned char*)"sharp", {226, 153, 175, 0}}, {(unsigned char*)"shchcy", {209, 137, 0}}, {(unsigned char*)"shcy", {209, 136, 0}}, {(unsigned char*)"shortmid", {226, 136, 163, 0}}, {(unsigned char*)"shortparallel", {226, 136, 165, 0}}, {(unsigned char*)"shy", {194, 173, 0}}, {(unsigned char*)"sigma", {207, 131, 0}}, {(unsigned char*)"sigmaf", {207, 130, 0}}, {(unsigned char*)"sigmav", {207, 130, 0}}, {(unsigned char*)"sim", {226, 136, 188, 0}}, {(unsigned char*)"simdot", {226, 169, 170, 0}}, {(unsigned char*)"sime", {226, 137, 131, 0}}, {(unsigned char*)"simeq", {226, 137, 131, 0}}, {(unsigned char*)"simg", {226, 170, 158, 0}}, {(unsigned char*)"simgE", {226, 170, 160, 0}}, {(unsigned char*)"siml", {226, 170, 157, 0}}, {(unsigned char*)"simlE", {226, 170, 159, 0}}, {(unsigned char*)"simne", {226, 137, 134, 0}}, {(unsigned char*)"simplus", {226, 168, 164, 0}}, {(unsigned char*)"simrarr", {226, 165, 178, 0}}, {(unsigned char*)"slarr", {226, 134, 144, 0}}, {(unsigned char*)"smallsetminus", {226, 136, 150, 0}}, {(unsigned char*)"smashp", {226, 168, 179, 0}}, {(unsigned char*)"smeparsl", {226, 167, 164, 0}}, {(unsigned char*)"smid", {226, 136, 163, 0}}, {(unsigned char*)"smile", {226, 140, 163, 0}}, {(unsigned char*)"smt", {226, 170, 170, 0}}, {(unsigned char*)"smte", {226, 170, 172, 0}}, {(unsigned char*)"smtes", {226, 170, 172, 239, 184, 128, 0}}, {(unsigned char*)"softcy", {209, 140, 0}}, {(unsigned char*)"sol", {47, 0}}, {(unsigned char*)"solb", {226, 167, 132, 0}}, {(unsigned char*)"solbar", {226, 140, 191, 0}}, {(unsigned char*)"sopf", {240, 157, 149, 164, 0}}, {(unsigned char*)"spades", {226, 153, 160, 0}}, {(unsigned char*)"spadesuit", {226, 153, 160, 0}}, {(unsigned char*)"spar", {226, 136, 165, 0}}, {(unsigned char*)"sqcap", {226, 138, 147, 0}}, {(unsigned char*)"sqcaps", {226, 138, 147, 239, 184, 128, 0}}, {(unsigned char*)"sqcup", {226, 138, 148, 0}}, {(unsigned char*)"sqcups", {226, 138, 148, 239, 184, 128, 0}}, {(unsigned char*)"sqsub", {226, 138, 143, 0}}, {(unsigned char*)"sqsube", {226, 138, 145, 0}}, {(unsigned char*)"sqsubset", {226, 138, 143, 0}}, {(unsigned char*)"sqsubseteq", {226, 138, 145, 0}}, {(unsigned char*)"sqsup", {226, 138, 144, 0}}, {(unsigned char*)"sqsupe", {226, 138, 146, 0}}, {(unsigned char*)"sqsupset", {226, 138, 144, 0}}, {(unsigned char*)"sqsupseteq", {226, 138, 146, 0}}, {(unsigned char*)"squ", {226, 150, 161, 0}}, {(unsigned char*)"square", {226, 150, 161, 0}}, {(unsigned char*)"squarf", {226, 150, 170, 0}}, {(unsigned char*)"squf", {226, 150, 170, 0}}, {(unsigned char*)"srarr", {226, 134, 146, 0}}, {(unsigned char*)"sscr", {240, 157, 147, 136, 0}}, {(unsigned char*)"ssetmn", {226, 136, 150, 0}}, {(unsigned char*)"ssmile", {226, 140, 163, 0}}, {(unsigned char*)"sstarf", {226, 139, 134, 0}}, {(unsigned char*)"star", {226, 152, 134, 0}}, {(unsigned char*)"starf", {226, 152, 133, 0}}, {(unsigned char*)"straightepsilon", {207, 181, 0}}, {(unsigned char*)"straightphi", {207, 149, 0}}, {(unsigned char*)"strns", {194, 175, 0}}, {(unsigned char*)"sub", {226, 138, 130, 0}}, {(unsigned char*)"subE", {226, 171, 133, 0}}, {(unsigned char*)"subdot", {226, 170, 189, 0}}, {(unsigned char*)"sube", {226, 138, 134, 0}}, {(unsigned char*)"subedot", {226, 171, 131, 0}}, {(unsigned char*)"submult", {226, 171, 129, 0}}, {(unsigned char*)"subnE", {226, 171, 139, 0}}, {(unsigned char*)"subne", {226, 138, 138, 0}}, {(unsigned char*)"subplus", {226, 170, 191, 0}}, {(unsigned char*)"subrarr", {226, 165, 185, 0}}, {(unsigned char*)"subset", {226, 138, 130, 0}}, {(unsigned char*)"subseteq", {226, 138, 134, 0}}, {(unsigned char*)"subseteqq", {226, 171, 133, 0}}, {(unsigned char*)"subsetneq", {226, 138, 138, 0}}, {(unsigned char*)"subsetneqq", {226, 171, 139, 0}}, {(unsigned char*)"subsim", {226, 171, 135, 0}}, {(unsigned char*)"subsub", {226, 171, 149, 0}}, {(unsigned char*)"subsup", {226, 171, 147, 0}}, {(unsigned char*)"succ", {226, 137, 187, 0}}, {(unsigned char*)"succapprox", {226, 170, 184, 0}}, {(unsigned char*)"succcurlyeq", {226, 137, 189, 0}}, {(unsigned char*)"succeq", {226, 170, 176, 0}}, {(unsigned char*)"succnapprox", {226, 170, 186, 0}}, {(unsigned char*)"succneqq", {226, 170, 182, 0}}, {(unsigned char*)"succnsim", {226, 139, 169, 0}}, {(unsigned char*)"succsim", {226, 137, 191, 0}}, {(unsigned char*)"sum", {226, 136, 145, 0}}, {(unsigned char*)"sung", {226, 153, 170, 0}}, {(unsigned char*)"sup", {226, 138, 131, 0}}, {(unsigned char*)"sup1", {194, 185, 0}}, {(unsigned char*)"sup2", {194, 178, 0}}, {(unsigned char*)"sup3", {194, 179, 0}}, {(unsigned char*)"supE", {226, 171, 134, 0}}, {(unsigned char*)"supdot", {226, 170, 190, 0}}, {(unsigned char*)"supdsub", {226, 171, 152, 0}}, {(unsigned char*)"supe", {226, 138, 135, 0}}, {(unsigned char*)"supedot", {226, 171, 132, 0}}, {(unsigned char*)"suphsol", {226, 159, 137, 0}}, {(unsigned char*)"suphsub", {226, 171, 151, 0}}, {(unsigned char*)"suplarr", {226, 165, 187, 0}}, {(unsigned char*)"supmult", {226, 171, 130, 0}}, {(unsigned char*)"supnE", {226, 171, 140, 0}}, {(unsigned char*)"supne", {226, 138, 139, 0}}, {(unsigned char*)"supplus", {226, 171, 128, 0}}, {(unsigned char*)"supset", {226, 138, 131, 0}}, {(unsigned char*)"supseteq", {226, 138, 135, 0}}, {(unsigned char*)"supseteqq", {226, 171, 134, 0}}, {(unsigned char*)"supsetneq", {226, 138, 139, 0}}, {(unsigned char*)"supsetneqq", {226, 171, 140, 0}}, {(unsigned char*)"supsim", {226, 171, 136, 0}}, {(unsigned char*)"supsub", {226, 171, 148, 0}}, {(unsigned char*)"supsup", {226, 171, 150, 0}}, {(unsigned char*)"swArr", {226, 135, 153, 0}}, {(unsigned char*)"swarhk", {226, 164, 166, 0}}, {(unsigned char*)"swarr", {226, 134, 153, 0}}, {(unsigned char*)"swarrow", {226, 134, 153, 0}}, {(unsigned char*)"swnwar", {226, 164, 170, 0}}, {(unsigned char*)"szlig", {195, 159, 0}}, {(unsigned char*)"target", {226, 140, 150, 0}}, {(unsigned char*)"tau", {207, 132, 0}}, {(unsigned char*)"tbrk", {226, 142, 180, 0}}, {(unsigned char*)"tcaron", {197, 165, 0}}, {(unsigned char*)"tcedil", {197, 163, 0}}, {(unsigned char*)"tcy", {209, 130, 0}}, {(unsigned char*)"tdot", {226, 131, 155, 0}}, {(unsigned char*)"telrec", {226, 140, 149, 0}}, {(unsigned char*)"tfr", {240, 157, 148, 177, 0}}, {(unsigned char*)"there4", {226, 136, 180, 0}}, {(unsigned char*)"therefore", {226, 136, 180, 0}}, {(unsigned char*)"theta", {206, 184, 0}}, {(unsigned char*)"thetasym", {207, 145, 0}}, {(unsigned char*)"thetav", {207, 145, 0}}, {(unsigned char*)"thickapprox", {226, 137, 136, 0}}, {(unsigned char*)"thicksim", {226, 136, 188, 0}}, {(unsigned char*)"thinsp", {226, 128, 137, 0}}, {(unsigned char*)"thkap", {226, 137, 136, 0}}, {(unsigned char*)"thksim", {226, 136, 188, 0}}, {(unsigned char*)"thorn", {195, 190, 0}}, {(unsigned char*)"tilde", {203, 156, 0}}, {(unsigned char*)"times", {195, 151, 0}}, {(unsigned char*)"timesb", {226, 138, 160, 0}}, {(unsigned char*)"timesbar", {226, 168, 177, 0}}, {(unsigned char*)"timesd", {226, 168, 176, 0}}, {(unsigned char*)"tint", {226, 136, 173, 0}}, {(unsigned char*)"toea", {226, 164, 168, 0}}, {(unsigned char*)"top", {226, 138, 164, 0}}, {(unsigned char*)"topbot", {226, 140, 182, 0}}, {(unsigned char*)"topcir", {226, 171, 177, 0}}, {(unsigned char*)"topf", {240, 157, 149, 165, 0}}, {(unsigned char*)"topfork", {226, 171, 154, 0}}, {(unsigned char*)"tosa", {226, 164, 169, 0}}, {(unsigned char*)"tprime", {226, 128, 180, 0}}, {(unsigned char*)"trade", {226, 132, 162, 0}}, {(unsigned char*)"triangle", {226, 150, 181, 0}}, {(unsigned char*)"triangledown", {226, 150, 191, 0}}, {(unsigned char*)"triangleleft", {226, 151, 131, 0}}, {(unsigned char*)"trianglelefteq", {226, 138, 180, 0}}, {(unsigned char*)"triangleq", {226, 137, 156, 0}}, {(unsigned char*)"triangleright", {226, 150, 185, 0}}, {(unsigned char*)"trianglerighteq", {226, 138, 181, 0}}, {(unsigned char*)"tridot", {226, 151, 172, 0}}, {(unsigned char*)"trie", {226, 137, 156, 0}}, {(unsigned char*)"triminus", {226, 168, 186, 0}}, {(unsigned char*)"triplus", {226, 168, 185, 0}}, {(unsigned char*)"trisb", {226, 167, 141, 0}}, {(unsigned char*)"tritime", {226, 168, 187, 0}}, {(unsigned char*)"trpezium", {226, 143, 162, 0}}, {(unsigned char*)"tscr", {240, 157, 147, 137, 0}}, {(unsigned char*)"tscy", {209, 134, 0}}, {(unsigned char*)"tshcy", {209, 155, 0}}, {(unsigned char*)"tstrok", {197, 167, 0}}, {(unsigned char*)"twixt", {226, 137, 172, 0}}, {(unsigned char*)"twoheadleftarrow", {226, 134, 158, 0}}, {(unsigned char*)"twoheadrightarrow", {226, 134, 160, 0}}, {(unsigned char*)"uArr", {226, 135, 145, 0}}, {(unsigned char*)"uHar", {226, 165, 163, 0}}, {(unsigned char*)"uacute", {195, 186, 0}}, {(unsigned char*)"uarr", {226, 134, 145, 0}}, {(unsigned char*)"ubrcy", {209, 158, 0}}, {(unsigned char*)"ubreve", {197, 173, 0}}, {(unsigned char*)"ucirc", {195, 187, 0}}, {(unsigned char*)"ucy", {209, 131, 0}}, {(unsigned char*)"udarr", {226, 135, 133, 0}}, {(unsigned char*)"udblac", {197, 177, 0}}, {(unsigned char*)"udhar", {226, 165, 174, 0}}, {(unsigned char*)"ufisht", {226, 165, 190, 0}}, {(unsigned char*)"ufr", {240, 157, 148, 178, 0}}, {(unsigned char*)"ugrave", {195, 185, 0}}, {(unsigned char*)"uharl", {226, 134, 191, 0}}, {(unsigned char*)"uharr", {226, 134, 190, 0}}, {(unsigned char*)"uhblk", {226, 150, 128, 0}}, {(unsigned char*)"ulcorn", {226, 140, 156, 0}}, {(unsigned char*)"ulcorner", {226, 140, 156, 0}}, {(unsigned char*)"ulcrop", {226, 140, 143, 0}}, {(unsigned char*)"ultri", {226, 151, 184, 0}}, {(unsigned char*)"umacr", {197, 171, 0}}, {(unsigned char*)"uml", {194, 168, 0}}, {(unsigned char*)"uogon", {197, 179, 0}}, {(unsigned char*)"uopf", {240, 157, 149, 166, 0}}, {(unsigned char*)"uparrow", {226, 134, 145, 0}}, {(unsigned char*)"updownarrow", {226, 134, 149, 0}}, {(unsigned char*)"upharpoonleft", {226, 134, 191, 0}}, {(unsigned char*)"upharpoonright", {226, 134, 190, 0}}, {(unsigned char*)"uplus", {226, 138, 142, 0}}, {(unsigned char*)"upsi", {207, 133, 0}}, {(unsigned char*)"upsih", {207, 146, 0}}, {(unsigned char*)"upsilon", {207, 133, 0}}, {(unsigned char*)"upuparrows", {226, 135, 136, 0}}, {(unsigned char*)"urcorn", {226, 140, 157, 0}}, {(unsigned char*)"urcorner", {226, 140, 157, 0}}, {(unsigned char*)"urcrop", {226, 140, 142, 0}}, {(unsigned char*)"uring", {197, 175, 0}}, {(unsigned char*)"urtri", {226, 151, 185, 0}}, {(unsigned char*)"uscr", {240, 157, 147, 138, 0}}, {(unsigned char*)"utdot", {226, 139, 176, 0}}, {(unsigned char*)"utilde", {197, 169, 0}}, {(unsigned char*)"utri", {226, 150, 181, 0}}, {(unsigned char*)"utrif", {226, 150, 180, 0}}, {(unsigned char*)"uuarr", {226, 135, 136, 0}}, {(unsigned char*)"uuml", {195, 188, 0}}, {(unsigned char*)"uwangle", {226, 166, 167, 0}}, {(unsigned char*)"vArr", {226, 135, 149, 0}}, {(unsigned char*)"vBar", {226, 171, 168, 0}}, {(unsigned char*)"vBarv", {226, 171, 169, 0}}, {(unsigned char*)"vDash", {226, 138, 168, 0}}, {(unsigned char*)"vangrt", {226, 166, 156, 0}}, {(unsigned char*)"varepsilon", {207, 181, 0}}, {(unsigned char*)"varkappa", {207, 176, 0}}, {(unsigned char*)"varnothing", {226, 136, 133, 0}}, {(unsigned char*)"varphi", {207, 149, 0}}, {(unsigned char*)"varpi", {207, 150, 0}}, {(unsigned char*)"varpropto", {226, 136, 157, 0}}, {(unsigned char*)"varr", {226, 134, 149, 0}}, {(unsigned char*)"varrho", {207, 177, 0}}, {(unsigned char*)"varsigma", {207, 130, 0}}, {(unsigned char*)"varsubsetneq", {226, 138, 138, 239, 184, 128, 0}}, {(unsigned char*)"varsubsetneqq", {226, 171, 139, 239, 184, 128, 0}}, {(unsigned char*)"varsupsetneq", {226, 138, 139, 239, 184, 128, 0}}, {(unsigned char*)"varsupsetneqq", {226, 171, 140, 239, 184, 128, 0}}, {(unsigned char*)"vartheta", {207, 145, 0}}, {(unsigned char*)"vartriangleleft", {226, 138, 178, 0}}, {(unsigned char*)"vartriangleright", {226, 138, 179, 0}}, {(unsigned char*)"vcy", {208, 178, 0}}, {(unsigned char*)"vdash", {226, 138, 162, 0}}, {(unsigned char*)"vee", {226, 136, 168, 0}}, {(unsigned char*)"veebar", {226, 138, 187, 0}}, {(unsigned char*)"veeeq", {226, 137, 154, 0}}, {(unsigned char*)"vellip", {226, 139, 174, 0}}, {(unsigned char*)"verbar", {124, 0}}, {(unsigned char*)"vert", {124, 0}}, {(unsigned char*)"vfr", {240, 157, 148, 179, 0}}, {(unsigned char*)"vltri", {226, 138, 178, 0}}, {(unsigned char*)"vnsub", {226, 138, 130, 226, 131, 146, 0}}, {(unsigned char*)"vnsup", {226, 138, 131, 226, 131, 146, 0}}, {(unsigned char*)"vopf", {240, 157, 149, 167, 0}}, {(unsigned char*)"vprop", {226, 136, 157, 0}}, {(unsigned char*)"vrtri", {226, 138, 179, 0}}, {(unsigned char*)"vscr", {240, 157, 147, 139, 0}}, {(unsigned char*)"vsubnE", {226, 171, 139, 239, 184, 128, 0}}, {(unsigned char*)"vsubne", {226, 138, 138, 239, 184, 128, 0}}, {(unsigned char*)"vsupnE", {226, 171, 140, 239, 184, 128, 0}}, {(unsigned char*)"vsupne", {226, 138, 139, 239, 184, 128, 0}}, {(unsigned char*)"vzigzag", {226, 166, 154, 0}}, {(unsigned char*)"wcirc", {197, 181, 0}}, {(unsigned char*)"wedbar", {226, 169, 159, 0}}, {(unsigned char*)"wedge", {226, 136, 167, 0}}, {(unsigned char*)"wedgeq", {226, 137, 153, 0}}, {(unsigned char*)"weierp", {226, 132, 152, 0}}, {(unsigned char*)"wfr", {240, 157, 148, 180, 0}}, {(unsigned char*)"wopf", {240, 157, 149, 168, 0}}, {(unsigned char*)"wp", {226, 132, 152, 0}}, {(unsigned char*)"wr", {226, 137, 128, 0}}, {(unsigned char*)"wreath", {226, 137, 128, 0}}, {(unsigned char*)"wscr", {240, 157, 147, 140, 0}}, {(unsigned char*)"xcap", {226, 139, 130, 0}}, {(unsigned char*)"xcirc", {226, 151, 175, 0}}, {(unsigned char*)"xcup", {226, 139, 131, 0}}, {(unsigned char*)"xdtri", {226, 150, 189, 0}}, {(unsigned char*)"xfr", {240, 157, 148, 181, 0}}, {(unsigned char*)"xhArr", {226, 159, 186, 0}}, {(unsigned char*)"xharr", {226, 159, 183, 0}}, {(unsigned char*)"xi", {206, 190, 0}}, {(unsigned char*)"xlArr", {226, 159, 184, 0}}, {(unsigned char*)"xlarr", {226, 159, 181, 0}}, {(unsigned char*)"xmap", {226, 159, 188, 0}}, {(unsigned char*)"xnis", {226, 139, 187, 0}}, {(unsigned char*)"xodot", {226, 168, 128, 0}}, {(unsigned char*)"xopf", {240, 157, 149, 169, 0}}, {(unsigned char*)"xoplus", {226, 168, 129, 0}}, {(unsigned char*)"xotime", {226, 168, 130, 0}}, {(unsigned char*)"xrArr", {226, 159, 185, 0}}, {(unsigned char*)"xrarr", {226, 159, 182, 0}}, {(unsigned char*)"xscr", {240, 157, 147, 141, 0}}, {(unsigned char*)"xsqcup", {226, 168, 134, 0}}, {(unsigned char*)"xuplus", {226, 168, 132, 0}}, {(unsigned char*)"xutri", {226, 150, 179, 0}}, {(unsigned char*)"xvee", {226, 139, 129, 0}}, {(unsigned char*)"xwedge", {226, 139, 128, 0}}, {(unsigned char*)"yacute", {195, 189, 0}}, {(unsigned char*)"yacy", {209, 143, 0}}, {(unsigned char*)"ycirc", {197, 183, 0}}, {(unsigned char*)"ycy", {209, 139, 0}}, {(unsigned char*)"yen", {194, 165, 0}}, {(unsigned char*)"yfr", {240, 157, 148, 182, 0}}, {(unsigned char*)"yicy", {209, 151, 0}}, {(unsigned char*)"yopf", {240, 157, 149, 170, 0}}, {(unsigned char*)"yscr", {240, 157, 147, 142, 0}}, {(unsigned char*)"yucy", {209, 142, 0}}, {(unsigned char*)"yuml", {195, 191, 0}}, {(unsigned char*)"zacute", {197, 186, 0}}, {(unsigned char*)"zcaron", {197, 190, 0}}, {(unsigned char*)"zcy", {208, 183, 0}}, {(unsigned char*)"zdot", {197, 188, 0}}, {(unsigned char*)"zeetrf", {226, 132, 168, 0}}, {(unsigned char*)"zeta", {206, 182, 0}}, {(unsigned char*)"zfr", {240, 157, 148, 183, 0}}, {(unsigned char*)"zhcy", {208, 182, 0}}, {(unsigned char*)"zigrarr", {226, 135, 157, 0}}, {(unsigned char*)"zopf", {240, 157, 149, 171, 0}}, {(unsigned char*)"zscr", {240, 157, 147, 143, 0}}, {(unsigned char*)"zwj", {226, 128, 141, 0}}, {(unsigned char*)"zwnj", {226, 128, 140, 0}}, }; ================================================ FILE: liteidex/src/3rdparty/cmark/src/houdini.h ================================================ #ifndef CMARK_HOUDINI_H #define CMARK_HOUDINI_H #ifdef __cplusplus extern "C" { #endif #include #include "config.h" #include "buffer.h" #ifdef HAVE___BUILTIN_EXPECT #define likely(x) __builtin_expect((x), 1) #define unlikely(x) __builtin_expect((x), 0) #else #define likely(x) (x) #define unlikely(x) (x) #endif #ifdef HOUDINI_USE_LOCALE #define _isxdigit(c) isxdigit(c) #define _isdigit(c) isdigit(c) #else /* * Helper _isdigit methods -- do not trust the current locale * */ #define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL) #define _isdigit(c) ((c) >= '0' && (c) <= '9') #endif #define HOUDINI_ESCAPED_SIZE(x) (((x)*12) / 10) #define HOUDINI_UNESCAPED_SIZE(x) (x) extern bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src, bufsize_t size); extern int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, bufsize_t size); extern int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, bufsize_t size, int secure); extern int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src, bufsize_t size); extern void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src, bufsize_t size); extern int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src, bufsize_t size); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/houdini_href_e.c ================================================ #include #include #include #include "houdini.h" /* * The following characters will not be escaped: * * -_.+!*'(),%#@?=;:/,+&$ alphanum * * Note that this character set is the addition of: * * - The characters which are safe to be in an URL * - The characters which are *not* safe to be in * an URL because they are RESERVED characters. * * We assume (lazily) that any RESERVED char that * appears inside an URL is actually meant to * have its native function (i.e. as an URL * component/separator) and hence needs no escaping. * * There are two exceptions: the chacters & (amp) * and ' (single quote) do not appear in the table. * They are meant to appear in the URL as components, * yet they require special HTML-entity escaping * to generate valid HTML markup. * * All other characters will be escaped to %XX. * */ static const char HREF_SAFE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { static const uint8_t hex_chars[] = "0123456789ABCDEF"; bufsize_t i = 0, org; uint8_t hex_str[3]; hex_str[0] = '%'; while (i < size) { org = i; while (i < size && HREF_SAFE[src[i]] != 0) i++; if (likely(i > org)) cmark_strbuf_put(ob, src + org, i - org); /* escaping */ if (i >= size) break; switch (src[i]) { /* amp appears all the time in URLs, but needs * HTML-entity escaping to be inside an href */ case '&': cmark_strbuf_puts(ob, "&"); break; /* the single quote is a valid URL character * according to the standard; it needs HTML * entity escaping too */ case '\'': cmark_strbuf_puts(ob, "'"); break; /* the space can be escaped to %20 or a plus * sign. we're going with the generic escape * for now. the plus thing is more commonly seen * when building GET strings */ #if 0 case ' ': cmark_strbuf_putc(ob, '+'); break; #endif /* every other character goes with a %XX escaping */ default: hex_str[1] = hex_chars[(src[i] >> 4) & 0xF]; hex_str[2] = hex_chars[src[i] & 0xF]; cmark_strbuf_put(ob, hex_str, 3); } i++; } return 1; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/houdini_html_e.c ================================================ #include #include #include #include "houdini.h" /** * According to the OWASP rules: * * & --> & * < --> < * > --> > * " --> " * ' --> ' ' is not recommended * / --> / forward slash is included as it helps end an HTML entity * */ static const char HTML_ESCAPE_TABLE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const char *HTML_ESCAPES[] = {"", """, "&", "'", "/", "<", ">"}; int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, bufsize_t size, int secure) { bufsize_t i = 0, org, esc = 0; while (i < size) { org = i; while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0) i++; if (i > org) cmark_strbuf_put(ob, src + org, i - org); /* escaping */ if (unlikely(i >= size)) break; /* The forward slash is only escaped in secure mode */ if ((src[i] == '/' || src[i] == '\'') && !secure) { cmark_strbuf_putc(ob, src[i]); } else { cmark_strbuf_puts(ob, HTML_ESCAPES[esc]); } i++; } return 1; } int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { return houdini_escape_html0(ob, src, size, 1); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/houdini_html_u.c ================================================ #include #include #include #include "buffer.h" #include "houdini.h" #include "utf8.h" #include "entities.inc" /* Binary tree lookup code for entities added by JGM */ static const unsigned char *S_lookup(int i, int low, int hi, const unsigned char *s, int len) { int j; int cmp = strncmp((const char *)s, (const char *)cmark_entities[i].entity, len); if (cmp == 0 && cmark_entities[i].entity[len] == 0) { return (const unsigned char *)cmark_entities[i].bytes; } else if (cmp <= 0 && i > low) { j = i - ((i - low) / 2); if (j == i) j -= 1; return S_lookup(j, low, i - 1, s, len); } else if (cmp > 0 && i < hi) { j = i + ((hi - i) / 2); if (j == i) j += 1; return S_lookup(j, i + 1, hi, s, len); } else { return NULL; } } static const unsigned char *S_lookup_entity(const unsigned char *s, int len) { return S_lookup(CMARK_NUM_ENTITIES / 2, 0, CMARK_NUM_ENTITIES - 1, s, len); } bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { bufsize_t i = 0; if (size >= 3 && src[0] == '#') { int codepoint = 0; int num_digits = 0; if (_isdigit(src[1])) { for (i = 1; i < size && _isdigit(src[i]); ++i) { codepoint = (codepoint * 10) + (src[i] - '0'); if (codepoint >= 0x110000) { // Keep counting digits but // avoid integer overflow. codepoint = 0x110000; } } num_digits = i - 1; } else if (src[1] == 'x' || src[1] == 'X') { for (i = 2; i < size && _isxdigit(src[i]); ++i) { codepoint = (codepoint * 16) + ((src[i] | 32) % 39 - 9); if (codepoint >= 0x110000) { // Keep counting digits but // avoid integer overflow. codepoint = 0x110000; } } num_digits = i - 2; } if (num_digits >= 1 && num_digits <= 8 && i < size && src[i] == ';') { if (codepoint == 0 || (codepoint >= 0xD800 && codepoint < 0xE000) || codepoint >= 0x110000) { codepoint = 0xFFFD; } cmark_utf8proc_encode_char(codepoint, ob); return i + 1; } } else { if (size > CMARK_ENTITY_MAX_LENGTH) size = CMARK_ENTITY_MAX_LENGTH; for (i = CMARK_ENTITY_MIN_LENGTH; i < size; ++i) { if (src[i] == ' ') break; if (src[i] == ';') { const unsigned char *entity = S_lookup_entity(src, i); if (entity != NULL) { cmark_strbuf_puts(ob, (const char *)entity); return i + 1; } break; } } } return 0; } int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { bufsize_t i = 0, org, ent; while (i < size) { org = i; while (i < size && src[i] != '&') i++; if (likely(i > org)) { if (unlikely(org == 0)) { if (i >= size) return 0; cmark_strbuf_grow(ob, HOUDINI_UNESCAPED_SIZE(size)); } cmark_strbuf_put(ob, src + org, i - org); } /* escaping */ if (i >= size) break; i++; ent = houdini_unescape_ent(ob, src + i, size - i); i += ent; /* not really an entity */ if (ent == 0) cmark_strbuf_putc(ob, '&'); } return 1; } void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) { if (!houdini_unescape_html(ob, src, size)) cmark_strbuf_put(ob, src, size); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/html.c ================================================ #include #include #include #include #include "cmark_ctype.h" #include "config.h" #include "cmark.h" #include "node.h" #include "buffer.h" #include "houdini.h" #include "scanners.h" #define BUFFER_SIZE 100 // Functions to convert cmark_nodes to HTML strings. static void escape_html(cmark_strbuf *dest, const unsigned char *source, bufsize_t length) { houdini_escape_html0(dest, source, length, 0); } static CMARK_INLINE void cr(cmark_strbuf *html) { if (html->size && html->ptr[html->size - 1] != '\n') cmark_strbuf_putc(html, '\n'); } struct render_state { cmark_strbuf *html; cmark_node *plain; }; static void S_render_sourcepos(cmark_node *node, cmark_strbuf *html, int options) { char buffer[BUFFER_SIZE]; if (CMARK_OPT_SOURCEPOS & options) { snprintf(buffer, BUFFER_SIZE, " data-sourcepos=\"%d:%d-%d:%d\"", cmark_node_get_start_line(node), cmark_node_get_start_column(node), cmark_node_get_end_line(node), cmark_node_get_end_column(node)); cmark_strbuf_puts(html, buffer); } } static int S_render_node(cmark_node *node, cmark_event_type ev_type, struct render_state *state, int options) { cmark_node *parent; cmark_node *grandparent; cmark_strbuf *html = state->html; char start_heading[] = "plain == node) { // back at original node state->plain = NULL; } if (state->plain != NULL) { switch (node->type) { case CMARK_NODE_TEXT: case CMARK_NODE_CODE: case CMARK_NODE_HTML_INLINE: escape_html(html, node->as.literal.data, node->as.literal.len); break; case CMARK_NODE_LINEBREAK: case CMARK_NODE_SOFTBREAK: cmark_strbuf_putc(html, ' '); break; default: break; } return 1; } switch (node->type) { case CMARK_NODE_DOCUMENT: break; case CMARK_NODE_BLOCK_QUOTE: if (entering) { cr(html); cmark_strbuf_puts(html, "\n"); } else { cr(html); cmark_strbuf_puts(html, "\n"); } break; case CMARK_NODE_LIST: { cmark_list_type list_type = node->as.list.list_type; int start = node->as.list.start; if (entering) { cr(html); if (list_type == CMARK_BULLET_LIST) { cmark_strbuf_puts(html, "\n"); } else if (start == 1) { cmark_strbuf_puts(html, "\n"); } else { snprintf(buffer, BUFFER_SIZE, "
    \n"); } } else { cmark_strbuf_puts(html, list_type == CMARK_BULLET_LIST ? "\n" : "
\n"); } break; } case CMARK_NODE_ITEM: if (entering) { cr(html); cmark_strbuf_puts(html, "'); } else { cmark_strbuf_puts(html, "\n"); } break; case CMARK_NODE_HEADING: if (entering) { cr(html); start_heading[2] = (char)('0' + node->as.heading.level); cmark_strbuf_puts(html, start_heading); S_render_sourcepos(node, html, options); cmark_strbuf_putc(html, '>'); } else { end_heading[3] = (char)('0' + node->as.heading.level); cmark_strbuf_puts(html, end_heading); cmark_strbuf_puts(html, ">\n"); } break; case CMARK_NODE_CODE_BLOCK: cr(html); if (node->as.code.info.len == 0) { cmark_strbuf_puts(html, ""); } else { bufsize_t first_tag = 0; while (first_tag < node->as.code.info.len && !cmark_isspace(node->as.code.info.data[first_tag])) { first_tag += 1; } cmark_strbuf_puts(html, "as.code.info.data, first_tag); cmark_strbuf_puts(html, "\">"); } escape_html(html, node->as.code.literal.data, node->as.code.literal.len); cmark_strbuf_puts(html, "\n"); break; case CMARK_NODE_HTML_BLOCK: cr(html); if (!(options & CMARK_OPT_UNSAFE)) { cmark_strbuf_puts(html, ""); } else { cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); } cr(html); break; case CMARK_NODE_CUSTOM_BLOCK: cr(html); if (entering) { cmark_strbuf_put(html, node->as.custom.on_enter.data, node->as.custom.on_enter.len); } else { cmark_strbuf_put(html, node->as.custom.on_exit.data, node->as.custom.on_exit.len); } cr(html); break; case CMARK_NODE_THEMATIC_BREAK: cr(html); cmark_strbuf_puts(html, "\n"); break; case CMARK_NODE_PARAGRAPH: parent = cmark_node_parent(node); grandparent = cmark_node_parent(parent); if (grandparent != NULL && grandparent->type == CMARK_NODE_LIST) { tight = grandparent->as.list.tight; } else { tight = false; } if (!tight) { if (entering) { cr(html); cmark_strbuf_puts(html, "'); } else { cmark_strbuf_puts(html, "

\n"); } } break; case CMARK_NODE_TEXT: escape_html(html, node->as.literal.data, node->as.literal.len); break; case CMARK_NODE_LINEBREAK: cmark_strbuf_puts(html, "
\n"); break; case CMARK_NODE_SOFTBREAK: if (options & CMARK_OPT_HARDBREAKS) { cmark_strbuf_puts(html, "
\n"); } else if (options & CMARK_OPT_NOBREAKS) { cmark_strbuf_putc(html, ' '); } else { cmark_strbuf_putc(html, '\n'); } break; case CMARK_NODE_CODE: cmark_strbuf_puts(html, ""); escape_html(html, node->as.literal.data, node->as.literal.len); cmark_strbuf_puts(html, ""); break; case CMARK_NODE_HTML_INLINE: if (!(options & CMARK_OPT_UNSAFE)) { cmark_strbuf_puts(html, ""); } else { cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); } break; case CMARK_NODE_CUSTOM_INLINE: if (entering) { cmark_strbuf_put(html, node->as.custom.on_enter.data, node->as.custom.on_enter.len); } else { cmark_strbuf_put(html, node->as.custom.on_exit.data, node->as.custom.on_exit.len); } break; case CMARK_NODE_STRONG: if (entering) { cmark_strbuf_puts(html, ""); } else { cmark_strbuf_puts(html, ""); } break; case CMARK_NODE_EMPH: if (entering) { cmark_strbuf_puts(html, ""); } else { cmark_strbuf_puts(html, ""); } break; case CMARK_NODE_LINK: if (entering) { cmark_strbuf_puts(html, "as.link.url, 0))) { houdini_escape_href(html, node->as.link.url.data, node->as.link.url.len); } if (node->as.link.title.len) { cmark_strbuf_puts(html, "\" title=\""); escape_html(html, node->as.link.title.data, node->as.link.title.len); } cmark_strbuf_puts(html, "\">"); } else { cmark_strbuf_puts(html, ""); } break; case CMARK_NODE_IMAGE: if (entering) { cmark_strbuf_puts(html, "as.link.url, 0))) { houdini_escape_href(html, node->as.link.url.data, node->as.link.url.len); } cmark_strbuf_puts(html, "\" alt=\""); state->plain = node; } else { if (node->as.link.title.len) { cmark_strbuf_puts(html, "\" title=\""); escape_html(html, node->as.link.title.data, node->as.link.title.len); } cmark_strbuf_puts(html, "\" />"); } break; default: assert(false); break; } // cmark_strbuf_putc(html, 'x'); return 1; } char *cmark_render_html(cmark_node *root, int options) { char *result; cmark_strbuf html = CMARK_BUF_INIT(cmark_node_mem(root)); cmark_event_type ev_type; cmark_node *cur; struct render_state state = {&html, NULL}; cmark_iter *iter = cmark_iter_new(root); while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { cur = cmark_iter_get_node(iter); S_render_node(cur, ev_type, &state, options); } result = (char *)cmark_strbuf_detach(&html); cmark_iter_free(iter); return result; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/inlines.c ================================================ #include #include #include #include "cmark_ctype.h" #include "config.h" #include "node.h" #include "parser.h" #include "references.h" #include "cmark.h" #include "houdini.h" #include "utf8.h" #include "scanners.h" #include "inlines.h" static const char *EMDASH = "\xE2\x80\x94"; static const char *ENDASH = "\xE2\x80\x93"; static const char *ELLIPSES = "\xE2\x80\xA6"; static const char *LEFTDOUBLEQUOTE = "\xE2\x80\x9C"; static const char *RIGHTDOUBLEQUOTE = "\xE2\x80\x9D"; static const char *LEFTSINGLEQUOTE = "\xE2\x80\x98"; static const char *RIGHTSINGLEQUOTE = "\xE2\x80\x99"; // Macros for creating various kinds of simple. #define make_str(subj, sc, ec, s) make_literal(subj, CMARK_NODE_TEXT, sc, ec, s) #define make_code(subj, sc, ec, s) make_literal(subj, CMARK_NODE_CODE, sc, ec, s) #define make_raw_html(subj, sc, ec, s) make_literal(subj, CMARK_NODE_HTML_INLINE, sc, ec, s) #define make_linebreak(mem) make_simple(mem, CMARK_NODE_LINEBREAK) #define make_softbreak(mem) make_simple(mem, CMARK_NODE_SOFTBREAK) #define make_emph(mem) make_simple(mem, CMARK_NODE_EMPH) #define make_strong(mem) make_simple(mem, CMARK_NODE_STRONG) #define MAXBACKTICKS 1000 typedef struct delimiter { struct delimiter *previous; struct delimiter *next; cmark_node *inl_text; bufsize_t length; unsigned char delim_char; bool can_open; bool can_close; } delimiter; typedef struct bracket { struct bracket *previous; struct delimiter *previous_delimiter; cmark_node *inl_text; bufsize_t position; bool image; bool active; bool bracket_after; } bracket; typedef struct { cmark_mem *mem; cmark_chunk input; int line; bufsize_t pos; int block_offset; int column_offset; cmark_reference_map *refmap; delimiter *last_delim; bracket *last_bracket; bufsize_t backticks[MAXBACKTICKS + 1]; bool scanned_for_backticks; } subject; static CMARK_INLINE bool S_is_line_end_char(char c) { return (c == '\n' || c == '\r'); } static delimiter *S_insert_emph(subject *subj, delimiter *opener, delimiter *closer); static int parse_inline(subject *subj, cmark_node *parent, int options); static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset, subject *e, cmark_chunk *chunk, cmark_reference_map *refmap); static bufsize_t subject_find_special_char(subject *subj, int options); // Create an inline with a literal string value. static CMARK_INLINE cmark_node *make_literal(subject *subj, cmark_node_type t, int start_column, int end_column, cmark_chunk s) { cmark_node *e = (cmark_node *)subj->mem->calloc(1, sizeof(*e)); cmark_strbuf_init(subj->mem, &e->content, 0); e->type = (uint16_t)t; e->as.literal = s; e->start_line = e->end_line = subj->line; // columns are 1 based. e->start_column = start_column + 1 + subj->column_offset + subj->block_offset; e->end_column = end_column + 1 + subj->column_offset + subj->block_offset; return e; } // Create an inline with no value. static CMARK_INLINE cmark_node *make_simple(cmark_mem *mem, cmark_node_type t) { cmark_node *e = (cmark_node *)mem->calloc(1, sizeof(*e)); cmark_strbuf_init(mem, &e->content, 0); e->type = t; return e; } // Like make_str, but parses entities. static cmark_node *make_str_with_entities(subject *subj, int start_column, int end_column, cmark_chunk *content) { cmark_strbuf unescaped = CMARK_BUF_INIT(subj->mem); if (houdini_unescape_html(&unescaped, content->data, content->len)) { return make_str(subj, start_column, end_column, cmark_chunk_buf_detach(&unescaped)); } else { return make_str(subj, start_column, end_column, *content); } } // Duplicate a chunk by creating a copy of the buffer not by reusing the // buffer like cmark_chunk_dup does. static cmark_chunk chunk_clone(cmark_mem *mem, cmark_chunk *src) { cmark_chunk c; bufsize_t len = src->len; c.len = len; c.data = (unsigned char *)mem->calloc(len + 1, 1); c.alloc = 1; if (len) memcpy(c.data, src->data, len); c.data[len] = '\0'; return c; } static cmark_chunk cmark_clean_autolink(cmark_mem *mem, cmark_chunk *url, int is_email) { cmark_strbuf buf = CMARK_BUF_INIT(mem); cmark_chunk_trim(url); if (url->len == 0) { cmark_chunk result = CMARK_CHUNK_EMPTY; return result; } if (is_email) cmark_strbuf_puts(&buf, "mailto:"); houdini_unescape_html_f(&buf, url->data, url->len); return cmark_chunk_buf_detach(&buf); } static CMARK_INLINE cmark_node *make_autolink(subject *subj, int start_column, int end_column, cmark_chunk url, int is_email) { cmark_node *link = make_simple(subj->mem, CMARK_NODE_LINK); link->as.link.url = cmark_clean_autolink(subj->mem, &url, is_email); link->as.link.title = cmark_chunk_literal(""); link->start_line = link->end_line = subj->line; link->start_column = start_column + 1; link->end_column = end_column + 1; cmark_node_append_child(link, make_str_with_entities(subj, start_column + 1, end_column - 1, &url)); return link; } static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset, subject *e, cmark_chunk *chunk, cmark_reference_map *refmap) { int i; e->mem = mem; e->input = *chunk; e->line = line_number; e->pos = 0; e->block_offset = block_offset; e->column_offset = 0; e->refmap = refmap; e->last_delim = NULL; e->last_bracket = NULL; for (i = 0; i <= MAXBACKTICKS; i++) { e->backticks[i] = 0; } e->scanned_for_backticks = false; } static CMARK_INLINE int isbacktick(int c) { return (c == '`'); } static CMARK_INLINE unsigned char peek_char(subject *subj) { // NULL bytes should have been stripped out by now. If they're // present, it's a programming error: assert(!(subj->pos < subj->input.len && subj->input.data[subj->pos] == 0)); return (subj->pos < subj->input.len) ? subj->input.data[subj->pos] : 0; } static CMARK_INLINE unsigned char peek_at(subject *subj, bufsize_t pos) { return subj->input.data[pos]; } // Return true if there are more characters in the subject. static CMARK_INLINE int is_eof(subject *subj) { return (subj->pos >= subj->input.len); } // Advance the subject. Doesn't check for eof. #define advance(subj) (subj)->pos += 1 static CMARK_INLINE bool skip_spaces(subject *subj) { bool skipped = false; while (peek_char(subj) == ' ' || peek_char(subj) == '\t') { advance(subj); skipped = true; } return skipped; } static CMARK_INLINE bool skip_line_end(subject *subj) { bool seen_line_end_char = false; if (peek_char(subj) == '\r') { advance(subj); seen_line_end_char = true; } if (peek_char(subj) == '\n') { advance(subj); seen_line_end_char = true; } return seen_line_end_char || is_eof(subj); } // Take characters while a predicate holds, and return a string. static CMARK_INLINE cmark_chunk take_while(subject *subj, int (*f)(int)) { unsigned char c; bufsize_t startpos = subj->pos; bufsize_t len = 0; while ((c = peek_char(subj)) && (*f)(c)) { advance(subj); len++; } return cmark_chunk_dup(&subj->input, startpos, len); } // Return the number of newlines in a given span of text in a subject. If // the number is greater than zero, also return the number of characters // between the last newline and the end of the span in `since_newline`. static int count_newlines(subject *subj, bufsize_t from, bufsize_t len, int *since_newline) { int nls = 0; int since_nl = 0; while (len--) { if (subj->input.data[from++] == '\n') { ++nls; since_nl = 0; } else { ++since_nl; } } if (!nls) return 0; *since_newline = since_nl; return nls; } // Adjust `node`'s `end_line`, `end_column`, and `subj`'s `line` and // `column_offset` according to the number of newlines in a just-matched span // of text in `subj`. static void adjust_subj_node_newlines(subject *subj, cmark_node *node, int matchlen, int extra, int options) { if (!(options & CMARK_OPT_SOURCEPOS)) { return; } int since_newline; int newlines = count_newlines(subj, subj->pos - matchlen - extra, matchlen, &since_newline); if (newlines) { subj->line += newlines; node->end_line += newlines; node->end_column = since_newline; subj->column_offset = -subj->pos + since_newline + extra; } } // Try to process a backtick code span that began with a // span of ticks of length openticklength length (already // parsed). Return 0 if you don't find matching closing // backticks, otherwise return the position in the subject // after the closing backticks. static bufsize_t scan_to_closing_backticks(subject *subj, bufsize_t openticklength) { bool found = false; if (openticklength > MAXBACKTICKS) { // we limit backtick string length because of the array subj->backticks: return 0; } if (subj->scanned_for_backticks && subj->backticks[openticklength] <= subj->pos) { // return if we already know there's no closer return 0; } while (!found) { // read non backticks unsigned char c; while ((c = peek_char(subj)) && c != '`') { advance(subj); } if (is_eof(subj)) { break; } bufsize_t numticks = 0; while (peek_char(subj) == '`') { advance(subj); numticks++; } // store position of ender if (numticks <= MAXBACKTICKS) { subj->backticks[numticks] = subj->pos - numticks; } if (numticks == openticklength) { return (subj->pos); } } // got through whole input without finding closer subj->scanned_for_backticks = true; return 0; } // Destructively modify string, converting newlines to // spaces, then removing a single leading + trailing space, // unless the code span consists entirely of space characters. static void S_normalize_code(cmark_strbuf *s) { bufsize_t r, w; bool contains_nonspace = false; for (r = 0, w = 0; r < s->size; ++r) { switch (s->ptr[r]) { case '\r': if (s->ptr[r + 1] != '\n') { s->ptr[w++] = ' '; } break; case '\n': s->ptr[w++] = ' '; break; default: s->ptr[w++] = s->ptr[r]; } if (s->ptr[r] != ' ') { contains_nonspace = true; } } // begins and ends with space? if (contains_nonspace && s->ptr[0] == ' ' && s->ptr[w - 1] == ' ') { cmark_strbuf_drop(s, 1); cmark_strbuf_truncate(s, w - 2); } else { cmark_strbuf_truncate(s, w); } } // Parse backtick code section or raw backticks, return an inline. // Assumes that the subject has a backtick at the current position. static cmark_node *handle_backticks(subject *subj, int options) { cmark_chunk openticks = take_while(subj, isbacktick); bufsize_t startpos = subj->pos; bufsize_t endpos = scan_to_closing_backticks(subj, openticks.len); if (endpos == 0) { // not found subj->pos = startpos; // rewind return make_str(subj, subj->pos, subj->pos, openticks); } else { cmark_strbuf buf = CMARK_BUF_INIT(subj->mem); cmark_strbuf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len); S_normalize_code(&buf); cmark_node *node = make_code(subj, startpos, endpos - openticks.len - 1, cmark_chunk_buf_detach(&buf)); adjust_subj_node_newlines(subj, node, endpos - startpos, openticks.len, options); return node; } } // Scan ***, **, or * and return number scanned, or 0. // Advances position. static int scan_delims(subject *subj, unsigned char c, bool *can_open, bool *can_close) { int numdelims = 0; bufsize_t before_char_pos; int32_t after_char = 0; int32_t before_char = 0; int len; bool left_flanking, right_flanking; if (subj->pos == 0) { before_char = 10; } else { before_char_pos = subj->pos - 1; // walk back to the beginning of the UTF_8 sequence: while (peek_at(subj, before_char_pos) >> 6 == 2 && before_char_pos > 0) { before_char_pos -= 1; } len = cmark_utf8proc_iterate(subj->input.data + before_char_pos, subj->pos - before_char_pos, &before_char); if (len == -1) { before_char = 10; } } if (c == '\'' || c == '"') { numdelims++; advance(subj); // limit to 1 delim for quotes } else { while (peek_char(subj) == c) { numdelims++; advance(subj); } } len = cmark_utf8proc_iterate(subj->input.data + subj->pos, subj->input.len - subj->pos, &after_char); if (len == -1) { after_char = 10; } left_flanking = numdelims > 0 && !cmark_utf8proc_is_space(after_char) && (!cmark_utf8proc_is_punctuation(after_char) || cmark_utf8proc_is_space(before_char) || cmark_utf8proc_is_punctuation(before_char)); right_flanking = numdelims > 0 && !cmark_utf8proc_is_space(before_char) && (!cmark_utf8proc_is_punctuation(before_char) || cmark_utf8proc_is_space(after_char) || cmark_utf8proc_is_punctuation(after_char)); if (c == '_') { *can_open = left_flanking && (!right_flanking || cmark_utf8proc_is_punctuation(before_char)); *can_close = right_flanking && (!left_flanking || cmark_utf8proc_is_punctuation(after_char)); } else if (c == '\'' || c == '"') { *can_open = left_flanking && !right_flanking && before_char != ']' && before_char != ')'; *can_close = right_flanking; } else { *can_open = left_flanking; *can_close = right_flanking; } return numdelims; } /* static void print_delimiters(subject *subj) { delimiter *delim; delim = subj->last_delim; while (delim != NULL) { printf("Item at stack pos %p: %d %d %d next(%p) prev(%p)\n", (void*)delim, delim->delim_char, delim->can_open, delim->can_close, (void*)delim->next, (void*)delim->previous); delim = delim->previous; } } */ static void remove_delimiter(subject *subj, delimiter *delim) { if (delim == NULL) return; if (delim->next == NULL) { // end of list: assert(delim == subj->last_delim); subj->last_delim = delim->previous; } else { delim->next->previous = delim->previous; } if (delim->previous != NULL) { delim->previous->next = delim->next; } subj->mem->free(delim); } static void pop_bracket(subject *subj) { bracket *b; if (subj->last_bracket == NULL) return; b = subj->last_bracket; subj->last_bracket = subj->last_bracket->previous; subj->mem->free(b); } static void push_delimiter(subject *subj, unsigned char c, bool can_open, bool can_close, cmark_node *inl_text) { delimiter *delim = (delimiter *)subj->mem->calloc(1, sizeof(delimiter)); delim->delim_char = c; delim->can_open = can_open; delim->can_close = can_close; delim->inl_text = inl_text; delim->length = inl_text->as.literal.len; delim->previous = subj->last_delim; delim->next = NULL; if (delim->previous != NULL) { delim->previous->next = delim; } subj->last_delim = delim; } static void push_bracket(subject *subj, bool image, cmark_node *inl_text) { bracket *b = (bracket *)subj->mem->calloc(1, sizeof(bracket)); if (subj->last_bracket != NULL) { subj->last_bracket->bracket_after = true; } b->image = image; b->active = true; b->inl_text = inl_text; b->previous = subj->last_bracket; b->previous_delimiter = subj->last_delim; b->position = subj->pos; b->bracket_after = false; subj->last_bracket = b; } // Assumes the subject has a c at the current position. static cmark_node *handle_delim(subject *subj, unsigned char c, bool smart) { bufsize_t numdelims; cmark_node *inl_text; bool can_open, can_close; cmark_chunk contents; numdelims = scan_delims(subj, c, &can_open, &can_close); if (c == '\'' && smart) { contents = cmark_chunk_literal(RIGHTSINGLEQUOTE); } else if (c == '"' && smart) { contents = cmark_chunk_literal(can_close ? RIGHTDOUBLEQUOTE : LEFTDOUBLEQUOTE); } else { contents = cmark_chunk_dup(&subj->input, subj->pos - numdelims, numdelims); } inl_text = make_str(subj, subj->pos - numdelims, subj->pos - 1, contents); if ((can_open || can_close) && (!(c == '\'' || c == '"') || smart)) { push_delimiter(subj, c, can_open, can_close, inl_text); } return inl_text; } // Assumes we have a hyphen at the current position. static cmark_node *handle_hyphen(subject *subj, bool smart) { int startpos = subj->pos; advance(subj); if (!smart || peek_char(subj) != '-') { return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("-")); } while (smart && peek_char(subj) == '-') { advance(subj); } int numhyphens = subj->pos - startpos; int en_count = 0; int em_count = 0; int i; cmark_strbuf buf = CMARK_BUF_INIT(subj->mem); if (numhyphens % 3 == 0) { // if divisible by 3, use all em dashes em_count = numhyphens / 3; } else if (numhyphens % 2 == 0) { // if divisible by 2, use all en dashes en_count = numhyphens / 2; } else if (numhyphens % 3 == 2) { // use one en dash at end en_count = 1; em_count = (numhyphens - 2) / 3; } else { // use two en dashes at the end en_count = 2; em_count = (numhyphens - 4) / 3; } for (i = em_count; i > 0; i--) { cmark_strbuf_puts(&buf, EMDASH); } for (i = en_count; i > 0; i--) { cmark_strbuf_puts(&buf, ENDASH); } return make_str(subj, startpos, subj->pos - 1, cmark_chunk_buf_detach(&buf)); } // Assumes we have a period at the current position. static cmark_node *handle_period(subject *subj, bool smart) { advance(subj); if (smart && peek_char(subj) == '.') { advance(subj); if (peek_char(subj) == '.') { advance(subj); return make_str(subj, subj->pos - 3, subj->pos - 1, cmark_chunk_literal(ELLIPSES)); } else { return make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_literal("..")); } } else { return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal(".")); } } static void process_emphasis(subject *subj, delimiter *stack_bottom) { delimiter *closer = subj->last_delim; delimiter *opener; delimiter *old_closer; bool opener_found; int openers_bottom_index = 0; delimiter *openers_bottom[6] = {stack_bottom, stack_bottom, stack_bottom, stack_bottom, stack_bottom, stack_bottom}; // move back to first relevant delim. while (closer != NULL && closer->previous != stack_bottom) { closer = closer->previous; } // now move forward, looking for closers, and handling each while (closer != NULL) { if (closer->can_close) { switch (closer->delim_char) { case '"': openers_bottom_index = 0; break; case '\'': openers_bottom_index = 1; break; case '_': openers_bottom_index = 2; break; case '*': openers_bottom_index = 3 + (closer->length % 3); break; default: assert(false); } // Now look backwards for first matching opener: opener = closer->previous; opener_found = false; while (opener != NULL && opener != openers_bottom[openers_bottom_index]) { if (opener->can_open && opener->delim_char == closer->delim_char) { // interior closer of size 2 can't match opener of size 1 // or of size 1 can't match 2 if (!(closer->can_open || opener->can_close) || closer->length % 3 == 0 || (opener->length + closer->length) % 3 != 0) { opener_found = true; break; } } opener = opener->previous; } old_closer = closer; if (closer->delim_char == '*' || closer->delim_char == '_') { if (opener_found) { closer = S_insert_emph(subj, opener, closer); } else { closer = closer->next; } } else if (closer->delim_char == '\'') { cmark_chunk_free(subj->mem, &closer->inl_text->as.literal); closer->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE); if (opener_found) { cmark_chunk_free(subj->mem, &opener->inl_text->as.literal); opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE); } closer = closer->next; } else if (closer->delim_char == '"') { cmark_chunk_free(subj->mem, &closer->inl_text->as.literal); closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE); if (opener_found) { cmark_chunk_free(subj->mem, &opener->inl_text->as.literal); opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE); } closer = closer->next; } if (!opener_found) { // set lower bound for future searches for openers openers_bottom[openers_bottom_index] = old_closer->previous; if (!old_closer->can_open) { // we can remove a closer that can't be an // opener, once we've seen there's no // matching opener: remove_delimiter(subj, old_closer); } } } else { closer = closer->next; } } // free all delimiters in list until stack_bottom: while (subj->last_delim != NULL && subj->last_delim != stack_bottom) { remove_delimiter(subj, subj->last_delim); } } static delimiter *S_insert_emph(subject *subj, delimiter *opener, delimiter *closer) { delimiter *delim, *tmp_delim; bufsize_t use_delims; cmark_node *opener_inl = opener->inl_text; cmark_node *closer_inl = closer->inl_text; bufsize_t opener_num_chars = opener_inl->as.literal.len; bufsize_t closer_num_chars = closer_inl->as.literal.len; cmark_node *tmp, *tmpnext, *emph; // calculate the actual number of characters used from this closer use_delims = (closer_num_chars >= 2 && opener_num_chars >= 2) ? 2 : 1; // remove used characters from associated inlines. opener_num_chars -= use_delims; closer_num_chars -= use_delims; opener_inl->as.literal.len = opener_num_chars; closer_inl->as.literal.len = closer_num_chars; // free delimiters between opener and closer delim = closer->previous; while (delim != NULL && delim != opener) { tmp_delim = delim->previous; remove_delimiter(subj, delim); delim = tmp_delim; } // create new emph or strong, and splice it in to our inlines // between the opener and closer emph = use_delims == 1 ? make_emph(subj->mem) : make_strong(subj->mem); tmp = opener_inl->next; while (tmp && tmp != closer_inl) { tmpnext = tmp->next; cmark_node_append_child(emph, tmp); tmp = tmpnext; } cmark_node_insert_after(opener_inl, emph); emph->start_line = opener_inl->start_line; emph->end_line = closer_inl->end_line; emph->start_column = opener_inl->start_column; emph->end_column = closer_inl->end_column; // if opener has 0 characters, remove it and its associated inline if (opener_num_chars == 0) { cmark_node_free(opener_inl); remove_delimiter(subj, opener); } // if closer has 0 characters, remove it and its associated inline if (closer_num_chars == 0) { // remove empty closer inline cmark_node_free(closer_inl); // remove closer from list tmp_delim = closer->next; remove_delimiter(subj, closer); closer = tmp_delim; } return closer; } // Parse backslash-escape or just a backslash, returning an inline. static cmark_node *handle_backslash(subject *subj) { advance(subj); unsigned char nextchar = peek_char(subj); if (cmark_ispunct( nextchar)) { // only ascii symbols and newline can be escaped advance(subj); return make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_dup(&subj->input, subj->pos - 1, 1)); } else if (!is_eof(subj) && skip_line_end(subj)) { return make_linebreak(subj->mem); } else { return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("\\")); } } // Parse an entity or a regular "&" string. // Assumes the subject has an '&' character at the current position. static cmark_node *handle_entity(subject *subj) { cmark_strbuf ent = CMARK_BUF_INIT(subj->mem); bufsize_t len; advance(subj); len = houdini_unescape_ent(&ent, subj->input.data + subj->pos, subj->input.len - subj->pos); if (len == 0) return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("&")); subj->pos += len; return make_str(subj, subj->pos - 1 - len, subj->pos - 1, cmark_chunk_buf_detach(&ent)); } // Clean a URL: remove surrounding whitespace, and remove \ that escape // punctuation. cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url) { cmark_strbuf buf = CMARK_BUF_INIT(mem); cmark_chunk_trim(url); if (url->len == 0) { cmark_chunk result = CMARK_CHUNK_EMPTY; return result; } houdini_unescape_html_f(&buf, url->data, url->len); cmark_strbuf_unescape(&buf); return cmark_chunk_buf_detach(&buf); } cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title) { cmark_strbuf buf = CMARK_BUF_INIT(mem); unsigned char first, last; if (title->len == 0) { cmark_chunk result = CMARK_CHUNK_EMPTY; return result; } first = title->data[0]; last = title->data[title->len - 1]; // remove surrounding quotes if any: if ((first == '\'' && last == '\'') || (first == '(' && last == ')') || (first == '"' && last == '"')) { houdini_unescape_html_f(&buf, title->data + 1, title->len - 2); } else { houdini_unescape_html_f(&buf, title->data, title->len); } cmark_strbuf_unescape(&buf); return cmark_chunk_buf_detach(&buf); } // Parse an autolink or HTML tag. // Assumes the subject has a '<' character at the current position. static cmark_node *handle_pointy_brace(subject *subj, int options) { bufsize_t matchlen = 0; cmark_chunk contents; advance(subj); // advance past first < // first try to match a URL autolink matchlen = scan_autolink_uri(&subj->input, subj->pos); if (matchlen > 0) { contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1); subj->pos += matchlen; return make_autolink(subj, subj->pos - 1 - matchlen, subj->pos - 1, contents, 0); } // next try to match an email autolink matchlen = scan_autolink_email(&subj->input, subj->pos); if (matchlen > 0) { contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1); subj->pos += matchlen; return make_autolink(subj, subj->pos - 1 - matchlen, subj->pos - 1, contents, 1); } // finally, try to match an html tag matchlen = scan_html_tag(&subj->input, subj->pos); if (matchlen > 0) { contents = cmark_chunk_dup(&subj->input, subj->pos - 1, matchlen + 1); subj->pos += matchlen; cmark_node *node = make_raw_html(subj, subj->pos - matchlen - 1, subj->pos - 1, contents); adjust_subj_node_newlines(subj, node, matchlen, 1, options); return node; } // if nothing matches, just return the opening <: return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("<")); } // Parse a link label. Returns 1 if successful. // Note: unescaped brackets are not allowed in labels. // The label begins with `[` and ends with the first `]` character // encountered. Backticks in labels do not start code spans. static int link_label(subject *subj, cmark_chunk *raw_label) { bufsize_t startpos = subj->pos; int length = 0; unsigned char c; // advance past [ if (peek_char(subj) == '[') { advance(subj); } else { return 0; } while ((c = peek_char(subj)) && c != '[' && c != ']') { if (c == '\\') { advance(subj); length++; if (cmark_ispunct(peek_char(subj))) { advance(subj); length++; } } else { advance(subj); length++; } if (length > MAX_LINK_LABEL_LENGTH) { goto noMatch; } } if (c == ']') { // match found *raw_label = cmark_chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1)); cmark_chunk_trim(raw_label); advance(subj); // advance past ] return 1; } noMatch: subj->pos = startpos; // rewind return 0; } static bufsize_t manual_scan_link_url_2(cmark_chunk *input, bufsize_t offset, cmark_chunk *output) { bufsize_t i = offset; size_t nb_p = 0; while (i < input->len) { if (input->data[i] == '\\' && i + 1 < input-> len && cmark_ispunct(input->data[i+1])) i += 2; else if (input->data[i] == '(') { ++nb_p; ++i; if (nb_p > 32) return -1; } else if (input->data[i] == ')') { if (nb_p == 0) break; --nb_p; ++i; } else if (cmark_isspace(input->data[i])) { if (i == offset) { return -1; } break; } else { ++i; } } if (i >= input->len) return -1; { cmark_chunk result = {input->data + offset, i - offset, 0}; *output = result; } return i - offset; } static bufsize_t manual_scan_link_url(cmark_chunk *input, bufsize_t offset, cmark_chunk *output) { bufsize_t i = offset; if (i < input->len && input->data[i] == '<') { ++i; while (i < input->len) { if (input->data[i] == '>') { ++i; break; } else if (input->data[i] == '\\') i += 2; else if (input->data[i] == '\n' || input->data[i] == '<') return -1; else ++i; } } else { return manual_scan_link_url_2(input, offset, output); } if (i >= input->len) return -1; { cmark_chunk result = {input->data + offset + 1, i - 2 - offset, 0}; *output = result; } return i - offset; } // Return a link, an image, or a literal close bracket. static cmark_node *handle_close_bracket(subject *subj) { bufsize_t initial_pos, after_link_text_pos; bufsize_t endurl, starttitle, endtitle, endall; bufsize_t sps, n; cmark_reference *ref = NULL; cmark_chunk url_chunk, title_chunk; cmark_chunk url, title; bracket *opener; cmark_node *inl; cmark_chunk raw_label; int found_label; cmark_node *tmp, *tmpnext; bool is_image; advance(subj); // advance past ] initial_pos = subj->pos; // get last [ or ![ opener = subj->last_bracket; if (opener == NULL) { return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]")); } if (!opener->active) { // take delimiter off stack pop_bracket(subj); return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]")); } // If we got here, we matched a potential link/image text. // Now we check to see if it's a link/image. is_image = opener->image; after_link_text_pos = subj->pos; // First, look for an inline link. if (peek_char(subj) == '(' && ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) && ((n = manual_scan_link_url(&subj->input, subj->pos + 1 + sps, &url_chunk)) > -1)) { // try to parse an explicit link: endurl = subj->pos + 1 + sps + n; starttitle = endurl + scan_spacechars(&subj->input, endurl); // ensure there are spaces btw url and title endtitle = (starttitle == endurl) ? starttitle : starttitle + scan_link_title(&subj->input, starttitle); endall = endtitle + scan_spacechars(&subj->input, endtitle); if (peek_at(subj, endall) == ')') { subj->pos = endall + 1; title_chunk = cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle); url = cmark_clean_url(subj->mem, &url_chunk); title = cmark_clean_title(subj->mem, &title_chunk); cmark_chunk_free(subj->mem, &url_chunk); cmark_chunk_free(subj->mem, &title_chunk); goto match; } else { // it could still be a shortcut reference link subj->pos = after_link_text_pos; } } // Next, look for a following [link label] that matches in refmap. // skip spaces raw_label = cmark_chunk_literal(""); found_label = link_label(subj, &raw_label); if (!found_label) { // If we have a shortcut reference link, back up // to before the spacse we skipped. subj->pos = initial_pos; } if ((!found_label || raw_label.len == 0) && !opener->bracket_after) { cmark_chunk_free(subj->mem, &raw_label); raw_label = cmark_chunk_dup(&subj->input, opener->position, initial_pos - opener->position - 1); found_label = true; } if (found_label) { ref = cmark_reference_lookup(subj->refmap, &raw_label); cmark_chunk_free(subj->mem, &raw_label); } if (ref != NULL) { // found url = chunk_clone(subj->mem, &ref->url); title = chunk_clone(subj->mem, &ref->title); goto match; } else { goto noMatch; } noMatch: // If we fall through to here, it means we didn't match a link: pop_bracket(subj); // remove this opener from delimiter list subj->pos = initial_pos; return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]")); match: inl = make_simple(subj->mem, is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK); inl->as.link.url = url; inl->as.link.title = title; inl->start_line = inl->end_line = subj->line; inl->start_column = opener->inl_text->start_column; inl->end_column = subj->pos + subj->column_offset + subj->block_offset; cmark_node_insert_before(opener->inl_text, inl); // Add link text: tmp = opener->inl_text->next; while (tmp) { tmpnext = tmp->next; cmark_node_append_child(inl, tmp); tmp = tmpnext; } // Free the bracket [: cmark_node_free(opener->inl_text); process_emphasis(subj, opener->previous_delimiter); pop_bracket(subj); // Now, if we have a link, we also want to deactivate earlier link // delimiters. (This code can be removed if we decide to allow links // inside links.) if (!is_image) { opener = subj->last_bracket; while (opener != NULL) { if (!opener->image) { if (!opener->active) { break; } else { opener->active = false; } } opener = opener->previous; } } return NULL; } // Parse a hard or soft linebreak, returning an inline. // Assumes the subject has a cr or newline at the current position. static cmark_node *handle_newline(subject *subj) { bufsize_t nlpos = subj->pos; // skip over cr, crlf, or lf: if (peek_at(subj, subj->pos) == '\r') { advance(subj); } if (peek_at(subj, subj->pos) == '\n') { advance(subj); } ++subj->line; subj->column_offset = -subj->pos; // skip spaces at beginning of line skip_spaces(subj); if (nlpos > 1 && peek_at(subj, nlpos - 1) == ' ' && peek_at(subj, nlpos - 2) == ' ') { return make_linebreak(subj->mem); } else { return make_softbreak(subj->mem); } } static bufsize_t subject_find_special_char(subject *subj, int options) { // "\r\n\\`&_*[]pos + 1; while (n < subj->input.len) { if (SPECIAL_CHARS[subj->input.data[n]]) return n; if (options & CMARK_OPT_SMART && SMART_PUNCT_CHARS[subj->input.data[n]]) return n; n++; } return subj->input.len; } // Parse an inline, advancing subject, and add it as a child of parent. // Return 0 if no inline can be parsed, 1 otherwise. static int parse_inline(subject *subj, cmark_node *parent, int options) { cmark_node *new_inl = NULL; cmark_chunk contents; unsigned char c; bufsize_t startpos, endpos; c = peek_char(subj); if (c == 0) { return 0; } switch (c) { case '\r': case '\n': new_inl = handle_newline(subj); break; case '`': new_inl = handle_backticks(subj, options); break; case '\\': new_inl = handle_backslash(subj); break; case '&': new_inl = handle_entity(subj); break; case '<': new_inl = handle_pointy_brace(subj, options); break; case '*': case '_': case '\'': case '"': new_inl = handle_delim(subj, c, (options & CMARK_OPT_SMART) != 0); break; case '-': new_inl = handle_hyphen(subj, (options & CMARK_OPT_SMART) != 0); break; case '.': new_inl = handle_period(subj, (options & CMARK_OPT_SMART) != 0); break; case '[': advance(subj); new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("[")); push_bracket(subj, false, new_inl); break; case ']': new_inl = handle_close_bracket(subj); break; case '!': advance(subj); if (peek_char(subj) == '[') { advance(subj); new_inl = make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_literal("![")); push_bracket(subj, true, new_inl); } else { new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("!")); } break; default: endpos = subject_find_special_char(subj, options); contents = cmark_chunk_dup(&subj->input, subj->pos, endpos - subj->pos); startpos = subj->pos; subj->pos = endpos; // if we're at a newline, strip trailing spaces. if (S_is_line_end_char(peek_char(subj))) { cmark_chunk_rtrim(&contents); } new_inl = make_str(subj, startpos, endpos - 1, contents); } if (new_inl != NULL) { cmark_node_append_child(parent, new_inl); } return 1; } // Parse inlines from parent's string_content, adding as children of parent. extern void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent, cmark_reference_map *refmap, int options) { subject subj; cmark_chunk content = {parent->content.ptr, parent->content.size, 0}; subject_from_buf(mem, parent->start_line, parent->start_column - 1 + parent->internal_offset, &subj, &content, refmap); cmark_chunk_rtrim(&subj.input); while (!is_eof(&subj) && parse_inline(&subj, parent, options)) ; process_emphasis(&subj, NULL); // free bracket and delim stack while (subj.last_delim) { remove_delimiter(&subj, subj.last_delim); } while (subj.last_bracket) { pop_bracket(&subj); } } // Parse zero or more space characters, including at most one newline. static void spnl(subject *subj) { skip_spaces(subj); if (skip_line_end(subj)) { skip_spaces(subj); } } // Parse reference. Assumes string begins with '[' character. // Modify refmap if a reference is encountered. // Return 0 if no reference found, otherwise position of subject // after reference is parsed. bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input, cmark_reference_map *refmap) { subject subj; cmark_chunk lab; cmark_chunk url; cmark_chunk title; bufsize_t matchlen = 0; bufsize_t beforetitle; subject_from_buf(mem, -1, 0, &subj, input, NULL); // parse label: if (!link_label(&subj, &lab) || lab.len == 0) return 0; // colon: if (peek_char(&subj) == ':') { advance(&subj); } else { return 0; } // parse link url: spnl(&subj); if ((matchlen = manual_scan_link_url(&subj.input, subj.pos, &url)) > -1) { subj.pos += matchlen; } else { return 0; } // parse optional link_title beforetitle = subj.pos; spnl(&subj); matchlen = subj.pos == beforetitle ? 0 : scan_link_title(&subj.input, subj.pos); if (matchlen) { title = cmark_chunk_dup(&subj.input, subj.pos, matchlen); subj.pos += matchlen; } else { subj.pos = beforetitle; title = cmark_chunk_literal(""); } // parse final spaces and newline: skip_spaces(&subj); if (!skip_line_end(&subj)) { if (matchlen) { // try rewinding before title subj.pos = beforetitle; skip_spaces(&subj); if (!skip_line_end(&subj)) { return 0; } } else { return 0; } } // insert reference into refmap cmark_reference_create(refmap, &lab, &url, &title); return subj.pos; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/inlines.h ================================================ #ifndef CMARK_INLINES_H #define CMARK_INLINES_H #ifdef __cplusplus extern "C" { #endif cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url); cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title); void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent, cmark_reference_map *refmap, int options); bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input, cmark_reference_map *refmap); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/iterator.c ================================================ #include #include #include "config.h" #include "node.h" #include "cmark.h" #include "iterator.h" static const int S_leaf_mask = (1 << CMARK_NODE_HTML_BLOCK) | (1 << CMARK_NODE_THEMATIC_BREAK) | (1 << CMARK_NODE_CODE_BLOCK) | (1 << CMARK_NODE_TEXT) | (1 << CMARK_NODE_SOFTBREAK) | (1 << CMARK_NODE_LINEBREAK) | (1 << CMARK_NODE_CODE) | (1 << CMARK_NODE_HTML_INLINE); cmark_iter *cmark_iter_new(cmark_node *root) { if (root == NULL) { return NULL; } cmark_mem *mem = root->content.mem; cmark_iter *iter = (cmark_iter *)mem->calloc(1, sizeof(cmark_iter)); iter->mem = mem; iter->root = root; iter->cur.ev_type = CMARK_EVENT_NONE; iter->cur.node = NULL; iter->next.ev_type = CMARK_EVENT_ENTER; iter->next.node = root; return iter; } void cmark_iter_free(cmark_iter *iter) { iter->mem->free(iter); } static bool S_is_leaf(cmark_node *node) { return ((1 << node->type) & S_leaf_mask) != 0; } cmark_event_type cmark_iter_next(cmark_iter *iter) { cmark_event_type ev_type = iter->next.ev_type; cmark_node *node = iter->next.node; iter->cur.ev_type = ev_type; iter->cur.node = node; if (ev_type == CMARK_EVENT_DONE) { return ev_type; } /* roll forward to next item, setting both fields */ if (ev_type == CMARK_EVENT_ENTER && !S_is_leaf(node)) { if (node->first_child == NULL) { /* stay on this node but exit */ iter->next.ev_type = CMARK_EVENT_EXIT; } else { iter->next.ev_type = CMARK_EVENT_ENTER; iter->next.node = node->first_child; } } else if (node == iter->root) { /* don't move past root */ iter->next.ev_type = CMARK_EVENT_DONE; iter->next.node = NULL; } else if (node->next) { iter->next.ev_type = CMARK_EVENT_ENTER; iter->next.node = node->next; } else if (node->parent) { iter->next.ev_type = CMARK_EVENT_EXIT; iter->next.node = node->parent; } else { assert(false); iter->next.ev_type = CMARK_EVENT_DONE; iter->next.node = NULL; } return ev_type; } void cmark_iter_reset(cmark_iter *iter, cmark_node *current, cmark_event_type event_type) { iter->next.ev_type = event_type; iter->next.node = current; cmark_iter_next(iter); } cmark_node *cmark_iter_get_node(cmark_iter *iter) { return iter->cur.node; } cmark_event_type cmark_iter_get_event_type(cmark_iter *iter) { return iter->cur.ev_type; } cmark_node *cmark_iter_get_root(cmark_iter *iter) { return iter->root; } void cmark_consolidate_text_nodes(cmark_node *root) { if (root == NULL) { return; } cmark_iter *iter = cmark_iter_new(root); cmark_strbuf buf = CMARK_BUF_INIT(iter->mem); cmark_event_type ev_type; cmark_node *cur, *tmp, *next; while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { cur = cmark_iter_get_node(iter); if (ev_type == CMARK_EVENT_ENTER && cur->type == CMARK_NODE_TEXT && cur->next && cur->next->type == CMARK_NODE_TEXT) { cmark_strbuf_clear(&buf); cmark_strbuf_put(&buf, cur->as.literal.data, cur->as.literal.len); tmp = cur->next; while (tmp && tmp->type == CMARK_NODE_TEXT) { cmark_iter_next(iter); // advance pointer cmark_strbuf_put(&buf, tmp->as.literal.data, tmp->as.literal.len); cur->end_column = tmp->end_column; next = tmp->next; cmark_node_free(tmp); tmp = next; } cmark_chunk_free(iter->mem, &cur->as.literal); cur->as.literal = cmark_chunk_buf_detach(&buf); } } cmark_strbuf_free(&buf); cmark_iter_free(iter); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/iterator.h ================================================ #ifndef CMARK_ITERATOR_H #define CMARK_ITERATOR_H #ifdef __cplusplus extern "C" { #endif #include "cmark.h" typedef struct { cmark_event_type ev_type; cmark_node *node; } cmark_iter_state; struct cmark_iter { cmark_mem *mem; cmark_node *root; cmark_iter_state cur; cmark_iter_state next; }; #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/latex.c ================================================ #include #include #include #include #include "config.h" #include "cmark.h" #include "node.h" #include "buffer.h" #include "utf8.h" #include "scanners.h" #include "render.h" #define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping) #define LIT(s) renderer->out(renderer, s, false, LITERAL) #define CR() renderer->cr(renderer) #define BLANKLINE() renderer->blankline(renderer) #define LIST_NUMBER_STRING_SIZE 20 static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c, unsigned char nextc) { if (escape == LITERAL) { cmark_render_code_point(renderer, c); return; } switch (c) { case 123: // '{' case 125: // '}' case 35: // '#' case 37: // '%' case 38: // '&' cmark_render_ascii(renderer, "\\"); cmark_render_code_point(renderer, c); break; case 36: // '$' case 95: // '_' if (escape == NORMAL) { cmark_render_ascii(renderer, "\\"); } cmark_render_code_point(renderer, c); break; case 45: // '-' if (nextc == 45) { // prevent ligature cmark_render_ascii(renderer, "-{}"); } else { cmark_render_ascii(renderer, "-"); } break; case 126: // '~' if (escape == NORMAL) { cmark_render_ascii(renderer, "\\textasciitilde{}"); } else { cmark_render_code_point(renderer, c); } break; case 94: // '^' cmark_render_ascii(renderer, "\\^{}"); break; case 92: // '\\' if (escape == URL) { // / acts as path sep even on windows: cmark_render_ascii(renderer, "/"); } else { cmark_render_ascii(renderer, "\\textbackslash{}"); } break; case 124: // '|' cmark_render_ascii(renderer, "\\textbar{}"); break; case 60: // '<' cmark_render_ascii(renderer, "\\textless{}"); break; case 62: // '>' cmark_render_ascii(renderer, "\\textgreater{}"); break; case 91: // '[' case 93: // ']' cmark_render_ascii(renderer, "{"); cmark_render_code_point(renderer, c); cmark_render_ascii(renderer, "}"); break; case 34: // '"' cmark_render_ascii(renderer, "\\textquotedbl{}"); // requires \usepackage[T1]{fontenc} break; case 39: // '\'' cmark_render_ascii(renderer, "\\textquotesingle{}"); // requires \usepackage{textcomp} break; case 160: // nbsp cmark_render_ascii(renderer, "~"); break; case 8230: // hellip cmark_render_ascii(renderer, "\\ldots{}"); break; case 8216: // lsquo if (escape == NORMAL) { cmark_render_ascii(renderer, "`"); } else { cmark_render_code_point(renderer, c); } break; case 8217: // rsquo if (escape == NORMAL) { cmark_render_ascii(renderer, "\'"); } else { cmark_render_code_point(renderer, c); } break; case 8220: // ldquo if (escape == NORMAL) { cmark_render_ascii(renderer, "``"); } else { cmark_render_code_point(renderer, c); } break; case 8221: // rdquo if (escape == NORMAL) { cmark_render_ascii(renderer, "''"); } else { cmark_render_code_point(renderer, c); } break; case 8212: // emdash if (escape == NORMAL) { cmark_render_ascii(renderer, "---"); } else { cmark_render_code_point(renderer, c); } break; case 8211: // endash if (escape == NORMAL) { cmark_render_ascii(renderer, "--"); } else { cmark_render_code_point(renderer, c); } break; default: cmark_render_code_point(renderer, c); } } typedef enum { NO_LINK, URL_AUTOLINK, EMAIL_AUTOLINK, NORMAL_LINK, INTERNAL_LINK } link_type; static link_type get_link_type(cmark_node *node) { size_t title_len, url_len; cmark_node *link_text; char *realurl; int realurllen; bool isemail = false; if (node->type != CMARK_NODE_LINK) { return NO_LINK; } const char *url = cmark_node_get_url(node); cmark_chunk url_chunk = cmark_chunk_literal(url); if (url && *url == '#') { return INTERNAL_LINK; } url_len = strlen(url); if (url_len == 0 || scan_scheme(&url_chunk, 0) == 0) { return NO_LINK; } const char *title = cmark_node_get_title(node); title_len = strlen(title); // if it has a title, we can't treat it as an autolink: if (title_len == 0) { link_text = node->first_child; cmark_consolidate_text_nodes(link_text); if (!link_text) return NO_LINK; realurl = (char *)url; realurllen = (int)url_len; if (strncmp(realurl, "mailto:", 7) == 0) { realurl += 7; realurllen -= 7; isemail = true; } if (realurllen == link_text->as.literal.len && strncmp(realurl, (char *)link_text->as.literal.data, link_text->as.literal.len) == 0) { if (isemail) { return EMAIL_AUTOLINK; } else { return URL_AUTOLINK; } } } return NORMAL_LINK; } static int S_get_enumlevel(cmark_node *node) { int enumlevel = 0; cmark_node *tmp = node; while (tmp) { if (tmp->type == CMARK_NODE_LIST && cmark_node_get_list_type(node) == CMARK_ORDERED_LIST) { enumlevel++; } tmp = tmp->parent; } return enumlevel; } static int S_render_node(cmark_renderer *renderer, cmark_node *node, cmark_event_type ev_type, int options) { int list_number; int enumlevel; char list_number_string[LIST_NUMBER_STRING_SIZE]; bool entering = (ev_type == CMARK_EVENT_ENTER); cmark_list_type list_type; bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options); // avoid warning about unused parameter: (void)(options); switch (node->type) { case CMARK_NODE_DOCUMENT: break; case CMARK_NODE_BLOCK_QUOTE: if (entering) { LIT("\\begin{quote}"); CR(); } else { LIT("\\end{quote}"); BLANKLINE(); } break; case CMARK_NODE_LIST: list_type = cmark_node_get_list_type(node); if (entering) { LIT("\\begin{"); LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize"); LIT("}"); CR(); list_number = cmark_node_get_list_start(node); if (list_number > 1) { enumlevel = S_get_enumlevel(node); // latex normally supports only five levels if (enumlevel >= 1 && enumlevel <= 5) { snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d", list_number); LIT("\\setcounter{enum"); switch (enumlevel) { case 1: LIT("i"); break; case 2: LIT("ii"); break; case 3: LIT("iii"); break; case 4: LIT("iv"); break; case 5: LIT("v"); break; default: LIT("i"); break; } LIT("}{"); OUT(list_number_string, false, NORMAL); LIT("}"); } CR(); } } else { LIT("\\end{"); LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize"); LIT("}"); BLANKLINE(); } break; case CMARK_NODE_ITEM: if (entering) { LIT("\\item "); } else { CR(); } break; case CMARK_NODE_HEADING: if (entering) { switch (cmark_node_get_heading_level(node)) { case 1: LIT("\\section"); break; case 2: LIT("\\subsection"); break; case 3: LIT("\\subsubsection"); break; case 4: LIT("\\paragraph"); break; case 5: LIT("\\subparagraph"); break; } LIT("{"); } else { LIT("}"); BLANKLINE(); } break; case CMARK_NODE_CODE_BLOCK: CR(); LIT("\\begin{verbatim}"); CR(); OUT(cmark_node_get_literal(node), false, LITERAL); CR(); LIT("\\end{verbatim}"); BLANKLINE(); break; case CMARK_NODE_HTML_BLOCK: break; case CMARK_NODE_CUSTOM_BLOCK: CR(); OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), false, LITERAL); CR(); break; case CMARK_NODE_THEMATIC_BREAK: BLANKLINE(); LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}"); BLANKLINE(); break; case CMARK_NODE_PARAGRAPH: if (!entering) { BLANKLINE(); } break; case CMARK_NODE_TEXT: OUT(cmark_node_get_literal(node), allow_wrap, NORMAL); break; case CMARK_NODE_LINEBREAK: LIT("\\\\"); CR(); break; case CMARK_NODE_SOFTBREAK: if (options & CMARK_OPT_HARDBREAKS) { LIT("\\\\"); CR(); } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) { CR(); } else { OUT(" ", allow_wrap, NORMAL); } break; case CMARK_NODE_CODE: LIT("\\texttt{"); OUT(cmark_node_get_literal(node), false, NORMAL); LIT("}"); break; case CMARK_NODE_HTML_INLINE: break; case CMARK_NODE_CUSTOM_INLINE: OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), false, LITERAL); break; case CMARK_NODE_STRONG: if (entering) { LIT("\\textbf{"); } else { LIT("}"); } break; case CMARK_NODE_EMPH: if (entering) { LIT("\\emph{"); } else { LIT("}"); } break; case CMARK_NODE_LINK: if (entering) { const char *url = cmark_node_get_url(node); // requires \usepackage{hyperref} switch (get_link_type(node)) { case URL_AUTOLINK: LIT("\\url{"); OUT(url, false, URL); LIT("}"); return 0; // Don't process further nodes to avoid double-rendering artefacts case EMAIL_AUTOLINK: LIT("\\href{"); OUT(url, false, URL); LIT("}\\nolinkurl{"); break; case NORMAL_LINK: LIT("\\href{"); OUT(url, false, URL); LIT("}{"); break; case INTERNAL_LINK: LIT("\\protect\\hyperlink{"); OUT(url + 1, false, URL); LIT("}{"); break; case NO_LINK: LIT("{"); // error? } } else { LIT("}"); } break; case CMARK_NODE_IMAGE: if (entering) { LIT("\\protect\\includegraphics{"); // requires \include{graphicx} OUT(cmark_node_get_url(node), false, URL); LIT("}"); return 0; } break; default: assert(false); break; } return 1; } char *cmark_render_latex(cmark_node *root, int options, int width) { return cmark_render(root, options, width, outc, S_render_node); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/libcmark.pc.in ================================================ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@CMAKE_INSTALL_PREFIX@/@libdir@ includedir=@CMAKE_INSTALL_PREFIX@/include Name: libcmark Description: CommonMark parsing, rendering, and manipulation Version: @PROJECT_VERSION@ Libs: -L${libdir} -lcmark Cflags: -I${includedir} ================================================ FILE: liteidex/src/3rdparty/cmark/src/main.c ================================================ #include #include #include #include #include "config.h" #include "cmark.h" #include "node.h" #if defined(__OpenBSD__) # include # if OpenBSD >= 201605 # define USE_PLEDGE # include # endif #endif #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #endif typedef enum { FORMAT_NONE, FORMAT_HTML, FORMAT_XML, FORMAT_MAN, FORMAT_COMMONMARK, FORMAT_LATEX } writer_format; void print_usage() { printf("Usage: cmark [FILE*]\n"); printf("Options:\n"); printf(" --to, -t FORMAT Specify output format (html, xml, man, " "commonmark, latex)\n"); printf(" --width WIDTH Specify wrap width (default 0 = nowrap)\n"); printf(" --sourcepos Include source position attribute\n"); printf(" --hardbreaks Treat newlines as hard line breaks\n"); printf(" --nobreaks Render soft line breaks as spaces\n"); printf(" --unsafe Render raw HTML and dangerous URLs\n"); printf(" --smart Use smart punctuation\n"); printf(" --validate-utf8 Replace UTF-8 invalid sequences with U+FFFD\n"); printf(" --help, -h Print usage information\n"); printf(" --version Print version\n"); } static void print_document(cmark_node *document, writer_format writer, int options, int width) { char *result; switch (writer) { case FORMAT_HTML: result = cmark_render_html(document, options); break; case FORMAT_XML: result = cmark_render_xml(document, options); break; case FORMAT_MAN: result = cmark_render_man(document, options, width); break; case FORMAT_COMMONMARK: result = cmark_render_commonmark(document, options, width); break; case FORMAT_LATEX: result = cmark_render_latex(document, options, width); break; default: fprintf(stderr, "Unknown format %d\n", writer); exit(1); } printf("%s", result); cmark_node_mem(document)->free(result); } int main(int argc, char *argv[]) { int i, numfps = 0; int *files; char buffer[4096]; cmark_parser *parser; size_t bytes; cmark_node *document; int width = 0; char *unparsed; writer_format writer = FORMAT_HTML; int options = CMARK_OPT_DEFAULT; #ifdef USE_PLEDGE if (pledge("stdio rpath", NULL) != 0) { perror("pledge"); return 1; } #endif #if defined(_WIN32) && !defined(__CYGWIN__) _setmode(_fileno(stdin), _O_BINARY); _setmode(_fileno(stdout), _O_BINARY); #endif files = (int *)calloc(argc, sizeof(*files)); for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--version") == 0) { printf("cmark %s", CMARK_VERSION_STRING); printf(" - CommonMark converter\n(C) 2014-2016 John MacFarlane\n"); exit(0); } else if (strcmp(argv[i], "--sourcepos") == 0) { options |= CMARK_OPT_SOURCEPOS; } else if (strcmp(argv[i], "--hardbreaks") == 0) { options |= CMARK_OPT_HARDBREAKS; } else if (strcmp(argv[i], "--nobreaks") == 0) { options |= CMARK_OPT_NOBREAKS; } else if (strcmp(argv[i], "--smart") == 0) { options |= CMARK_OPT_SMART; } else if (strcmp(argv[i], "--unsafe") == 0) { options |= CMARK_OPT_UNSAFE; } else if (strcmp(argv[i], "--validate-utf8") == 0) { options |= CMARK_OPT_VALIDATE_UTF8; } else if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0)) { print_usage(); exit(0); } else if (strcmp(argv[i], "--width") == 0) { i += 1; if (i < argc) { width = (int)strtol(argv[i], &unparsed, 10); if (unparsed && strlen(unparsed) > 0) { fprintf(stderr, "failed parsing width '%s' at '%s'\n", argv[i], unparsed); exit(1); } } else { fprintf(stderr, "--width requires an argument\n"); exit(1); } } else if ((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--to") == 0)) { i += 1; if (i < argc) { if (strcmp(argv[i], "man") == 0) { writer = FORMAT_MAN; } else if (strcmp(argv[i], "html") == 0) { writer = FORMAT_HTML; } else if (strcmp(argv[i], "xml") == 0) { writer = FORMAT_XML; } else if (strcmp(argv[i], "commonmark") == 0) { writer = FORMAT_COMMONMARK; } else if (strcmp(argv[i], "latex") == 0) { writer = FORMAT_LATEX; } else { fprintf(stderr, "Unknown format %s\n", argv[i]); exit(1); } } else { fprintf(stderr, "No argument provided for %s\n", argv[i - 1]); exit(1); } } else if (*argv[i] == '-') { print_usage(); exit(1); } else { // treat as file argument files[numfps++] = i; } } parser = cmark_parser_new(options); for (i = 0; i < numfps; i++) { FILE *fp = fopen(argv[files[i]], "rb"); if (fp == NULL) { fprintf(stderr, "Error opening file %s: %s\n", argv[files[i]], strerror(errno)); exit(1); } while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { cmark_parser_feed(parser, buffer, bytes); if (bytes < sizeof(buffer)) { break; } } fclose(fp); } if (numfps == 0) { while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) { cmark_parser_feed(parser, buffer, bytes); if (bytes < sizeof(buffer)) { break; } } } #ifdef USE_PLEDGE if (pledge("stdio", NULL) != 0) { perror("pledge"); return 1; } #endif document = cmark_parser_finish(parser); cmark_parser_free(parser); print_document(document, writer, options, width); cmark_node_free(document); free(files); return 0; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/man.c ================================================ #include #include #include #include #include "config.h" #include "cmark.h" #include "node.h" #include "buffer.h" #include "utf8.h" #include "render.h" #define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping) #define LIT(s) renderer->out(renderer, s, false, LITERAL) #define CR() renderer->cr(renderer) #define BLANKLINE() renderer->blankline(renderer) #define LIST_NUMBER_SIZE 20 // Functions to convert cmark_nodes to groff man strings. static void S_outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c, unsigned char nextc) { (void)(nextc); if (escape == LITERAL) { cmark_render_code_point(renderer, c); return; } switch (c) { case 46: if (renderer->begin_line) { cmark_render_ascii(renderer, "\\&."); } else { cmark_render_code_point(renderer, c); } break; case 39: if (renderer->begin_line) { cmark_render_ascii(renderer, "\\&'"); } else { cmark_render_code_point(renderer, c); } break; case 45: cmark_render_ascii(renderer, "\\-"); break; case 92: cmark_render_ascii(renderer, "\\e"); break; case 8216: // left single quote cmark_render_ascii(renderer, "\\[oq]"); break; case 8217: // right single quote cmark_render_ascii(renderer, "\\[cq]"); break; case 8220: // left double quote cmark_render_ascii(renderer, "\\[lq]"); break; case 8221: // right double quote cmark_render_ascii(renderer, "\\[rq]"); break; case 8212: // em dash cmark_render_ascii(renderer, "\\[em]"); break; case 8211: // en dash cmark_render_ascii(renderer, "\\[en]"); break; default: cmark_render_code_point(renderer, c); } } static int S_render_node(cmark_renderer *renderer, cmark_node *node, cmark_event_type ev_type, int options) { cmark_node *tmp; int list_number; bool entering = (ev_type == CMARK_EVENT_ENTER); bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options); // avoid unused parameter error: (void)(options); switch (node->type) { case CMARK_NODE_DOCUMENT: break; case CMARK_NODE_BLOCK_QUOTE: if (entering) { CR(); LIT(".RS"); CR(); } else { CR(); LIT(".RE"); CR(); } break; case CMARK_NODE_LIST: break; case CMARK_NODE_ITEM: if (entering) { CR(); LIT(".IP "); if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) { LIT("\\[bu] 2"); } else { list_number = cmark_node_get_list_start(node->parent); tmp = node; while (tmp->prev) { tmp = tmp->prev; list_number += 1; } char list_number_s[LIST_NUMBER_SIZE]; snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number); LIT(list_number_s); } CR(); } else { CR(); } break; case CMARK_NODE_HEADING: if (entering) { CR(); LIT(cmark_node_get_heading_level(node) == 1 ? ".SH" : ".SS"); CR(); } else { CR(); } break; case CMARK_NODE_CODE_BLOCK: CR(); LIT(".IP\n.nf\n\\f[C]\n"); OUT(cmark_node_get_literal(node), false, NORMAL); CR(); LIT("\\f[]\n.fi"); CR(); break; case CMARK_NODE_HTML_BLOCK: break; case CMARK_NODE_CUSTOM_BLOCK: CR(); OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), false, LITERAL); CR(); break; case CMARK_NODE_THEMATIC_BREAK: CR(); LIT(".PP\n * * * * *"); CR(); break; case CMARK_NODE_PARAGRAPH: if (entering) { // no blank line if first paragraph in list: if (node->parent && node->parent->type == CMARK_NODE_ITEM && node->prev == NULL) { // no blank line or .PP } else { CR(); LIT(".PP"); CR(); } } else { CR(); } break; case CMARK_NODE_TEXT: OUT(cmark_node_get_literal(node), allow_wrap, NORMAL); break; case CMARK_NODE_LINEBREAK: LIT(".PD 0\n.P\n.PD"); CR(); break; case CMARK_NODE_SOFTBREAK: if (options & CMARK_OPT_HARDBREAKS) { LIT(".PD 0\n.P\n.PD"); CR(); } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) { CR(); } else { OUT(" ", allow_wrap, LITERAL); } break; case CMARK_NODE_CODE: LIT("\\f[C]"); OUT(cmark_node_get_literal(node), allow_wrap, NORMAL); LIT("\\f[]"); break; case CMARK_NODE_HTML_INLINE: break; case CMARK_NODE_CUSTOM_INLINE: OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), false, LITERAL); break; case CMARK_NODE_STRONG: if (entering) { LIT("\\f[B]"); } else { LIT("\\f[]"); } break; case CMARK_NODE_EMPH: if (entering) { LIT("\\f[I]"); } else { LIT("\\f[]"); } break; case CMARK_NODE_LINK: if (!entering) { LIT(" ("); OUT(cmark_node_get_url(node), allow_wrap, URL); LIT(")"); } break; case CMARK_NODE_IMAGE: if (entering) { LIT("[IMAGE: "); } else { LIT("]"); } break; default: assert(false); break; } return 1; } char *cmark_render_man(cmark_node *root, int options, int width) { return cmark_render(root, options, width, S_outc, S_render_node); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/node.c ================================================ #include #include #include "config.h" #include "node.h" static void S_node_unlink(cmark_node *node); #define NODE_MEM(node) cmark_node_mem(node) static CMARK_INLINE bool S_is_block(cmark_node *node) { if (node == NULL) { return false; } return node->type >= CMARK_NODE_FIRST_BLOCK && node->type <= CMARK_NODE_LAST_BLOCK; } static CMARK_INLINE bool S_is_inline(cmark_node *node) { if (node == NULL) { return false; } return node->type >= CMARK_NODE_FIRST_INLINE && node->type <= CMARK_NODE_LAST_INLINE; } static bool S_can_contain(cmark_node *node, cmark_node *child) { cmark_node *cur; if (node == NULL || child == NULL) { return false; } // Verify that child is not an ancestor of node or equal to node. cur = node; do { if (cur == child) { return false; } cur = cur->parent; } while (cur != NULL); if (child->type == CMARK_NODE_DOCUMENT) { return false; } switch (node->type) { case CMARK_NODE_DOCUMENT: case CMARK_NODE_BLOCK_QUOTE: case CMARK_NODE_ITEM: return S_is_block(child) && child->type != CMARK_NODE_ITEM; case CMARK_NODE_LIST: return child->type == CMARK_NODE_ITEM; case CMARK_NODE_CUSTOM_BLOCK: return true; case CMARK_NODE_PARAGRAPH: case CMARK_NODE_HEADING: case CMARK_NODE_EMPH: case CMARK_NODE_STRONG: case CMARK_NODE_LINK: case CMARK_NODE_IMAGE: case CMARK_NODE_CUSTOM_INLINE: return S_is_inline(child); default: break; } return false; } cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem) { cmark_node *node = (cmark_node *)mem->calloc(1, sizeof(*node)); cmark_strbuf_init(mem, &node->content, 0); node->type = (uint16_t)type; switch (node->type) { case CMARK_NODE_HEADING: node->as.heading.level = 1; break; case CMARK_NODE_LIST: { cmark_list *list = &node->as.list; list->list_type = CMARK_BULLET_LIST; list->start = 0; list->tight = false; break; } default: break; } return node; } cmark_node *cmark_node_new(cmark_node_type type) { extern cmark_mem DEFAULT_MEM_ALLOCATOR; return cmark_node_new_with_mem(type, &DEFAULT_MEM_ALLOCATOR); } // Free a cmark_node list and any children. static void S_free_nodes(cmark_node *e) { cmark_node *next; while (e != NULL) { cmark_strbuf_free(&e->content); switch (e->type) { case CMARK_NODE_CODE_BLOCK: cmark_chunk_free(NODE_MEM(e), &e->as.code.info); cmark_chunk_free(NODE_MEM(e), &e->as.code.literal); break; case CMARK_NODE_TEXT: case CMARK_NODE_HTML_INLINE: case CMARK_NODE_CODE: case CMARK_NODE_HTML_BLOCK: cmark_chunk_free(NODE_MEM(e), &e->as.literal); break; case CMARK_NODE_LINK: case CMARK_NODE_IMAGE: cmark_chunk_free(NODE_MEM(e), &e->as.link.url); cmark_chunk_free(NODE_MEM(e), &e->as.link.title); break; case CMARK_NODE_CUSTOM_BLOCK: case CMARK_NODE_CUSTOM_INLINE: cmark_chunk_free(NODE_MEM(e), &e->as.custom.on_enter); cmark_chunk_free(NODE_MEM(e), &e->as.custom.on_exit); break; default: break; } if (e->last_child) { // Splice children into list e->last_child->next = e->next; e->next = e->first_child; } next = e->next; NODE_MEM(e)->free(e); e = next; } } void cmark_node_free(cmark_node *node) { S_node_unlink(node); node->next = NULL; S_free_nodes(node); } cmark_node_type cmark_node_get_type(cmark_node *node) { if (node == NULL) { return CMARK_NODE_NONE; } else { return (cmark_node_type)node->type; } } const char *cmark_node_get_type_string(cmark_node *node) { if (node == NULL) { return "NONE"; } switch (node->type) { case CMARK_NODE_NONE: return "none"; case CMARK_NODE_DOCUMENT: return "document"; case CMARK_NODE_BLOCK_QUOTE: return "block_quote"; case CMARK_NODE_LIST: return "list"; case CMARK_NODE_ITEM: return "item"; case CMARK_NODE_CODE_BLOCK: return "code_block"; case CMARK_NODE_HTML_BLOCK: return "html_block"; case CMARK_NODE_CUSTOM_BLOCK: return "custom_block"; case CMARK_NODE_PARAGRAPH: return "paragraph"; case CMARK_NODE_HEADING: return "heading"; case CMARK_NODE_THEMATIC_BREAK: return "thematic_break"; case CMARK_NODE_TEXT: return "text"; case CMARK_NODE_SOFTBREAK: return "softbreak"; case CMARK_NODE_LINEBREAK: return "linebreak"; case CMARK_NODE_CODE: return "code"; case CMARK_NODE_HTML_INLINE: return "html_inline"; case CMARK_NODE_CUSTOM_INLINE: return "custom_inline"; case CMARK_NODE_EMPH: return "emph"; case CMARK_NODE_STRONG: return "strong"; case CMARK_NODE_LINK: return "link"; case CMARK_NODE_IMAGE: return "image"; } return ""; } cmark_node *cmark_node_next(cmark_node *node) { if (node == NULL) { return NULL; } else { return node->next; } } cmark_node *cmark_node_previous(cmark_node *node) { if (node == NULL) { return NULL; } else { return node->prev; } } cmark_node *cmark_node_parent(cmark_node *node) { if (node == NULL) { return NULL; } else { return node->parent; } } cmark_node *cmark_node_first_child(cmark_node *node) { if (node == NULL) { return NULL; } else { return node->first_child; } } cmark_node *cmark_node_last_child(cmark_node *node) { if (node == NULL) { return NULL; } else { return node->last_child; } } void *cmark_node_get_user_data(cmark_node *node) { if (node == NULL) { return NULL; } else { return node->user_data; } } int cmark_node_set_user_data(cmark_node *node, void *user_data) { if (node == NULL) { return 0; } node->user_data = user_data; return 1; } const char *cmark_node_get_literal(cmark_node *node) { if (node == NULL) { return NULL; } switch (node->type) { case CMARK_NODE_HTML_BLOCK: case CMARK_NODE_TEXT: case CMARK_NODE_HTML_INLINE: case CMARK_NODE_CODE: return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal); case CMARK_NODE_CODE_BLOCK: return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.literal); default: break; } return NULL; } int cmark_node_set_literal(cmark_node *node, const char *content) { if (node == NULL) { return 0; } switch (node->type) { case CMARK_NODE_HTML_BLOCK: case CMARK_NODE_TEXT: case CMARK_NODE_HTML_INLINE: case CMARK_NODE_CODE: cmark_chunk_set_cstr(NODE_MEM(node), &node->as.literal, content); return 1; case CMARK_NODE_CODE_BLOCK: cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.literal, content); return 1; default: break; } return 0; } int cmark_node_get_heading_level(cmark_node *node) { if (node == NULL) { return 0; } switch (node->type) { case CMARK_NODE_HEADING: return node->as.heading.level; default: break; } return 0; } int cmark_node_set_heading_level(cmark_node *node, int level) { if (node == NULL || level < 1 || level > 6) { return 0; } switch (node->type) { case CMARK_NODE_HEADING: node->as.heading.level = level; return 1; default: break; } return 0; } cmark_list_type cmark_node_get_list_type(cmark_node *node) { if (node == NULL) { return CMARK_NO_LIST; } if (node->type == CMARK_NODE_LIST) { return node->as.list.list_type; } else { return CMARK_NO_LIST; } } int cmark_node_set_list_type(cmark_node *node, cmark_list_type type) { if (!(type == CMARK_BULLET_LIST || type == CMARK_ORDERED_LIST)) { return 0; } if (node == NULL) { return 0; } if (node->type == CMARK_NODE_LIST) { node->as.list.list_type = type; return 1; } else { return 0; } } cmark_delim_type cmark_node_get_list_delim(cmark_node *node) { if (node == NULL) { return CMARK_NO_DELIM; } if (node->type == CMARK_NODE_LIST) { return node->as.list.delimiter; } else { return CMARK_NO_DELIM; } } int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim) { if (!(delim == CMARK_PERIOD_DELIM || delim == CMARK_PAREN_DELIM)) { return 0; } if (node == NULL) { return 0; } if (node->type == CMARK_NODE_LIST) { node->as.list.delimiter = delim; return 1; } else { return 0; } } int cmark_node_get_list_start(cmark_node *node) { if (node == NULL) { return 0; } if (node->type == CMARK_NODE_LIST) { return node->as.list.start; } else { return 0; } } int cmark_node_set_list_start(cmark_node *node, int start) { if (node == NULL || start < 0) { return 0; } if (node->type == CMARK_NODE_LIST) { node->as.list.start = start; return 1; } else { return 0; } } int cmark_node_get_list_tight(cmark_node *node) { if (node == NULL) { return 0; } if (node->type == CMARK_NODE_LIST) { return node->as.list.tight; } else { return 0; } } int cmark_node_set_list_tight(cmark_node *node, int tight) { if (node == NULL) { return 0; } if (node->type == CMARK_NODE_LIST) { node->as.list.tight = tight == 1; return 1; } else { return 0; } } const char *cmark_node_get_fence_info(cmark_node *node) { if (node == NULL) { return NULL; } if (node->type == CMARK_NODE_CODE_BLOCK) { return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.info); } else { return NULL; } } int cmark_node_set_fence_info(cmark_node *node, const char *info) { if (node == NULL) { return 0; } if (node->type == CMARK_NODE_CODE_BLOCK) { cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.info, info); return 1; } else { return 0; } } const char *cmark_node_get_url(cmark_node *node) { if (node == NULL) { return NULL; } switch (node->type) { case CMARK_NODE_LINK: case CMARK_NODE_IMAGE: return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.url); default: break; } return NULL; } int cmark_node_set_url(cmark_node *node, const char *url) { if (node == NULL) { return 0; } switch (node->type) { case CMARK_NODE_LINK: case CMARK_NODE_IMAGE: cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.url, url); return 1; default: break; } return 0; } const char *cmark_node_get_title(cmark_node *node) { if (node == NULL) { return NULL; } switch (node->type) { case CMARK_NODE_LINK: case CMARK_NODE_IMAGE: return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.title); default: break; } return NULL; } int cmark_node_set_title(cmark_node *node, const char *title) { if (node == NULL) { return 0; } switch (node->type) { case CMARK_NODE_LINK: case CMARK_NODE_IMAGE: cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.title, title); return 1; default: break; } return 0; } const char *cmark_node_get_on_enter(cmark_node *node) { if (node == NULL) { return NULL; } switch (node->type) { case CMARK_NODE_CUSTOM_INLINE: case CMARK_NODE_CUSTOM_BLOCK: return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_enter); default: break; } return NULL; } int cmark_node_set_on_enter(cmark_node *node, const char *on_enter) { if (node == NULL) { return 0; } switch (node->type) { case CMARK_NODE_CUSTOM_INLINE: case CMARK_NODE_CUSTOM_BLOCK: cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_enter, on_enter); return 1; default: break; } return 0; } const char *cmark_node_get_on_exit(cmark_node *node) { if (node == NULL) { return NULL; } switch (node->type) { case CMARK_NODE_CUSTOM_INLINE: case CMARK_NODE_CUSTOM_BLOCK: return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_exit); default: break; } return NULL; } int cmark_node_set_on_exit(cmark_node *node, const char *on_exit) { if (node == NULL) { return 0; } switch (node->type) { case CMARK_NODE_CUSTOM_INLINE: case CMARK_NODE_CUSTOM_BLOCK: cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_exit, on_exit); return 1; default: break; } return 0; } int cmark_node_get_start_line(cmark_node *node) { if (node == NULL) { return 0; } return node->start_line; } int cmark_node_get_start_column(cmark_node *node) { if (node == NULL) { return 0; } return node->start_column; } int cmark_node_get_end_line(cmark_node *node) { if (node == NULL) { return 0; } return node->end_line; } int cmark_node_get_end_column(cmark_node *node) { if (node == NULL) { return 0; } return node->end_column; } // Unlink a node without adjusting its next, prev, and parent pointers. static void S_node_unlink(cmark_node *node) { if (node == NULL) { return; } if (node->prev) { node->prev->next = node->next; } if (node->next) { node->next->prev = node->prev; } // Adjust first_child and last_child of parent. cmark_node *parent = node->parent; if (parent) { if (parent->first_child == node) { parent->first_child = node->next; } if (parent->last_child == node) { parent->last_child = node->prev; } } } void cmark_node_unlink(cmark_node *node) { S_node_unlink(node); node->next = NULL; node->prev = NULL; node->parent = NULL; } int cmark_node_insert_before(cmark_node *node, cmark_node *sibling) { if (node == NULL || sibling == NULL) { return 0; } if (!node->parent || !S_can_contain(node->parent, sibling)) { return 0; } S_node_unlink(sibling); cmark_node *old_prev = node->prev; // Insert 'sibling' between 'old_prev' and 'node'. if (old_prev) { old_prev->next = sibling; } sibling->prev = old_prev; sibling->next = node; node->prev = sibling; // Set new parent. cmark_node *parent = node->parent; sibling->parent = parent; // Adjust first_child of parent if inserted as first child. if (parent && !old_prev) { parent->first_child = sibling; } return 1; } int cmark_node_insert_after(cmark_node *node, cmark_node *sibling) { if (node == NULL || sibling == NULL) { return 0; } if (!node->parent || !S_can_contain(node->parent, sibling)) { return 0; } S_node_unlink(sibling); cmark_node *old_next = node->next; // Insert 'sibling' between 'node' and 'old_next'. if (old_next) { old_next->prev = sibling; } sibling->next = old_next; sibling->prev = node; node->next = sibling; // Set new parent. cmark_node *parent = node->parent; sibling->parent = parent; // Adjust last_child of parent if inserted as last child. if (parent && !old_next) { parent->last_child = sibling; } return 1; } int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode) { if (!cmark_node_insert_before(oldnode, newnode)) { return 0; } cmark_node_unlink(oldnode); return 1; } int cmark_node_prepend_child(cmark_node *node, cmark_node *child) { if (!S_can_contain(node, child)) { return 0; } S_node_unlink(child); cmark_node *old_first_child = node->first_child; child->next = old_first_child; child->prev = NULL; child->parent = node; node->first_child = child; if (old_first_child) { old_first_child->prev = child; } else { // Also set last_child if node previously had no children. node->last_child = child; } return 1; } int cmark_node_append_child(cmark_node *node, cmark_node *child) { if (!S_can_contain(node, child)) { return 0; } S_node_unlink(child); cmark_node *old_last_child = node->last_child; child->next = NULL; child->prev = old_last_child; child->parent = node; node->last_child = child; if (old_last_child) { old_last_child->next = child; } else { // Also set first_child if node previously had no children. node->first_child = child; } return 1; } static void S_print_error(FILE *out, cmark_node *node, const char *elem) { if (out == NULL) { return; } fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem, cmark_node_get_type_string(node), node->start_line, node->start_column); } int cmark_node_check(cmark_node *node, FILE *out) { cmark_node *cur; int errors = 0; if (!node) { return 0; } cur = node; for (;;) { if (cur->first_child) { if (cur->first_child->prev != NULL) { S_print_error(out, cur->first_child, "prev"); cur->first_child->prev = NULL; ++errors; } if (cur->first_child->parent != cur) { S_print_error(out, cur->first_child, "parent"); cur->first_child->parent = cur; ++errors; } cur = cur->first_child; continue; } next_sibling: if (cur == node) { break; } if (cur->next) { if (cur->next->prev != cur) { S_print_error(out, cur->next, "prev"); cur->next->prev = cur; ++errors; } if (cur->next->parent != cur->parent) { S_print_error(out, cur->next, "parent"); cur->next->parent = cur->parent; ++errors; } cur = cur->next; continue; } if (cur->parent->last_child != cur) { S_print_error(out, cur->parent, "last_child"); cur->parent->last_child = cur; ++errors; } cur = cur->parent; goto next_sibling; } return errors; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/node.h ================================================ #ifndef CMARK_NODE_H #define CMARK_NODE_H #ifdef __cplusplus extern "C" { #endif #include #include #include "cmark.h" #include "buffer.h" #include "chunk.h" typedef struct { cmark_list_type list_type; int marker_offset; int padding; int start; cmark_delim_type delimiter; unsigned char bullet_char; bool tight; } cmark_list; typedef struct { cmark_chunk info; cmark_chunk literal; uint8_t fence_length; uint8_t fence_offset; unsigned char fence_char; int8_t fenced; } cmark_code; typedef struct { int level; bool setext; } cmark_heading; typedef struct { cmark_chunk url; cmark_chunk title; } cmark_link; typedef struct { cmark_chunk on_enter; cmark_chunk on_exit; } cmark_custom; enum cmark_node__internal_flags { CMARK_NODE__OPEN = (1 << 0), CMARK_NODE__LAST_LINE_BLANK = (1 << 1), CMARK_NODE__LAST_LINE_CHECKED = (1 << 2), }; struct cmark_node { cmark_strbuf content; struct cmark_node *next; struct cmark_node *prev; struct cmark_node *parent; struct cmark_node *first_child; struct cmark_node *last_child; void *user_data; int start_line; int start_column; int end_line; int end_column; int internal_offset; uint16_t type; uint16_t flags; union { cmark_chunk literal; cmark_list list; cmark_code code; cmark_heading heading; cmark_link link; cmark_custom custom; int html_block_type; } as; }; static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) { return node->content.mem; } CMARK_EXPORT int cmark_node_check(cmark_node *node, FILE *out); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/parser.h ================================================ #ifndef CMARK_AST_H #define CMARK_AST_H #include #include "references.h" #include "node.h" #include "buffer.h" #ifdef __cplusplus extern "C" { #endif #define MAX_LINK_LABEL_LENGTH 1000 struct cmark_parser { struct cmark_mem *mem; struct cmark_reference_map *refmap; struct cmark_node *root; struct cmark_node *current; int line_number; bufsize_t offset; bufsize_t column; bufsize_t first_nonspace; bufsize_t first_nonspace_column; bufsize_t thematic_break_kill_pos; int indent; bool blank; bool partially_consumed_tab; cmark_strbuf curline; bufsize_t last_line_length; cmark_strbuf linebuf; int options; bool last_buffer_ended_with_cr; }; #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/references.c ================================================ #include "cmark.h" #include "utf8.h" #include "parser.h" #include "references.h" #include "inlines.h" #include "chunk.h" static unsigned int refhash(const unsigned char *link_ref) { unsigned int hash = 0; while (*link_ref) hash = (*link_ref++) + (hash << 6) + (hash << 16) - hash; return hash; } static void reference_free(cmark_reference_map *map, cmark_reference *ref) { cmark_mem *mem = map->mem; if (ref != NULL) { mem->free(ref->label); cmark_chunk_free(mem, &ref->url); cmark_chunk_free(mem, &ref->title); mem->free(ref); } } // normalize reference: collapse internal whitespace to single space, // remove leading/trailing whitespace, case fold // Return NULL if the reference name is actually empty (i.e. composed // solely from whitespace) static unsigned char *normalize_reference(cmark_mem *mem, cmark_chunk *ref) { cmark_strbuf normalized = CMARK_BUF_INIT(mem); unsigned char *result; if (ref == NULL) return NULL; if (ref->len == 0) return NULL; cmark_utf8proc_case_fold(&normalized, ref->data, ref->len); cmark_strbuf_trim(&normalized); cmark_strbuf_normalize_whitespace(&normalized); result = cmark_strbuf_detach(&normalized); assert(result); if (result[0] == '\0') { mem->free(result); return NULL; } return result; } static void add_reference(cmark_reference_map *map, cmark_reference *ref) { cmark_reference *t = ref->next = map->table[ref->hash % REFMAP_SIZE]; while (t) { if (t->hash == ref->hash && !strcmp((char *)t->label, (char *)ref->label)) { reference_free(map, ref); return; } t = t->next; } map->table[ref->hash % REFMAP_SIZE] = ref; } void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label, cmark_chunk *url, cmark_chunk *title) { cmark_reference *ref; unsigned char *reflabel = normalize_reference(map->mem, label); /* empty reference name, or composed from only whitespace */ if (reflabel == NULL) return; ref = (cmark_reference *)map->mem->calloc(1, sizeof(*ref)); ref->label = reflabel; ref->hash = refhash(ref->label); ref->url = cmark_clean_url(map->mem, url); ref->title = cmark_clean_title(map->mem, title); ref->next = NULL; add_reference(map, ref); } // Returns reference if refmap contains a reference with matching // label, otherwise NULL. cmark_reference *cmark_reference_lookup(cmark_reference_map *map, cmark_chunk *label) { cmark_reference *ref = NULL; unsigned char *norm; unsigned int hash; if (label->len < 1 || label->len > MAX_LINK_LABEL_LENGTH) return NULL; if (map == NULL) return NULL; norm = normalize_reference(map->mem, label); if (norm == NULL) return NULL; hash = refhash(norm); ref = map->table[hash % REFMAP_SIZE]; while (ref) { if (ref->hash == hash && !strcmp((char *)ref->label, (char *)norm)) break; ref = ref->next; } map->mem->free(norm); return ref; } void cmark_reference_map_free(cmark_reference_map *map) { unsigned int i; if (map == NULL) return; for (i = 0; i < REFMAP_SIZE; ++i) { cmark_reference *ref = map->table[i]; cmark_reference *next; while (ref) { next = ref->next; reference_free(map, ref); ref = next; } } map->mem->free(map); } cmark_reference_map *cmark_reference_map_new(cmark_mem *mem) { cmark_reference_map *map = (cmark_reference_map *)mem->calloc(1, sizeof(cmark_reference_map)); map->mem = mem; return map; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/references.h ================================================ #ifndef CMARK_REFERENCES_H #define CMARK_REFERENCES_H #include "chunk.h" #ifdef __cplusplus extern "C" { #endif #define REFMAP_SIZE 16 struct cmark_reference { struct cmark_reference *next; unsigned char *label; cmark_chunk url; cmark_chunk title; unsigned int hash; }; typedef struct cmark_reference cmark_reference; struct cmark_reference_map { cmark_mem *mem; cmark_reference *table[REFMAP_SIZE]; }; typedef struct cmark_reference_map cmark_reference_map; cmark_reference_map *cmark_reference_map_new(cmark_mem *mem); void cmark_reference_map_free(cmark_reference_map *map); cmark_reference *cmark_reference_lookup(cmark_reference_map *map, cmark_chunk *label); extern void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label, cmark_chunk *url, cmark_chunk *title); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/render.c ================================================ #include #include "buffer.h" #include "chunk.h" #include "cmark.h" #include "utf8.h" #include "render.h" #include "node.h" static CMARK_INLINE void S_cr(cmark_renderer *renderer) { if (renderer->need_cr < 1) { renderer->need_cr = 1; } } static CMARK_INLINE void S_blankline(cmark_renderer *renderer) { if (renderer->need_cr < 2) { renderer->need_cr = 2; } } static void S_out(cmark_renderer *renderer, const char *source, bool wrap, cmark_escaping escape) { int length = strlen(source); unsigned char nextc; int32_t c; int i = 0; int last_nonspace; int len; cmark_chunk remainder = cmark_chunk_literal(""); int k = renderer->buffer->size - 1; wrap = wrap && !renderer->no_linebreaks; if (renderer->in_tight_list_item && renderer->need_cr > 1) { renderer->need_cr = 1; } while (renderer->need_cr) { if (k < 0 || renderer->buffer->ptr[k] == '\n') { k -= 1; } else { cmark_strbuf_putc(renderer->buffer, '\n'); if (renderer->need_cr > 1) { cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr, renderer->prefix->size); } } renderer->column = 0; renderer->last_breakable = 0; renderer->begin_line = true; renderer->begin_content = true; renderer->need_cr -= 1; } while (i < length) { if (renderer->begin_line) { cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr, renderer->prefix->size); // note: this assumes prefix is ascii: renderer->column = renderer->prefix->size; } len = cmark_utf8proc_iterate((const uint8_t *)source + i, length - i, &c); if (len == -1) { // error condition return; // return without rendering rest of string } nextc = source[i + len]; if (c == 32 && wrap) { if (!renderer->begin_line) { last_nonspace = renderer->buffer->size; cmark_strbuf_putc(renderer->buffer, ' '); renderer->column += 1; renderer->begin_line = false; renderer->begin_content = false; // skip following spaces while (source[i + 1] == ' ') { i++; } // We don't allow breaks that make a digit the first character // because this causes problems with commonmark output. if (!cmark_isdigit(source[i + 1])) { renderer->last_breakable = last_nonspace; } } } else if (escape == LITERAL) { if (c == 10) { cmark_strbuf_putc(renderer->buffer, '\n'); renderer->column = 0; renderer->begin_line = true; renderer->begin_content = true; renderer->last_breakable = 0; } else { cmark_render_code_point(renderer, c); renderer->begin_line = false; // we don't set 'begin_content' to false til we've // finished parsing a digit. Reason: in commonmark // we need to escape a potential list marker after // a digit: renderer->begin_content = renderer->begin_content && cmark_isdigit(c) == 1; } } else { (renderer->outc)(renderer, escape, c, nextc); renderer->begin_line = false; renderer->begin_content = renderer->begin_content && cmark_isdigit(c) == 1; } // If adding the character went beyond width, look for an // earlier place where the line could be broken: if (renderer->width > 0 && renderer->column > renderer->width && !renderer->begin_line && renderer->last_breakable > 0) { // copy from last_breakable to remainder cmark_chunk_set_cstr(renderer->mem, &remainder, (char *)renderer->buffer->ptr + renderer->last_breakable + 1); // truncate at last_breakable cmark_strbuf_truncate(renderer->buffer, renderer->last_breakable); // add newline, prefix, and remainder cmark_strbuf_putc(renderer->buffer, '\n'); cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr, renderer->prefix->size); cmark_strbuf_put(renderer->buffer, remainder.data, remainder.len); renderer->column = renderer->prefix->size + remainder.len; cmark_chunk_free(renderer->mem, &remainder); renderer->last_breakable = 0; renderer->begin_line = false; renderer->begin_content = false; } i += len; } } // Assumes no newlines, assumes ascii content: void cmark_render_ascii(cmark_renderer *renderer, const char *s) { int origsize = renderer->buffer->size; cmark_strbuf_puts(renderer->buffer, s); renderer->column += renderer->buffer->size - origsize; } void cmark_render_code_point(cmark_renderer *renderer, uint32_t c) { cmark_utf8proc_encode_char(c, renderer->buffer); renderer->column += 1; } char *cmark_render(cmark_node *root, int options, int width, void (*outc)(cmark_renderer *, cmark_escaping, int32_t, unsigned char), int (*render_node)(cmark_renderer *renderer, cmark_node *node, cmark_event_type ev_type, int options)) { cmark_mem *mem = cmark_node_mem(root); cmark_strbuf pref = CMARK_BUF_INIT(mem); cmark_strbuf buf = CMARK_BUF_INIT(mem); cmark_node *cur; cmark_event_type ev_type; char *result; cmark_iter *iter = cmark_iter_new(root); cmark_renderer renderer = {mem, &buf, &pref, 0, width, 0, 0, true, true, false, false, outc, S_cr, S_blankline, S_out}; while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { cur = cmark_iter_get_node(iter); if (!render_node(&renderer, cur, ev_type, options)) { // a false value causes us to skip processing // the node's contents. this is used for // autolinks. cmark_iter_reset(iter, cur, CMARK_EVENT_EXIT); } } // ensure final newline if (renderer.buffer->size == 0 || renderer.buffer->ptr[renderer.buffer->size - 1] != '\n') { cmark_strbuf_putc(renderer.buffer, '\n'); } result = (char *)cmark_strbuf_detach(renderer.buffer); cmark_iter_free(iter); cmark_strbuf_free(renderer.prefix); cmark_strbuf_free(renderer.buffer); return result; } ================================================ FILE: liteidex/src/3rdparty/cmark/src/render.h ================================================ #ifndef CMARK_RENDER_H #define CMARK_RENDER_H #ifdef __cplusplus extern "C" { #endif #include #include "buffer.h" #include "chunk.h" typedef enum { LITERAL, NORMAL, TITLE, URL } cmark_escaping; struct cmark_renderer { cmark_mem *mem; cmark_strbuf *buffer; cmark_strbuf *prefix; int column; int width; int need_cr; bufsize_t last_breakable; bool begin_line; bool begin_content; bool no_linebreaks; bool in_tight_list_item; void (*outc)(struct cmark_renderer *, cmark_escaping, int32_t, unsigned char); void (*cr)(struct cmark_renderer *); void (*blankline)(struct cmark_renderer *); void (*out)(struct cmark_renderer *, const char *, bool, cmark_escaping); }; typedef struct cmark_renderer cmark_renderer; void cmark_render_ascii(cmark_renderer *renderer, const char *s); void cmark_render_code_point(cmark_renderer *renderer, uint32_t c); char *cmark_render(cmark_node *root, int options, int width, void (*outc)(cmark_renderer *, cmark_escaping, int32_t, unsigned char), int (*render_node)(cmark_renderer *renderer, cmark_node *node, cmark_event_type ev_type, int options)); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/scanners.c ================================================ /* Generated by re2c 0.16 */ #include #include "chunk.h" #include "scanners.h" bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c, bufsize_t offset) { bufsize_t res; unsigned char *ptr = (unsigned char *)c->data; if (ptr == NULL || offset > c->len) { return 0; } else { unsigned char lim = ptr[c->len]; ptr[c->len] = '\0'; res = scanner(ptr + offset); ptr[c->len] = lim; } return res; } // Try to match a scheme including colon. bufsize_t _scan_scheme(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; yych = *p; if (yych <= '@') goto yy2; if (yych <= 'Z') goto yy4; if (yych <= '`') goto yy2; if (yych <= 'z') goto yy4; yy2: ++p; yy3 : { return 0; } yy4: yych = *(marker = ++p); if (yych <= '/') { if (yych <= '+') { if (yych <= '*') goto yy3; } else { if (yych <= ',') goto yy3; if (yych >= '/') goto yy3; } } else { if (yych <= 'Z') { if (yych <= '9') goto yy5; if (yych <= '@') goto yy3; } else { if (yych <= '`') goto yy3; if (yych >= '{') goto yy3; } } yy5: yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych == '+') goto yy7; } else { if (yych != '/') goto yy7; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych >= 'A') goto yy7; } else { if (yych <= '`') goto yy6; if (yych <= 'z') goto yy7; } } yy6: p = marker; goto yy3; yy7: yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych == '+') goto yy10; goto yy6; } else { if (yych == '/') goto yy6; goto yy10; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; goto yy10; } else { if (yych <= '`') goto yy6; if (yych <= 'z') goto yy10; goto yy6; } } yy8: ++p; { return (bufsize_t)(p - start); } yy10: yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy6; } else { if (yych == '/') goto yy6; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy8; if (yych <= '@') goto yy6; } else { if (yych <= '`') goto yy6; if (yych >= '{') goto yy6; } } ++p; if ((yych = *p) == ':') goto yy8; goto yy6; } } // Try to match URI autolink after first <, returning number of chars matched. bufsize_t _scan_autolink_uri(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= '@') goto yy41; if (yych <= 'Z') goto yy43; if (yych <= '`') goto yy41; if (yych <= 'z') goto yy43; yy41: ++p; yy42 : { return 0; } yy43: yych = *(marker = ++p); if (yych <= '/') { if (yych <= '+') { if (yych <= '*') goto yy42; } else { if (yych <= ',') goto yy42; if (yych >= '/') goto yy42; } } else { if (yych <= 'Z') { if (yych <= '9') goto yy44; if (yych <= '@') goto yy42; } else { if (yych <= '`') goto yy42; if (yych >= '{') goto yy42; } } yy44: yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych == '+') goto yy46; } else { if (yych != '/') goto yy46; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych >= 'A') goto yy46; } else { if (yych <= '`') goto yy45; if (yych <= 'z') goto yy46; } } yy45: p = marker; goto yy42; yy46: yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych == '+') goto yy49; goto yy45; } else { if (yych == '/') goto yy45; goto yy49; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; goto yy49; } else { if (yych <= '`') goto yy45; if (yych <= 'z') goto yy49; goto yy45; } } yy47: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy47; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '<') goto yy45; if (yych <= '>') goto yy50; goto yy45; } else { if (yych <= 0xDF) goto yy52; if (yych <= 0xE0) goto yy53; goto yy54; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy55; if (yych <= 0xEF) goto yy54; goto yy56; } else { if (yych <= 0xF3) goto yy57; if (yych <= 0xF4) goto yy58; goto yy45; } } yy49: yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych == '+') goto yy59; goto yy45; } else { if (yych == '/') goto yy45; goto yy59; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; goto yy59; } else { if (yych <= '`') goto yy45; if (yych <= 'z') goto yy59; goto yy45; } } yy50: ++p; { return (bufsize_t)(p - start); } yy52: ++p; yych = *p; if (yych <= 0x7F) goto yy45; if (yych <= 0xBF) goto yy47; goto yy45; yy53: ++p; yych = *p; if (yych <= 0x9F) goto yy45; if (yych <= 0xBF) goto yy52; goto yy45; yy54: ++p; yych = *p; if (yych <= 0x7F) goto yy45; if (yych <= 0xBF) goto yy52; goto yy45; yy55: ++p; yych = *p; if (yych <= 0x7F) goto yy45; if (yych <= 0x9F) goto yy52; goto yy45; yy56: ++p; yych = *p; if (yych <= 0x8F) goto yy45; if (yych <= 0xBF) goto yy54; goto yy45; yy57: ++p; yych = *p; if (yych <= 0x7F) goto yy45; if (yych <= 0xBF) goto yy54; goto yy45; yy58: ++p; yych = *p; if (yych <= 0x7F) goto yy45; if (yych <= 0x8F) goto yy54; goto yy45; yy59: yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } yych = *++p; if (yych <= '9') { if (yych <= ',') { if (yych != '+') goto yy45; } else { if (yych == '/') goto yy45; } } else { if (yych <= 'Z') { if (yych <= ':') goto yy47; if (yych <= '@') goto yy45; } else { if (yych <= '`') goto yy45; if (yych >= '{') goto yy45; } } ++p; if ((yych = *p) == ':') goto yy47; goto yy45; } } // Try to match email autolink after first <, returning num of chars matched. bufsize_t _scan_autolink_email(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 128, 128, 128, 128, 0, 0, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 128, 0, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= '9') { if (yych <= '\'') { if (yych == '!') goto yy91; if (yych >= '#') goto yy91; } else { if (yych <= ')') goto yy89; if (yych != ',') goto yy91; } } else { if (yych <= '?') { if (yych == '=') goto yy91; if (yych >= '?') goto yy91; } else { if (yych <= 'Z') { if (yych >= 'A') goto yy91; } else { if (yych <= ']') goto yy89; if (yych <= '~') goto yy91; } } } yy89: ++p; yy90 : { return 0; } yy91: yych = *(marker = ++p); if (yych <= ',') { if (yych <= '"') { if (yych == '!') goto yy93; goto yy90; } else { if (yych <= '\'') goto yy93; if (yych <= ')') goto yy90; if (yych <= '+') goto yy93; goto yy90; } } else { if (yych <= '>') { if (yych <= '9') goto yy93; if (yych == '=') goto yy93; goto yy90; } else { if (yych <= 'Z') goto yy93; if (yych <= ']') goto yy90; if (yych <= '~') goto yy93; goto yy90; } } yy92: ++p; yych = *p; yy93: if (yybm[0 + yych] & 128) { goto yy92; } if (yych <= '>') goto yy94; if (yych <= '@') goto yy95; yy94: p = marker; goto yy90; yy95: ++p; yych = *p; if (yych <= '@') { if (yych <= '/') goto yy94; if (yych >= ':') goto yy94; } else { if (yych <= 'Z') goto yy96; if (yych <= '`') goto yy94; if (yych >= '{') goto yy94; } yy96: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy98; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy98; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy98; goto yy94; } } ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy101; if (yych <= '/') goto yy94; goto yy102; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy102; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy102; goto yy94; } } yy98: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych <= '-') goto yy101; goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy102; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy102; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy102; goto yy94; } } yy99: ++p; { return (bufsize_t)(p - start); } yy101: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy103; if (yych <= '/') goto yy94; goto yy104; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy104; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy104; goto yy94; } } yy102: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy104; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy104; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy104; goto yy94; } } yy103: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy105; if (yych <= '/') goto yy94; goto yy106; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy106; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy106; goto yy94; } } yy104: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy106; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy106; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy106; goto yy94; } } yy105: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy107; if (yych <= '/') goto yy94; goto yy108; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy108; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy108; goto yy94; } } yy106: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy108; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy108; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy108; goto yy94; } } yy107: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy109; if (yych <= '/') goto yy94; goto yy110; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy110; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy110; goto yy94; } } yy108: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy110; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy110; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy110; goto yy94; } } yy109: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy111; if (yych <= '/') goto yy94; goto yy112; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy112; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy112; goto yy94; } } yy110: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy112; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy112; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy112; goto yy94; } } yy111: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy113; if (yych <= '/') goto yy94; goto yy114; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy114; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy114; goto yy94; } } yy112: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy114; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy114; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy114; goto yy94; } } yy113: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy115; if (yych <= '/') goto yy94; goto yy116; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy116; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy116; goto yy94; } } yy114: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy116; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy116; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy116; goto yy94; } } yy115: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy117; if (yych <= '/') goto yy94; goto yy118; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy118; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy118; goto yy94; } } yy116: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy118; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy118; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy118; goto yy94; } } yy117: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy119; if (yych <= '/') goto yy94; goto yy120; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy120; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy120; goto yy94; } } yy118: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy120; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy120; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy120; goto yy94; } } yy119: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy121; if (yych <= '/') goto yy94; goto yy122; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy122; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy122; goto yy94; } } yy120: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy122; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy122; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy122; goto yy94; } } yy121: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy123; if (yych <= '/') goto yy94; goto yy124; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy124; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy124; goto yy94; } } yy122: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy124; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy124; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy124; goto yy94; } } yy123: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy125; if (yych <= '/') goto yy94; goto yy126; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy126; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy126; goto yy94; } } yy124: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy126; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy126; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy126; goto yy94; } } yy125: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy127; if (yych <= '/') goto yy94; goto yy128; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy128; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy128; goto yy94; } } yy126: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy128; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy128; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy128; goto yy94; } } yy127: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy129; if (yych <= '/') goto yy94; goto yy130; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy130; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy130; goto yy94; } } yy128: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy130; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy130; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy130; goto yy94; } } yy129: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy131; if (yych <= '/') goto yy94; goto yy132; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy132; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy132; goto yy94; } } yy130: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy132; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy132; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy132; goto yy94; } } yy131: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy133; if (yych <= '/') goto yy94; goto yy134; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy134; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy134; goto yy94; } } yy132: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy134; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy134; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy134; goto yy94; } } yy133: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy135; if (yych <= '/') goto yy94; goto yy136; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy136; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy136; goto yy94; } } yy134: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy136; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy136; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy136; goto yy94; } } yy135: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy137; if (yych <= '/') goto yy94; goto yy138; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy138; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy138; goto yy94; } } yy136: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy138; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy138; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy138; goto yy94; } } yy137: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy139; if (yych <= '/') goto yy94; goto yy140; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy140; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy140; goto yy94; } } yy138: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy140; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy140; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy140; goto yy94; } } yy139: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy141; if (yych <= '/') goto yy94; goto yy142; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy142; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy142; goto yy94; } } yy140: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy142; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy142; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy142; goto yy94; } } yy141: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy143; if (yych <= '/') goto yy94; goto yy144; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy144; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy144; goto yy94; } } yy142: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy144; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy144; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy144; goto yy94; } } yy143: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy145; if (yych <= '/') goto yy94; goto yy146; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy146; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy146; goto yy94; } } yy144: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy146; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy146; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy146; goto yy94; } } yy145: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy147; if (yych <= '/') goto yy94; goto yy148; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy148; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy148; goto yy94; } } yy146: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy148; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy148; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy148; goto yy94; } } yy147: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy149; if (yych <= '/') goto yy94; goto yy150; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy150; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy150; goto yy94; } } yy148: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy150; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy150; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy150; goto yy94; } } yy149: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy151; if (yych <= '/') goto yy94; goto yy152; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy152; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy152; goto yy94; } } yy150: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy152; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy152; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy152; goto yy94; } } yy151: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy153; if (yych <= '/') goto yy94; goto yy154; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy154; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy154; goto yy94; } } yy152: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy154; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy154; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy154; goto yy94; } } yy153: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy155; if (yych <= '/') goto yy94; goto yy156; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy156; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy156; goto yy94; } } yy154: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy156; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy156; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy156; goto yy94; } } yy155: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy157; if (yych <= '/') goto yy94; goto yy158; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy158; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy158; goto yy94; } } yy156: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy158; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy158; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy158; goto yy94; } } yy157: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy159; if (yych <= '/') goto yy94; goto yy160; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy160; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy160; goto yy94; } } yy158: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy160; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy160; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy160; goto yy94; } } yy159: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy161; if (yych <= '/') goto yy94; goto yy162; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy162; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy162; goto yy94; } } yy160: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy162; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy162; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy162; goto yy94; } } yy161: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy163; if (yych <= '/') goto yy94; goto yy164; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy164; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy164; goto yy94; } } yy162: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy164; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy164; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy164; goto yy94; } } yy163: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy165; if (yych <= '/') goto yy94; goto yy166; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy166; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy166; goto yy94; } } yy164: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy166; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy166; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy166; goto yy94; } } yy165: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy167; if (yych <= '/') goto yy94; goto yy168; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy168; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy168; goto yy94; } } yy166: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy168; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy168; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy168; goto yy94; } } yy167: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy169; if (yych <= '/') goto yy94; goto yy170; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy170; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy170; goto yy94; } } yy168: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy170; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy170; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy170; goto yy94; } } yy169: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy171; if (yych <= '/') goto yy94; goto yy172; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy172; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy172; goto yy94; } } yy170: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy172; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy172; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy172; goto yy94; } } yy171: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy173; if (yych <= '/') goto yy94; goto yy174; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy174; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy174; goto yy94; } } yy172: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy174; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy174; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy174; goto yy94; } } yy173: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy175; if (yych <= '/') goto yy94; goto yy176; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy176; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy176; goto yy94; } } yy174: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy176; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy176; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy176; goto yy94; } } yy175: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy177; if (yych <= '/') goto yy94; goto yy178; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy178; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy178; goto yy94; } } yy176: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy178; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy178; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy178; goto yy94; } } yy177: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy179; if (yych <= '/') goto yy94; goto yy180; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy180; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy180; goto yy94; } } yy178: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy180; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy180; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy180; goto yy94; } } yy179: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy181; if (yych <= '/') goto yy94; goto yy182; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy182; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy182; goto yy94; } } yy180: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy182; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy182; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy182; goto yy94; } } yy181: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy183; if (yych <= '/') goto yy94; goto yy184; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy184; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy184; goto yy94; } } yy182: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy184; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy184; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy184; goto yy94; } } yy183: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy185; if (yych <= '/') goto yy94; goto yy186; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy186; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy186; goto yy94; } } yy184: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy186; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy186; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy186; goto yy94; } } yy185: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy187; if (yych <= '/') goto yy94; goto yy188; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy188; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy188; goto yy94; } } yy186: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy188; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy188; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy188; goto yy94; } } yy187: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy189; if (yych <= '/') goto yy94; goto yy190; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy190; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy190; goto yy94; } } yy188: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy190; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy190; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy190; goto yy94; } } yy189: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy191; if (yych <= '/') goto yy94; goto yy192; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy192; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy192; goto yy94; } } yy190: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy192; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy192; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy192; goto yy94; } } yy191: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy193; if (yych <= '/') goto yy94; goto yy194; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy194; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy194; goto yy94; } } yy192: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy194; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy194; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy194; goto yy94; } } yy193: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy195; if (yych <= '/') goto yy94; goto yy196; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy196; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy196; goto yy94; } } yy194: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy196; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy196; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy196; goto yy94; } } yy195: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy197; if (yych <= '/') goto yy94; goto yy198; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy198; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy198; goto yy94; } } yy196: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy198; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy198; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy198; goto yy94; } } yy197: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy199; if (yych <= '/') goto yy94; goto yy200; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy200; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy200; goto yy94; } } yy198: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy200; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy200; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy200; goto yy94; } } yy199: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy201; if (yych <= '/') goto yy94; goto yy202; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy202; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy202; goto yy94; } } yy200: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy202; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy202; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy202; goto yy94; } } yy201: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy203; if (yych <= '/') goto yy94; goto yy204; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy204; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy204; goto yy94; } } yy202: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy204; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy204; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy204; goto yy94; } } yy203: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy205; if (yych <= '/') goto yy94; goto yy206; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy206; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy206; goto yy94; } } yy204: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy206; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy206; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy206; goto yy94; } } yy205: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy207; if (yych <= '/') goto yy94; goto yy208; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy208; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy208; goto yy94; } } yy206: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy208; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy208; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy208; goto yy94; } } yy207: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy209; if (yych <= '/') goto yy94; goto yy210; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy210; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy210; goto yy94; } } yy208: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy210; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy210; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy210; goto yy94; } } yy209: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy211; if (yych <= '/') goto yy94; goto yy212; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy212; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy212; goto yy94; } } yy210: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy212; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy212; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy212; goto yy94; } } yy211: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy213; if (yych <= '/') goto yy94; goto yy214; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy214; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy214; goto yy94; } } yy212: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy214; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy214; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy214; goto yy94; } } yy213: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy215; if (yych <= '/') goto yy94; goto yy216; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy216; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy216; goto yy94; } } yy214: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy216; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy216; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy216; goto yy94; } } yy215: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy217; if (yych <= '/') goto yy94; goto yy218; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy218; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy218; goto yy94; } } yy216: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy218; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy218; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy218; goto yy94; } } yy217: ++p; yych = *p; if (yych <= '9') { if (yych == '-') goto yy219; if (yych <= '/') goto yy94; goto yy220; } else { if (yych <= 'Z') { if (yych <= '@') goto yy94; goto yy220; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy220; goto yy94; } } yy218: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= ',') goto yy94; if (yych >= '.') goto yy95; } else { if (yych <= '/') goto yy94; if (yych <= '9') goto yy220; goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; goto yy220; } else { if (yych <= '`') goto yy94; if (yych <= 'z') goto yy220; goto yy94; } } yy219: ++p; yych = *p; if (yych <= '@') { if (yych <= '/') goto yy94; if (yych <= '9') goto yy221; goto yy94; } else { if (yych <= 'Z') goto yy221; if (yych <= '`') goto yy94; if (yych <= 'z') goto yy221; goto yy94; } yy220: ++p; yych = *p; if (yych <= '=') { if (yych <= '.') { if (yych <= '-') goto yy94; goto yy95; } else { if (yych <= '/') goto yy94; if (yych >= ':') goto yy94; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy99; if (yych <= '@') goto yy94; } else { if (yych <= '`') goto yy94; if (yych >= '{') goto yy94; } } yy221: ++p; yych = *p; if (yych == '.') goto yy95; if (yych == '>') goto yy99; goto yy94; } } // Try to match an HTML tag after first <, returning num of chars matched. bufsize_t _scan_html_tag(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; static const unsigned char yybm[] = { /* table 1 .. 8: 0 */ 0, 250, 250, 250, 250, 250, 250, 250, 250, 235, 235, 235, 235, 235, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 235, 250, 202, 250, 250, 250, 250, 170, 250, 250, 250, 250, 250, 246, 254, 250, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 250, 234, 234, 232, 250, 250, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 250, 250, 122, 250, 254, 234, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 250, 250, 250, 250, 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* table 9 .. 11: 256 */ 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 192, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 128, 0, 128, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 128, 128, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= '>') { if (yych <= '!') { if (yych >= '!') goto yy226; } else { if (yych == '/') goto yy227; } } else { if (yych <= 'Z') { if (yych <= '?') goto yy228; if (yych >= 'A') goto yy229; } else { if (yych <= '`') goto yy224; if (yych <= 'z') goto yy229; } } yy224: ++p; yy225 : { return 0; } yy226: yych = *(marker = ++p); if (yybm[256 + yych] & 32) { goto yy232; } if (yych == '-') goto yy230; if (yych <= '@') goto yy225; if (yych <= '[') goto yy234; goto yy225; yy227: yych = *(marker = ++p); if (yych <= '@') goto yy225; if (yych <= 'Z') goto yy235; if (yych <= '`') goto yy225; if (yych <= 'z') goto yy235; goto yy225; yy228: yych = *(marker = ++p); if (yych <= 0x00) goto yy225; if (yych <= 0x7F) goto yy238; if (yych <= 0xC1) goto yy225; if (yych <= 0xF4) goto yy238; goto yy225; yy229: yych = *(marker = ++p); if (yybm[0 + yych] & 1) { goto yy247; } if (yych <= '=') { if (yych <= '.') { if (yych == '-') goto yy249; goto yy225; } else { if (yych <= '/') goto yy251; if (yych <= '9') goto yy249; goto yy225; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy252; if (yych <= '@') goto yy225; goto yy249; } else { if (yych <= '`') goto yy225; if (yych <= 'z') goto yy249; goto yy225; } } yy230: yych = *++p; if (yych == '-') goto yy254; yy231: p = marker; goto yy225; yy232: ++p; yych = *p; if (yybm[256 + yych] & 32) { goto yy232; } if (yych <= 0x08) goto yy231; if (yych <= '\r') goto yy255; if (yych == ' ') goto yy255; goto yy231; yy234: yych = *++p; if (yych == 'C') goto yy257; if (yych == 'c') goto yy257; goto yy231; yy235: ++p; yych = *p; if (yybm[256 + yych] & 64) { goto yy235; } if (yych <= 0x1F) { if (yych <= 0x08) goto yy231; if (yych <= '\r') goto yy258; goto yy231; } else { if (yych <= ' ') goto yy258; if (yych == '>') goto yy252; goto yy231; } yy237: ++p; yych = *p; yy238: if (yybm[256 + yych] & 128) { goto yy237; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych >= '@') goto yy231; } else { if (yych <= 0xDF) goto yy240; if (yych <= 0xE0) goto yy241; goto yy242; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy243; if (yych <= 0xEF) goto yy242; goto yy244; } else { if (yych <= 0xF3) goto yy245; if (yych <= 0xF4) goto yy246; goto yy231; } } ++p; yych = *p; if (yych <= 0xE0) { if (yych <= '>') { if (yych <= 0x00) goto yy231; if (yych <= '=') goto yy237; goto yy252; } else { if (yych <= 0x7F) goto yy237; if (yych <= 0xC1) goto yy231; if (yych >= 0xE0) goto yy241; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy243; goto yy242; } else { if (yych <= 0xF0) goto yy244; if (yych <= 0xF3) goto yy245; if (yych <= 0xF4) goto yy246; goto yy231; } } yy240: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy237; goto yy231; yy241: ++p; yych = *p; if (yych <= 0x9F) goto yy231; if (yych <= 0xBF) goto yy240; goto yy231; yy242: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy240; goto yy231; yy243: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x9F) goto yy240; goto yy231; yy244: ++p; yych = *p; if (yych <= 0x8F) goto yy231; if (yych <= 0xBF) goto yy242; goto yy231; yy245: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy242; goto yy231; yy246: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x8F) goto yy242; goto yy231; yy247: ++p; yych = *p; if (yybm[0 + yych] & 1) { goto yy247; } if (yych <= '>') { if (yych <= '9') { if (yych == '/') goto yy251; goto yy231; } else { if (yych <= ':') goto yy260; if (yych <= '=') goto yy231; goto yy252; } } else { if (yych <= '^') { if (yych <= '@') goto yy231; if (yych <= 'Z') goto yy260; goto yy231; } else { if (yych == '`') goto yy231; if (yych <= 'z') goto yy260; goto yy231; } } yy249: ++p; yych = *p; if (yybm[0 + yych] & 1) { goto yy247; } if (yych <= '=') { if (yych <= '.') { if (yych == '-') goto yy249; goto yy231; } else { if (yych <= '/') goto yy251; if (yych <= '9') goto yy249; goto yy231; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy252; if (yych <= '@') goto yy231; goto yy249; } else { if (yych <= '`') goto yy231; if (yych <= 'z') goto yy249; goto yy231; } } yy251: yych = *++p; if (yych != '>') goto yy231; yy252: ++p; { return (bufsize_t)(p - start); } yy254: yych = *++p; if (yych == '-') goto yy264; if (yych == '>') goto yy231; goto yy263; yy255: ++p; yych = *p; if (yybm[0 + yych] & 2) { goto yy255; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych <= '>') goto yy252; goto yy231; } else { if (yych <= 0xDF) goto yy272; if (yych <= 0xE0) goto yy273; goto yy274; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy275; if (yych <= 0xEF) goto yy274; goto yy276; } else { if (yych <= 0xF3) goto yy277; if (yych <= 0xF4) goto yy278; goto yy231; } } yy257: yych = *++p; if (yych == 'D') goto yy279; if (yych == 'd') goto yy279; goto yy231; yy258: ++p; yych = *p; if (yych <= 0x1F) { if (yych <= 0x08) goto yy231; if (yych <= '\r') goto yy258; goto yy231; } else { if (yych <= ' ') goto yy258; if (yych == '>') goto yy252; goto yy231; } yy260: ++p; yych = *p; if (yybm[0 + yych] & 4) { goto yy260; } if (yych <= ',') { if (yych <= '\r') { if (yych <= 0x08) goto yy231; goto yy280; } else { if (yych == ' ') goto yy280; goto yy231; } } else { if (yych <= '<') { if (yych <= '/') goto yy251; goto yy231; } else { if (yych <= '=') goto yy282; if (yych <= '>') goto yy252; goto yy231; } } yy262: ++p; yych = *p; yy263: if (yybm[0 + yych] & 8) { goto yy262; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych <= '-') goto yy284; goto yy231; } else { if (yych <= 0xDF) goto yy265; if (yych <= 0xE0) goto yy266; goto yy267; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy268; if (yych <= 0xEF) goto yy267; goto yy269; } else { if (yych <= 0xF3) goto yy270; if (yych <= 0xF4) goto yy271; goto yy231; } } yy264: yych = *++p; if (yych == '-') goto yy251; if (yych == '>') goto yy231; goto yy263; yy265: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy262; goto yy231; yy266: ++p; yych = *p; if (yych <= 0x9F) goto yy231; if (yych <= 0xBF) goto yy265; goto yy231; yy267: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy265; goto yy231; yy268: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x9F) goto yy265; goto yy231; yy269: ++p; yych = *p; if (yych <= 0x8F) goto yy231; if (yych <= 0xBF) goto yy267; goto yy231; yy270: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy267; goto yy231; yy271: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x8F) goto yy267; goto yy231; yy272: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy255; goto yy231; yy273: ++p; yych = *p; if (yych <= 0x9F) goto yy231; if (yych <= 0xBF) goto yy272; goto yy231; yy274: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy272; goto yy231; yy275: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x9F) goto yy272; goto yy231; yy276: ++p; yych = *p; if (yych <= 0x8F) goto yy231; if (yych <= 0xBF) goto yy274; goto yy231; yy277: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy274; goto yy231; yy278: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x8F) goto yy274; goto yy231; yy279: yych = *++p; if (yych == 'A') goto yy285; if (yych == 'a') goto yy285; goto yy231; yy280: ++p; yych = *p; if (yych <= '<') { if (yych <= ' ') { if (yych <= 0x08) goto yy231; if (yych <= '\r') goto yy280; if (yych <= 0x1F) goto yy231; goto yy280; } else { if (yych <= '/') { if (yych <= '.') goto yy231; goto yy251; } else { if (yych == ':') goto yy260; goto yy231; } } } else { if (yych <= 'Z') { if (yych <= '=') goto yy282; if (yych <= '>') goto yy252; if (yych <= '@') goto yy231; goto yy260; } else { if (yych <= '_') { if (yych <= '^') goto yy231; goto yy260; } else { if (yych <= '`') goto yy231; if (yych <= 'z') goto yy260; goto yy231; } } } yy282: ++p; yych = *p; if (yybm[0 + yych] & 16) { goto yy286; } if (yych <= 0xE0) { if (yych <= '"') { if (yych <= 0x00) goto yy231; if (yych <= ' ') goto yy282; goto yy288; } else { if (yych <= '\'') goto yy290; if (yych <= 0xC1) goto yy231; if (yych <= 0xDF) goto yy292; goto yy293; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy295; goto yy294; } else { if (yych <= 0xF0) goto yy296; if (yych <= 0xF3) goto yy297; if (yych <= 0xF4) goto yy298; goto yy231; } } yy284: ++p; yych = *p; if (yybm[0 + yych] & 8) { goto yy262; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych <= '-') goto yy251; goto yy231; } else { if (yych <= 0xDF) goto yy265; if (yych <= 0xE0) goto yy266; goto yy267; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy268; if (yych <= 0xEF) goto yy267; goto yy269; } else { if (yych <= 0xF3) goto yy270; if (yych <= 0xF4) goto yy271; goto yy231; } } yy285: yych = *++p; if (yych == 'T') goto yy299; if (yych == 't') goto yy299; goto yy231; yy286: ++p; yych = *p; if (yybm[0 + yych] & 16) { goto yy286; } if (yych <= 0xE0) { if (yych <= '=') { if (yych <= 0x00) goto yy231; if (yych <= ' ') goto yy247; goto yy231; } else { if (yych <= '>') goto yy252; if (yych <= 0xC1) goto yy231; if (yych <= 0xDF) goto yy292; goto yy293; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy295; goto yy294; } else { if (yych <= 0xF0) goto yy296; if (yych <= 0xF3) goto yy297; if (yych <= 0xF4) goto yy298; goto yy231; } } yy288: ++p; yych = *p; if (yybm[0 + yych] & 32) { goto yy288; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych <= '"') goto yy300; goto yy231; } else { if (yych <= 0xDF) goto yy301; if (yych <= 0xE0) goto yy302; goto yy303; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy304; if (yych <= 0xEF) goto yy303; goto yy305; } else { if (yych <= 0xF3) goto yy306; if (yych <= 0xF4) goto yy307; goto yy231; } } yy290: ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy290; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych <= '\'') goto yy300; goto yy231; } else { if (yych <= 0xDF) goto yy308; if (yych <= 0xE0) goto yy309; goto yy310; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy311; if (yych <= 0xEF) goto yy310; goto yy312; } else { if (yych <= 0xF3) goto yy313; if (yych <= 0xF4) goto yy314; goto yy231; } } yy292: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy286; goto yy231; yy293: ++p; yych = *p; if (yych <= 0x9F) goto yy231; if (yych <= 0xBF) goto yy292; goto yy231; yy294: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy292; goto yy231; yy295: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x9F) goto yy292; goto yy231; yy296: ++p; yych = *p; if (yych <= 0x8F) goto yy231; if (yych <= 0xBF) goto yy294; goto yy231; yy297: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy294; goto yy231; yy298: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x8F) goto yy294; goto yy231; yy299: yych = *++p; if (yych == 'A') goto yy315; if (yych == 'a') goto yy315; goto yy231; yy300: ++p; yych = *p; if (yybm[0 + yych] & 1) { goto yy247; } if (yych == '/') goto yy251; if (yych == '>') goto yy252; goto yy231; yy301: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy288; goto yy231; yy302: ++p; yych = *p; if (yych <= 0x9F) goto yy231; if (yych <= 0xBF) goto yy301; goto yy231; yy303: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy301; goto yy231; yy304: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x9F) goto yy301; goto yy231; yy305: ++p; yych = *p; if (yych <= 0x8F) goto yy231; if (yych <= 0xBF) goto yy303; goto yy231; yy306: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy303; goto yy231; yy307: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x8F) goto yy303; goto yy231; yy308: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy290; goto yy231; yy309: ++p; yych = *p; if (yych <= 0x9F) goto yy231; if (yych <= 0xBF) goto yy308; goto yy231; yy310: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy308; goto yy231; yy311: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x9F) goto yy308; goto yy231; yy312: ++p; yych = *p; if (yych <= 0x8F) goto yy231; if (yych <= 0xBF) goto yy310; goto yy231; yy313: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy310; goto yy231; yy314: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x8F) goto yy310; goto yy231; yy315: yych = *++p; if (yych != '[') goto yy231; yy316: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy316; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych >= '^') goto yy231; } else { if (yych <= 0xDF) goto yy319; if (yych <= 0xE0) goto yy320; goto yy321; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy322; if (yych <= 0xEF) goto yy321; goto yy323; } else { if (yych <= 0xF3) goto yy324; if (yych <= 0xF4) goto yy325; goto yy231; } } ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy316; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy231; if (yych <= ']') goto yy326; goto yy231; } else { if (yych <= 0xDF) goto yy319; if (yych <= 0xE0) goto yy320; goto yy321; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy322; if (yych <= 0xEF) goto yy321; goto yy323; } else { if (yych <= 0xF3) goto yy324; if (yych <= 0xF4) goto yy325; goto yy231; } } yy319: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy316; goto yy231; yy320: ++p; yych = *p; if (yych <= 0x9F) goto yy231; if (yych <= 0xBF) goto yy319; goto yy231; yy321: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy319; goto yy231; yy322: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x9F) goto yy319; goto yy231; yy323: ++p; yych = *p; if (yych <= 0x8F) goto yy231; if (yych <= 0xBF) goto yy321; goto yy231; yy324: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0xBF) goto yy321; goto yy231; yy325: ++p; yych = *p; if (yych <= 0x7F) goto yy231; if (yych <= 0x8F) goto yy321; goto yy231; yy326: ++p; yych = *p; if (yych <= 0xE0) { if (yych <= '>') { if (yych <= 0x00) goto yy231; if (yych <= '=') goto yy316; goto yy252; } else { if (yych <= 0x7F) goto yy316; if (yych <= 0xC1) goto yy231; if (yych <= 0xDF) goto yy319; goto yy320; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy322; goto yy321; } else { if (yych <= 0xF0) goto yy323; if (yych <= 0xF3) goto yy324; if (yych <= 0xF4) goto yy325; goto yy231; } } } } // Try to match an HTML block tag start line, returning // an integer code for the type of block (1-6, matching the spec). // #7 is handled by a separate function, below. bufsize_t _scan_html_block_start(const unsigned char *p) { const unsigned char *marker = NULL; { unsigned char yych; yych = *p; if (yych == '<') goto yy331; ++p; yy330 : { return 0; } yy331: yych = *(marker = ++p); switch (yych) { case '!': goto yy332; case '/': goto yy334; case '?': goto yy335; case 'A': case 'a': goto yy337; case 'B': case 'b': goto yy338; case 'C': case 'c': goto yy339; case 'D': case 'd': goto yy340; case 'F': case 'f': goto yy341; case 'H': case 'h': goto yy342; case 'I': case 'i': goto yy343; case 'L': case 'l': goto yy344; case 'M': case 'm': goto yy345; case 'N': case 'n': goto yy346; case 'O': case 'o': goto yy347; case 'P': case 'p': goto yy348; case 'S': case 's': goto yy349; case 'T': case 't': goto yy350; case 'U': case 'u': goto yy351; default: goto yy330; } yy332: yych = *++p; if (yych <= '@') { if (yych == '-') goto yy352; } else { if (yych <= 'Z') goto yy353; if (yych <= '[') goto yy355; } yy333: p = marker; goto yy330; yy334: yych = *++p; switch (yych) { case 'A': case 'a': goto yy337; case 'B': case 'b': goto yy338; case 'C': case 'c': goto yy339; case 'D': case 'd': goto yy340; case 'F': case 'f': goto yy341; case 'H': case 'h': goto yy342; case 'I': case 'i': goto yy343; case 'L': case 'l': goto yy344; case 'M': case 'm': goto yy345; case 'N': case 'n': goto yy346; case 'O': case 'o': goto yy347; case 'P': case 'p': goto yy356; case 'S': case 's': goto yy357; case 'T': case 't': goto yy350; case 'U': case 'u': goto yy351; default: goto yy333; } yy335: ++p; { return 3; } yy337: yych = *++p; if (yych <= 'S') { if (yych <= 'D') { if (yych <= 'C') goto yy333; goto yy358; } else { if (yych <= 'Q') goto yy333; if (yych <= 'R') goto yy359; goto yy360; } } else { if (yych <= 'q') { if (yych == 'd') goto yy358; goto yy333; } else { if (yych <= 'r') goto yy359; if (yych <= 's') goto yy360; goto yy333; } } yy338: yych = *++p; if (yych <= 'O') { if (yych <= 'K') { if (yych == 'A') goto yy361; goto yy333; } else { if (yych <= 'L') goto yy362; if (yych <= 'N') goto yy333; goto yy363; } } else { if (yych <= 'k') { if (yych == 'a') goto yy361; goto yy333; } else { if (yych <= 'l') goto yy362; if (yych == 'o') goto yy363; goto yy333; } } yy339: yych = *++p; if (yych <= 'O') { if (yych <= 'D') { if (yych == 'A') goto yy364; goto yy333; } else { if (yych <= 'E') goto yy365; if (yych <= 'N') goto yy333; goto yy366; } } else { if (yych <= 'd') { if (yych == 'a') goto yy364; goto yy333; } else { if (yych <= 'e') goto yy365; if (yych == 'o') goto yy366; goto yy333; } } yy340: yych = *++p; switch (yych) { case 'D': case 'L': case 'T': case 'd': case 'l': case 't': goto yy367; case 'E': case 'e': goto yy368; case 'I': case 'i': goto yy369; default: goto yy333; } yy341: yych = *++p; if (yych <= 'R') { if (yych <= 'N') { if (yych == 'I') goto yy370; goto yy333; } else { if (yych <= 'O') goto yy371; if (yych <= 'Q') goto yy333; goto yy372; } } else { if (yych <= 'n') { if (yych == 'i') goto yy370; goto yy333; } else { if (yych <= 'o') goto yy371; if (yych == 'r') goto yy372; goto yy333; } } yy342: yych = *++p; if (yych <= 'S') { if (yych <= 'D') { if (yych <= '0') goto yy333; if (yych <= '6') goto yy367; goto yy333; } else { if (yych <= 'E') goto yy373; if (yych == 'R') goto yy367; goto yy333; } } else { if (yych <= 'q') { if (yych <= 'T') goto yy374; if (yych == 'e') goto yy373; goto yy333; } else { if (yych <= 'r') goto yy367; if (yych == 't') goto yy374; goto yy333; } } yy343: yych = *++p; if (yych == 'F') goto yy375; if (yych == 'f') goto yy375; goto yy333; yy344: yych = *++p; if (yych <= 'I') { if (yych == 'E') goto yy376; if (yych <= 'H') goto yy333; goto yy377; } else { if (yych <= 'e') { if (yych <= 'd') goto yy333; goto yy376; } else { if (yych == 'i') goto yy377; goto yy333; } } yy345: yych = *++p; if (yych <= 'E') { if (yych == 'A') goto yy378; if (yych <= 'D') goto yy333; goto yy379; } else { if (yych <= 'a') { if (yych <= '`') goto yy333; goto yy378; } else { if (yych == 'e') goto yy379; goto yy333; } } yy346: yych = *++p; if (yych <= 'O') { if (yych == 'A') goto yy380; if (yych <= 'N') goto yy333; goto yy381; } else { if (yych <= 'a') { if (yych <= '`') goto yy333; goto yy380; } else { if (yych == 'o') goto yy381; goto yy333; } } yy347: yych = *++p; if (yych <= 'P') { if (yych == 'L') goto yy367; if (yych <= 'O') goto yy333; goto yy382; } else { if (yych <= 'l') { if (yych <= 'k') goto yy333; goto yy367; } else { if (yych == 'p') goto yy382; goto yy333; } } yy348: yych = *++p; if (yych <= '>') { if (yych <= ' ') { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; if (yych <= 0x1F) goto yy333; goto yy383; } else { if (yych == '/') goto yy385; if (yych <= '=') goto yy333; goto yy383; } } else { if (yych <= 'R') { if (yych == 'A') goto yy386; if (yych <= 'Q') goto yy333; goto yy387; } else { if (yych <= 'a') { if (yych <= '`') goto yy333; goto yy386; } else { if (yych == 'r') goto yy387; goto yy333; } } } yy349: yych = *++p; switch (yych) { case 'C': case 'c': goto yy388; case 'E': case 'e': goto yy389; case 'O': case 'o': goto yy390; case 'T': case 't': goto yy391; case 'U': case 'u': goto yy392; default: goto yy333; } yy350: yych = *++p; switch (yych) { case 'A': case 'a': goto yy393; case 'B': case 'b': goto yy394; case 'D': case 'd': goto yy367; case 'F': case 'f': goto yy395; case 'H': case 'h': goto yy396; case 'I': case 'i': goto yy397; case 'R': case 'r': goto yy398; default: goto yy333; } yy351: yych = *++p; if (yych == 'L') goto yy367; if (yych == 'l') goto yy367; goto yy333; yy352: yych = *++p; if (yych == '-') goto yy399; goto yy333; yy353: ++p; { return 4; } yy355: yych = *++p; if (yych == 'C') goto yy401; if (yych == 'c') goto yy401; goto yy333; yy356: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= '@') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'A') goto yy386; if (yych == 'a') goto yy386; goto yy333; } } yy357: yych = *++p; if (yych <= 'U') { if (yych <= 'N') { if (yych == 'E') goto yy389; goto yy333; } else { if (yych <= 'O') goto yy390; if (yych <= 'T') goto yy333; goto yy392; } } else { if (yych <= 'n') { if (yych == 'e') goto yy389; goto yy333; } else { if (yych <= 'o') goto yy390; if (yych == 'u') goto yy392; goto yy333; } } yy358: yych = *++p; if (yych == 'D') goto yy402; if (yych == 'd') goto yy402; goto yy333; yy359: yych = *++p; if (yych == 'T') goto yy403; if (yych == 't') goto yy403; goto yy333; yy360: yych = *++p; if (yych == 'I') goto yy404; if (yych == 'i') goto yy404; goto yy333; yy361: yych = *++p; if (yych == 'S') goto yy405; if (yych == 's') goto yy405; goto yy333; yy362: yych = *++p; if (yych == 'O') goto yy406; if (yych == 'o') goto yy406; goto yy333; yy363: yych = *++p; if (yych == 'D') goto yy407; if (yych == 'd') goto yy407; goto yy333; yy364: yych = *++p; if (yych == 'P') goto yy408; if (yych == 'p') goto yy408; goto yy333; yy365: yych = *++p; if (yych == 'N') goto yy409; if (yych == 'n') goto yy409; goto yy333; yy366: yych = *++p; if (yych == 'L') goto yy410; if (yych == 'l') goto yy410; goto yy333; yy367: yych = *++p; if (yych <= ' ') { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; if (yych <= 0x1F) goto yy333; goto yy383; } else { if (yych <= '/') { if (yych <= '.') goto yy333; goto yy385; } else { if (yych == '>') goto yy383; goto yy333; } } yy368: yych = *++p; if (yych == 'T') goto yy411; if (yych == 't') goto yy411; goto yy333; yy369: yych = *++p; if (yych <= 'V') { if (yych <= 'Q') { if (yych == 'A') goto yy412; goto yy333; } else { if (yych <= 'R') goto yy367; if (yych <= 'U') goto yy333; goto yy367; } } else { if (yych <= 'q') { if (yych == 'a') goto yy412; goto yy333; } else { if (yych <= 'r') goto yy367; if (yych == 'v') goto yy367; goto yy333; } } yy370: yych = *++p; if (yych <= 'G') { if (yych == 'E') goto yy413; if (yych <= 'F') goto yy333; goto yy414; } else { if (yych <= 'e') { if (yych <= 'd') goto yy333; goto yy413; } else { if (yych == 'g') goto yy414; goto yy333; } } yy371: yych = *++p; if (yych <= 'R') { if (yych == 'O') goto yy409; if (yych <= 'Q') goto yy333; goto yy415; } else { if (yych <= 'o') { if (yych <= 'n') goto yy333; goto yy409; } else { if (yych == 'r') goto yy415; goto yy333; } } yy372: yych = *++p; if (yych == 'A') goto yy416; if (yych == 'a') goto yy416; goto yy333; yy373: yych = *++p; if (yych == 'A') goto yy417; if (yych == 'a') goto yy417; goto yy333; yy374: yych = *++p; if (yych == 'M') goto yy351; if (yych == 'm') goto yy351; goto yy333; yy375: yych = *++p; if (yych == 'R') goto yy418; if (yych == 'r') goto yy418; goto yy333; yy376: yych = *++p; if (yych == 'G') goto yy419; if (yych == 'g') goto yy419; goto yy333; yy377: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= 'M') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'N') goto yy420; if (yych == 'n') goto yy420; goto yy333; } } yy378: yych = *++p; if (yych == 'I') goto yy421; if (yych == 'i') goto yy421; goto yy333; yy379: yych = *++p; if (yych == 'N') goto yy422; if (yych == 'n') goto yy422; goto yy333; yy380: yych = *++p; if (yych == 'V') goto yy367; if (yych == 'v') goto yy367; goto yy333; yy381: yych = *++p; if (yych == 'F') goto yy423; if (yych == 'f') goto yy423; goto yy333; yy382: yych = *++p; if (yych == 'T') goto yy424; if (yych == 't') goto yy424; goto yy333; yy383: ++p; { return 6; } yy385: yych = *++p; if (yych == '>') goto yy383; goto yy333; yy386: yych = *++p; if (yych == 'R') goto yy425; if (yych == 'r') goto yy425; goto yy333; yy387: yych = *++p; if (yych == 'E') goto yy426; if (yych == 'e') goto yy426; goto yy333; yy388: yych = *++p; if (yych == 'R') goto yy427; if (yych == 'r') goto yy427; goto yy333; yy389: yych = *++p; if (yych == 'C') goto yy408; if (yych == 'c') goto yy408; goto yy333; yy390: yych = *++p; if (yych == 'U') goto yy428; if (yych == 'u') goto yy428; goto yy333; yy391: yych = *++p; if (yych == 'Y') goto yy429; if (yych == 'y') goto yy429; goto yy333; yy392: yych = *++p; if (yych == 'M') goto yy430; if (yych == 'm') goto yy430; goto yy333; yy393: yych = *++p; if (yych == 'B') goto yy431; if (yych == 'b') goto yy431; goto yy333; yy394: yych = *++p; if (yych == 'O') goto yy363; if (yych == 'o') goto yy363; goto yy333; yy395: yych = *++p; if (yych == 'O') goto yy432; if (yych == 'o') goto yy432; goto yy333; yy396: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= 'D') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'E') goto yy433; if (yych == 'e') goto yy433; goto yy333; } } yy397: yych = *++p; if (yych == 'T') goto yy431; if (yych == 't') goto yy431; goto yy333; yy398: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= '@') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'A') goto yy434; if (yych == 'a') goto yy434; goto yy333; } } yy399: ++p; { return 2; } yy401: yych = *++p; if (yych == 'D') goto yy435; if (yych == 'd') goto yy435; goto yy333; yy402: yych = *++p; if (yych == 'R') goto yy436; if (yych == 'r') goto yy436; goto yy333; yy403: yych = *++p; if (yych == 'I') goto yy437; if (yych == 'i') goto yy437; goto yy333; yy404: yych = *++p; if (yych == 'D') goto yy438; if (yych == 'd') goto yy438; goto yy333; yy405: yych = *++p; if (yych == 'E') goto yy439; if (yych == 'e') goto yy439; goto yy333; yy406: yych = *++p; if (yych == 'C') goto yy440; if (yych == 'c') goto yy440; goto yy333; yy407: yych = *++p; if (yych == 'Y') goto yy367; if (yych == 'y') goto yy367; goto yy333; yy408: yych = *++p; if (yych == 'T') goto yy441; if (yych == 't') goto yy441; goto yy333; yy409: yych = *++p; if (yych == 'T') goto yy442; if (yych == 't') goto yy442; goto yy333; yy410: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= 'F') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'G') goto yy443; if (yych == 'g') goto yy443; goto yy333; } } yy411: yych = *++p; if (yych == 'A') goto yy444; if (yych == 'a') goto yy444; goto yy333; yy412: yych = *++p; if (yych == 'L') goto yy445; if (yych == 'l') goto yy445; goto yy333; yy413: yych = *++p; if (yych == 'L') goto yy446; if (yych == 'l') goto yy446; goto yy333; yy414: yych = *++p; if (yych <= 'U') { if (yych == 'C') goto yy447; if (yych <= 'T') goto yy333; goto yy448; } else { if (yych <= 'c') { if (yych <= 'b') goto yy333; goto yy447; } else { if (yych == 'u') goto yy448; goto yy333; } } yy415: yych = *++p; if (yych == 'M') goto yy367; if (yych == 'm') goto yy367; goto yy333; yy416: yych = *++p; if (yych == 'M') goto yy449; if (yych == 'm') goto yy449; goto yy333; yy417: yych = *++p; if (yych == 'D') goto yy450; if (yych == 'd') goto yy450; goto yy333; yy418: yych = *++p; if (yych == 'A') goto yy451; if (yych == 'a') goto yy451; goto yy333; yy419: yych = *++p; if (yych == 'E') goto yy452; if (yych == 'e') goto yy452; goto yy333; yy420: yych = *++p; if (yych == 'K') goto yy367; if (yych == 'k') goto yy367; goto yy333; yy421: yych = *++p; if (yych == 'N') goto yy367; if (yych == 'n') goto yy367; goto yy333; yy422: yych = *++p; if (yych == 'U') goto yy453; if (yych == 'u') goto yy453; goto yy333; yy423: yych = *++p; if (yych == 'R') goto yy454; if (yych == 'r') goto yy454; goto yy333; yy424: yych = *++p; if (yych <= 'I') { if (yych == 'G') goto yy443; if (yych <= 'H') goto yy333; goto yy455; } else { if (yych <= 'g') { if (yych <= 'f') goto yy333; goto yy443; } else { if (yych == 'i') goto yy455; goto yy333; } } yy425: yych = *++p; if (yych == 'A') goto yy415; if (yych == 'a') goto yy415; goto yy333; yy426: yych = *++p; if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy456; goto yy333; } else { if (yych <= ' ') goto yy456; if (yych == '>') goto yy456; goto yy333; } yy427: yych = *++p; if (yych == 'I') goto yy458; if (yych == 'i') goto yy458; goto yy333; yy428: yych = *++p; if (yych == 'R') goto yy459; if (yych == 'r') goto yy459; goto yy333; yy429: yych = *++p; if (yych == 'L') goto yy387; if (yych == 'l') goto yy387; goto yy333; yy430: yych = *++p; if (yych == 'M') goto yy460; if (yych == 'm') goto yy460; goto yy333; yy431: yych = *++p; if (yych == 'L') goto yy438; if (yych == 'l') goto yy438; goto yy333; yy432: yych = *++p; if (yych == 'O') goto yy461; if (yych == 'o') goto yy461; goto yy333; yy433: yych = *++p; if (yych == 'A') goto yy462; if (yych == 'a') goto yy462; goto yy333; yy434: yych = *++p; if (yych == 'C') goto yy420; if (yych == 'c') goto yy420; goto yy333; yy435: yych = *++p; if (yych == 'A') goto yy463; if (yych == 'a') goto yy463; goto yy333; yy436: yych = *++p; if (yych == 'E') goto yy464; if (yych == 'e') goto yy464; goto yy333; yy437: yych = *++p; if (yych == 'C') goto yy431; if (yych == 'c') goto yy431; goto yy333; yy438: yych = *++p; if (yych == 'E') goto yy367; if (yych == 'e') goto yy367; goto yy333; yy439: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= 'E') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'F') goto yy465; if (yych == 'f') goto yy465; goto yy333; } } yy440: yych = *++p; if (yych == 'K') goto yy466; if (yych == 'k') goto yy466; goto yy333; yy441: yych = *++p; if (yych == 'I') goto yy455; if (yych == 'i') goto yy455; goto yy333; yy442: yych = *++p; if (yych == 'E') goto yy467; if (yych == 'e') goto yy467; goto yy333; yy443: yych = *++p; if (yych == 'R') goto yy468; if (yych == 'r') goto yy468; goto yy333; yy444: yych = *++p; if (yych == 'I') goto yy469; if (yych == 'i') goto yy469; goto yy333; yy445: yych = *++p; if (yych == 'O') goto yy470; if (yych == 'o') goto yy470; goto yy333; yy446: yych = *++p; if (yych == 'D') goto yy471; if (yych == 'd') goto yy471; goto yy333; yy447: yych = *++p; if (yych == 'A') goto yy364; if (yych == 'a') goto yy364; goto yy333; yy448: yych = *++p; if (yych == 'R') goto yy438; if (yych == 'r') goto yy438; goto yy333; yy449: yych = *++p; if (yych == 'E') goto yy472; if (yych == 'e') goto yy472; goto yy333; yy450: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= 'D') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'E') goto yy467; if (yych == 'e') goto yy467; goto yy333; } } yy451: yych = *++p; if (yych == 'M') goto yy438; if (yych == 'm') goto yy438; goto yy333; yy452: yych = *++p; if (yych == 'N') goto yy462; if (yych == 'n') goto yy462; goto yy333; yy453: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= 'H') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'I') goto yy473; if (yych == 'i') goto yy473; goto yy333; } } yy454: yych = *++p; if (yych == 'A') goto yy474; if (yych == 'a') goto yy474; goto yy333; yy455: yych = *++p; if (yych == 'O') goto yy421; if (yych == 'o') goto yy421; goto yy333; yy456: ++p; { return 1; } yy458: yych = *++p; if (yych == 'P') goto yy475; if (yych == 'p') goto yy475; goto yy333; yy459: yych = *++p; if (yych == 'C') goto yy438; if (yych == 'c') goto yy438; goto yy333; yy460: yych = *++p; if (yych == 'A') goto yy476; if (yych == 'a') goto yy476; goto yy333; yy461: yych = *++p; if (yych == 'T') goto yy367; if (yych == 't') goto yy367; goto yy333; yy462: yych = *++p; if (yych == 'D') goto yy367; if (yych == 'd') goto yy367; goto yy333; yy463: yych = *++p; if (yych == 'T') goto yy477; if (yych == 't') goto yy477; goto yy333; yy464: yych = *++p; if (yych == 'S') goto yy478; if (yych == 's') goto yy478; goto yy333; yy465: yych = *++p; if (yych == 'O') goto yy479; if (yych == 'o') goto yy479; goto yy333; yy466: yych = *++p; if (yych == 'Q') goto yy480; if (yych == 'q') goto yy480; goto yy333; yy467: yych = *++p; if (yych == 'R') goto yy367; if (yych == 'r') goto yy367; goto yy333; yy468: yych = *++p; if (yych == 'O') goto yy481; if (yych == 'o') goto yy481; goto yy333; yy469: yych = *++p; if (yych == 'L') goto yy478; if (yych == 'l') goto yy478; goto yy333; yy470: yych = *++p; if (yych == 'G') goto yy367; if (yych == 'g') goto yy367; goto yy333; yy471: yych = *++p; if (yych == 'S') goto yy482; if (yych == 's') goto yy482; goto yy333; yy472: yych = *++p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy333; if (yych <= '\r') goto yy383; goto yy333; } else { if (yych <= ' ') goto yy383; if (yych <= '.') goto yy333; goto yy385; } } else { if (yych <= 'R') { if (yych == '>') goto yy383; goto yy333; } else { if (yych <= 'S') goto yy482; if (yych == 's') goto yy482; goto yy333; } } yy473: yych = *++p; if (yych == 'T') goto yy483; if (yych == 't') goto yy483; goto yy333; yy474: yych = *++p; if (yych == 'M') goto yy484; if (yych == 'm') goto yy484; goto yy333; yy475: yych = *++p; if (yych == 'T') goto yy426; if (yych == 't') goto yy426; goto yy333; yy476: yych = *++p; if (yych == 'R') goto yy407; if (yych == 'r') goto yy407; goto yy333; yy477: yych = *++p; if (yych == 'A') goto yy485; if (yych == 'a') goto yy485; goto yy333; yy478: yych = *++p; if (yych == 'S') goto yy367; if (yych == 's') goto yy367; goto yy333; yy479: yych = *++p; if (yych == 'N') goto yy461; if (yych == 'n') goto yy461; goto yy333; yy480: yych = *++p; if (yych == 'U') goto yy486; if (yych == 'u') goto yy486; goto yy333; yy481: yych = *++p; if (yych == 'U') goto yy487; if (yych == 'u') goto yy487; goto yy333; yy482: yych = *++p; if (yych == 'E') goto yy461; if (yych == 'e') goto yy461; goto yy333; yy483: yych = *++p; if (yych == 'E') goto yy415; if (yych == 'e') goto yy415; goto yy333; yy484: yych = *++p; if (yych == 'E') goto yy478; if (yych == 'e') goto yy478; goto yy333; yy485: yych = *++p; if (yych == '[') goto yy488; goto yy333; yy486: yych = *++p; if (yych == 'O') goto yy490; if (yych == 'o') goto yy490; goto yy333; yy487: yych = *++p; if (yych == 'P') goto yy367; if (yych == 'p') goto yy367; goto yy333; yy488: ++p; { return 5; } yy490: ++p; if ((yych = *p) == 'T') goto yy438; if (yych == 't') goto yy438; goto yy333; } } // Try to match an HTML block tag start line of type 7, returning // 7 if successful, 0 if not. bufsize_t _scan_html_block_start_7(const unsigned char *p) { const unsigned char *marker = NULL; { unsigned char yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 224, 224, 224, 224, 224, 224, 224, 224, 198, 210, 194, 198, 194, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 198, 224, 128, 224, 224, 224, 224, 64, 224, 224, 224, 224, 224, 233, 232, 224, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 232, 224, 192, 192, 192, 224, 224, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 224, 224, 224, 224, 232, 192, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 224, 224, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych == '<') goto yy495; ++p; yy494 : { return 0; } yy495: yyaccept = 0; yych = *(marker = ++p); if (yych <= '@') { if (yych != '/') goto yy494; } else { if (yych <= 'Z') goto yy498; if (yych <= '`') goto yy494; if (yych <= 'z') goto yy498; goto yy494; } yych = *++p; if (yych <= '@') goto yy497; if (yych <= 'Z') goto yy500; if (yych <= '`') goto yy497; if (yych <= 'z') goto yy500; yy497: p = marker; if (yyaccept == 0) { goto yy494; } else { goto yy513; } yy498: ++p; yych = *p; if (yybm[0 + yych] & 2) { goto yy502; } if (yych <= '=') { if (yych <= '.') { if (yych == '-') goto yy498; goto yy497; } else { if (yych <= '/') goto yy504; if (yych <= '9') goto yy498; goto yy497; } } else { if (yych <= 'Z') { if (yych <= '>') goto yy505; if (yych <= '@') goto yy497; goto yy498; } else { if (yych <= '`') goto yy497; if (yych <= 'z') goto yy498; goto yy497; } } yy500: ++p; yych = *p; if (yych <= '/') { if (yych <= 0x1F) { if (yych <= 0x08) goto yy497; if (yych <= '\r') goto yy507; goto yy497; } else { if (yych <= ' ') goto yy507; if (yych == '-') goto yy500; goto yy497; } } else { if (yych <= '@') { if (yych <= '9') goto yy500; if (yych == '>') goto yy505; goto yy497; } else { if (yych <= 'Z') goto yy500; if (yych <= '`') goto yy497; if (yych <= 'z') goto yy500; goto yy497; } } yy502: ++p; yych = *p; if (yybm[0 + yych] & 2) { goto yy502; } if (yych <= '>') { if (yych <= '9') { if (yych != '/') goto yy497; } else { if (yych <= ':') goto yy509; if (yych <= '=') goto yy497; goto yy505; } } else { if (yych <= '^') { if (yych <= '@') goto yy497; if (yych <= 'Z') goto yy509; goto yy497; } else { if (yych == '`') goto yy497; if (yych <= 'z') goto yy509; goto yy497; } } yy504: yych = *++p; if (yych != '>') goto yy497; yy505: ++p; yych = *p; if (yybm[0 + yych] & 4) { goto yy505; } if (yych <= 0x08) goto yy497; if (yych <= '\n') goto yy511; if (yych <= '\v') goto yy497; if (yych <= '\r') goto yy514; goto yy497; yy507: ++p; yych = *p; if (yych <= 0x1F) { if (yych <= 0x08) goto yy497; if (yych <= '\r') goto yy507; goto yy497; } else { if (yych <= ' ') goto yy507; if (yych == '>') goto yy505; goto yy497; } yy509: ++p; yych = *p; if (yybm[0 + yych] & 8) { goto yy509; } if (yych <= ',') { if (yych <= '\r') { if (yych <= 0x08) goto yy497; goto yy515; } else { if (yych == ' ') goto yy515; goto yy497; } } else { if (yych <= '<') { if (yych <= '/') goto yy504; goto yy497; } else { if (yych <= '=') goto yy517; if (yych <= '>') goto yy505; goto yy497; } } yy511: yyaccept = 1; marker = ++p; yych = *p; if (yybm[0 + yych] & 4) { goto yy505; } if (yych <= 0x08) goto yy513; if (yych <= '\n') goto yy511; if (yych <= '\v') goto yy513; if (yych <= '\r') goto yy514; yy513 : { return 7; } yy514: yych = *++p; goto yy513; yy515: ++p; yych = *p; if (yych <= '<') { if (yych <= ' ') { if (yych <= 0x08) goto yy497; if (yych <= '\r') goto yy515; if (yych <= 0x1F) goto yy497; goto yy515; } else { if (yych <= '/') { if (yych <= '.') goto yy497; goto yy504; } else { if (yych == ':') goto yy509; goto yy497; } } } else { if (yych <= 'Z') { if (yych <= '=') goto yy517; if (yych <= '>') goto yy505; if (yych <= '@') goto yy497; goto yy509; } else { if (yych <= '_') { if (yych <= '^') goto yy497; goto yy509; } else { if (yych <= '`') goto yy497; if (yych <= 'z') goto yy509; goto yy497; } } } yy517: ++p; yych = *p; if (yybm[0 + yych] & 32) { goto yy519; } if (yych <= 0xE0) { if (yych <= '"') { if (yych <= 0x00) goto yy497; if (yych <= ' ') goto yy517; goto yy521; } else { if (yych <= '\'') goto yy523; if (yych <= 0xC1) goto yy497; if (yych <= 0xDF) goto yy525; goto yy526; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy528; goto yy527; } else { if (yych <= 0xF0) goto yy529; if (yych <= 0xF3) goto yy530; if (yych <= 0xF4) goto yy531; goto yy497; } } yy519: ++p; yych = *p; if (yybm[0 + yych] & 32) { goto yy519; } if (yych <= 0xE0) { if (yych <= '=') { if (yych <= 0x00) goto yy497; if (yych <= ' ') goto yy502; goto yy497; } else { if (yych <= '>') goto yy505; if (yych <= 0xC1) goto yy497; if (yych <= 0xDF) goto yy525; goto yy526; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy528; goto yy527; } else { if (yych <= 0xF0) goto yy529; if (yych <= 0xF3) goto yy530; if (yych <= 0xF4) goto yy531; goto yy497; } } yy521: ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy521; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy497; if (yych <= '"') goto yy532; goto yy497; } else { if (yych <= 0xDF) goto yy533; if (yych <= 0xE0) goto yy534; goto yy535; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy536; if (yych <= 0xEF) goto yy535; goto yy537; } else { if (yych <= 0xF3) goto yy538; if (yych <= 0xF4) goto yy539; goto yy497; } } yy523: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy523; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy497; if (yych <= '\'') goto yy532; goto yy497; } else { if (yych <= 0xDF) goto yy540; if (yych <= 0xE0) goto yy541; goto yy542; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy543; if (yych <= 0xEF) goto yy542; goto yy544; } else { if (yych <= 0xF3) goto yy545; if (yych <= 0xF4) goto yy546; goto yy497; } } yy525: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy519; goto yy497; yy526: ++p; yych = *p; if (yych <= 0x9F) goto yy497; if (yych <= 0xBF) goto yy525; goto yy497; yy527: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy525; goto yy497; yy528: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0x9F) goto yy525; goto yy497; yy529: ++p; yych = *p; if (yych <= 0x8F) goto yy497; if (yych <= 0xBF) goto yy527; goto yy497; yy530: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy527; goto yy497; yy531: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0x8F) goto yy527; goto yy497; yy532: ++p; yych = *p; if (yybm[0 + yych] & 2) { goto yy502; } if (yych == '/') goto yy504; if (yych == '>') goto yy505; goto yy497; yy533: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy521; goto yy497; yy534: ++p; yych = *p; if (yych <= 0x9F) goto yy497; if (yych <= 0xBF) goto yy533; goto yy497; yy535: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy533; goto yy497; yy536: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0x9F) goto yy533; goto yy497; yy537: ++p; yych = *p; if (yych <= 0x8F) goto yy497; if (yych <= 0xBF) goto yy535; goto yy497; yy538: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy535; goto yy497; yy539: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0x8F) goto yy535; goto yy497; yy540: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy523; goto yy497; yy541: ++p; yych = *p; if (yych <= 0x9F) goto yy497; if (yych <= 0xBF) goto yy540; goto yy497; yy542: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy540; goto yy497; yy543: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0x9F) goto yy540; goto yy497; yy544: ++p; yych = *p; if (yych <= 0x8F) goto yy497; if (yych <= 0xBF) goto yy542; goto yy497; yy545: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0xBF) goto yy542; goto yy497; yy546: ++p; yych = *p; if (yych <= 0x7F) goto yy497; if (yych <= 0x8F) goto yy542; goto yy497; } } // Try to match an HTML block end line of type 1 bufsize_t _scan_html_block_end_1(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= 0xDF) { if (yych <= ';') { if (yych <= 0x00) goto yy549; if (yych != '\n') goto yy551; } else { if (yych <= '<') goto yy552; if (yych <= 0x7F) goto yy551; if (yych >= 0xC2) goto yy553; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy554; if (yych == 0xED) goto yy556; goto yy555; } else { if (yych <= 0xF0) goto yy557; if (yych <= 0xF3) goto yy558; if (yych <= 0xF4) goto yy559; } } yy549: ++p; yy550 : { return 0; } yy551: yyaccept = 0; yych = *(marker = ++p); if (yych <= '\n') { if (yych <= 0x00) goto yy550; if (yych <= '\t') goto yy561; goto yy550; } else { if (yych <= 0x7F) goto yy561; if (yych <= 0xC1) goto yy550; if (yych <= 0xF4) goto yy561; goto yy550; } yy552: yyaccept = 0; yych = *(marker = ++p); if (yych <= '.') { if (yych <= 0x00) goto yy550; if (yych == '\n') goto yy550; goto yy561; } else { if (yych <= 0x7F) { if (yych <= '/') goto yy572; goto yy561; } else { if (yych <= 0xC1) goto yy550; if (yych <= 0xF4) goto yy561; goto yy550; } } yy553: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy550; if (yych <= 0xBF) goto yy560; goto yy550; yy554: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x9F) goto yy550; if (yych <= 0xBF) goto yy565; goto yy550; yy555: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy550; if (yych <= 0xBF) goto yy565; goto yy550; yy556: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy550; if (yych <= 0x9F) goto yy565; goto yy550; yy557: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x8F) goto yy550; if (yych <= 0xBF) goto yy567; goto yy550; yy558: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy550; if (yych <= 0xBF) goto yy567; goto yy550; yy559: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy550; if (yych <= 0x8F) goto yy567; goto yy550; yy560: ++p; yych = *p; yy561: if (yybm[0 + yych] & 64) { goto yy560; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy562; if (yych <= '<') goto yy563; } else { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; goto yy567; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy568; if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; } } yy562: p = marker; if (yyaccept == 0) { goto yy550; } else { goto yy582; } yy563: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xDF) { if (yych <= '.') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= '/') goto yy572; if (yych <= 0x7F) goto yy560; if (yych <= 0xC1) goto yy562; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy566; if (yych == 0xED) goto yy568; goto yy567; } else { if (yych <= 0xF0) goto yy569; if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } yy565: ++p; yych = *p; if (yych <= 0x7F) goto yy562; if (yych <= 0xBF) goto yy560; goto yy562; yy566: ++p; yych = *p; if (yych <= 0x9F) goto yy562; if (yych <= 0xBF) goto yy565; goto yy562; yy567: ++p; yych = *p; if (yych <= 0x7F) goto yy562; if (yych <= 0xBF) goto yy565; goto yy562; yy568: ++p; yych = *p; if (yych <= 0x7F) goto yy562; if (yych <= 0x9F) goto yy565; goto yy562; yy569: ++p; yych = *p; if (yych <= 0x8F) goto yy562; if (yych <= 0xBF) goto yy567; goto yy562; yy570: ++p; yych = *p; if (yych <= 0x7F) goto yy562; if (yych <= 0xBF) goto yy567; goto yy562; yy571: ++p; yych = *p; if (yych <= 0x7F) goto yy562; if (yych <= 0x8F) goto yy567; goto yy562; yy572: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 's') { if (yych <= 'P') { if (yych <= '\t') { if (yych <= 0x00) goto yy562; goto yy560; } else { if (yych <= '\n') goto yy562; if (yych <= 'O') goto yy560; } } else { if (yych <= 'o') { if (yych == 'S') goto yy574; goto yy560; } else { if (yych <= 'p') goto yy573; if (yych <= 'r') goto yy560; goto yy574; } } } else { if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x7F) goto yy560; goto yy562; } else { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; goto yy567; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy568; if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy573: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'Q') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 'q') { if (yych <= 'R') goto yy575; goto yy560; } else { if (yych <= 'r') goto yy575; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy574: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 't') { if (yych <= 'C') { if (yych <= '\t') { if (yych <= 0x00) goto yy562; goto yy560; } else { if (yych <= '\n') goto yy562; if (yych <= 'B') goto yy560; goto yy576; } } else { if (yych <= 'b') { if (yych == 'T') goto yy577; goto yy560; } else { if (yych <= 'c') goto yy576; if (yych <= 's') goto yy560; goto yy577; } } } else { if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x7F) goto yy560; goto yy562; } else { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; goto yy567; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy568; if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy575: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'D') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 'd') { if (yych <= 'E') goto yy578; goto yy560; } else { if (yych <= 'e') goto yy578; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy576: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'Q') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 'q') { if (yych <= 'R') goto yy579; goto yy560; } else { if (yych <= 'r') goto yy579; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy577: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'X') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 'x') { if (yych <= 'Y') goto yy580; goto yy560; } else { if (yych <= 'y') goto yy580; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy578: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xDF) { if (yych <= '=') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= '>') goto yy581; if (yych <= 0x7F) goto yy560; if (yych <= 0xC1) goto yy562; goto yy565; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy566; if (yych == 0xED) goto yy568; goto yy567; } else { if (yych <= 0xF0) goto yy569; if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } yy579: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'H') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 'h') { if (yych <= 'I') goto yy583; goto yy560; } else { if (yych <= 'i') goto yy583; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy580: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'K') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 'k') { if (yych <= 'L') goto yy575; goto yy560; } else { if (yych <= 'l') goto yy575; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy581: yyaccept = 1; marker = ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy560; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy582; if (yych <= '<') goto yy563; } else { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; goto yy567; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy568; if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; } } yy582 : { return (bufsize_t)(p - start); } yy583: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'O') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 'o') { if (yych >= 'Q') goto yy560; } else { if (yych <= 'p') goto yy584; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } yy584: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy563; } if (yych <= 0xC1) { if (yych <= 'S') { if (yych <= 0x00) goto yy562; if (yych == '\n') goto yy562; goto yy560; } else { if (yych <= 's') { if (yych <= 'T') goto yy578; goto yy560; } else { if (yych <= 't') goto yy578; if (yych <= 0x7F) goto yy560; goto yy562; } } } else { if (yych <= 0xED) { if (yych <= 0xDF) goto yy565; if (yych <= 0xE0) goto yy566; if (yych <= 0xEC) goto yy567; goto yy568; } else { if (yych <= 0xF0) { if (yych <= 0xEF) goto yy567; goto yy569; } else { if (yych <= 0xF3) goto yy570; if (yych <= 0xF4) goto yy571; goto yy562; } } } } } // Try to match an HTML block end line of type 2 bufsize_t _scan_html_block_end_2(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= 0xDF) { if (yych <= ',') { if (yych <= 0x00) goto yy587; if (yych != '\n') goto yy589; } else { if (yych <= '-') goto yy590; if (yych <= 0x7F) goto yy589; if (yych >= 0xC2) goto yy591; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy592; if (yych == 0xED) goto yy594; goto yy593; } else { if (yych <= 0xF0) goto yy595; if (yych <= 0xF3) goto yy596; if (yych <= 0xF4) goto yy597; } } yy587: ++p; yy588 : { return 0; } yy589: yyaccept = 0; yych = *(marker = ++p); if (yych <= '\n') { if (yych <= 0x00) goto yy588; if (yych <= '\t') goto yy599; goto yy588; } else { if (yych <= 0x7F) goto yy599; if (yych <= 0xC1) goto yy588; if (yych <= 0xF4) goto yy599; goto yy588; } yy590: yyaccept = 0; yych = *(marker = ++p); if (yybm[0 + yych] & 128) { goto yy609; } if (yych <= '\n') { if (yych <= 0x00) goto yy588; if (yych <= '\t') goto yy599; goto yy588; } else { if (yych <= 0x7F) goto yy599; if (yych <= 0xC1) goto yy588; if (yych <= 0xF4) goto yy599; goto yy588; } yy591: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy588; if (yych <= 0xBF) goto yy598; goto yy588; yy592: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x9F) goto yy588; if (yych <= 0xBF) goto yy602; goto yy588; yy593: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy588; if (yych <= 0xBF) goto yy602; goto yy588; yy594: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy588; if (yych <= 0x9F) goto yy602; goto yy588; yy595: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x8F) goto yy588; if (yych <= 0xBF) goto yy604; goto yy588; yy596: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy588; if (yych <= 0xBF) goto yy604; goto yy588; yy597: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy588; if (yych <= 0x8F) goto yy604; goto yy588; yy598: ++p; yych = *p; yy599: if (yybm[0 + yych] & 64) { goto yy598; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy600; if (yych <= '-') goto yy601; } else { if (yych <= 0xDF) goto yy602; if (yych <= 0xE0) goto yy603; goto yy604; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy605; if (yych <= 0xEF) goto yy604; goto yy606; } else { if (yych <= 0xF3) goto yy607; if (yych <= 0xF4) goto yy608; } } yy600: p = marker; if (yyaccept == 0) { goto yy588; } else { goto yy612; } yy601: ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy598; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy600; if (yych <= '-') goto yy609; goto yy600; } else { if (yych <= 0xDF) goto yy602; if (yych <= 0xE0) goto yy603; goto yy604; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy605; if (yych <= 0xEF) goto yy604; goto yy606; } else { if (yych <= 0xF3) goto yy607; if (yych <= 0xF4) goto yy608; goto yy600; } } yy602: ++p; yych = *p; if (yych <= 0x7F) goto yy600; if (yych <= 0xBF) goto yy598; goto yy600; yy603: ++p; yych = *p; if (yych <= 0x9F) goto yy600; if (yych <= 0xBF) goto yy602; goto yy600; yy604: ++p; yych = *p; if (yych <= 0x7F) goto yy600; if (yych <= 0xBF) goto yy602; goto yy600; yy605: ++p; yych = *p; if (yych <= 0x7F) goto yy600; if (yych <= 0x9F) goto yy602; goto yy600; yy606: ++p; yych = *p; if (yych <= 0x8F) goto yy600; if (yych <= 0xBF) goto yy604; goto yy600; yy607: ++p; yych = *p; if (yych <= 0x7F) goto yy600; if (yych <= 0xBF) goto yy604; goto yy600; yy608: ++p; yych = *p; if (yych <= 0x7F) goto yy600; if (yych <= 0x8F) goto yy604; goto yy600; yy609: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy609; } if (yych <= 0xDF) { if (yych <= '=') { if (yych <= 0x00) goto yy600; if (yych == '\n') goto yy600; goto yy598; } else { if (yych <= '>') goto yy611; if (yych <= 0x7F) goto yy598; if (yych <= 0xC1) goto yy600; goto yy602; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy603; if (yych == 0xED) goto yy605; goto yy604; } else { if (yych <= 0xF0) goto yy606; if (yych <= 0xF3) goto yy607; if (yych <= 0xF4) goto yy608; goto yy600; } } yy611: yyaccept = 1; marker = ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy598; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy612; if (yych <= '-') goto yy601; } else { if (yych <= 0xDF) goto yy602; if (yych <= 0xE0) goto yy603; goto yy604; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy605; if (yych <= 0xEF) goto yy604; goto yy606; } else { if (yych <= 0xF3) goto yy607; if (yych <= 0xF4) goto yy608; } } yy612 : { return (bufsize_t)(p - start); } } } // Try to match an HTML block end line of type 3 bufsize_t _scan_html_block_end_3(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= 0xDF) { if (yych <= '>') { if (yych <= 0x00) goto yy615; if (yych != '\n') goto yy617; } else { if (yych <= '?') goto yy618; if (yych <= 0x7F) goto yy617; if (yych >= 0xC2) goto yy619; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy620; if (yych == 0xED) goto yy622; goto yy621; } else { if (yych <= 0xF0) goto yy623; if (yych <= 0xF3) goto yy624; if (yych <= 0xF4) goto yy625; } } yy615: ++p; yy616 : { return 0; } yy617: yyaccept = 0; yych = *(marker = ++p); if (yych <= '\n') { if (yych <= 0x00) goto yy616; if (yych <= '\t') goto yy627; goto yy616; } else { if (yych <= 0x7F) goto yy627; if (yych <= 0xC1) goto yy616; if (yych <= 0xF4) goto yy627; goto yy616; } yy618: yyaccept = 0; yych = *(marker = ++p); if (yych <= '=') { if (yych <= 0x00) goto yy616; if (yych == '\n') goto yy616; goto yy627; } else { if (yych <= 0x7F) { if (yych <= '>') goto yy638; goto yy627; } else { if (yych <= 0xC1) goto yy616; if (yych <= 0xF4) goto yy627; goto yy616; } } yy619: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy616; if (yych <= 0xBF) goto yy626; goto yy616; yy620: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x9F) goto yy616; if (yych <= 0xBF) goto yy631; goto yy616; yy621: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy616; if (yych <= 0xBF) goto yy631; goto yy616; yy622: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy616; if (yych <= 0x9F) goto yy631; goto yy616; yy623: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x8F) goto yy616; if (yych <= 0xBF) goto yy633; goto yy616; yy624: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy616; if (yych <= 0xBF) goto yy633; goto yy616; yy625: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy616; if (yych <= 0x8F) goto yy633; goto yy616; yy626: ++p; yych = *p; yy627: if (yybm[0 + yych] & 64) { goto yy626; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy628; if (yych <= '?') goto yy629; } else { if (yych <= 0xDF) goto yy631; if (yych <= 0xE0) goto yy632; goto yy633; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy634; if (yych <= 0xEF) goto yy633; goto yy635; } else { if (yych <= 0xF3) goto yy636; if (yych <= 0xF4) goto yy637; } } yy628: p = marker; if (yyaccept == 0) { goto yy616; } else { goto yy639; } yy629: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy629; } if (yych <= 0xDF) { if (yych <= '=') { if (yych <= 0x00) goto yy628; if (yych == '\n') goto yy628; goto yy626; } else { if (yych <= '>') goto yy638; if (yych <= 0x7F) goto yy626; if (yych <= 0xC1) goto yy628; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy632; if (yych == 0xED) goto yy634; goto yy633; } else { if (yych <= 0xF0) goto yy635; if (yych <= 0xF3) goto yy636; if (yych <= 0xF4) goto yy637; goto yy628; } } yy631: ++p; yych = *p; if (yych <= 0x7F) goto yy628; if (yych <= 0xBF) goto yy626; goto yy628; yy632: ++p; yych = *p; if (yych <= 0x9F) goto yy628; if (yych <= 0xBF) goto yy631; goto yy628; yy633: ++p; yych = *p; if (yych <= 0x7F) goto yy628; if (yych <= 0xBF) goto yy631; goto yy628; yy634: ++p; yych = *p; if (yych <= 0x7F) goto yy628; if (yych <= 0x9F) goto yy631; goto yy628; yy635: ++p; yych = *p; if (yych <= 0x8F) goto yy628; if (yych <= 0xBF) goto yy633; goto yy628; yy636: ++p; yych = *p; if (yych <= 0x7F) goto yy628; if (yych <= 0xBF) goto yy633; goto yy628; yy637: ++p; yych = *p; if (yych <= 0x7F) goto yy628; if (yych <= 0x8F) goto yy633; goto yy628; yy638: yyaccept = 1; marker = ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy626; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy639; if (yych <= '?') goto yy629; } else { if (yych <= 0xDF) goto yy631; if (yych <= 0xE0) goto yy632; goto yy633; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy634; if (yych <= 0xEF) goto yy633; goto yy635; } else { if (yych <= 0xF3) goto yy636; if (yych <= 0xF4) goto yy637; } } yy639 : { return (bufsize_t)(p - start); } } } // Try to match an HTML block end line of type 4 bufsize_t _scan_html_block_end_4(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yybm[0 + yych] & 64) { goto yy645; } if (yych <= 0xE0) { if (yych <= '\n') { if (yych <= 0x00) goto yy642; if (yych <= '\t') goto yy644; } else { if (yych <= 0x7F) goto yy644; if (yych <= 0xC1) goto yy642; if (yych <= 0xDF) goto yy648; goto yy649; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy651; goto yy650; } else { if (yych <= 0xF0) goto yy652; if (yych <= 0xF3) goto yy653; if (yych <= 0xF4) goto yy654; } } yy642: ++p; yy643 : { return 0; } yy644: yyaccept = 0; yych = *(marker = ++p); if (yych <= '\n') { if (yych <= 0x00) goto yy643; if (yych <= '\t') goto yy656; goto yy643; } else { if (yych <= 0x7F) goto yy656; if (yych <= 0xC1) goto yy643; if (yych <= 0xF4) goto yy656; goto yy643; } yy645: yyaccept = 1; marker = ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy655; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy647; if (yych <= '>') goto yy645; } else { if (yych <= 0xDF) goto yy658; if (yych <= 0xE0) goto yy659; goto yy660; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy661; if (yych <= 0xEF) goto yy660; goto yy662; } else { if (yych <= 0xF3) goto yy663; if (yych <= 0xF4) goto yy664; } } yy647 : { return (bufsize_t)(p - start); } yy648: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy643; if (yych <= 0xBF) goto yy655; goto yy643; yy649: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x9F) goto yy643; if (yych <= 0xBF) goto yy658; goto yy643; yy650: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy643; if (yych <= 0xBF) goto yy658; goto yy643; yy651: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy643; if (yych <= 0x9F) goto yy658; goto yy643; yy652: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x8F) goto yy643; if (yych <= 0xBF) goto yy660; goto yy643; yy653: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy643; if (yych <= 0xBF) goto yy660; goto yy643; yy654: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy643; if (yych <= 0x8F) goto yy660; goto yy643; yy655: ++p; yych = *p; yy656: if (yybm[0 + yych] & 128) { goto yy655; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy657; if (yych <= '>') goto yy645; } else { if (yych <= 0xDF) goto yy658; if (yych <= 0xE0) goto yy659; goto yy660; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy661; if (yych <= 0xEF) goto yy660; goto yy662; } else { if (yych <= 0xF3) goto yy663; if (yych <= 0xF4) goto yy664; } } yy657: p = marker; if (yyaccept == 0) { goto yy643; } else { goto yy647; } yy658: ++p; yych = *p; if (yych <= 0x7F) goto yy657; if (yych <= 0xBF) goto yy655; goto yy657; yy659: ++p; yych = *p; if (yych <= 0x9F) goto yy657; if (yych <= 0xBF) goto yy658; goto yy657; yy660: ++p; yych = *p; if (yych <= 0x7F) goto yy657; if (yych <= 0xBF) goto yy658; goto yy657; yy661: ++p; yych = *p; if (yych <= 0x7F) goto yy657; if (yych <= 0x9F) goto yy658; goto yy657; yy662: ++p; yych = *p; if (yych <= 0x8F) goto yy657; if (yych <= 0xBF) goto yy660; goto yy657; yy663: ++p; yych = *p; if (yych <= 0x7F) goto yy657; if (yych <= 0xBF) goto yy660; goto yy657; yy664: ++p; yych = *p; if (yych <= 0x7F) goto yy657; if (yych <= 0x8F) goto yy660; goto yy657; } } // Try to match an HTML block end line of type 5 bufsize_t _scan_html_block_end_5(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= 0xDF) { if (yych <= '\\') { if (yych <= 0x00) goto yy667; if (yych != '\n') goto yy669; } else { if (yych <= ']') goto yy670; if (yych <= 0x7F) goto yy669; if (yych >= 0xC2) goto yy671; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy672; if (yych == 0xED) goto yy674; goto yy673; } else { if (yych <= 0xF0) goto yy675; if (yych <= 0xF3) goto yy676; if (yych <= 0xF4) goto yy677; } } yy667: ++p; yy668 : { return 0; } yy669: yyaccept = 0; yych = *(marker = ++p); if (yych <= '\n') { if (yych <= 0x00) goto yy668; if (yych <= '\t') goto yy679; goto yy668; } else { if (yych <= 0x7F) goto yy679; if (yych <= 0xC1) goto yy668; if (yych <= 0xF4) goto yy679; goto yy668; } yy670: yyaccept = 0; yych = *(marker = ++p); if (yybm[0 + yych] & 128) { goto yy689; } if (yych <= '\n') { if (yych <= 0x00) goto yy668; if (yych <= '\t') goto yy679; goto yy668; } else { if (yych <= 0x7F) goto yy679; if (yych <= 0xC1) goto yy668; if (yych <= 0xF4) goto yy679; goto yy668; } yy671: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy668; if (yych <= 0xBF) goto yy678; goto yy668; yy672: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x9F) goto yy668; if (yych <= 0xBF) goto yy682; goto yy668; yy673: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy668; if (yych <= 0xBF) goto yy682; goto yy668; yy674: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy668; if (yych <= 0x9F) goto yy682; goto yy668; yy675: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x8F) goto yy668; if (yych <= 0xBF) goto yy684; goto yy668; yy676: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy668; if (yych <= 0xBF) goto yy684; goto yy668; yy677: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x7F) goto yy668; if (yych <= 0x8F) goto yy684; goto yy668; yy678: ++p; yych = *p; yy679: if (yybm[0 + yych] & 64) { goto yy678; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy680; if (yych <= ']') goto yy681; } else { if (yych <= 0xDF) goto yy682; if (yych <= 0xE0) goto yy683; goto yy684; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy685; if (yych <= 0xEF) goto yy684; goto yy686; } else { if (yych <= 0xF3) goto yy687; if (yych <= 0xF4) goto yy688; } } yy680: p = marker; if (yyaccept == 0) { goto yy668; } else { goto yy692; } yy681: ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy678; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy680; if (yych <= ']') goto yy689; goto yy680; } else { if (yych <= 0xDF) goto yy682; if (yych <= 0xE0) goto yy683; goto yy684; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy685; if (yych <= 0xEF) goto yy684; goto yy686; } else { if (yych <= 0xF3) goto yy687; if (yych <= 0xF4) goto yy688; goto yy680; } } yy682: ++p; yych = *p; if (yych <= 0x7F) goto yy680; if (yych <= 0xBF) goto yy678; goto yy680; yy683: ++p; yych = *p; if (yych <= 0x9F) goto yy680; if (yych <= 0xBF) goto yy682; goto yy680; yy684: ++p; yych = *p; if (yych <= 0x7F) goto yy680; if (yych <= 0xBF) goto yy682; goto yy680; yy685: ++p; yych = *p; if (yych <= 0x7F) goto yy680; if (yych <= 0x9F) goto yy682; goto yy680; yy686: ++p; yych = *p; if (yych <= 0x8F) goto yy680; if (yych <= 0xBF) goto yy684; goto yy680; yy687: ++p; yych = *p; if (yych <= 0x7F) goto yy680; if (yych <= 0xBF) goto yy684; goto yy680; yy688: ++p; yych = *p; if (yych <= 0x7F) goto yy680; if (yych <= 0x8F) goto yy684; goto yy680; yy689: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy689; } if (yych <= 0xDF) { if (yych <= '=') { if (yych <= 0x00) goto yy680; if (yych == '\n') goto yy680; goto yy678; } else { if (yych <= '>') goto yy691; if (yych <= 0x7F) goto yy678; if (yych <= 0xC1) goto yy680; goto yy682; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy683; if (yych == 0xED) goto yy685; goto yy684; } else { if (yych <= 0xF0) goto yy686; if (yych <= 0xF3) goto yy687; if (yych <= 0xF4) goto yy688; goto yy680; } } yy691: yyaccept = 1; marker = ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy678; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= '\n') goto yy692; if (yych <= ']') goto yy681; } else { if (yych <= 0xDF) goto yy682; if (yych <= 0xE0) goto yy683; goto yy684; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy685; if (yych <= 0xEF) goto yy684; goto yy686; } else { if (yych <= 0xF3) goto yy687; if (yych <= 0xF4) goto yy688; } } yy692 : { return (bufsize_t)(p - start); } } } // Try to match a link title (in single quotes, in double quotes, or // in parentheses), returning number of chars matched. Allow one // level of internal nesting (quotes within quotes). bufsize_t _scan_link_title(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; unsigned int yyaccept = 0; static const unsigned char yybm[] = { 0, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 192, 208, 208, 208, 208, 144, 80, 80, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 32, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych <= '&') { if (yych == '"') goto yy697; } else { if (yych <= '\'') goto yy698; if (yych <= '(') goto yy699; } ++p; yy696 : { return 0; } yy697: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x00) goto yy696; if (yych <= 0x7F) goto yy701; if (yych <= 0xC1) goto yy696; if (yych <= 0xF4) goto yy701; goto yy696; yy698: yyaccept = 0; yych = *(marker = ++p); if (yych <= 0x00) goto yy696; if (yych <= 0x7F) goto yy715; if (yych <= 0xC1) goto yy696; if (yych <= 0xF4) goto yy715; goto yy696; yy699: yyaccept = 0; yych = *(marker = ++p); if (yych <= '(') { if (yych <= 0x00) goto yy696; if (yych <= '\'') goto yy728; goto yy696; } else { if (yych <= 0x7F) goto yy728; if (yych <= 0xC1) goto yy696; if (yych <= 0xF4) goto yy728; goto yy696; } yy700: ++p; yych = *p; yy701: if (yybm[0 + yych] & 16) { goto yy700; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= 0x00) goto yy702; if (yych <= '"') goto yy703; goto yy705; } else { if (yych <= 0xC1) goto yy702; if (yych <= 0xDF) goto yy707; goto yy708; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy710; goto yy709; } else { if (yych <= 0xF0) goto yy711; if (yych <= 0xF3) goto yy712; if (yych <= 0xF4) goto yy713; } } yy702: p = marker; if (yyaccept <= 1) { if (yyaccept == 0) { goto yy696; } else { goto yy704; } } else { if (yyaccept == 2) { goto yy717; } else { goto yy730; } } yy703: ++p; yy704 : { return (bufsize_t)(p - start); } yy705: ++p; yych = *p; if (yybm[0 + yych] & 16) { goto yy700; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= 0x00) goto yy702; if (yych <= '"') goto yy740; goto yy705; } else { if (yych <= 0xC1) goto yy702; if (yych >= 0xE0) goto yy708; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy710; goto yy709; } else { if (yych <= 0xF0) goto yy711; if (yych <= 0xF3) goto yy712; if (yych <= 0xF4) goto yy713; goto yy702; } } yy707: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy700; goto yy702; yy708: ++p; yych = *p; if (yych <= 0x9F) goto yy702; if (yych <= 0xBF) goto yy707; goto yy702; yy709: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy707; goto yy702; yy710: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0x9F) goto yy707; goto yy702; yy711: ++p; yych = *p; if (yych <= 0x8F) goto yy702; if (yych <= 0xBF) goto yy709; goto yy702; yy712: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy709; goto yy702; yy713: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0x8F) goto yy709; goto yy702; yy714: ++p; yych = *p; yy715: if (yybm[0 + yych] & 64) { goto yy714; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= 0x00) goto yy702; if (yych >= '(') goto yy718; } else { if (yych <= 0xC1) goto yy702; if (yych <= 0xDF) goto yy720; goto yy721; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy723; goto yy722; } else { if (yych <= 0xF0) goto yy724; if (yych <= 0xF3) goto yy725; if (yych <= 0xF4) goto yy726; goto yy702; } } yy716: ++p; yy717 : { return (bufsize_t)(p - start); } yy718: ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy714; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= 0x00) goto yy702; if (yych <= '\'') goto yy741; goto yy718; } else { if (yych <= 0xC1) goto yy702; if (yych >= 0xE0) goto yy721; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy723; goto yy722; } else { if (yych <= 0xF0) goto yy724; if (yych <= 0xF3) goto yy725; if (yych <= 0xF4) goto yy726; goto yy702; } } yy720: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy714; goto yy702; yy721: ++p; yych = *p; if (yych <= 0x9F) goto yy702; if (yych <= 0xBF) goto yy720; goto yy702; yy722: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy720; goto yy702; yy723: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0x9F) goto yy720; goto yy702; yy724: ++p; yych = *p; if (yych <= 0x8F) goto yy702; if (yych <= 0xBF) goto yy722; goto yy702; yy725: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy722; goto yy702; yy726: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0x8F) goto yy722; goto yy702; yy727: ++p; yych = *p; yy728: if (yybm[0 + yych] & 128) { goto yy727; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= '(') goto yy702; if (yych >= '*') goto yy731; } else { if (yych <= 0xC1) goto yy702; if (yych <= 0xDF) goto yy733; goto yy734; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy736; goto yy735; } else { if (yych <= 0xF0) goto yy737; if (yych <= 0xF3) goto yy738; if (yych <= 0xF4) goto yy739; goto yy702; } } yy729: ++p; yy730 : { return (bufsize_t)(p - start); } yy731: ++p; yych = *p; if (yych <= 0xDF) { if (yych <= '[') { if (yych <= 0x00) goto yy702; if (yych == ')') goto yy742; goto yy727; } else { if (yych <= '\\') goto yy731; if (yych <= 0x7F) goto yy727; if (yych <= 0xC1) goto yy702; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy734; if (yych == 0xED) goto yy736; goto yy735; } else { if (yych <= 0xF0) goto yy737; if (yych <= 0xF3) goto yy738; if (yych <= 0xF4) goto yy739; goto yy702; } } yy733: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy727; goto yy702; yy734: ++p; yych = *p; if (yych <= 0x9F) goto yy702; if (yych <= 0xBF) goto yy733; goto yy702; yy735: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy733; goto yy702; yy736: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0x9F) goto yy733; goto yy702; yy737: ++p; yych = *p; if (yych <= 0x8F) goto yy702; if (yych <= 0xBF) goto yy735; goto yy702; yy738: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0xBF) goto yy735; goto yy702; yy739: ++p; yych = *p; if (yych <= 0x7F) goto yy702; if (yych <= 0x8F) goto yy735; goto yy702; yy740: yyaccept = 1; marker = ++p; yych = *p; if (yybm[0 + yych] & 16) { goto yy700; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= 0x00) goto yy704; if (yych <= '"') goto yy703; goto yy705; } else { if (yych <= 0xC1) goto yy704; if (yych <= 0xDF) goto yy707; goto yy708; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy710; goto yy709; } else { if (yych <= 0xF0) goto yy711; if (yych <= 0xF3) goto yy712; if (yych <= 0xF4) goto yy713; goto yy704; } } yy741: yyaccept = 2; marker = ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy714; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= 0x00) goto yy717; if (yych <= '\'') goto yy716; goto yy718; } else { if (yych <= 0xC1) goto yy717; if (yych <= 0xDF) goto yy720; goto yy721; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy723; goto yy722; } else { if (yych <= 0xF0) goto yy724; if (yych <= 0xF3) goto yy725; if (yych <= 0xF4) goto yy726; goto yy717; } } yy742: yyaccept = 3; marker = ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy727; } if (yych <= 0xE0) { if (yych <= '\\') { if (yych <= '(') goto yy730; if (yych <= ')') goto yy729; goto yy731; } else { if (yych <= 0xC1) goto yy730; if (yych <= 0xDF) goto yy733; goto yy734; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy736; goto yy735; } else { if (yych <= 0xF0) goto yy737; if (yych <= 0xF3) goto yy738; if (yych <= 0xF4) goto yy739; goto yy730; } } } } // Match space characters, including newlines. bufsize_t _scan_spacechars(const unsigned char *p) { const unsigned char *start = p; { unsigned char yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yybm[0 + yych] & 128) { goto yy747; } ++p; { return 0; } yy747: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy747; } { return (bufsize_t)(p - start); } } } // Match ATX heading start. bufsize_t _scan_atx_heading_start(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych == '#') goto yy754; ++p; yy753 : { return 0; } yy754: yych = *(marker = ++p); if (yybm[0 + yych] & 128) { goto yy755; } if (yych <= '\f') { if (yych <= 0x08) goto yy753; if (yych <= '\n') goto yy758; goto yy753; } else { if (yych <= '\r') goto yy758; if (yych == '#') goto yy759; goto yy753; } yy755: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy755; } yy757 : { return (bufsize_t)(p - start); } yy758: yych = *++p; goto yy757; yy759: yych = *++p; if (yybm[0 + yych] & 128) { goto yy755; } if (yych <= '\f') { if (yych <= 0x08) goto yy760; if (yych <= '\n') goto yy758; } else { if (yych <= '\r') goto yy758; if (yych == '#') goto yy761; } yy760: p = marker; goto yy753; yy761: yych = *++p; if (yybm[0 + yych] & 128) { goto yy755; } if (yych <= '\f') { if (yych <= 0x08) goto yy760; if (yych <= '\n') goto yy758; goto yy760; } else { if (yych <= '\r') goto yy758; if (yych != '#') goto yy760; } yych = *++p; if (yybm[0 + yych] & 128) { goto yy755; } if (yych <= '\f') { if (yych <= 0x08) goto yy760; if (yych <= '\n') goto yy758; goto yy760; } else { if (yych <= '\r') goto yy758; if (yych != '#') goto yy760; } yych = *++p; if (yybm[0 + yych] & 128) { goto yy755; } if (yych <= '\f') { if (yych <= 0x08) goto yy760; if (yych <= '\n') goto yy758; goto yy760; } else { if (yych <= '\r') goto yy758; if (yych != '#') goto yy760; } ++p; if (yybm[0 + (yych = *p)] & 128) { goto yy755; } if (yych <= 0x08) goto yy760; if (yych <= '\n') goto yy758; if (yych == '\r') goto yy758; goto yy760; } } // Match setext heading line. Return 1 for level-1 heading, // 2 for level-2, 0 for no match. bufsize_t _scan_setext_heading_line(const unsigned char *p) { const unsigned char *marker = NULL; { unsigned char yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych == '-') goto yy769; if (yych == '=') goto yy770; ++p; yy768 : { return 0; } yy769: yych = *(marker = ++p); if (yybm[0 + yych] & 64) { goto yy776; } if (yych <= '\f') { if (yych <= 0x08) goto yy768; if (yych <= '\n') goto yy772; goto yy768; } else { if (yych <= '\r') goto yy772; if (yych == ' ') goto yy772; goto yy768; } yy770: yych = *(marker = ++p); if (yybm[0 + yych] & 128) { goto yy782; } if (yych <= '\f') { if (yych <= 0x08) goto yy768; if (yych <= '\n') goto yy779; goto yy768; } else { if (yych <= '\r') goto yy779; if (yych == ' ') goto yy779; goto yy768; } yy771: ++p; yych = *p; yy772: if (yybm[0 + yych] & 32) { goto yy771; } if (yych <= 0x08) goto yy773; if (yych <= '\n') goto yy774; if (yych == '\r') goto yy774; yy773: p = marker; goto yy768; yy774: ++p; { return 2; } yy776: ++p; yych = *p; if (yybm[0 + yych] & 32) { goto yy771; } if (yych <= '\f') { if (yych <= 0x08) goto yy773; if (yych <= '\n') goto yy774; goto yy773; } else { if (yych <= '\r') goto yy774; if (yych == '-') goto yy776; goto yy773; } yy778: ++p; yych = *p; yy779: if (yych <= '\f') { if (yych <= 0x08) goto yy773; if (yych <= '\t') goto yy778; if (yych >= '\v') goto yy773; } else { if (yych <= '\r') goto yy780; if (yych == ' ') goto yy778; goto yy773; } yy780: ++p; { return 1; } yy782: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy782; } if (yych <= '\f') { if (yych <= 0x08) goto yy773; if (yych <= '\t') goto yy778; if (yych <= '\n') goto yy780; goto yy773; } else { if (yych <= '\r') goto yy780; if (yych == ' ') goto yy778; goto yy773; } } } // Scan an opening code fence. bufsize_t _scan_open_code_fence(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; static const unsigned char yybm[] = { 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 192, 192, 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 144, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 224, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych == '`') goto yy788; if (yych == '~') goto yy789; ++p; yy787 : { return 0; } yy788: yych = *(marker = ++p); if (yych == '`') goto yy790; goto yy787; yy789: yych = *(marker = ++p); if (yych == '~') goto yy792; goto yy787; yy790: yych = *++p; if (yybm[0 + yych] & 16) { goto yy793; } yy791: p = marker; goto yy787; yy792: yych = *++p; if (yybm[0 + yych] & 32) { goto yy795; } goto yy791; yy793: ++p; yych = *p; marker = p; if (yybm[0 + yych] & 64) { goto yy797; } if (yych <= 0xE0) { if (yych <= '`') { if (yych <= 0x00) goto yy791; if (yych <= '\r') goto yy799; goto yy793; } else { if (yych <= 0xC1) goto yy791; if (yych <= 0xDF) goto yy801; goto yy802; } } else { if (yych <= 0xEF) { if (yych == 0xED) goto yy804; goto yy803; } else { if (yych <= 0xF0) goto yy805; if (yych <= 0xF3) goto yy806; if (yych <= 0xF4) goto yy807; goto yy791; } } yy795: ++p; yych = *p; marker = p; if (yybm[0 + yych] & 32) { goto yy795; } if (yych <= 0xDF) { if (yych <= '\f') { if (yych <= 0x00) goto yy791; if (yych == '\n') goto yy810; goto yy808; } else { if (yych <= '\r') goto yy810; if (yych <= 0x7F) goto yy808; if (yych <= 0xC1) goto yy791; goto yy812; } } else { if (yych <= 0xEF) { if (yych <= 0xE0) goto yy813; if (yych == 0xED) goto yy815; goto yy814; } else { if (yych <= 0xF0) goto yy816; if (yych <= 0xF3) goto yy817; if (yych <= 0xF4) goto yy818; goto yy791; } } yy797: ++p; yych = *p; if (yybm[0 + yych] & 64) { goto yy797; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy791; if (yych >= 0x0E) goto yy791; } else { if (yych <= 0xDF) goto yy801; if (yych <= 0xE0) goto yy802; goto yy803; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy804; if (yych <= 0xEF) goto yy803; goto yy805; } else { if (yych <= 0xF3) goto yy806; if (yych <= 0xF4) goto yy807; goto yy791; } } yy799: ++p; p = marker; { return (bufsize_t)(p - start); } yy801: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0xBF) goto yy797; goto yy791; yy802: ++p; yych = *p; if (yych <= 0x9F) goto yy791; if (yych <= 0xBF) goto yy801; goto yy791; yy803: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0xBF) goto yy801; goto yy791; yy804: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0x9F) goto yy801; goto yy791; yy805: ++p; yych = *p; if (yych <= 0x8F) goto yy791; if (yych <= 0xBF) goto yy803; goto yy791; yy806: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0xBF) goto yy803; goto yy791; yy807: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0x8F) goto yy803; goto yy791; yy808: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy808; } if (yych <= 0xEC) { if (yych <= 0xC1) { if (yych <= 0x00) goto yy791; if (yych >= 0x0E) goto yy791; } else { if (yych <= 0xDF) goto yy812; if (yych <= 0xE0) goto yy813; goto yy814; } } else { if (yych <= 0xF0) { if (yych <= 0xED) goto yy815; if (yych <= 0xEF) goto yy814; goto yy816; } else { if (yych <= 0xF3) goto yy817; if (yych <= 0xF4) goto yy818; goto yy791; } } yy810: ++p; p = marker; { return (bufsize_t)(p - start); } yy812: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0xBF) goto yy808; goto yy791; yy813: ++p; yych = *p; if (yych <= 0x9F) goto yy791; if (yych <= 0xBF) goto yy812; goto yy791; yy814: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0xBF) goto yy812; goto yy791; yy815: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0x9F) goto yy812; goto yy791; yy816: ++p; yych = *p; if (yych <= 0x8F) goto yy791; if (yych <= 0xBF) goto yy814; goto yy791; yy817: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0xBF) goto yy814; goto yy791; yy818: ++p; yych = *p; if (yych <= 0x7F) goto yy791; if (yych <= 0x8F) goto yy814; goto yy791; } } // Scan a closing code fence with length at least len. bufsize_t _scan_close_code_fence(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; yych = *p; if (yych == '`') goto yy823; if (yych == '~') goto yy824; ++p; yy822 : { return 0; } yy823: yych = *(marker = ++p); if (yych == '`') goto yy825; goto yy822; yy824: yych = *(marker = ++p); if (yych == '~') goto yy827; goto yy822; yy825: yych = *++p; if (yybm[0 + yych] & 32) { goto yy828; } yy826: p = marker; goto yy822; yy827: yych = *++p; if (yybm[0 + yych] & 64) { goto yy830; } goto yy826; yy828: ++p; yych = *p; marker = p; if (yybm[0 + yych] & 128) { goto yy832; } if (yych <= '\f') { if (yych <= 0x08) goto yy826; if (yych <= '\n') goto yy834; goto yy826; } else { if (yych <= '\r') goto yy834; if (yych == '`') goto yy828; goto yy826; } yy830: ++p; yych = *p; marker = p; if (yybm[0 + yych] & 64) { goto yy830; } if (yych <= '\f') { if (yych <= 0x08) goto yy826; if (yych <= '\t') goto yy836; if (yych <= '\n') goto yy838; goto yy826; } else { if (yych <= '\r') goto yy838; if (yych == ' ') goto yy836; goto yy826; } yy832: ++p; yych = *p; if (yybm[0 + yych] & 128) { goto yy832; } if (yych <= 0x08) goto yy826; if (yych <= '\n') goto yy834; if (yych != '\r') goto yy826; yy834: ++p; p = marker; { return (bufsize_t)(p - start); } yy836: ++p; yych = *p; if (yych <= '\f') { if (yych <= 0x08) goto yy826; if (yych <= '\t') goto yy836; if (yych >= '\v') goto yy826; } else { if (yych <= '\r') goto yy838; if (yych == ' ') goto yy836; goto yy826; } yy838: ++p; p = marker; { return (bufsize_t)(p - start); } } } // Scans an entity. // Returns number of chars matched. bufsize_t _scan_entity(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; yych = *p; if (yych == '&') goto yy844; ++p; yy843 : { return 0; } yy844: yych = *(marker = ++p); if (yych <= '@') { if (yych != '#') goto yy843; } else { if (yych <= 'Z') goto yy847; if (yych <= '`') goto yy843; if (yych <= 'z') goto yy847; goto yy843; } yych = *++p; if (yych <= 'W') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy848; } else { if (yych <= 'X') goto yy849; if (yych == 'x') goto yy849; } yy846: p = marker; goto yy843; yy847: yych = *++p; if (yych <= '@') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy850; goto yy846; } else { if (yych <= 'Z') goto yy850; if (yych <= '`') goto yy846; if (yych <= 'z') goto yy850; goto yy846; } yy848: yych = *++p; if (yych <= '/') goto yy846; if (yych <= '9') goto yy851; if (yych == ';') goto yy852; goto yy846; yy849: yych = *++p; if (yych <= '@') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy854; goto yy846; } else { if (yych <= 'F') goto yy854; if (yych <= '`') goto yy846; if (yych <= 'f') goto yy854; goto yy846; } yy850: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy855; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; goto yy855; } else { if (yych <= '`') goto yy846; if (yych <= 'z') goto yy855; goto yy846; } } yy851: yych = *++p; if (yych <= '/') goto yy846; if (yych <= '9') goto yy856; if (yych != ';') goto yy846; yy852: ++p; { return (bufsize_t)(p - start); } yy854: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy857; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'F') { if (yych <= '@') goto yy846; goto yy857; } else { if (yych <= '`') goto yy846; if (yych <= 'f') goto yy857; goto yy846; } } yy855: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy858; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; goto yy858; } else { if (yych <= '`') goto yy846; if (yych <= 'z') goto yy858; goto yy846; } } yy856: yych = *++p; if (yych <= '/') goto yy846; if (yych <= '9') goto yy859; if (yych == ';') goto yy852; goto yy846; yy857: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy860; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'F') { if (yych <= '@') goto yy846; goto yy860; } else { if (yych <= '`') goto yy846; if (yych <= 'f') goto yy860; goto yy846; } } yy858: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy861; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; goto yy861; } else { if (yych <= '`') goto yy846; if (yych <= 'z') goto yy861; goto yy846; } } yy859: yych = *++p; if (yych <= '/') goto yy846; if (yych <= '9') goto yy862; if (yych == ';') goto yy852; goto yy846; yy860: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy863; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'F') { if (yych <= '@') goto yy846; goto yy863; } else { if (yych <= '`') goto yy846; if (yych <= 'f') goto yy863; goto yy846; } } yy861: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy864; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; goto yy864; } else { if (yych <= '`') goto yy846; if (yych <= 'z') goto yy864; goto yy846; } } yy862: yych = *++p; if (yych <= '/') goto yy846; if (yych <= '9') goto yy865; if (yych == ';') goto yy852; goto yy846; yy863: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy866; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'F') { if (yych <= '@') goto yy846; goto yy866; } else { if (yych <= '`') goto yy846; if (yych <= 'f') goto yy866; goto yy846; } } yy864: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy867; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; goto yy867; } else { if (yych <= '`') goto yy846; if (yych <= 'z') goto yy867; goto yy846; } } yy865: yych = *++p; if (yych <= '/') goto yy846; if (yych <= '9') goto yy868; if (yych == ';') goto yy852; goto yy846; yy866: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy868; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'F') { if (yych <= '@') goto yy846; goto yy868; } else { if (yych <= '`') goto yy846; if (yych <= 'f') goto yy868; goto yy846; } } yy867: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy869; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; goto yy869; } else { if (yych <= '`') goto yy846; if (yych <= 'z') goto yy869; goto yy846; } } yy868: yych = *++p; if (yych == ';') goto yy852; goto yy846; yy869: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy870; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy870: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy871; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy871: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy872; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy872: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy873; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy873: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy874; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy874: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy875; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy875: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy876; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy876: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy877; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy877: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy878; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy878: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy879; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy879: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy880; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy880: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy881; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy881: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy882; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy882: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy883; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy883: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy884; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy884: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy885; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy885: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy886; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy886: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy887; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy887: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy888; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy888: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy889; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy889: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy890; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy890: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy891; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy891: yych = *++p; if (yych <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy892; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; } else { if (yych <= '`') goto yy846; if (yych >= '{') goto yy846; } } yy892: ++p; if ((yych = *p) <= ';') { if (yych <= '/') goto yy846; if (yych <= '9') goto yy868; if (yych <= ':') goto yy846; goto yy852; } else { if (yych <= 'Z') { if (yych <= '@') goto yy846; goto yy868; } else { if (yych <= '`') goto yy846; if (yych <= 'z') goto yy868; goto yy846; } } } } // Returns positive value if a URL begins in a way that is potentially // dangerous, with javascript:, vbscript:, file:, or data:, otherwise 0. bufsize_t _scan_dangerous_url(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; { unsigned char yych; unsigned int yyaccept = 0; yych = *p; if (yych <= 'V') { if (yych <= 'F') { if (yych == 'D') goto yy897; if (yych >= 'F') goto yy898; } else { if (yych == 'J') goto yy899; if (yych >= 'V') goto yy900; } } else { if (yych <= 'f') { if (yych == 'd') goto yy897; if (yych >= 'f') goto yy898; } else { if (yych <= 'j') { if (yych >= 'j') goto yy899; } else { if (yych == 'v') goto yy900; } } } ++p; yy896 : { return 0; } yy897: yyaccept = 0; yych = *(marker = ++p); if (yych == 'A') goto yy901; if (yych == 'a') goto yy901; goto yy896; yy898: yyaccept = 0; yych = *(marker = ++p); if (yych == 'I') goto yy903; if (yych == 'i') goto yy903; goto yy896; yy899: yyaccept = 0; yych = *(marker = ++p); if (yych == 'A') goto yy904; if (yych == 'a') goto yy904; goto yy896; yy900: yyaccept = 0; yych = *(marker = ++p); if (yych == 'B') goto yy905; if (yych == 'b') goto yy905; goto yy896; yy901: yych = *++p; if (yych == 'T') goto yy906; if (yych == 't') goto yy906; yy902: p = marker; if (yyaccept == 0) { goto yy896; } else { goto yy914; } yy903: yych = *++p; if (yych == 'L') goto yy907; if (yych == 'l') goto yy907; goto yy902; yy904: yych = *++p; if (yych == 'V') goto yy908; if (yych == 'v') goto yy908; goto yy902; yy905: yych = *++p; if (yych == 'S') goto yy909; if (yych == 's') goto yy909; goto yy902; yy906: yych = *++p; if (yych == 'A') goto yy910; if (yych == 'a') goto yy910; goto yy902; yy907: yych = *++p; if (yych == 'E') goto yy911; if (yych == 'e') goto yy911; goto yy902; yy908: yych = *++p; if (yych == 'A') goto yy905; if (yych == 'a') goto yy905; goto yy902; yy909: yych = *++p; if (yych == 'C') goto yy912; if (yych == 'c') goto yy912; goto yy902; yy910: yych = *++p; if (yych == ':') goto yy913; goto yy902; yy911: yych = *++p; if (yych == ':') goto yy915; goto yy902; yy912: yych = *++p; if (yych == 'R') goto yy916; if (yych == 'r') goto yy916; goto yy902; yy913: yyaccept = 1; yych = *(marker = ++p); if (yych == 'I') goto yy917; if (yych == 'i') goto yy917; yy914 : { return (bufsize_t)(p - start); } yy915: yych = *++p; goto yy914; yy916: yych = *++p; if (yych == 'I') goto yy918; if (yych == 'i') goto yy918; goto yy902; yy917: yych = *++p; if (yych == 'M') goto yy919; if (yych == 'm') goto yy919; goto yy902; yy918: yych = *++p; if (yych == 'P') goto yy920; if (yych == 'p') goto yy920; goto yy902; yy919: yych = *++p; if (yych == 'A') goto yy921; if (yych == 'a') goto yy921; goto yy902; yy920: yych = *++p; if (yych == 'T') goto yy911; if (yych == 't') goto yy911; goto yy902; yy921: yych = *++p; if (yych == 'G') goto yy922; if (yych != 'g') goto yy902; yy922: yych = *++p; if (yych == 'E') goto yy923; if (yych != 'e') goto yy902; yy923: yych = *++p; if (yych != '/') goto yy902; yych = *++p; if (yych <= 'W') { if (yych <= 'J') { if (yych == 'G') goto yy925; if (yych <= 'I') goto yy902; goto yy926; } else { if (yych == 'P') goto yy927; if (yych <= 'V') goto yy902; goto yy928; } } else { if (yych <= 'j') { if (yych == 'g') goto yy925; if (yych <= 'i') goto yy902; goto yy926; } else { if (yych <= 'p') { if (yych <= 'o') goto yy902; goto yy927; } else { if (yych == 'w') goto yy928; goto yy902; } } } yy925: yych = *++p; if (yych == 'I') goto yy929; if (yych == 'i') goto yy929; goto yy902; yy926: yych = *++p; if (yych == 'P') goto yy930; if (yych == 'p') goto yy930; goto yy902; yy927: yych = *++p; if (yych == 'N') goto yy931; if (yych == 'n') goto yy931; goto yy902; yy928: yych = *++p; if (yych == 'E') goto yy932; if (yych == 'e') goto yy932; goto yy902; yy929: yych = *++p; if (yych == 'F') goto yy933; if (yych == 'f') goto yy933; goto yy902; yy930: yych = *++p; if (yych == 'E') goto yy931; if (yych != 'e') goto yy902; yy931: yych = *++p; if (yych == 'G') goto yy933; if (yych == 'g') goto yy933; goto yy902; yy932: yych = *++p; if (yych == 'B') goto yy935; if (yych == 'b') goto yy935; goto yy902; yy933: ++p; { return 0; } yy935: ++p; if ((yych = *p) == 'P') goto yy933; if (yych == 'p') goto yy933; goto yy902; } } ================================================ FILE: liteidex/src/3rdparty/cmark/src/scanners.h ================================================ #include "cmark.h" #include "chunk.h" #ifdef __cplusplus extern "C" { #endif bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c, bufsize_t offset); bufsize_t _scan_scheme(const unsigned char *p); bufsize_t _scan_autolink_uri(const unsigned char *p); bufsize_t _scan_autolink_email(const unsigned char *p); bufsize_t _scan_html_tag(const unsigned char *p); bufsize_t _scan_html_block_start(const unsigned char *p); bufsize_t _scan_html_block_start_7(const unsigned char *p); bufsize_t _scan_html_block_end_1(const unsigned char *p); bufsize_t _scan_html_block_end_2(const unsigned char *p); bufsize_t _scan_html_block_end_3(const unsigned char *p); bufsize_t _scan_html_block_end_4(const unsigned char *p); bufsize_t _scan_html_block_end_5(const unsigned char *p); bufsize_t _scan_link_title(const unsigned char *p); bufsize_t _scan_spacechars(const unsigned char *p); bufsize_t _scan_atx_heading_start(const unsigned char *p); bufsize_t _scan_setext_heading_line(const unsigned char *p); bufsize_t _scan_open_code_fence(const unsigned char *p); bufsize_t _scan_close_code_fence(const unsigned char *p); bufsize_t _scan_entity(const unsigned char *p); bufsize_t _scan_dangerous_url(const unsigned char *p); #define scan_scheme(c, n) _scan_at(&_scan_scheme, c, n) #define scan_autolink_uri(c, n) _scan_at(&_scan_autolink_uri, c, n) #define scan_autolink_email(c, n) _scan_at(&_scan_autolink_email, c, n) #define scan_html_tag(c, n) _scan_at(&_scan_html_tag, c, n) #define scan_html_block_start(c, n) _scan_at(&_scan_html_block_start, c, n) #define scan_html_block_start_7(c, n) _scan_at(&_scan_html_block_start_7, c, n) #define scan_html_block_end_1(c, n) _scan_at(&_scan_html_block_end_1, c, n) #define scan_html_block_end_2(c, n) _scan_at(&_scan_html_block_end_2, c, n) #define scan_html_block_end_3(c, n) _scan_at(&_scan_html_block_end_3, c, n) #define scan_html_block_end_4(c, n) _scan_at(&_scan_html_block_end_4, c, n) #define scan_html_block_end_5(c, n) _scan_at(&_scan_html_block_end_5, c, n) #define scan_link_title(c, n) _scan_at(&_scan_link_title, c, n) #define scan_spacechars(c, n) _scan_at(&_scan_spacechars, c, n) #define scan_atx_heading_start(c, n) _scan_at(&_scan_atx_heading_start, c, n) #define scan_setext_heading_line(c, n) \ _scan_at(&_scan_setext_heading_line, c, n) #define scan_open_code_fence(c, n) _scan_at(&_scan_open_code_fence, c, n) #define scan_close_code_fence(c, n) _scan_at(&_scan_close_code_fence, c, n) #define scan_entity(c, n) _scan_at(&_scan_entity, c, n) #define scan_dangerous_url(c, n) _scan_at(&_scan_dangerous_url, c, n) #ifdef __cplusplus } #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/scanners.re ================================================ #include #include "chunk.h" #include "scanners.h" bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c, bufsize_t offset) { bufsize_t res; unsigned char *ptr = (unsigned char *)c->data; if (ptr == NULL || offset > c->len) { return 0; } else { unsigned char lim = ptr[c->len]; ptr[c->len] = '\0'; res = scanner(ptr + offset); ptr[c->len] = lim; } return res; } /*!re2c re2c:define:YYCTYPE = "unsigned char"; re2c:define:YYCURSOR = p; re2c:define:YYMARKER = marker; re2c:define:YYCTXMARKER = marker; re2c:yyfill:enable = 0; wordchar = [^\x00-\x20]; spacechar = [ \t\v\f\r\n]; reg_char = [^\\()\x00-\x20]; escaped_char = [\\][!"#$%&'()*+,./:;<=>?@[\\\]^_`{|}~-]; tagname = [A-Za-z][A-Za-z0-9-]*; blocktagname = 'address'|'article'|'aside'|'base'|'basefont'|'blockquote'|'body'|'caption'|'center'|'col'|'colgroup'|'dd'|'details'|'dialog'|'dir'|'div'|'dl'|'dt'|'fieldset'|'figcaption'|'figure'|'footer'|'form'|'frame'|'frameset'|'h1'|'h2'|'h3'|'h4'|'h5'|'h6'|'head'|'header'|'hr'|'html'|'iframe'|'legend'|'li'|'link'|'main'|'menu'|'menuitem'|'nav'|'noframes'|'ol'|'optgroup'|'option'|'p'|'param'|'section'|'source'|'title'|'summary'|'table'|'tbody'|'td'|'tfoot'|'th'|'thead'|'title'|'tr'|'track'|'ul'; attributename = [a-zA-Z_:][a-zA-Z0-9:._-]*; unquotedvalue = [^ \t\r\n\v\f"'=<>`\x00]+; singlequotedvalue = ['][^'\x00]*[']; doublequotedvalue = ["][^"\x00]*["]; attributevalue = unquotedvalue | singlequotedvalue | doublequotedvalue; attributevaluespec = spacechar* [=] spacechar* attributevalue; attribute = spacechar+ attributename attributevaluespec?; opentag = tagname attribute* spacechar* [/]? [>]; closetag = [/] tagname spacechar* [>]; htmlcomment = "!---->" | ("!--" ([-]? [^\x00>-]) ([-]? [^\x00-])* "-->"); processinginstruction = "?" ([^?>\x00]+ | [?][^>\x00] | [>])* "?>"; declaration = "!" [A-Z]+ spacechar+ [^>\x00]* ">"; cdata = "![CDATA[" ([^\]\x00]+ | "]" [^\]\x00] | "]]" [^>\x00])* "]]>"; htmltag = opentag | closetag | htmlcomment | processinginstruction | declaration | cdata; in_parens_nosp = [(] (reg_char|escaped_char|[\\])* [)]; in_double_quotes = ["] (escaped_char|[^"\x00])* ["]; in_single_quotes = ['] (escaped_char|[^'\x00])* [']; in_parens = [(] (escaped_char|[^)\x00])* [)]; scheme = [A-Za-z][A-Za-z0-9.+-]{1,31}; */ // Try to match a scheme including colon. bufsize_t _scan_scheme(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c scheme [:] { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match URI autolink after first <, returning number of chars matched. bufsize_t _scan_autolink_uri(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c scheme [:][^\x00-\x20<>]*[>] { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match email autolink after first <, returning num of chars matched. bufsize_t _scan_autolink_email(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+ [@] [a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? ([.][a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)* [>] { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match an HTML tag after first <, returning num of chars matched. bufsize_t _scan_html_tag(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c htmltag { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match an HTML block tag start line, returning // an integer code for the type of block (1-6, matching the spec). // #7 is handled by a separate function, below. bufsize_t _scan_html_block_start(const unsigned char *p) { const unsigned char *marker = NULL; /*!re2c [<] ('script'|'pre'|'style') (spacechar | [>]) { return 1; } '' { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match an HTML block end line of type 3 bufsize_t _scan_html_block_end_3(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [^\n\x00]* '?>' { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match an HTML block end line of type 4 bufsize_t _scan_html_block_end_4(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [^\n\x00]* '>' { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match an HTML block end line of type 5 bufsize_t _scan_html_block_end_5(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [^\n\x00]* ']]>' { return (bufsize_t)(p - start); } * { return 0; } */ } // Try to match a link title (in single quotes, in double quotes, or // in parentheses), returning number of chars matched. Allow one // level of internal nesting (quotes within quotes). bufsize_t _scan_link_title(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c ["] (escaped_char|[^"\x00])* ["] { return (bufsize_t)(p - start); } ['] (escaped_char|[^'\x00])* ['] { return (bufsize_t)(p - start); } [(] (escaped_char|[^()\x00])* [)] { return (bufsize_t)(p - start); } * { return 0; } */ } // Match space characters, including newlines. bufsize_t _scan_spacechars(const unsigned char *p) { const unsigned char *start = p; \ /*!re2c [ \t\v\f\r\n]+ { return (bufsize_t)(p - start); } * { return 0; } */ } // Match ATX heading start. bufsize_t _scan_atx_heading_start(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [#]{1,6} ([ \t]+|[\r\n]) { return (bufsize_t)(p - start); } * { return 0; } */ } // Match setext heading line. Return 1 for level-1 heading, // 2 for level-2, 0 for no match. bufsize_t _scan_setext_heading_line(const unsigned char *p) { const unsigned char *marker = NULL; /*!re2c [=]+ [ \t]* [\r\n] { return 1; } [-]+ [ \t]* [\r\n] { return 2; } * { return 0; } */ } // Scan an opening code fence. bufsize_t _scan_open_code_fence(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [`]{3,} / [^`\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); } [~]{3,} / [^\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); } * { return 0; } */ } // Scan a closing code fence with length at least len. bufsize_t _scan_close_code_fence(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [`]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); } [~]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); } * { return 0; } */ } // Scans an entity. // Returns number of chars matched. bufsize_t _scan_entity(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c [&] ([#] ([Xx][A-Fa-f0-9]{1,6}|[0-9]{1,7}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;] { return (bufsize_t)(p - start); } * { return 0; } */ } // Returns positive value if a URL begins in a way that is potentially // dangerous, with javascript:, vbscript:, file:, or data:, otherwise 0. bufsize_t _scan_dangerous_url(const unsigned char *p) { const unsigned char *marker = NULL; const unsigned char *start = p; /*!re2c 'data:image/' ('png'|'gif'|'jpeg'|'webp') { return 0; } 'javascript:' | 'vbscript:' | 'file:' | 'data:' { return (bufsize_t)(p - start); } * { return 0; } */ } ================================================ FILE: liteidex/src/3rdparty/cmark/src/utf8.c ================================================ #include #include #include #include "cmark_ctype.h" #include "utf8.h" static const int8_t utf8proc_utf8class[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0}; static void encode_unknown(cmark_strbuf *buf) { static const uint8_t repl[] = {239, 191, 189}; cmark_strbuf_put(buf, repl, 3); } static int utf8proc_charlen(const uint8_t *str, bufsize_t str_len) { int length, i; if (!str_len) return 0; length = utf8proc_utf8class[str[0]]; if (!length) return -1; if (str_len >= 0 && (bufsize_t)length > str_len) return -str_len; for (i = 1; i < length; i++) { if ((str[i] & 0xC0) != 0x80) return -i; } return length; } // Validate a single UTF-8 character according to RFC 3629. static int utf8proc_valid(const uint8_t *str, bufsize_t str_len) { int length = utf8proc_utf8class[str[0]]; if (!length) return -1; if ((bufsize_t)length > str_len) return -str_len; switch (length) { case 2: if ((str[1] & 0xC0) != 0x80) return -1; if (str[0] < 0xC2) { // Overlong return -length; } break; case 3: if ((str[1] & 0xC0) != 0x80) return -1; if ((str[2] & 0xC0) != 0x80) return -2; if (str[0] == 0xE0) { if (str[1] < 0xA0) { // Overlong return -length; } } else if (str[0] == 0xED) { if (str[1] >= 0xA0) { // Surrogate return -length; } } break; case 4: if ((str[1] & 0xC0) != 0x80) return -1; if ((str[2] & 0xC0) != 0x80) return -2; if ((str[3] & 0xC0) != 0x80) return -3; if (str[0] == 0xF0) { if (str[1] < 0x90) { // Overlong return -length; } } else if (str[0] >= 0xF4) { if (str[0] > 0xF4 || str[1] >= 0x90) { // Above 0x10FFFF return -length; } } break; } return length; } void cmark_utf8proc_check(cmark_strbuf *ob, const uint8_t *line, bufsize_t size) { bufsize_t i = 0; while (i < size) { bufsize_t org = i; int charlen = 0; while (i < size) { if (line[i] < 0x80 && line[i] != 0) { i++; } else if (line[i] >= 0x80) { charlen = utf8proc_valid(line + i, size - i); if (charlen < 0) { charlen = -charlen; break; } i += charlen; } else if (line[i] == 0) { // ASCII NUL is technically valid but rejected // for security reasons. charlen = 1; break; } } if (i > org) { cmark_strbuf_put(ob, line + org, i - org); } if (i >= size) { break; } else { // Invalid UTF-8 encode_unknown(ob); i += charlen; } } } int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len, int32_t *dst) { int length; int32_t uc = -1; *dst = -1; length = utf8proc_charlen(str, str_len); if (length < 0) return -1; switch (length) { case 1: uc = str[0]; break; case 2: uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F); if (uc < 0x80) uc = -1; break; case 3: uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6) + (str[2] & 0x3F); if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000)) uc = -1; break; case 4: uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12) + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F); if (uc < 0x10000 || uc >= 0x110000) uc = -1; break; } if (uc < 0) return -1; *dst = uc; return length; } void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf) { uint8_t dst[4]; bufsize_t len = 0; assert(uc >= 0); if (uc < 0x80) { dst[0] = (uint8_t)(uc); len = 1; } else if (uc < 0x800) { dst[0] = (uint8_t)(0xC0 + (uc >> 6)); dst[1] = 0x80 + (uc & 0x3F); len = 2; } else if (uc == 0xFFFF) { dst[0] = 0xFF; len = 1; } else if (uc == 0xFFFE) { dst[0] = 0xFE; len = 1; } else if (uc < 0x10000) { dst[0] = (uint8_t)(0xE0 + (uc >> 12)); dst[1] = 0x80 + ((uc >> 6) & 0x3F); dst[2] = 0x80 + (uc & 0x3F); len = 3; } else if (uc < 0x110000) { dst[0] = (uint8_t)(0xF0 + (uc >> 18)); dst[1] = 0x80 + ((uc >> 12) & 0x3F); dst[2] = 0x80 + ((uc >> 6) & 0x3F); dst[3] = 0x80 + (uc & 0x3F); len = 4; } else { encode_unknown(buf); return; } cmark_strbuf_put(buf, dst, len); } void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str, bufsize_t len) { int32_t c; #define bufpush(x) cmark_utf8proc_encode_char(x, dest) while (len > 0) { bufsize_t char_len = cmark_utf8proc_iterate(str, len, &c); if (char_len >= 0) { #include "case_fold_switch.inc" } else { encode_unknown(dest); char_len = -char_len; } str += char_len; len -= char_len; } } // matches anything in the Zs class, plus LF, CR, TAB, FF. int cmark_utf8proc_is_space(int32_t uc) { return (uc == 9 || uc == 10 || uc == 12 || uc == 13 || uc == 32 || uc == 160 || uc == 5760 || (uc >= 8192 && uc <= 8202) || uc == 8239 || uc == 8287 || uc == 12288); } // matches anything in the P[cdefios] classes. int cmark_utf8proc_is_punctuation(int32_t uc) { return ( (uc < 128 && cmark_ispunct((char)uc)) || uc == 161 || uc == 167 || uc == 171 || uc == 182 || uc == 183 || uc == 187 || uc == 191 || uc == 894 || uc == 903 || (uc >= 1370 && uc <= 1375) || uc == 1417 || uc == 1418 || uc == 1470 || uc == 1472 || uc == 1475 || uc == 1478 || uc == 1523 || uc == 1524 || uc == 1545 || uc == 1546 || uc == 1548 || uc == 1549 || uc == 1563 || uc == 1566 || uc == 1567 || (uc >= 1642 && uc <= 1645) || uc == 1748 || (uc >= 1792 && uc <= 1805) || (uc >= 2039 && uc <= 2041) || (uc >= 2096 && uc <= 2110) || uc == 2142 || uc == 2404 || uc == 2405 || uc == 2416 || uc == 2800 || uc == 3572 || uc == 3663 || uc == 3674 || uc == 3675 || (uc >= 3844 && uc <= 3858) || uc == 3860 || (uc >= 3898 && uc <= 3901) || uc == 3973 || (uc >= 4048 && uc <= 4052) || uc == 4057 || uc == 4058 || (uc >= 4170 && uc <= 4175) || uc == 4347 || (uc >= 4960 && uc <= 4968) || uc == 5120 || uc == 5741 || uc == 5742 || uc == 5787 || uc == 5788 || (uc >= 5867 && uc <= 5869) || uc == 5941 || uc == 5942 || (uc >= 6100 && uc <= 6102) || (uc >= 6104 && uc <= 6106) || (uc >= 6144 && uc <= 6154) || uc == 6468 || uc == 6469 || uc == 6686 || uc == 6687 || (uc >= 6816 && uc <= 6822) || (uc >= 6824 && uc <= 6829) || (uc >= 7002 && uc <= 7008) || (uc >= 7164 && uc <= 7167) || (uc >= 7227 && uc <= 7231) || uc == 7294 || uc == 7295 || (uc >= 7360 && uc <= 7367) || uc == 7379 || (uc >= 8208 && uc <= 8231) || (uc >= 8240 && uc <= 8259) || (uc >= 8261 && uc <= 8273) || (uc >= 8275 && uc <= 8286) || uc == 8317 || uc == 8318 || uc == 8333 || uc == 8334 || (uc >= 8968 && uc <= 8971) || uc == 9001 || uc == 9002 || (uc >= 10088 && uc <= 10101) || uc == 10181 || uc == 10182 || (uc >= 10214 && uc <= 10223) || (uc >= 10627 && uc <= 10648) || (uc >= 10712 && uc <= 10715) || uc == 10748 || uc == 10749 || (uc >= 11513 && uc <= 11516) || uc == 11518 || uc == 11519 || uc == 11632 || (uc >= 11776 && uc <= 11822) || (uc >= 11824 && uc <= 11842) || (uc >= 12289 && uc <= 12291) || (uc >= 12296 && uc <= 12305) || (uc >= 12308 && uc <= 12319) || uc == 12336 || uc == 12349 || uc == 12448 || uc == 12539 || uc == 42238 || uc == 42239 || (uc >= 42509 && uc <= 42511) || uc == 42611 || uc == 42622 || (uc >= 42738 && uc <= 42743) || (uc >= 43124 && uc <= 43127) || uc == 43214 || uc == 43215 || (uc >= 43256 && uc <= 43258) || uc == 43310 || uc == 43311 || uc == 43359 || (uc >= 43457 && uc <= 43469) || uc == 43486 || uc == 43487 || (uc >= 43612 && uc <= 43615) || uc == 43742 || uc == 43743 || uc == 43760 || uc == 43761 || uc == 44011 || uc == 64830 || uc == 64831 || (uc >= 65040 && uc <= 65049) || (uc >= 65072 && uc <= 65106) || (uc >= 65108 && uc <= 65121) || uc == 65123 || uc == 65128 || uc == 65130 || uc == 65131 || (uc >= 65281 && uc <= 65283) || (uc >= 65285 && uc <= 65290) || (uc >= 65292 && uc <= 65295) || uc == 65306 || uc == 65307 || uc == 65311 || uc == 65312 || (uc >= 65339 && uc <= 65341) || uc == 65343 || uc == 65371 || uc == 65373 || (uc >= 65375 && uc <= 65381) || (uc >= 65792 && uc <= 65794) || uc == 66463 || uc == 66512 || uc == 66927 || uc == 67671 || uc == 67871 || uc == 67903 || (uc >= 68176 && uc <= 68184) || uc == 68223 || (uc >= 68336 && uc <= 68342) || (uc >= 68409 && uc <= 68415) || (uc >= 68505 && uc <= 68508) || (uc >= 69703 && uc <= 69709) || uc == 69819 || uc == 69820 || (uc >= 69822 && uc <= 69825) || (uc >= 69952 && uc <= 69955) || uc == 70004 || uc == 70005 || (uc >= 70085 && uc <= 70088) || uc == 70093 || (uc >= 70200 && uc <= 70205) || uc == 70854 || (uc >= 71105 && uc <= 71113) || (uc >= 71233 && uc <= 71235) || (uc >= 74864 && uc <= 74868) || uc == 92782 || uc == 92783 || uc == 92917 || (uc >= 92983 && uc <= 92987) || uc == 92996 || uc == 113823); } ================================================ FILE: liteidex/src/3rdparty/cmark/src/utf8.h ================================================ #ifndef CMARK_UTF8_H #define CMARK_UTF8_H #include #include "buffer.h" #ifdef __cplusplus extern "C" { #endif void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str, bufsize_t len); void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf); int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len, int32_t *dst); void cmark_utf8proc_check(cmark_strbuf *dest, const uint8_t *line, bufsize_t size); int cmark_utf8proc_is_space(int32_t uc); int cmark_utf8proc_is_punctuation(int32_t uc); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/cmark/src/xml.c ================================================ #include #include #include #include #include "config.h" #include "cmark.h" #include "node.h" #include "buffer.h" #include "houdini.h" #define BUFFER_SIZE 100 // Functions to convert cmark_nodes to XML strings. static void escape_xml(cmark_strbuf *dest, const unsigned char *source, bufsize_t length) { houdini_escape_html0(dest, source, length, 0); } struct render_state { cmark_strbuf *xml; int indent; }; static CMARK_INLINE void indent(struct render_state *state) { int i; for (i = 0; i < state->indent; i++) { cmark_strbuf_putc(state->xml, ' '); } } static int S_render_node(cmark_node *node, cmark_event_type ev_type, struct render_state *state, int options) { cmark_strbuf *xml = state->xml; bool literal = false; cmark_delim_type delim; bool entering = (ev_type == CMARK_EVENT_ENTER); char buffer[BUFFER_SIZE]; if (entering) { indent(state); cmark_strbuf_putc(xml, '<'); cmark_strbuf_puts(xml, cmark_node_get_type_string(node)); if (options & CMARK_OPT_SOURCEPOS && node->start_line != 0) { snprintf(buffer, BUFFER_SIZE, " sourcepos=\"%d:%d-%d:%d\"", node->start_line, node->start_column, node->end_line, node->end_column); cmark_strbuf_puts(xml, buffer); } literal = false; switch (node->type) { case CMARK_NODE_DOCUMENT: cmark_strbuf_puts(xml, " xmlns=\"http://commonmark.org/xml/1.0\""); break; case CMARK_NODE_TEXT: case CMARK_NODE_CODE: case CMARK_NODE_HTML_BLOCK: case CMARK_NODE_HTML_INLINE: cmark_strbuf_puts(xml, " xml:space=\"preserve\">"); escape_xml(xml, node->as.literal.data, node->as.literal.len); cmark_strbuf_puts(xml, "as.heading.level); cmark_strbuf_puts(xml, buffer); break; case CMARK_NODE_CODE_BLOCK: if (node->as.code.info.len > 0) { cmark_strbuf_puts(xml, " info=\""); escape_xml(xml, node->as.code.info.data, node->as.code.info.len); cmark_strbuf_putc(xml, '"'); } cmark_strbuf_puts(xml, " xml:space=\"preserve\">"); escape_xml(xml, node->as.code.literal.data, node->as.code.literal.len); cmark_strbuf_puts(xml, "as.custom.on_enter.data, node->as.custom.on_enter.len); cmark_strbuf_putc(xml, '"'); cmark_strbuf_puts(xml, " on_exit=\""); escape_xml(xml, node->as.custom.on_exit.data, node->as.custom.on_exit.len); cmark_strbuf_putc(xml, '"'); break; case CMARK_NODE_LINK: case CMARK_NODE_IMAGE: cmark_strbuf_puts(xml, " destination=\""); escape_xml(xml, node->as.link.url.data, node->as.link.url.len); cmark_strbuf_putc(xml, '"'); cmark_strbuf_puts(xml, " title=\""); escape_xml(xml, node->as.link.title.data, node->as.link.title.len); cmark_strbuf_putc(xml, '"'); break; default: break; } if (node->first_child) { state->indent += 2; } else if (!literal) { cmark_strbuf_puts(xml, " /"); } cmark_strbuf_puts(xml, ">\n"); } else if (node->first_child) { state->indent -= 2; indent(state); cmark_strbuf_puts(xml, "\n"); } return 1; } char *cmark_render_xml(cmark_node *root, int options) { char *result; cmark_strbuf xml = CMARK_BUF_INIT(cmark_node_mem(root)); cmark_event_type ev_type; cmark_node *cur; struct render_state state = {&xml, 0}; cmark_iter *iter = cmark_iter_new(root); cmark_strbuf_puts(state.xml, "\n"); cmark_strbuf_puts(state.xml, "\n"); while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { cur = cmark_iter_get_node(iter); S_render_node(cur, ev_type, &state, options); } result = (char *)cmark_strbuf_detach(&xml); cmark_iter_free(iter); return result; } ================================================ FILE: liteidex/src/3rdparty/cplusplus/BackwardsScanner.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "BackwardsScanner.h" #include #include #include using namespace CPlusPlus; BackwardsScanner::BackwardsScanner(LanguageFeatures features, const QTextCursor &cursor, int maxBlockCount, const QString &suffix, bool skipComments) : _offset(0) , _blocksTokenized(0) , _block(cursor.block()) , _maxBlockCount(maxBlockCount) { // FIXME: Why these defaults? _tokenize.setLanguageFeatures(features); _tokenize.setSkipComments(skipComments); _text = _block.text().left(cursor.position() - cursor.block().position()); if (! suffix.isEmpty()) _text += suffix; _tokens.append(_tokenize(_text, previousBlockState(_block))); _startToken = _tokens.size(); } Token BackwardsScanner::LA(int index) const { return const_cast(this)->fetchToken(_startToken - index); } Token BackwardsScanner::operator[](int index) const { return const_cast(this)->fetchToken(index); } const Token &BackwardsScanner::fetchToken(int tokenIndex) { while (_offset + tokenIndex < 0) { _block = _block.previous(); if (_blocksTokenized == _maxBlockCount || !_block.isValid()) { ++_offset; _tokens.prepend(Token()); // sentinel break; } else { ++_blocksTokenized; QString blockText = _block.text(); _text.prepend(QLatin1Char('\n')); _text.prepend(blockText); QList adaptedTokens; for (int i = 0; i < _tokens.size(); ++i) { Token t = _tokens.at(i); t.offset += + blockText.length() + 1; adaptedTokens.append(t); } _tokens = _tokenize(blockText, previousBlockState(_block)); _offset += _tokens.size(); _tokens += adaptedTokens; } } return _tokens.at(_offset + tokenIndex); } int BackwardsScanner::startToken() const { return _startToken; } int BackwardsScanner::startPosition() const { return _block.position(); } QString BackwardsScanner::text() const { return _text; } QString BackwardsScanner::mid(int index) const { const Token &firstToken = _tokens.at(index + _offset); return _text.mid(firstToken.begin()); } QString BackwardsScanner::text(int index) const { const Token &firstToken = _tokens.at(index + _offset); return _text.mid(firstToken.begin(), firstToken.length()); } QStringRef BackwardsScanner::textRef(int index) const { const Token &firstToken = _tokens.at(index + _offset); return _text.midRef(firstToken.begin(), firstToken.length()); } int BackwardsScanner::size() const { return _tokens.size(); } int BackwardsScanner::startOfMatchingBrace(int index) const { const BackwardsScanner &tk = *this; if (tk[index - 1].is(T_RPAREN)) { int i = index - 1; int count = 0; do { if (tk[i].is(T_LPAREN)) { if (! ++count) return i; } else if (tk[i].is(T_RPAREN)) --count; --i; } while (count != 0 && tk[i].isNot(T_EOF_SYMBOL)); } else if (tk[index - 1].is(T_RBRACKET)) { int i = index - 1; int count = 0; do { if (tk[i].is(T_LBRACKET)) { if (! ++count) return i; } else if (tk[i].is(T_RBRACKET)) --count; --i; } while (count != 0 && tk[i].isNot(T_EOF_SYMBOL)); } else if (tk[index - 1].is(T_RBRACE)) { int i = index - 1; int count = 0; do { if (tk[i].is(T_LBRACE)) { if (! ++count) return i; } else if (tk[i].is(T_RBRACE)) --count; --i; } while (count != 0 && tk[i].isNot(T_EOF_SYMBOL)); } else if (tk[index - 1].is(T_GREATER)) { int i = index - 1; int count = 0; do { if (tk[i].is(T_LESS)) { if (! ++count) return i; } else if (tk[i].is(T_GREATER)) --count; --i; } while (count != 0 && tk[i].isNot(T_EOF_SYMBOL)); } else { Q_ASSERT(0); } return index; } int BackwardsScanner::startOfLine(int index) const { const BackwardsScanner tk(*this); forever { const Token &tok = tk[index - 1]; if (tok.is(T_EOF_SYMBOL)) break; else if (tok.newline()) return index - 1; --index; } return index; } int BackwardsScanner::startOfBlock(int index) const { const BackwardsScanner tk(*this); const int start = index; forever { Token token = tk[index - 1]; if (token.is(T_EOF_SYMBOL)) { break; } else if (token.is(T_GREATER)) { const int matchingBrace = startOfMatchingBrace(index); if (matchingBrace != index && tk[matchingBrace - 1].is(T_TEMPLATE)) index = matchingBrace; } else if (token.is(T_RPAREN) || token.is(T_RBRACKET) || token.is(T_RBRACE)) { const int matchingBrace = startOfMatchingBrace(index); if (matchingBrace != index) index = matchingBrace; } else if (token.is(T_LPAREN) || token.is(T_LBRACKET)) { break; // unmatched brace } else if (token.is(T_LBRACE)) { return index - 1; } --index; } return start; } QString BackwardsScanner::indentationString(int index) const { const Token tokenAfterNewline = operator[](startOfLine(index + 1)); const int newlinePos = qMax(0, _text.lastIndexOf(QLatin1Char('\n'), tokenAfterNewline.begin())); return _text.mid(newlinePos, tokenAfterNewline.begin() - newlinePos); } int BackwardsScanner::previousBlockState(const QTextBlock &block) { const QTextBlock prevBlock = block.previous(); if (prevBlock.isValid()) { int state = prevBlock.userState(); if (state != -1) return state; } return 0; } ================================================ FILE: liteidex/src/3rdparty/cplusplus/BackwardsScanner.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CPLUSPLUS_BACKWARDSSCANNER_H #define CPLUSPLUS_BACKWARDSSCANNER_H #include "SimpleLexer.h" #include QT_FORWARD_DECLARE_CLASS(QTextCursor) namespace CPlusPlus { class BackwardsScanner { enum { MAX_BLOCK_COUNT = 10 }; public: explicit BackwardsScanner(LanguageFeatures features, const QTextCursor &cursor, int maxBlockCount = MAX_BLOCK_COUNT, const QString &suffix = QString(), bool skipComments = true); int startToken() const; int startPosition() const; QString text() const; QString mid(int index) const; QString text(int index) const; QStringRef textRef(int index) const; // 1-based Token LA(int index) const; // n-la token is [startToken - n] Token operator[](int index) const; // ### deprecate QString indentationString(int index) const; int startOfLine(int index) const; int startOfMatchingBrace(int index) const; int startOfBlock(int index) const; int size() const; static int previousBlockState(const QTextBlock &block); private: const Token &fetchToken(int tokenIndex); private: QList _tokens; int _offset; int _blocksTokenized; QTextBlock _block; SimpleLexer _tokenize; QString _text; int _maxBlockCount; int _startToken; }; } // namespace CPlusPlus #endif // CPLUSPLUS_BACKWARDSSCANNER_H ================================================ FILE: liteidex/src/3rdparty/cplusplus/Keywords.cpp ================================================ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Lexer.h" #include "Token.h" namespace CPlusPlus { static inline int classify2(const char *s, LanguageFeatures) { if (s[0] == 'd') { if (s[1] == 'o') { return T_DO; } } else if (s[0] == 'i') { if (s[1] == 'f') { return T_IF; } } return T_IDENTIFIER; } static inline int classify3(const char *s, LanguageFeatures features) { if (s[0] == 'a') { if (s[1] == 's') { if (s[2] == 'm') { return T_ASM; } } } else if (s[0] == 'f') { if (s[1] == 'o') { if (s[2] == 'r') { return T_FOR; } } } else if (s[0] == 'i') { if (s[1] == 'n') { if (s[2] == 't') { return T_INT; } } } else if (s[0] == 'n') { if (s[1] == 'e') { if (s[2] == 'w') { return T_NEW; } } } else if (s[0] == 't') { if (s[1] == 'r') { if (s[2] == 'y') { return T_TRY; } } } else if (features.qtMocRunEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'D') { return T_Q_D; } else if (s[2] == 'Q') { return T_Q_Q; } } } return T_IDENTIFIER; } static inline int classify4(const char *s, LanguageFeatures features) { if (s[0] == 'a') { if (s[1] == 'u') { if (s[2] == 't') { if (s[3] == 'o') { return T_AUTO; } } } } else if (s[0] == 'b') { if (s[1] == 'o') { if (s[2] == 'o') { if (s[3] == 'l') { return T_BOOL; } } } } else if (s[0] == 'c') { if (s[1] == 'a') { if (s[2] == 's') { if (s[3] == 'e') { return T_CASE; } } } else if (s[1] == 'h') { if (s[2] == 'a') { if (s[3] == 'r') { return T_CHAR; } } } } else if (s[0] == 'e') { if (s[1] == 'l') { if (s[2] == 's') { if (s[3] == 'e') { return T_ELSE; } } } else if (s[1] == 'n') { if (s[2] == 'u') { if (s[3] == 'm') { return T_ENUM; } } } else if (features.qtKeywordsEnabled && s[1] == 'm') { if (s[2] == 'i') { if (s[3] == 't') { return T_EMIT; } } } } else if (s[0] == 'g') { if (s[1] == 'o') { if (s[2] == 't') { if (s[3] == 'o') { return T_GOTO; } } } } else if (s[0] == 'l') { if (s[1] == 'o') { if (s[2] == 'n') { if (s[3] == 'g') { return T_LONG; } } } } else if (s[0] == 't') { if (s[1] == 'h') { if (s[2] == 'i') { if (s[3] == 's') { return T_THIS; } } } else if (s[1] == 'r') { if (s[2] == 'u') { if (s[3] == 'e') { return T_TRUE; } } } } else if (s[0] == 'v') { if (s[1] == 'o') { if (s[2] == 'i') { if (s[3] == 'd') { return T_VOID; } } } } else if (features.qtEnabled && s[0] == 'S') { if (s[1] == 'L') { if (s[2] == 'O') { if (s[3] == 'T') { return T_SLOT; } } } } return T_IDENTIFIER; } static inline int classify5(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { if (s[3] == 's') { if (s[4] == 'm') { return T___ASM; } } } } } else if (s[0] == 'b') { if (s[1] == 'r') { if (s[2] == 'e') { if (s[3] == 'a') { if (s[4] == 'k') { return T_BREAK; } } } } } else if (s[0] == 'c') { if (s[1] == 'a') { if (s[2] == 't') { if (s[3] == 'c') { if (s[4] == 'h') { return T_CATCH; } } } } else if (s[1] == 'l') { if (s[2] == 'a') { if (s[3] == 's') { if (s[4] == 's') { return T_CLASS; } } } } else if (s[1] == 'o') { if (s[2] == 'n') { if (s[3] == 's') { if (s[4] == 't') { return T_CONST; } } } } } else if (s[0] == 'f') { if (s[1] == 'a') { if (s[2] == 'l') { if (s[3] == 's') { if (s[4] == 'e') { return T_FALSE; } } } } else if (s[1] == 'l') { if (s[2] == 'o') { if (s[3] == 'a') { if (s[4] == 't') { return T_FLOAT; } } } } } else if (s[0] == 's') { if (s[1] == 'h') { if (s[2] == 'o') { if (s[3] == 'r') { if (s[4] == 't') { return T_SHORT; } } } } else if (features.qtKeywordsEnabled) { if (s[1] == 'l') { if (s[2] == 'o') { if (s[3] == 't') { if (s[4] == 's') { return T_Q_SLOTS; } } } } } } else if (s[0] == 't') { if (s[1] == 'h') { if (s[2] == 'r') { if (s[3] == 'o') { if (s[4] == 'w') { return T_THROW; } } } } } else if (s[0] == 'u') { if (s[1] == 'n') { if (s[2] == 'i') { if (s[3] == 'o') { if (s[4] == 'n') { return T_UNION; } } } } else if (s[1] == 's') { if (s[2] == 'i') { if (s[3] == 'n') { if (s[4] == 'g') { return T_USING; } } } } } else if (s[0] == 'w') { if (s[1] == 'h') { if (s[2] == 'i') { if (s[3] == 'l') { if (s[4] == 'e') { return T_WHILE; } } } } } return T_IDENTIFIER; } static inline int classify6(const char *s, LanguageFeatures features) { if (s[0] == 'd') { if (s[1] == 'e') { if (s[2] == 'l') { if (s[3] == 'e') { if (s[4] == 't') { if (s[5] == 'e') { return T_DELETE; } } } } } else if (s[1] == 'o') { if (s[2] == 'u') { if (s[3] == 'b') { if (s[4] == 'l') { if (s[5] == 'e') { return T_DOUBLE; } } } } } } else if (s[0] == 'e') { if (s[1] == 'x') { if (s[2] == 'p') { if (s[3] == 'o') { if (s[4] == 'r') { if (s[5] == 't') { return T_EXPORT; } } } } else if (s[2] == 't') { if (s[3] == 'e') { if (s[4] == 'r') { if (s[5] == 'n') { return T_EXTERN; } } } } } } else if (s[0] == 'f') { if (s[1] == 'r') { if (s[2] == 'i') { if (s[3] == 'e') { if (s[4] == 'n') { if (s[5] == 'd') { return T_FRIEND; } } } } } } else if (s[0] == 'i') { if (s[1] == 'n') { if (s[2] == 'l') { if (s[3] == 'i') { if (s[4] == 'n') { if (s[5] == 'e') { return T_INLINE; } } } } } } else if (s[0] == 'p') { if (s[1] == 'u') { if (s[2] == 'b') { if (s[3] == 'l') { if (s[4] == 'i') { if (s[5] == 'c') { return T_PUBLIC; } } } } } } else if (s[0] == 'r') { if (s[1] == 'e') { if (s[2] == 't') { if (s[3] == 'u') { if (s[4] == 'r') { if (s[5] == 'n') { return T_RETURN; } } } } } } else if (s[0] == 's') { if (s[1] == 'i') { if (s[2] == 'g') { if (s[3] == 'n') { if (s[4] == 'e') { if (s[5] == 'd') { return T_SIGNED; } } } } else if (s[2] == 'z') { if (s[3] == 'e') { if (s[4] == 'o') { if (s[5] == 'f') { return T_SIZEOF; } } } } } else if (s[1] == 't') { if (s[2] == 'a') { if (s[3] == 't') { if (s[4] == 'i') { if (s[5] == 'c') { return T_STATIC; } } } } else if (s[2] == 'r') { if (s[3] == 'u') { if (s[4] == 'c') { if (s[5] == 't') { return T_STRUCT; } } } } } else if (s[1] == 'w') { if (s[2] == 'i') { if (s[3] == 't') { if (s[4] == 'c') { if (s[5] == 'h') { return T_SWITCH; } } } } } } else if (s[0] == 't') { if (s[1] == 'y') { if (s[2] == 'p') { if (s[3] == 'e') { if (s[4] == 'i') { if (s[5] == 'd') { return T_TYPEID; } } else if (s[4] == 'o') { if (s[5] == 'f') { return T_TYPEOF; } } } } } } else if (features.qtKeywordsEnabled && s[0] == 'S') { if (s[1] == 'I') { if (s[2] == 'G') { if (s[3] == 'N') { if (s[4] == 'A') { if (s[5] == 'L') { return T_SIGNAL; } } } } } } else if (features.qtKeywordsEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'S') { if (s[3] == 'L') { if (s[4] == 'O') { if (s[5] == 'T') { return T_Q_SLOT; } } } } else if (s[2] == 'E') { if (s[3] == 'M') { if (s[4] == 'I') { if (s[5] == 'T') { return T_Q_EMIT; } } } } } } return T_IDENTIFIER; } static inline int classify7(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { if (s[3] == 's') { if (s[4] == 'm') { if (s[5] == '_') { if (s[6] == '_') { return T___ASM__; } } } } } else if (s[2] == 'c') { if (s[3] == 'o') { if (s[4] == 'n') { if (s[5] == 's') { if (s[6] == 't') { return T___CONST; } } } } } } } else if (features.cxx11Enabled && s[0] == 'a') { if (s[1] == 'l') { if (s[2] == 'i') { if (s[3] == 'g') { if (s[4] == 'n') { if (s[5] == 'a') { if (s[6] == 's') { return T_ALIGNAS; } } else if (s[5] == 'o') { if (s[6] == 'f') { return T_ALIGNOF; } } } } } } } else if (s[0] == 'd') { if (s[1] == 'e') { if (s[2] == 'f') { if (s[3] == 'a') { if (s[4] == 'u') { if (s[5] == 'l') { if (s[6] == 't') { return T_DEFAULT; } } } } } } } else if (s[0] == 'm') { if (s[1] == 'u') { if (s[2] == 't') { if (s[3] == 'a') { if (s[4] == 'b') { if (s[5] == 'l') { if (s[6] == 'e') { return T_MUTABLE; } } } } } } } else if (features.cxx11Enabled && s[0] == 'n') { if (s[1] == 'u') { if (s[2] == 'l') { if (s[3] == 'l') { if (s[4] == 'p') { if (s[5] == 't') { if (s[6] == 'r') { return T_NULLPTR; } } } } } } } else if (s[0] == 'p') { if (s[1] == 'r') { if (s[2] == 'i') { if (s[3] == 'v') { if (s[4] == 'a') { if (s[5] == 't') { if (s[6] == 'e') { return T_PRIVATE; } } } } } } } else if (features.qtKeywordsEnabled && s[0] == 'f') { if (s[1] == 'o') { if (s[2] == 'r') { if (s[3] == 'e') { if (s[4] == 'a') { if (s[5] == 'c') { if (s[6] == 'h') { return T_Q_FOREACH; } } } } } } } else if (features.qtEnabled && s[0] == 's') { if (s[1] == 'i') { if (s[2] == 'g') { if (s[3] == 'n') { if (s[4] == 'a') { if (s[5] == 'l') { if (s[6] == 's') { return T_Q_SIGNALS; } } } } } } } else if (s[0] == 't') { if (s[1] == 'y') { if (s[2] == 'p') { if (s[3] == 'e') { if (s[4] == 'd') { if (s[5] == 'e') { if (s[6] == 'f') { return T_TYPEDEF; } } } } } } } else if (s[0] == 'v') { if (s[1] == 'i') { if (s[2] == 'r') { if (s[3] == 't') { if (s[4] == 'u') { if (s[5] == 'a') { if (s[6] == 'l') { return T_VIRTUAL; } } } } } } } else if (s[0] == 'w') { if (s[1] == 'c') { if (s[2] == 'h') { if (s[3] == 'a') { if (s[4] == 'r') { if (s[5] == '_') { if (s[6] == 't') { return T_WCHAR_T; } } } } } } } else if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'S') { if (s[3] == 'L') { if (s[4] == 'O') { if (s[5] == 'T') { if (s[6] == 'S') { return T_Q_SLOTS; } } } } } else if (s[2] == 'E') { if (s[3] == 'N') { if (s[4] == 'U') { if (s[5] == 'M') { if (s[6] == 'S') { return T_Q_ENUMS; } } } } } else if (s[2] == 'F') { if (s[3] == 'L') { if (s[4] == 'A') { if (s[5] == 'G') { if (s[6] == 'S') { return T_Q_FLAGS; } } } } } } } return T_IDENTIFIER; } static inline int classify8(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'i') { if (s[3] == 'n') { if (s[4] == 'l') { if (s[5] == 'i') { if (s[6] == 'n') { if (s[7] == 'e') { return T___INLINE; } } } } } } else if (s[2] == 't') { if (s[3] == 'y') { if (s[4] == 'p') { if (s[5] == 'e') { if (s[6] == 'o') { if (s[7] == 'f') { return T___TYPEOF; } } } } } else if (s[3] == 'h') { if (s[4] == 'r') { if (s[5] == 'e') { if (s[6] == 'a') { if (s[7] == 'd') { return T___THREAD; } } } } } } } } else if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'n') { if (s[3] == 't') { if (s[4] == 'i') { if (s[5] == 'n') { if (s[6] == 'u') { if (s[7] == 'e') { return T_CONTINUE; } } } } } } } else if (features.cxx11Enabled && s[1] == 'h') { if (s[2] == 'a') { if (s[3] == 'r') { if (s[4] == '1') { if (s[5] == '6') { if (s[6] == '_') { if (s[7] == 't') { return T_CHAR16_T; } } } } else if (s[4] == '3') { if (s[5] == '2') { if (s[6] == '_') { if (s[7] == 't') { return T_CHAR32_T; } } } } } } } } else if (features.cxx11Enabled && s[0] == 'd') { if (s[1] == 'e') { if (s[2] == 'c') { if (s[3] == 'l') { if (s[4] == 't') { if (s[5] == 'y') { if (s[6] == 'p') { if (s[7] == 'e') { return T_DECLTYPE; } } } } } } } } else if (s[0] == 'e') { if (s[1] == 'x') { if (s[2] == 'p') { if (s[3] == 'l') { if (s[4] == 'i') { if (s[5] == 'c') { if (s[6] == 'i') { if (s[7] == 't') { return T_EXPLICIT; } } } } } } } } else if (features.cxx11Enabled && s[0] == 'n') { if (s[1] == 'o') { if (s[2] == 'e') { if (s[3] == 'x') { if (s[4] == 'c') { if (s[5] == 'e') { if (s[6] == 'p') { if (s[7] == 't') { return T_NOEXCEPT; } } } } } } } } else if (s[0] == 'o') { if (s[1] == 'p') { if (s[2] == 'e') { if (s[3] == 'r') { if (s[4] == 'a') { if (s[5] == 't') { if (s[6] == 'o') { if (s[7] == 'r') { return T_OPERATOR; } } } } } } } } else if (s[0] == 'r') { if (s[1] == 'e') { if (s[2] == 'g') { if (s[3] == 'i') { if (s[4] == 's') { if (s[5] == 't') { if (s[6] == 'e') { if (s[7] == 'r') { return T_REGISTER; } } } } } } } } else if (s[0] == 't') { if (s[1] == 'e') { if (s[2] == 'm') { if (s[3] == 'p') { if (s[4] == 'l') { if (s[5] == 'a') { if (s[6] == 't') { if (s[7] == 'e') { return T_TEMPLATE; } } } } } } } else if (s[1] == 'y') { if (s[2] == 'p') { if (s[3] == 'e') { if (s[4] == 'n') { if (s[5] == 'a') { if (s[6] == 'm') { if (s[7] == 'e') { return T_TYPENAME; } } } } } } } } else if (s[0] == 'u') { if (s[1] == 'n') { if (s[2] == 's') { if (s[3] == 'i') { if (s[4] == 'g') { if (s[5] == 'n') { if (s[6] == 'e') { if (s[7] == 'd') { return T_UNSIGNED; } } } } } } } } else if (s[0] == 'v') { if (s[1] == 'o') { if (s[2] == 'l') { if (s[3] == 'a') { if (s[4] == 't') { if (s[5] == 'i') { if (s[6] == 'l') { if (s[7] == 'e') { return T_VOLATILE; } } } } } } } } else if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'G') { if (s[3] == 'A') { if (s[4] == 'D') { if (s[5] == 'G') { if (s[6] == 'E') { if (s[7] == 'T') { return T_Q_GADGET; } } } } } } else if (s[2] == 'O') { if (s[3] == 'B') { if (s[4] == 'J') { if (s[5] == 'E') { if (s[6] == 'C') { if (s[7] == 'T') { return T_Q_OBJECT; } } } } } } else if (s[2] == 'S') { if (s[3] == 'I') { if (s[4] == 'G') { if (s[5] == 'N') { if (s[6] == 'A') { if (s[7] == 'L') { return T_Q_SIGNAL; } } } } } } } } return T_IDENTIFIER; } static inline int classify9(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'c') { if (s[3] == 'o') { if (s[4] == 'n') { if (s[5] == 's') { if (s[6] == 't') { if (s[7] == '_') { if (s[8] == '_') { return T___CONST__; } } } } } } } } } else if (features.cxx11Enabled && s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'n') { if (s[3] == 's') { if (s[4] == 't') { if (s[5] == 'e') { if (s[6] == 'x') { if (s[7] == 'p') { if (s[8] == 'r') { return T_CONSTEXPR; } } } } } } } } } else if (s[0] == 'n') { if (s[1] == 'a') { if (s[2] == 'm') { if (s[3] == 'e') { if (s[4] == 's') { if (s[5] == 'p') { if (s[6] == 'a') { if (s[7] == 'c') { if (s[8] == 'e') { return T_NAMESPACE; } } } } } } } } } else if (s[0] == 'p') { if (s[1] == 'r') { if (s[2] == 'o') { if (s[3] == 't') { if (s[4] == 'e') { if (s[5] == 'c') { if (s[6] == 't') { if (s[7] == 'e') { if (s[8] == 'd') { return T_PROTECTED; } } } } } } } } } else if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'S') { if (s[3] == 'I') { if (s[4] == 'G') { if (s[5] == 'N') { if (s[6] == 'A') { if (s[7] == 'L') { if (s[8] == 'S') { return T_Q_SIGNALS; } } } } } } } else if (s[2] == 'F') { if (s[3] == 'O') { if (s[4] == 'R') { if (s[5] == 'E') { if (s[6] == 'A') { if (s[7] == 'C') { if (s[8] == 'H') { return T_Q_FOREACH; } } } } } } } } } return T_IDENTIFIER; } static inline int classify10(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'i') { if (s[3] == 'n') { if (s[4] == 'l') { if (s[5] == 'i') { if (s[6] == 'n') { if (s[7] == 'e') { if (s[8] == '_') { if (s[9] == '_') { return T___INLINE__; } } } } } } } } else if (s[2] == 'd') { if (s[3] == 'e') { if (s[4] == 'c') { if (s[5] == 'l') { if (s[6] == 't') { if (s[7] == 'y') { if (s[8] == 'p') { if (s[9] == 'e') { return T___DECLTYPE; } } } } } } } } else if (s[2] == 't') { if (s[3] == 'y') { if (s[4] == 'p') { if (s[5] == 'e') { if (s[6] == 'o') { if (s[7] == 'f') { if (s[8] == '_') { if (s[9] == '_') { return T___TYPEOF__; } } } } } } } } else if (s[2] == 'v') { if (s[3] == 'o') { if (s[4] == 'l') { if (s[5] == 'a') { if (s[6] == 't') { if (s[7] == 'i') { if (s[8] == 'l') { if (s[9] == 'e') { return T___VOLATILE; } } } } } } } } } } else if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'n') { if (s[3] == 's') { if (s[4] == 't') { if (s[5] == '_') { if (s[6] == 'c') { if (s[7] == 'a') { if (s[8] == 's') { if (s[9] == 't') { return T_CONST_CAST; } } } } } } } } } } else if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'O') { if (s[3] == 'V') { if (s[4] == 'E') { if (s[5] == 'R') { if (s[6] == 'R') { if (s[7] == 'I') { if (s[8] == 'D') { if (s[9] == 'E') { return T_Q_PROPERTY; // Q_OVERRIDE is just an alias for Q_PROPERTY } } } } } } } } else if (s[2] == 'P') { if (s[3] == 'R') { if (s[4] == 'O') { if (s[5] == 'P') { if (s[6] == 'E') { if (s[7] == 'R') { if (s[8] == 'T') { if (s[9] == 'Y') { return T_Q_PROPERTY; } } } } } } } } } } return T_IDENTIFIER; } static inline int classify11(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { if (s[3] == 't') { if (s[4] == 't') { if (s[5] == 'r') { if (s[6] == 'i') { if (s[7] == 'b') { if (s[8] == 'u') { if (s[9] == 't') { if (s[10] == 'e') { return T___ATTRIBUTE; } } } } } } } } } } } else if (s[0] == 's') { if (s[1] == 't') { if (s[2] == 'a') { if (s[3] == 't') { if (s[4] == 'i') { if (s[5] == 'c') { if (s[6] == '_') { if (s[7] == 'c') { if (s[8] == 'a') { if (s[9] == 's') { if (s[10] == 't') { return T_STATIC_CAST; } } } } } } } } } } } else if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'I') { if (s[3] == 'N') { if (s[4] == 'V') { if (s[5] == 'O') { if (s[6] == 'K') { if (s[7] == 'A') { if (s[8] == 'B') { if (s[9] == 'L') { if (s[10] == 'E') { return T_Q_INVOKABLE; } } } } } } } } } } } return T_IDENTIFIER; } static inline int classify12(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'v') { if (s[3] == 'o') { if (s[4] == 'l') { if (s[5] == 'a') { if (s[6] == 't') { if (s[7] == 'i') { if (s[8] == 'l') { if (s[9] == 'e') { if (s[10] == '_') { if (s[11] == '_') { return T___VOLATILE__; } } } } } } } } } } } } else if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'I') { if (s[3] == 'N') { if (s[4] == 'T') { if (s[5] == 'E') { if (s[6] == 'R') { if (s[7] == 'F') { if (s[8] == 'A') { if (s[9] == 'C') { if (s[10] == 'E') { if (s[11] == 'S') { return T_Q_INTERFACES; } } } } } } } } } } } } else if (s[0] == 'd') { if (s[1] == 'y') { if (s[2] == 'n') { if (s[3] == 'a') { if (s[4] == 'm') { if (s[5] == 'i') { if (s[6] == 'c') { if (s[7] == '_') { if (s[8] == 'c') { if (s[9] == 'a') { if (s[10] == 's') { if (s[11] == 't') { return T_DYNAMIC_CAST; } } } } } } } } } } } } else if (features.cxx11Enabled && s[0] == 't') { if (s[1] == 'h') { if (s[2] == 'r') { if (s[3] == 'e') { if (s[4] == 'a') { if (s[5] == 'd') { if (s[6] == '_') { if (s[7] == 'l') { if (s[8] == 'o') { if (s[9] == 'c') { if (s[10] == 'a') { if (s[11] == 'l') { return T_THREAD_LOCAL; } } } } } } } } } } } } return T_IDENTIFIER; } static inline int classify13(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'a') { if (s[3] == 't') { if (s[4] == 't') { if (s[5] == 'r') { if (s[6] == 'i') { if (s[7] == 'b') { if (s[8] == 'u') { if (s[9] == 't') { if (s[10] == 'e') { if (s[11] == '_') { if (s[12] == '_') { return T___ATTRIBUTE__; } } } } } } } } } } } } } else if (features.cxx11Enabled && s[0] == 's') { if (s[1] == 't') { if (s[2] == 'a') { if (s[3] == 't') { if (s[4] == 'i') { if (s[5] == 'c') { if (s[6] == '_') { if (s[7] == 'a') { if (s[8] == 's') { if (s[9] == 's') { if (s[10] == 'e') { if (s[11] == 'r') { if (s[12] == 't') { return T_STATIC_ASSERT; } } } } } } } } } } } } } return T_IDENTIFIER; } static inline int classify16(const char *s, LanguageFeatures) { if (s[0] == 'r') { if (s[1] == 'e') { if (s[2] == 'i') { if (s[3] == 'n') { if (s[4] == 't') { if (s[5] == 'e') { if (s[6] == 'r') { if (s[7] == 'p') { if (s[8] == 'r') { if (s[9] == 'e') { if (s[10] == 't') { if (s[11] == '_') { if (s[12] == 'c') { if (s[13] == 'a') { if (s[14] == 's') { if (s[15] == 't') { return T_REINTERPRET_CAST; } } } } } } } } } } } } } } } } return T_IDENTIFIER; } static inline int classify14(const char *s, LanguageFeatures features) { if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'P') { if (s[3] == 'R') { if (s[4] == 'I') { if (s[5] == 'V') { if (s[6] == 'A') { if (s[7] == 'T') { if (s[8] == 'E') { if (s[9] == '_') { if (s[10] == 'S') { if (s[11] == 'L') { if (s[12] == 'O') { if (s[13] == 'T') { return T_Q_PRIVATE_SLOT; } } } } } } } } } } } } } } return T_IDENTIFIER; } static inline int classify18(const char *s, LanguageFeatures features) { if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'P') { if (s[3] == 'R') { if (s[4] == 'I') { if (s[5] == 'V') { if (s[6] == 'A') { if (s[7] == 'T') { if (s[8] == 'E') { if (s[9] == '_') { if (s[10] == 'P') { if (s[11] == 'R') { if (s[12] == 'O') { if (s[13] == 'P') { if (s[14] == 'E') { if (s[15] == 'R') { if (s[16] == 'T') { if (s[17] == 'Y') { return T_Q_PRIVATE_PROPERTY; } } } } } } } } } } } } } } } } } } return T_IDENTIFIER; } static inline int classify19(const char *s, LanguageFeatures features) { if (features.qtEnabled && s[0] == 'Q') { if (s[1] == '_') { if (s[2] == 'D') { if (s[3] == 'E') { if (s[4] == 'C') { if (s[5] == 'L') { if (s[6] == 'A') { if (s[7] == 'R') { if (s[8] == 'E') { if (s[9] == '_') { if (s[10] == 'I') { if (s[11] == 'N') { if (s[12] == 'T') { if (s[13] == 'E') { if (s[14] == 'R') { if (s[15] == 'F') { if (s[16] == 'A') { if (s[17] == 'C') { if (s[18] == 'E') { return T_Q_DECLARE_INTERFACE; } } } } } } } } } } } } } } } } } } } return T_IDENTIFIER; } int Lexer::classify(const char *s, int n, LanguageFeatures features) { switch (n) { case 2: return classify2(s, features); case 3: return classify3(s, features); case 4: return classify4(s, features); case 5: return classify5(s, features); case 6: return classify6(s, features); case 7: return classify7(s, features); case 8: return classify8(s, features); case 9: return classify9(s, features); case 10: return classify10(s, features); case 11: return classify11(s, features); case 12: return classify12(s, features); case 13: return classify13(s, features); case 14: return classify14(s, features); case 16: return classify16(s, features); case 18: return classify18(s, features); case 19: return classify19(s, features); default: return T_IDENTIFIER; } // switch } static inline int classifyOperator2(const char *s) { if (s[0] == 'o') { if (s[1] == 'r') { return T_OR; } } return T_IDENTIFIER; } static inline int classifyOperator3(const char *s) { if (s[0] == 'a') { if (s[1] == 'n') { if (s[2] == 'd') { return T_AND; } } } else if (s[0] == 'n') { if (s[1] == 'o') { if (s[2] == 't') { return T_NOT; } } } else if (s[0] == 'x') { if (s[1] == 'o') { if (s[2] == 'r') { return T_XOR; } } } return T_IDENTIFIER; } static inline int classifyOperator5(const char *s) { if (s[0] == 'b') { if (s[1] == 'i') { if (s[2] == 't') { if (s[3] == 'o') { if (s[4] == 'r') { return T_BITOR; } } } } } else if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'm') { if (s[3] == 'p') { if (s[4] == 'l') { return T_COMPL; } } } } } else if (s[0] == 'o') { if (s[1] == 'r') { if (s[2] == '_') { if (s[3] == 'e') { if (s[4] == 'q') { return T_OR_EQ; } } } } } return T_IDENTIFIER; } static inline int classifyOperator6(const char *s) { if (s[0] == 'a') { if (s[1] == 'n') { if (s[2] == 'd') { if (s[3] == '_') { if (s[4] == 'e') { if (s[5] == 'q') { return T_AND_EQ; } } } } } } else if (s[0] == 'b') { if (s[1] == 'i') { if (s[2] == 't') { if (s[3] == 'a') { if (s[4] == 'n') { if (s[5] == 'd') { return T_BITAND; } } } } } } else if (s[0] == 'n') { if (s[1] == 'o') { if (s[2] == 't') { if (s[3] == '_') { if (s[4] == 'e') { if (s[5] == 'q') { return T_NOT_EQ; } } } } } } else if (s[0] == 'x') { if (s[1] == 'o') { if (s[2] == 'r') { if (s[3] == '_') { if (s[4] == 'e') { if (s[5] == 'q') { return T_XOR_EQ; } } } } } } return T_IDENTIFIER; } int Lexer::classifyOperator(const char *s, int n) { switch (n) { case 2: return classifyOperator2(s); case 3: return classifyOperator3(s); case 5: return classifyOperator5(s); case 6: return classifyOperator6(s); default: return T_IDENTIFIER; } // switch } } // namespace CPlusPlus ================================================ FILE: liteidex/src/3rdparty/cplusplus/Keywords.kwgen ================================================ #include "Lexer.h" #include "Token.h" %token-prefix=T_ %toupper %no-enums %namespace=Lexer %% __asm __asm__ __attribute __attribute__ __const __const__ __inline __inline__ __typeof __typeof__ __volatile __volatile__ asm auto bool break case catch char class const const_cast continue default delete do double dynamic_cast else enum explicit export extern false float for friend goto if inline int long mutable namespace new operator private protected public register reinterpret_cast return short signed sizeof static static_cast struct switch template this throw true try typedef typeid typename typeof union unsigned using virtual void volatile wchar_t while ================================================ FILE: liteidex/src/3rdparty/cplusplus/Lexer.cpp ================================================ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Lexer.h" #include "cppassert.h" #include using namespace CPlusPlus; //Lexer::Lexer(TranslationUnit *unit) // : _translationUnit(unit), // //_control(unit->control()), // _state(0), // _flags(0), // _currentLine(1) //{ // f._scanKeywords = true; // setSource(_translationUnit->firstSourceChar(), // _translationUnit->lastSourceChar()); //} Lexer::Lexer(const char *firstChar, const char *lastChar) : //_translationUnit(0), //_control(0), _state(0), _flags(0), _currentLine(1) { f._scanKeywords = true; setSource(firstChar, lastChar); } Lexer::~Lexer() { } //TranslationUnit *Lexer::translationUnit() const //{ return _translationUnit; } void Lexer::setSource(const char *firstChar, const char *lastChar) { _firstChar = firstChar; _lastChar = lastChar; _currentChar = _firstChar - 1; _tokenStart = _currentChar; _yychar = '\n'; } void Lexer::setStartWithNewline(bool enabled) { if (enabled) _yychar = '\n'; else _yychar = ' '; } int Lexer::state() const { return _state; } void Lexer::setState(int state) { _state = state; } bool Lexer::scanCommentTokens() const { return f._scanCommentTokens; } void Lexer::setScanCommentTokens(bool onoff) { f._scanCommentTokens = onoff; } bool Lexer::scanKeywords() const { return f._scanKeywords; } void Lexer::setScanKeywords(bool onoff) { f._scanKeywords = onoff; } void Lexer::setScanAngleStringLiteralTokens(bool onoff) { f._scanAngleStringLiteralTokens = onoff; } void Lexer::pushLineStartOffset() { ++_currentLine; // if (_translationUnit) // _translationUnit->pushLineOffset(_currentChar - _firstChar); } unsigned Lexer::tokenOffset() const { return _tokenStart - _firstChar; } unsigned Lexer::tokenLength() const { return _currentChar - _tokenStart; } const char *Lexer::tokenBegin() const { return _tokenStart; } const char *Lexer::tokenEnd() const { return _currentChar; } unsigned Lexer::currentLine() const { return _currentLine; } void Lexer::scan(Token *tok) { tok->reset(); scan_helper(tok); tok->f.length = _currentChar - _tokenStart; } void Lexer::scan_helper(Token *tok) { _Lagain: while (_yychar && std::isspace(_yychar)) { if (_yychar == '\n') { tok->f.joined = s._newlineExpected; tok->f.newline = !s._newlineExpected; if (s._newlineExpected) { s._newlineExpected = false; } else { switch (s._tokenKind) { case T_EOF_SYMBOL: case T_COMMENT: case T_DOXY_COMMENT: case T_RAW_STRING_LITERAL: break; // multiline tokens, don't break on newline default: // Strings and C++ comments _state = 0; } } } else { tok->f.whitespace = true; } yyinp(); } // if (! _translationUnit) // tok->lineno = _currentLine; _tokenStart = _currentChar; tok->offset = _currentChar - _firstChar; if (_yychar) { s._newlineExpected = false; } else if (s._tokenKind) { tok->f.kind = T_EOF_SYMBOL; return; } switch (s._tokenKind) { case T_EOF_SYMBOL: break; case T_COMMENT: case T_DOXY_COMMENT: { const int originalKind = s._tokenKind; while (_yychar) { if (_yychar != '*') yyinp(); else { yyinp(); if (_yychar == '/') { yyinp(); _state = 0; break; } } } if (! f._scanCommentTokens) goto _Lagain; tok->f.kind = originalKind; return; // done } case T_CPP_COMMENT: case T_CPP_DOXY_COMMENT: { const Kind originalKind = (Kind)s._tokenKind; tok->f.joined = true; if (f._scanCommentTokens) tok->f.kind = originalKind; _state = 0; scanCppComment(originalKind); return; } case T_RAW_STRING_LITERAL: tok->f.joined = true; tok->f.kind = s._tokenKind; _state = 0; scanUntilQuote(tok, '`',true); return; break; default: // Strings tok->f.joined = true; tok->f.kind = s._tokenKind; _state = 0; scanUntilQuote(tok, '"'); return; } if (! _yychar) { tok->f.kind = T_EOF_SYMBOL; return; } unsigned char ch = _yychar; yyinp(); switch (ch) { case '\\': s._newlineExpected = true; goto _Lagain; case '"': scanStringLiteral(tok); break; case '`': scanGoRawStringLiteral(tok); break; case '\'': scanCharLiteral(tok); break; case '{': tok->f.kind = T_LBRACE; break; case '}': tok->f.kind = T_RBRACE; break; case '[': tok->f.kind = T_LBRACKET; break; case ']': tok->f.kind = T_RBRACKET; break; case '#': if (_yychar == '#') { tok->f.kind = T_POUND_POUND; yyinp(); } else { tok->f.kind = T_POUND; } break; case '(': tok->f.kind = T_LPAREN; break; case ')': tok->f.kind = T_RPAREN; break; case ';': tok->f.kind = T_SEMICOLON; break; case ':': if (_yychar == '=') { yyinp(); tok->f.kind = T_COLON_EQUAL; } else if (_yychar == ':') { yyinp(); tok->f.kind = T_COLON_COLON; } else if (_yychar == '>') { yyinp(); tok->f.kind = T_RBRACKET; } else { tok->f.kind = T_COLON; } break; case '.': if (_yychar == '*') { yyinp(); tok->f.kind = T_DOT_STAR; } else if (_yychar == '.') { yyinp(); // ### CPP_CHECK(_yychar); if (_yychar == '.') { yyinp(); tok->f.kind = T_DOT_DOT_DOT; } else { tok->f.kind = T_ERROR; } } else if (std::isdigit(_yychar)) { //const char *yytext = _currentChar - 2; do { if (_yychar == 'e' || _yychar == 'E') { yyinp(); if (_yychar == '-' || _yychar == '+') { yyinp(); // ### CPP_CHECK(std::isdigit(_yychar)); } } else if (_yychar == 'p' || _yychar == 'P'){ yyinp(); if (_yychar == '-') { yyinp(); } } else if (std::isalnum(_yychar) || _yychar == '.' || _yychar == '_') { yyinp(); } else { break; } } while (_yychar); //int yylen = _currentChar - yytext; tok->f.kind = T_NUMERIC_LITERAL; // if (control()) // tok->number = control()->numericLiteral(yytext, yylen); } else { tok->f.kind = T_DOT; } break; case '?': if (_yychar == '?') { yyinp(); if (_yychar == '(') { yyinp(); tok->f.kind = T_LBRACKET; } else if (_yychar == ')') { yyinp(); tok->f.kind = T_RBRACKET; } else if (_yychar == '<') { yyinp(); tok->f.kind = T_LBRACE; } else if (_yychar == '>') { yyinp(); tok->f.kind = T_RBRACE; } } else { tok->f.kind = T_QUESTION; } break; case '+': if (_yychar == '+') { yyinp(); tok->f.kind = T_PLUS_PLUS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_PLUS_EQUAL; } else { tok->f.kind = T_PLUS; } break; case '-': if (_yychar == '-') { yyinp(); tok->f.kind = T_MINUS_MINUS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_MINUS_EQUAL; } else if (_yychar == '>') { yyinp(); if (_yychar == '*') { yyinp(); tok->f.kind = T_ARROW_STAR; } else { tok->f.kind = T_ARROW; } } else { tok->f.kind = T_MINUS; } break; case '*': if (_yychar == '=') { yyinp(); tok->f.kind = T_STAR_EQUAL; } else { tok->f.kind = T_STAR; } break; case '/': if (_yychar == '/') { yyinp(); Kind commentType = T_CPP_COMMENT; if (_yychar == '/' || _yychar == '!') { yyinp(); commentType = T_CPP_DOXY_COMMENT; } scanCppComment(commentType); if (! f._scanCommentTokens) goto _Lagain; tok->f.kind = commentType; } else if (_yychar == '*') { yyinp(); Kind commentKind = T_COMMENT; if (_yychar == '*' || _yychar == '!') { const char ch = _yychar; yyinp(); if (ch == '*' && _yychar == '/') goto _Ldone; if (_yychar == '<') yyinp(); if (! _yychar || std::isspace(_yychar)) commentKind = T_DOXY_COMMENT; } while (_yychar) { if (_yychar != '*') { yyinp(); } else { yyinp(); if (_yychar == '/') break; } } _Ldone: if (_yychar) yyinp(); else s._tokenKind = commentKind; if (! f._scanCommentTokens) goto _Lagain; tok->f.kind = commentKind; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_SLASH_EQUAL; } else { tok->f.kind = T_SLASH; } break; case '%': if (_yychar == '=') { yyinp(); tok->f.kind = T_PERCENT_EQUAL; } else if (_yychar == '>') { yyinp(); tok->f.kind = T_RBRACE; } else if (_yychar == ':') { yyinp(); tok->f.kind = T_POUND; } else { tok->f.kind = T_PERCENT; } break; case '^': if (_yychar == '=') { yyinp(); tok->f.kind = T_CARET_EQUAL; } else { tok->f.kind = T_CARET; } break; case '&': if (_yychar == '&') { yyinp(); tok->f.kind = T_AMPER_AMPER; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_AMPER_EQUAL; } else { tok->f.kind = T_AMPER; } break; case '|': if (_yychar == '|') { yyinp(); tok->f.kind = T_PIPE_PIPE; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_PIPE_EQUAL; } else { tok->f.kind = T_PIPE; } break; case '~': if (_yychar == '=') { yyinp(); tok->f.kind = T_TILDE_EQUAL; } else { tok->f.kind = T_TILDE; } break; case '!': if (_yychar == '=') { yyinp(); tok->f.kind = T_EXCLAIM_EQUAL; } else { tok->f.kind = T_EXCLAIM; } break; case '=': if (_yychar == '=') { yyinp(); tok->f.kind = T_EQUAL_EQUAL; } else { tok->f.kind = T_EQUAL; } break; case '<': if (f._scanAngleStringLiteralTokens) { //const char *yytext = _currentChar; while (_yychar && _yychar != '>') yyinp(); //int yylen = _currentChar - yytext; // ### CPP_CHECK(_yychar == '>'); if (_yychar == '>') yyinp(); // if (control()) // tok->string = control()->stringLiteral(yytext, yylen); tok->f.kind = T_ANGLE_STRING_LITERAL; } else if (_yychar == '<') { yyinp(); if (_yychar == '=') { yyinp(); tok->f.kind = T_LESS_LESS_EQUAL; } else tok->f.kind = T_LESS_LESS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_LESS_EQUAL; } else if (_yychar == ':') { yyinp(); tok->f.kind = T_LBRACKET; } else if (_yychar == '%') { yyinp(); tok->f.kind = T_LBRACE; } else { tok->f.kind = T_LESS; } break; case '>': if (_yychar == '>') { yyinp(); if (_yychar == '=') { yyinp(); tok->f.kind = T_GREATER_GREATER_EQUAL; } else tok->f.kind = T_LESS_LESS; tok->f.kind = T_GREATER_GREATER; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_GREATER_EQUAL; } else { tok->f.kind = T_GREATER; } break; case ',': tok->f.kind = T_COMMA; break; default: { if (ch == 'L' || ch == 'u' || ch == 'U' || ch == 'R') { // Either a literal or still an identifier. if (_yychar == '"') { yyinp(); if (ch == 'R') scanRawStringLiteral(tok); else scanStringLiteral(tok, ch); } else if (_yychar == '\'') { yyinp(); scanCharLiteral(tok, ch); } else if (ch != 'R' && _yychar == 'R') { yyinp(); if (_yychar == '"') { yyinp(); scanRawStringLiteral(tok, ch); } else { scanIdentifier(tok, 1); } } else if (ch == 'u' && _yychar == '8') { yyinp(); if (_yychar == '"') { yyinp(); scanStringLiteral(tok, '8'); } else if (_yychar == '\'') { yyinp(); scanCharLiteral(tok, '8'); } else if (_yychar == 'R') { yyinp(); if (_yychar == '"') { yyinp(); scanRawStringLiteral(tok, '8'); } else { scanIdentifier(tok, 2); } } else { scanIdentifier(tok, 1); } } else { scanIdentifier(tok); } } else if (std::isalpha(ch) || ch == '_' || ch == '$') { scanIdentifier(tok); } else if (std::isdigit(ch)) { scanNumericLiteral(tok); } else { tok->f.kind = T_ERROR; } break; } // default } // switch } void Lexer::scanStringLiteral(Token *tok, unsigned char hint) { if (hint == 'L') tok->f.kind = T_WIDE_STRING_LITERAL; else if (hint == 'U') tok->f.kind = T_UTF32_STRING_LITERAL; else if (hint == 'u') tok->f.kind = T_UTF16_STRING_LITERAL; else if (hint == '8') tok->f.kind = T_UTF8_STRING_LITERAL; else if (hint == '@') tok->f.kind = T_AT_STRING_LITERAL; else tok->f.kind = T_STRING_LITERAL; scanUntilQuote(tok, '"'); } void Lexer::scanGoRawStringLiteral(Token *tok, unsigned char /*hint*/) { tok->f.kind = T_RAW_STRING_LITERAL; scanUntilQuote(tok, '`',true); } void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint) { const char *yytext = _currentChar; int delimLength = -1; const char *closingDelimCandidate = 0; while (_yychar) { if (_yychar == '(' && delimLength == -1) { delimLength = _currentChar - yytext; yyinp(); } else if (_yychar == ')') { yyinp(); if (delimLength == -1) break; closingDelimCandidate = _currentChar; } else { if (delimLength == -1) { if (_yychar == '\\' || std::isspace(_yychar)) break; yyinp(); } else { if (!closingDelimCandidate) { yyinp(); } else { if (_yychar == '"') { if (delimLength == _currentChar - closingDelimCandidate) { // Got a matching closing delimiter. break; } } // Make sure this continues to be a valid candidate. if (_yychar != *(yytext + (_currentChar - closingDelimCandidate))) closingDelimCandidate = 0; yyinp(); } } } } //int yylen = _currentChar - yytext; if (_yychar == '"') yyinp(); // if (control()) // tok->string = control()->stringLiteral(yytext, yylen); if (hint == 'L') tok->f.kind = T_RAW_WIDE_STRING_LITERAL; else if (hint == 'U') tok->f.kind = T_RAW_UTF32_STRING_LITERAL; else if (hint == 'u') tok->f.kind = T_RAW_UTF16_STRING_LITERAL; else if (hint == '8') tok->f.kind = T_RAW_UTF8_STRING_LITERAL; else tok->f.kind = T_RAW_STRING_LITERAL; } void Lexer::scanCharLiteral(Token *tok, unsigned char hint) { if (hint == 'L') tok->f.kind = T_WIDE_CHAR_LITERAL; else if (hint == 'U') tok->f.kind = T_UTF32_CHAR_LITERAL; else if (hint == 'u') tok->f.kind = T_UTF16_CHAR_LITERAL; else tok->f.kind = T_CHAR_LITERAL; scanUntilQuote(tok, '\''); } void Lexer::scanUntilQuote(Token *tok, unsigned char quote, bool containNewLines) { CPP_CHECK(quote == '"' || quote == '\'' || quote == '`'); //const char *yytext = _currentChar; if (containNewLines) { while (_yychar && _yychar != quote) { yyinp(); } } else { while (_yychar && _yychar != quote && _yychar != '\n') { if (_yychar == '\\') scanBackslash((Kind)tok->f.kind); else yyinp(); } } //int yylen = _currentChar - yytext; if (_yychar == quote) yyinp(); else if (quote == '`') { s._tokenKind = T_RAW_STRING_LITERAL; } // if (control()) // tok->string = control()->stringLiteral(yytext, yylen); } void Lexer::scanNumericLiteral(Token *tok) { //const char *yytext = _currentChar - 1; while (_yychar) { if (_yychar == 'e' || _yychar == 'E') { yyinp(); if (_yychar == '-' || _yychar == '+') { yyinp(); // ### CPP_CHECK(std::isdigit(_yychar)); } } else if (_yychar == 'p' || _yychar == 'P'){ yyinp(); if (_yychar == '-') { yyinp(); } } else if (std::isalnum(_yychar) || _yychar == '.' || _yychar == '_') { yyinp(); } else { break; } } //int yylen = _currentChar - yytext; tok->f.kind = T_NUMERIC_LITERAL; // if (control()) // tok->number = control()->numericLiteral(yytext, yylen); } void Lexer::scanIdentifier(Token *tok, unsigned extraProcessedChars) { const char *yytext = _currentChar - 1 - extraProcessedChars; while (std::isalnum(_yychar) || _yychar == '_' || _yychar == '$') yyinp(); int yylen = _currentChar - yytext; if (_languageFeatures.golangEnable) { tok->f.kind = Lexer::golangKeywords(yytext,yylen); if (tok->f.kind == T_IDENTIFIER) { tok->f.kind = Lexer::golangTypes(yytext,yylen); if (tok->f.kind == T_IDENTIFIER) { tok->f.kind = Lexer::golangBuiltinFunc(yytext,yylen); if (tok->f.kind == T_IDENTIFIER) { tok->f.kind = Lexer::golangPredecl(yytext,yylen); } } } } else { if (f._scanKeywords) tok->f.kind = classify(yytext, yylen, _languageFeatures); else tok->f.kind = T_IDENTIFIER; if (tok->f.kind == T_IDENTIFIER) { tok->f.kind = classifyOperator(yytext, yylen); } // if (control()) // tok->identifier = control()->identifier(yytext, yylen); } } void Lexer::scanBackslash(Kind type) { yyinp(); // skip '\\' if (_yychar && !std::isspace(_yychar)) { yyinp(); return; } while (_yychar != '\n' && std::isspace(_yychar)) yyinp(); if (!_yychar) { s._tokenKind = type; s._newlineExpected = true; return; } if (_yychar == '\n') { yyinp(); while (_yychar != '\n' && std::isspace(_yychar)) yyinp(); if (!_yychar) s._tokenKind = type; } } void Lexer::scanCppComment(Kind type) { while (_yychar && _yychar != '\n') { if (_yychar == '\\') scanBackslash(type); else if (_yychar) yyinp(); } } ================================================ FILE: liteidex/src/3rdparty/cplusplus/Lexer.h ================================================ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_LEXER_H #define CPLUSPLUS_LEXER_H #include "Token.h" namespace CPlusPlus { class Lexer { Lexer(const Lexer &other); void operator =(const Lexer &other); public: //Lexer(TranslationUnit *unit); Lexer(const char *firstChar, const char *lastChar); ~Lexer(); //Control *control() const { return _control; } //TranslationUnit *translationUnit() const; void scan(Token *tok); inline void operator()(Token *tok) { scan(tok); } unsigned tokenOffset() const; unsigned tokenLength() const; const char *tokenBegin() const; const char *tokenEnd() const; unsigned currentLine() const; bool scanCommentTokens() const; void setScanCommentTokens(bool onoff); bool scanKeywords() const; void setScanKeywords(bool onoff); bool scanAngleStringLiteralTokens() const; void setScanAngleStringLiteralTokens(bool onoff); void setStartWithNewline(bool enabled); int state() const; void setState(int state); LanguageFeatures languageFeatures() const { return _languageFeatures; } void setLanguageFeatures(LanguageFeatures features) { _languageFeatures = features; } private: void scan_helper(Token *tok); void setSource(const char *firstChar, const char *lastChar); static int classify(const char *string, int length, LanguageFeatures features); static int classifyObjCAtKeyword(const char *s, int n); static int golangTypes(const char *s, int n); static int golangKeywords(const char *s, int n); static int golangPredecl(const char *s, int n); static int golangBuiltinFunc(const char *s, int n); static int classifyOperator(const char *string, int length); void scanStringLiteral(Token *tok, unsigned char hint = 0); void scanGoRawStringLiteral(Token *tok, unsigned char hint = 0); void scanRawStringLiteral(Token *tok, unsigned char hint = 0); void scanCharLiteral(Token *tok, unsigned char hint = 0); void scanUntilQuote(Token *tok, unsigned char quote, bool containNewLines = false); void scanNumericLiteral(Token *tok); void scanIdentifier(Token *tok, unsigned extraProcessedChars = 0); void scanBackslash(Kind type); void scanCppComment(Kind type); inline void yyinp() { _yychar = *++_currentChar; if (_yychar == '\n') pushLineStartOffset(); } void pushLineStartOffset(); private: struct Flags { unsigned _scanCommentTokens: 1; unsigned _scanKeywords: 1; unsigned _scanAngleStringLiteralTokens: 1; }; struct State { unsigned char _tokenKind : 7; unsigned char _newlineExpected : 1; }; //TranslationUnit *_translationUnit; //Control *_control; const char *_firstChar; const char *_currentChar; const char *_lastChar; const char *_tokenStart; unsigned char _yychar; union { unsigned char _state; State s; }; union { unsigned _flags; Flags f; }; unsigned _currentLine; LanguageFeatures _languageFeatures; }; } // namespace CPlusPlus #endif // CPLUSPLUS_LEXER_H ================================================ FILE: liteidex/src/3rdparty/cplusplus/SimpleLexer.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "SimpleLexer.h" #include "Lexer.h" #include "Token.h" #include using namespace CPlusPlus; SimpleLexer::SimpleLexer() : _lastState(0), _skipComments(false), _endedJoined(false) {} SimpleLexer::~SimpleLexer() { } bool SimpleLexer::skipComments() const { return _skipComments; } void SimpleLexer::setSkipComments(bool skipComments) { _skipComments = skipComments; } bool SimpleLexer::endedJoined() const { return _endedJoined; } QList SimpleLexer::operator()(const QString &text, int state) { QList tokens; const QByteArray bytes = text.toLatin1(); const char *firstChar = bytes.constData(); const char *lastChar = firstChar + bytes.size(); Lexer lex(firstChar, lastChar); lex.setLanguageFeatures(_languageFeatures); lex.setStartWithNewline(true); if (! _skipComments) lex.setScanCommentTokens(true); if (state != -1) lex.setState(state & 0xff); bool inPreproc = false; for (;;) { Token tk; lex(&tk); if (tk.is(T_EOF_SYMBOL)) { _endedJoined = tk.joined(); break; } QStringRef spell = text.midRef(lex.tokenOffset(), lex.tokenLength()); lex.setScanAngleStringLiteralTokens(false); if (tk.f.newline && tk.is(T_POUND)) inPreproc = true; else if (inPreproc && tokens.size() == 1 && tk.is(T_IDENTIFIER) && spell == QLatin1String("include")) lex.setScanAngleStringLiteralTokens(true); else if (inPreproc && tokens.size() == 1 && tk.is(T_IDENTIFIER) && spell == QLatin1String("include_next")) lex.setScanAngleStringLiteralTokens(true); else if (_languageFeatures.objCEnabled && inPreproc && tokens.size() == 1 && tk.is(T_IDENTIFIER) && spell == QLatin1String("import")) lex.setScanAngleStringLiteralTokens(true); tokens.append(tk); } _lastState = lex.state(); return tokens; } int SimpleLexer::tokenAt(const QList &tokens, unsigned offset) { for (int index = tokens.size() - 1; index >= 0; --index) { const Token &tk = tokens.at(index); if (tk.begin() <= offset && tk.end() >= offset) return index; } return -1; } Token SimpleLexer::tokenAt(const QString &text, unsigned offset, int state, bool qtMocRunEnabled) { // FIXME: Check default values. LanguageFeatures features; features.qtMocRunEnabled = qtMocRunEnabled; features.qtEnabled = qtMocRunEnabled; features.qtKeywordsEnabled = qtMocRunEnabled; SimpleLexer tokenize; tokenize.setLanguageFeatures(features); const QList tokens = tokenize(text, state); const int tokenIdx = tokenAt(tokens, offset); return (tokenIdx == -1) ? Token() : tokens.at(tokenIdx); } int SimpleLexer::tokenBefore(const QList &tokens, unsigned offset) { for (int index = tokens.size() - 1; index >= 0; --index) { const Token &tk = tokens.at(index); if (tk.begin() <= offset) return index; } return -1; } ================================================ FILE: liteidex/src/3rdparty/cplusplus/SimpleLexer.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CPLUSPLUS_SIMPLELEXER_H #define CPLUSPLUS_SIMPLELEXER_H #include "Token.h" #include #include namespace CPlusPlus { class SimpleLexer; class Token; class SimpleLexer { public: SimpleLexer(); ~SimpleLexer(); bool skipComments() const; void setSkipComments(bool skipComments); LanguageFeatures languageFeatures() const { return _languageFeatures; } void setLanguageFeatures(LanguageFeatures features) { _languageFeatures = features; } bool endedJoined() const; QList operator()(const QString &text, int state = 0); int state() const { return _lastState; } static int tokenAt(const QList &tokens, unsigned offset); static Token tokenAt(const QString &text, unsigned offset, int state, bool qtMocRunEnabled = false); static int tokenBefore(const QList &tokens, unsigned offset); private: int _lastState; LanguageFeatures _languageFeatures; bool _skipComments: 1; bool _endedJoined: 1; }; } // namespace CPlusPlus #endif // CPLUSPLUS_SIMPLELEXER_H ================================================ FILE: liteidex/src/3rdparty/cplusplus/Token.cpp ================================================ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Token.h" using namespace CPlusPlus; const char *token_names[] = { (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), ("<@string literal>"), (""), ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), (":="), ("::"), (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"), ("!="), (">"), (">="), (">>"), (">>="), ("{"), ("["), ("<"), ("<="), ("<<"), ("<<="), ("("), ("-"), ("-="), ("--"), ("%"), ("%="), ("|"), ("|="), ("||"), ("+"), ("+="), ("++"), ("#"), ("##"), ("?"), ("}"), ("]"), (")"), (";"), ("*"), ("*="), ("~"), ("~="), ("alignas"), ("alignof"), ("asm"), ("auto"), ("bool"), ("break"), ("case"), ("catch"), ("char"), ("char16_t"), ("char32_t"), ("class"), ("const"), ("const_cast"), ("constexpr"), ("continue"), ("decltype"), ("default"), ("delete"), ("do"), ("double"), ("dynamic_cast"), ("else"), ("enum"), ("explicit"), ("export"), ("extern"), ("false"), ("float"), ("for"), ("friend"), ("goto"), ("if"), ("inline"), ("int"), ("long"), ("mutable"), ("namespace"), ("new"), ("noexcept"), ("nullptr"), ("operator"), ("private"), ("protected"), ("public"), ("register"), ("reinterpret_cast"), ("return"), ("short"), ("signed"), ("sizeof"), ("static"),("static_assert"), ("static_cast"), ("struct"), ("switch"), ("template"), ("this"), ("thread_local"), ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"), ("union"), ("unsigned"), ("using"), ("virtual"), ("void"), ("volatile"), ("wchar_t"), ("while"), // gnu ("__attribute__"), ("__thread"), ("__typeof__"), // objc @keywords ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"), ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"), ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"), ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), // Qt keywords ("emit"), ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q"), ("Q_INVOKABLE"), ("Q_PROPERTY"), ("T_Q_PRIVATE_PROPERTY"), ("Q_INTERFACES"), ("Q_EMIT"), ("Q_ENUMS"), ("Q_FLAGS"), ("Q_PRIVATE_SLOT"), ("Q_DECLARE_INTERFACE"), ("Q_OBJECT"), ("Q_GADGET"), // Go keywords ("go"),("if"),("map"),("for"),("var"),("func"), ("case"),("chan"),("else"),("goto"),("type"),("break"), ("defer"),("const"),("range"),("select"),("struct"),("switch"), ("import"),("return"),("default"),("package"),("continue"),("interface"), ("fallthrough"), // Go typed ("int"),("bool"),("int8"),("byte"),("rune"),("uint"), ("uint8"),("int16"),("int32"),("int64"),("error"),("uint16"), ("uint32"),("uint64"),("string"),("float32"),("float64"),("uintptr"), ("complex64"),("complex128"), // Go predecl ("nil"),("true"),("iota"),("false"), // Go builtin ("cap"),("len"),("new"),("copy"),("imag"),("make"), ("real"),("close"),("panic"),("print"),("append"),("delete"), ("complex"),("println"),("recover"), }; void Token::reset() { flags = 0; offset = 0; ptr = 0; } const char *Token::name(int kind) { return token_names[kind]; } const char *Token::spell() const { switch (f.kind) { case T_IDENTIFIER: return "";//identifier->chars(); case T_NUMERIC_LITERAL: case T_CHAR_LITERAL: case T_WIDE_CHAR_LITERAL: case T_UTF16_CHAR_LITERAL: case T_UTF32_CHAR_LITERAL: case T_STRING_LITERAL: case T_WIDE_STRING_LITERAL: case T_UTF8_STRING_LITERAL: case T_UTF16_STRING_LITERAL: case T_UTF32_STRING_LITERAL: case T_RAW_STRING_LITERAL: case T_RAW_WIDE_STRING_LITERAL: case T_RAW_UTF8_STRING_LITERAL: case T_RAW_UTF16_STRING_LITERAL: case T_RAW_UTF32_STRING_LITERAL: case T_AT_STRING_LITERAL: case T_ANGLE_STRING_LITERAL: return "";//literal->chars(); default: return token_names[f.kind]; } // switch } ================================================ FILE: liteidex/src/3rdparty/cplusplus/Token.h ================================================ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_TOKEN_H #define CPLUSPLUS_TOKEN_H namespace CPlusPlus { enum Kind { T_EOF_SYMBOL = 0, T_ERROR, T_CPP_COMMENT, T_CPP_DOXY_COMMENT, T_COMMENT, T_DOXY_COMMENT, T_IDENTIFIER, T_FIRST_LITERAL, T_NUMERIC_LITERAL = T_FIRST_LITERAL, T_FIRST_CHAR_LITERAL, T_CHAR_LITERAL = T_FIRST_CHAR_LITERAL, T_WIDE_CHAR_LITERAL, T_UTF16_CHAR_LITERAL, T_UTF32_CHAR_LITERAL, T_LAST_CHAR_LITERAL = T_UTF32_CHAR_LITERAL, T_FIRST_STRING_LITERAL, T_STRING_LITERAL = T_FIRST_STRING_LITERAL, T_WIDE_STRING_LITERAL, T_UTF8_STRING_LITERAL, T_UTF16_STRING_LITERAL, T_UTF32_STRING_LITERAL, T_RAW_STRING_LITERAL, T_RAW_WIDE_STRING_LITERAL, T_RAW_UTF8_STRING_LITERAL, T_RAW_UTF16_STRING_LITERAL, T_RAW_UTF32_STRING_LITERAL, T_AT_STRING_LITERAL, T_ANGLE_STRING_LITERAL, T_LAST_STRING_LITERAL = T_ANGLE_STRING_LITERAL, T_LAST_LITERAL = T_ANGLE_STRING_LITERAL, T_FIRST_OPERATOR, T_AMPER = T_FIRST_OPERATOR, T_AMPER_AMPER, T_AMPER_EQUAL, T_ARROW, T_ARROW_STAR, T_CARET, T_CARET_EQUAL, T_COLON, T_COLON_EQUAL, T_COLON_COLON, T_COMMA, T_SLASH, T_SLASH_EQUAL, T_DOT, T_DOT_DOT_DOT, T_DOT_STAR, T_EQUAL, T_EQUAL_EQUAL, T_EXCLAIM, T_EXCLAIM_EQUAL, T_GREATER, T_GREATER_EQUAL, T_GREATER_GREATER, T_GREATER_GREATER_EQUAL, T_LBRACE, T_LBRACKET, T_LESS, T_LESS_EQUAL, T_LESS_LESS, T_LESS_LESS_EQUAL, T_LPAREN, T_MINUS, T_MINUS_EQUAL, T_MINUS_MINUS, T_PERCENT, T_PERCENT_EQUAL, T_PIPE, T_PIPE_EQUAL, T_PIPE_PIPE, T_PLUS, T_PLUS_EQUAL, T_PLUS_PLUS, T_POUND, T_POUND_POUND, T_QUESTION, T_RBRACE, T_RBRACKET, T_RPAREN, T_SEMICOLON, T_STAR, T_STAR_EQUAL, T_TILDE, T_TILDE_EQUAL, T_LAST_OPERATOR = T_TILDE_EQUAL, T_FIRST_KEYWORD, T_ALIGNAS = T_FIRST_KEYWORD, T_ALIGNOF, T_ASM, T_AUTO, T_BOOL, T_BREAK, T_CASE, T_CATCH, T_CHAR, T_CHAR16_T, T_CHAR32_T, T_CLASS, T_CONST, T_CONST_CAST, T_CONSTEXPR, T_CONTINUE, T_DECLTYPE, T_DEFAULT, T_DELETE, T_DO, T_DOUBLE, T_DYNAMIC_CAST, T_ELSE, T_ENUM, T_EXPLICIT, T_EXPORT, T_EXTERN, T_FALSE, T_FLOAT, T_FOR, T_FRIEND, T_GOTO, T_IF, T_INLINE, T_INT, T_LONG, T_MUTABLE, T_NAMESPACE, T_NEW, T_NOEXCEPT, T_NULLPTR, T_OPERATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_REGISTER, T_REINTERPRET_CAST, T_RETURN, T_SHORT, T_SIGNED, T_SIZEOF, T_STATIC, T_STATIC_ASSERT, T_STATIC_CAST, T_STRUCT, T_SWITCH, T_TEMPLATE, T_THIS, T_THREAD_LOCAL, T_THROW, T_TRUE, T_TRY, T_TYPEDEF, T_TYPEID, T_TYPENAME, T_UNION, T_UNSIGNED, T_USING, T_VIRTUAL, T_VOID, T_VOLATILE, T_WCHAR_T, T_WHILE, T___ATTRIBUTE__, T___THREAD, T___TYPEOF__, // obj c++ @ keywords T_FIRST_OBJC_AT_KEYWORD, T_AT_CATCH = T_FIRST_OBJC_AT_KEYWORD, T_AT_CLASS, T_AT_COMPATIBILITY_ALIAS, T_AT_DEFS, T_AT_DYNAMIC, T_AT_ENCODE, T_AT_END, T_AT_FINALLY, T_AT_IMPLEMENTATION, T_AT_INTERFACE, T_AT_NOT_KEYWORD, T_AT_OPTIONAL, T_AT_PACKAGE, T_AT_PRIVATE, T_AT_PROPERTY, T_AT_PROTECTED, T_AT_PROTOCOL, T_AT_PUBLIC, T_AT_REQUIRED, T_AT_SELECTOR, T_AT_SYNCHRONIZED, T_AT_SYNTHESIZE, T_AT_THROW, T_AT_TRY, T_LAST_OBJC_AT_KEYWORD = T_AT_TRY, T_FIRST_QT_KEYWORD, // Qt keywords T_EMIT = T_FIRST_QT_KEYWORD, T_SIGNAL, T_SLOT, T_Q_SIGNAL, T_Q_SLOT, T_Q_SIGNALS, T_Q_SLOTS, T_Q_FOREACH, T_Q_D, T_Q_Q, T_Q_INVOKABLE, T_Q_PROPERTY, T_Q_PRIVATE_PROPERTY, T_Q_INTERFACES, T_Q_EMIT, T_Q_ENUMS, T_Q_FLAGS, T_Q_PRIVATE_SLOT, T_Q_DECLARE_INTERFACE, T_Q_OBJECT, T_Q_GADGET, T_LAST_KEYWORD = T_Q_GADGET, T_FIRST_GO_KEYWORD, T_GO_GO = T_FIRST_GO_KEYWORD, T_GO_IF, T_GO_MAP, T_GO_FOR, T_GO_VAR, T_GO_FUNC, T_GO_CASE, T_GO_CHAN, T_GO_ELSE, T_GO_GOTO, T_GO_TYPE, T_GO_BREAK, T_GO_DEFER, T_GO_CONST, T_GO_RANGE, T_GO_SELECT, T_GO_STRUCT, T_GO_SWITCH, T_GO_IMPORT, T_GO_RETURN, T_GO_DEFAULT, T_GO_PACKAGE, T_GO_CONTINUE, T_GO_INTERFACE, T_GO_FALLTHROUGH, T_LAST_GO_KEYWORD = T_GO_FALLTHROUGH, T_FIRST_GO_TYPED, T_GO_INT = T_FIRST_GO_TYPED, T_GO_BOOL, T_GO_INT8, T_GO_BYTE, T_GO_RUNE, T_GO_UINT, T_GO_UINT8, T_GO_INT16, T_GO_INT32, T_GO_INT64, T_GO_ERROR, T_GO_UINT16, T_GO_UINT32, T_GO_UINT64, T_GO_STRING, T_GO_FLOAT32, T_GO_FLOAT64, T_GO_UINTPTR, T_GO_ANY, T_GO_COMPARABLE, T_GO_COMPLEX64, T_GO_COMPLEX128, T_LAST_GO_TYPED = T_GO_COMPLEX128, T_FIRST_GO_PREDECL, T_GO_NIL = T_FIRST_GO_PREDECL, T_GO_TRUE, T_GO_IOTA, T_GO_FALSE, T_LAST_GO_PREDECL = T_GO_FALSE, T_FIRST_GO_BUILTIN, T_GO_CAP = T_FIRST_GO_BUILTIN, T_GO_LEN, T_GO_NEW, T_GO_COPY, T_GO_IMAG, T_GO_MAKE, T_GO_REAL, T_GO_CLOSE, T_GO_PANIC, T_GO_PRINT, T_GO_APPEND, T_GO_DELETE, T_GO_COMPLEX, T_GO_PRINTLN, T_GO_RECOVER, T_LAST_GO_BUILTIN = T_GO_RECOVER, // aliases T_OR = T_PIPE_PIPE, T_AND = T_AMPER_AMPER, T_NOT = T_EXCLAIM, T_XOR = T_CARET, T_BITOR = T_PIPE, T_COMPL = T_TILDE, T_OR_EQ = T_PIPE_EQUAL, T_AND_EQ = T_AMPER_EQUAL, T_BITAND = T_AMPER, T_NOT_EQ = T_EXCLAIM_EQUAL, T_XOR_EQ = T_CARET_EQUAL, T___ASM = T_ASM, T___ASM__ = T_ASM, T_TYPEOF = T___TYPEOF__, T___TYPEOF = T___TYPEOF__, T___DECLTYPE = T_DECLTYPE, T___INLINE = T_INLINE, T___INLINE__ = T_INLINE, T___CONST = T_CONST, T___CONST__ = T_CONST, T___VOLATILE = T_VOLATILE, T___VOLATILE__ = T_VOLATILE, T___ATTRIBUTE = T___ATTRIBUTE__ }; class Token { public: Token() : flags(0), offset(0), ptr(0) {} inline bool is(unsigned k) const { return f.kind == k; } inline bool isNot(unsigned k) const { return f.kind != k; } const char *spell() const; void reset(); inline unsigned kind() const { return f.kind; } inline bool newline() const { return f.newline; } inline bool whitespace() const { return f.whitespace; } inline bool joined() const { return f.joined; } inline bool expanded() const { return f.expanded; } inline bool generated() const { return f.generated; } inline unsigned length() const { return f.length; } inline unsigned begin() const { return offset; } inline unsigned end() const { return offset + f.length; } inline bool isLiteral() const { return f.kind >= T_FIRST_LITERAL && f.kind <= T_LAST_LITERAL; } inline bool isCharLiteral() const { return f.kind >= T_FIRST_CHAR_LITERAL && f.kind <= T_LAST_CHAR_LITERAL; } inline bool isStringLiteral() const { return f.kind >= T_FIRST_STRING_LITERAL && f.kind <= T_LAST_STRING_LITERAL; } inline bool isOperator() const { return f.kind >= T_FIRST_OPERATOR && f.kind <= T_LAST_OPERATOR; } inline bool isKeyword() const { return f.kind >= T_FIRST_KEYWORD && f.kind < T_FIRST_QT_KEYWORD; } inline bool isComment() const { return f.kind == T_COMMENT || f.kind == T_DOXY_COMMENT || f.kind == T_CPP_COMMENT || f.kind == T_CPP_DOXY_COMMENT; } inline bool isObjCAtKeyword() const { return f.kind >= T_FIRST_OBJC_AT_KEYWORD && f.kind <= T_LAST_OBJC_AT_KEYWORD; } inline bool isGoKeyword() const { return f.kind >= T_FIRST_GO_KEYWORD && f.kind <= T_LAST_GO_KEYWORD; } inline bool isGoTyped() const { return f.kind >= T_FIRST_GO_TYPED && f.kind <= T_LAST_GO_TYPED; } inline bool isGoPredecl() const { return f.kind >= T_FIRST_GO_PREDECL && f.kind <= T_LAST_GO_PREDECL; } inline bool isGoBuiltin() const { return f.kind >= T_FIRST_GO_BUILTIN && f.kind <= T_LAST_GO_BUILTIN; } static const char *name(int kind); public: struct Flags { // The token kind. unsigned kind : 10; // The token starts a new line. unsigned newline : 1; // The token is preceded by whitespace(s). unsigned whitespace : 1; // The token is joined with the previous one. unsigned joined : 1; // The token originates from a macro expansion. unsigned expanded : 1; // The token originates from a macro expansion and does not correspond to an // argument that went through substitution. Notice the example: // // #define FOO(a, b) a + b; // FOO(1, 2) // // After preprocessing we would expect the following tokens: 1 + 2; // Tokens '1', '+', '2', and ';' are all expanded. However only tokens '+' and ';' // are generated. unsigned generated : 1; // Unused... unsigned pad : 1; // The token length. unsigned length : 16; }; union { unsigned flags; Flags f; }; unsigned offset; union { void *ptr; //const Literal *literal; //const NumericLiteral *number; //const StringLiteral *string; //const Identifier *identifier; //unsigned close_brace; //unsigned lineno; }; }; struct LanguageFeatures { LanguageFeatures() : flags(0) {} union { unsigned int flags; struct { unsigned int qtEnabled : 1; // If Qt is used. unsigned int qtMocRunEnabled : 1; unsigned int qtKeywordsEnabled : 1; // If Qt is used but QT_NO_KEYWORDS defined unsigned int cxx11Enabled : 1; unsigned int objCEnabled : 1; unsigned int golangEnable : 1; }; }; }; } // namespace CPlusPlus #endif // CPLUSPLUS_TOKEN_H ================================================ FILE: liteidex/src/3rdparty/cplusplus/cplusplus.pri ================================================ LIBS *= -l$$qtLibraryName(cplusplus) ================================================ FILE: liteidex/src/3rdparty/cplusplus/cplusplus.pro ================================================ TARGET = cplusplus TEMPLATE = lib CONFIG += staticlib include (../../liteideutils.pri) HEADERS += \ cppassert.h \ Lexer.h \ SimpleLexer.h \ Token.h \ BackwardsScanner.h \ gopredecl.kwgen SOURCES += \ gokeyword.cpp \ gotypes.cpp \ Keywords.cpp \ Lexer.cpp \ SimpleLexer.cpp \ Token.cpp \ BackwardsScanner.cpp \ gopredecl.cpp \ gobuiltin.cpp ================================================ FILE: liteidex/src/3rdparty/cplusplus/cppassert.h ================================================ /**************************************************************************** * ** * ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). * ** Contact: http://www.qt-project.org/legal * ** * ** This file is part of Qt Creator. * ** * ** Commercial License Usage * ** Licensees holding valid commercial Qt licenses may use this file in * ** accordance with the commercial license agreement provided with the * ** Software or, alternatively, in accordance with the terms contained in * ** a written agreement between you and Digia. For licensing terms and * ** conditions see http://qt.digia.com/licensing. For further information * ** use the contact form at http://qt.digia.com/contact-us. * ** * ** GNU Lesser General Public License Usage * ** Alternatively, this file may be used under the terms of the GNU Lesser * ** General Public License version 2.1 as published by the Free Software * ** Foundation and appearing in the file LICENSE.LGPL included in the * ** packaging of this file. Please review the following information to * ** ensure the GNU Lesser General Public License version 2.1 requirements * ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * ** * ** In addition, as a special exception, Digia gives you certain additional * ** rights. These rights are described in the Digia Qt LGPL Exception * ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. * ** * ****************************************************************************/ #ifndef SOFT_ASSERT_H #define SOFT_ASSERT_H #include #define CPP_ASSERT_STRINGIFY_HELPER(x) #x #define CPP_ASSERT_STRINGIFY(x) CPP_ASSERT_STRINGIFY_HELPER(x) #define CPP_ASSERT_STRING(cond) std::cerr \ << "SOFT ASSERT: \"" cond"\" in file " __FILE__ ", line " CPP_ASSERT_STRINGIFY(__LINE__) \ << std::endl; #define CPP_ASSERT(cond, action) if (cond) {} else { CPP_ASSERT_STRING(#cond); action; } do {} while (0) #define CPP_CHECK(cond) if (cond) {} else { CPP_ASSERT_STRING(#cond); } do {} while (0) #endif // SOFT_ASSERT_H ================================================ FILE: liteidex/src/3rdparty/cplusplus/gobuiltin.cpp ================================================ #include "Lexer.h" #include "Token.h" /* T_GO_CAP, T_GO_LEN, T_GO_NEW, T_GO_COPY, T_GO_IMAG, T_GO_MAKE, T_GO_REAL, T_GO_CLOSE, T_GO_PANIC, T_GO_PRINT, T_GO_APPEND, T_GO_DELETE, T_GO_COMPLEX, T_GO_PRINTLN, T_GO_RECOVER, */ /* ("cap"),("len"),("new"),("copy"),("imag"),("make"), ("real"),("close"),("panic"),("print"),("append"),("delete"), ("complex"),("println"),("recover"), */ namespace CPlusPlus { static inline int golangBuiltinFunc3(const char *s) { if (s[0] == 'c') { if (s[1] == 'a') { if (s[2] == 'p') { return T_GO_CAP; } } } else if (s[0] == 'l') { if (s[1] == 'e') { if (s[2] == 'n') { return T_GO_LEN; } } } else if (s[0] == 'n') { if (s[1] == 'e') { if (s[2] == 'w') { return T_GO_NEW; } } } return T_IDENTIFIER; } static inline int golangBuiltinFunc4(const char *s) { if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'p') { if (s[3] == 'y') { return T_GO_COPY; } } } } else if (s[0] == 'i') { if (s[1] == 'm') { if (s[2] == 'a') { if (s[3] == 'g') { return T_GO_IMAG; } } } } else if (s[0] == 'm') { if (s[1] == 'a') { if (s[2] == 'k') { if (s[3] == 'e') { return T_GO_MAKE; } } } } else if (s[0] == 'r') { if (s[1] == 'e') { if (s[2] == 'a') { if (s[3] == 'l') { return T_GO_REAL; } } } } return T_IDENTIFIER; } static inline int golangBuiltinFunc5(const char *s) { if (s[0] == 'c') { if (s[1] == 'l') { if (s[2] == 'o') { if (s[3] == 's') { if (s[4] == 'e') { return T_GO_CLOSE; } } } } } else if (s[0] == 'p') { if (s[1] == 'a') { if (s[2] == 'n') { if (s[3] == 'i') { if (s[4] == 'c') { return T_GO_PANIC; } } } } else if (s[1] == 'r') { if (s[2] == 'i') { if (s[3] == 'n') { if (s[4] == 't') { return T_GO_PRINT; } } } } } return T_IDENTIFIER; } static inline int golangBuiltinFunc6(const char *s) { if (s[0] == 'a') { if (s[1] == 'p') { if (s[2] == 'p') { if (s[3] == 'e') { if (s[4] == 'n') { if (s[5] == 'd') { return T_GO_APPEND; } } } } } } else if (s[0] == 'd') { if (s[1] == 'e') { if (s[2] == 'l') { if (s[3] == 'e') { if (s[4] == 't') { if (s[5] == 'e') { return T_GO_DELETE; } } } } } } return T_IDENTIFIER; } static inline int golangBuiltinFunc7(const char *s) { if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'm') { if (s[3] == 'p') { if (s[4] == 'l') { if (s[5] == 'e') { if (s[6] == 'x') { return T_GO_COMPLEX; } } } } } } } else if (s[0] == 'p') { if (s[1] == 'r') { if (s[2] == 'i') { if (s[3] == 'n') { if (s[4] == 't') { if (s[5] == 'l') { if (s[6] == 'n') { return T_GO_PRINTLN; } } } } } } } else if (s[0] == 'r') { if (s[1] == 'e') { if (s[2] == 'c') { if (s[3] == 'o') { if (s[4] == 'v') { if (s[5] == 'e') { if (s[6] == 'r') { return T_GO_RECOVER; } } } } } } } return T_IDENTIFIER; } int Lexer::golangBuiltinFunc(const char *s, int n) { switch (n) { case 3: return golangBuiltinFunc3(s); case 4: return golangBuiltinFunc4(s); case 5: return golangBuiltinFunc5(s); case 6: return golangBuiltinFunc6(s); case 7: return golangBuiltinFunc7(s); default: return T_IDENTIFIER; } // switch } } //namespace CPlusPlus ================================================ FILE: liteidex/src/3rdparty/cplusplus/gobuiltin.kwgen ================================================ #include "Lexer.h" #include "Token.h" %token-prefix=T_GO_ %toupper %no-enums %namespace=CPlusPlus %lexer-class=Lexer %classify_prefix=golangBuiltinFunc %identifier=T_IDENTIFIER %% append delete cap close complex copy imag len make new panic print println real recover ================================================ FILE: liteidex/src/3rdparty/cplusplus/gogen.bat ================================================ kwgen < gotypes.kwgen > gotypes.cpp kwgen < gokeyword.kwgen > gokeyword.cpp kwgen < gobuiltin.kwgen > gobuiltin.cpp kwgen < gopredecl.kwgen > gopredecl.cpp ================================================ FILE: liteidex/src/3rdparty/cplusplus/gokeyword.cpp ================================================ #include "Lexer.h" #include "Token.h" /* T_GO_GO, T_GO_IF, T_GO_MAP, T_GO_FOR, T_GO_VAR, T_GO_FUNC, T_GO_CASE, T_GO_CHAN, T_GO_ELSE, T_GO_GOTO, T_GO_TYPE, T_GO_BREAK, T_GO_DEFER, T_GO_CONST, T_GO_RANGE, T_GO_SELECT, T_GO_STRUCT, T_GO_SWITCH, T_GO_IMPORT, T_GO_RETURN, T_GO_DEFAULT, T_GO_PACKAGE, T_GO_CONTINUE, T_GO_INTERFACE, T_GO_FALLTHROUGH, */ /* ("go"),("if"),("map"),("for"),("var"),("func"), ("case"),("chan"),("else"),("goto"),("type"),("break"), ("defer"),("const"),("range"),("select"),("struct"),("switch"), ("import"),("return"),("default"),("package"),("continue"),("interface"), ("fallthrough"), */ namespace CPlusPlus { static inline int golangKeywords2(const char *s) { if (s[0] == 'g') { if (s[1] == 'o') { return T_GO_GO; } } else if (s[0] == 'i') { if (s[1] == 'f') { return T_GO_IF; } } return T_IDENTIFIER; } static inline int golangKeywords3(const char *s) { if (s[0] == 'f') { if (s[1] == 'o') { if (s[2] == 'r') { return T_GO_FOR; } } } else if (s[0] == 'm') { if (s[1] == 'a') { if (s[2] == 'p') { return T_GO_MAP; } } } else if (s[0] == 'v') { if (s[1] == 'a') { if (s[2] == 'r') { return T_GO_VAR; } } } return T_IDENTIFIER; } static inline int golangKeywords4(const char *s) { if (s[0] == 'c') { if (s[1] == 'a') { if (s[2] == 's') { if (s[3] == 'e') { return T_GO_CASE; } } } else if (s[1] == 'h') { if (s[2] == 'a') { if (s[3] == 'n') { return T_GO_CHAN; } } } } else if (s[0] == 'e') { if (s[1] == 'l') { if (s[2] == 's') { if (s[3] == 'e') { return T_GO_ELSE; } } } } else if (s[0] == 'f') { if (s[1] == 'u') { if (s[2] == 'n') { if (s[3] == 'c') { return T_GO_FUNC; } } } } else if (s[0] == 'g') { if (s[1] == 'o') { if (s[2] == 't') { if (s[3] == 'o') { return T_GO_GOTO; } } } } else if (s[0] == 't') { if (s[1] == 'y') { if (s[2] == 'p') { if (s[3] == 'e') { return T_GO_TYPE; } } } } return T_IDENTIFIER; } static inline int golangKeywords5(const char *s) { if (s[0] == 'b') { if (s[1] == 'r') { if (s[2] == 'e') { if (s[3] == 'a') { if (s[4] == 'k') { return T_GO_BREAK; } } } } } else if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'n') { if (s[3] == 's') { if (s[4] == 't') { return T_GO_CONST; } } } } } else if (s[0] == 'd') { if (s[1] == 'e') { if (s[2] == 'f') { if (s[3] == 'e') { if (s[4] == 'r') { return T_GO_DEFER; } } } } } else if (s[0] == 'r') { if (s[1] == 'a') { if (s[2] == 'n') { if (s[3] == 'g') { if (s[4] == 'e') { return T_GO_RANGE; } } } } } return T_IDENTIFIER; } static inline int golangKeywords6(const char *s) { if (s[0] == 'i') { if (s[1] == 'm') { if (s[2] == 'p') { if (s[3] == 'o') { if (s[4] == 'r') { if (s[5] == 't') { return T_GO_IMPORT; } } } } } } else if (s[0] == 'r') { if (s[1] == 'e') { if (s[2] == 't') { if (s[3] == 'u') { if (s[4] == 'r') { if (s[5] == 'n') { return T_GO_RETURN; } } } } } } else if (s[0] == 's') { if (s[1] == 'e') { if (s[2] == 'l') { if (s[3] == 'e') { if (s[4] == 'c') { if (s[5] == 't') { return T_GO_SELECT; } } } } } else if (s[1] == 't') { if (s[2] == 'r') { if (s[3] == 'u') { if (s[4] == 'c') { if (s[5] == 't') { return T_GO_STRUCT; } } } } } else if (s[1] == 'w') { if (s[2] == 'i') { if (s[3] == 't') { if (s[4] == 'c') { if (s[5] == 'h') { return T_GO_SWITCH; } } } } } } return T_IDENTIFIER; } static inline int golangKeywords7(const char *s) { if (s[0] == 'd') { if (s[1] == 'e') { if (s[2] == 'f') { if (s[3] == 'a') { if (s[4] == 'u') { if (s[5] == 'l') { if (s[6] == 't') { return T_GO_DEFAULT; } } } } } } } else if (s[0] == 'p') { if (s[1] == 'a') { if (s[2] == 'c') { if (s[3] == 'k') { if (s[4] == 'a') { if (s[5] == 'g') { if (s[6] == 'e') { return T_GO_PACKAGE; } } } } } } } return T_IDENTIFIER; } static inline int golangKeywords8(const char *s) { if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'n') { if (s[3] == 't') { if (s[4] == 'i') { if (s[5] == 'n') { if (s[6] == 'u') { if (s[7] == 'e') { return T_GO_CONTINUE; } } } } } } } } return T_IDENTIFIER; } static inline int golangKeywords9(const char *s) { if (s[0] == 'i') { if (s[1] == 'n') { if (s[2] == 't') { if (s[3] == 'e') { if (s[4] == 'r') { if (s[5] == 'f') { if (s[6] == 'a') { if (s[7] == 'c') { if (s[8] == 'e') { return T_GO_INTERFACE; } } } } } } } } } return T_IDENTIFIER; } static inline int golangKeywords11(const char *s) { if (s[0] == 'f') { if (s[1] == 'a') { if (s[2] == 'l') { if (s[3] == 'l') { if (s[4] == 't') { if (s[5] == 'h') { if (s[6] == 'r') { if (s[7] == 'o') { if (s[8] == 'u') { if (s[9] == 'g') { if (s[10] == 'h') { return T_GO_FALLTHROUGH; } } } } } } } } } } } return T_IDENTIFIER; } int Lexer::golangKeywords(const char *s, int n) { switch (n) { case 2: return golangKeywords2(s); case 3: return golangKeywords3(s); case 4: return golangKeywords4(s); case 5: return golangKeywords5(s); case 6: return golangKeywords6(s); case 7: return golangKeywords7(s); case 8: return golangKeywords8(s); case 9: return golangKeywords9(s); case 11: return golangKeywords11(s); default: return T_IDENTIFIER; } // switch } } //namespace CPlusPlus ================================================ FILE: liteidex/src/3rdparty/cplusplus/gokeyword.kwgen ================================================ #include "Lexer.h" #include "Token.h" %token-prefix=T_GO_ %toupper %no-enums %namespace=CPlusPlus %lexer-class=Lexer %classify_prefix=golangKeywords %identifier=T_IDENTIFIER %% break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var ================================================ FILE: liteidex/src/3rdparty/cplusplus/gopredecl.cpp ================================================ #include "Lexer.h" #include "Token.h" /* T_GO_NIL, T_GO_TRUE, T_GO_IOTA, T_GO_FALSE, */ /* ("nil"),("true"),("iota"),("false"), */ namespace CPlusPlus { static inline int golangPredecl3(const char *s) { if (s[0] == 'n') { if (s[1] == 'i') { if (s[2] == 'l') { return T_GO_NIL; } } } return T_IDENTIFIER; } static inline int golangPredecl4(const char *s) { if (s[0] == 'i') { if (s[1] == 'o') { if (s[2] == 't') { if (s[3] == 'a') { return T_GO_IOTA; } } } } else if (s[0] == 't') { if (s[1] == 'r') { if (s[2] == 'u') { if (s[3] == 'e') { return T_GO_TRUE; } } } } return T_IDENTIFIER; } static inline int golangPredecl5(const char *s) { if (s[0] == 'f') { if (s[1] == 'a') { if (s[2] == 'l') { if (s[3] == 's') { if (s[4] == 'e') { return T_GO_FALSE; } } } } } return T_IDENTIFIER; } int Lexer::golangPredecl(const char *s, int n) { switch (n) { case 3: return golangPredecl3(s); case 4: return golangPredecl4(s); case 5: return golangPredecl5(s); default: return T_IDENTIFIER; } // switch } } //namespace CPlusPlus ================================================ FILE: liteidex/src/3rdparty/cplusplus/gopredecl.kwgen ================================================ #include "Lexer.h" #include "Token.h" %token-prefix=T_GO_ %toupper %no-enums %namespace=CPlusPlus %lexer-class=Lexer %classify_prefix=golangPredecl %identifier=T_IDENTIFIER %% true false nil iota ================================================ FILE: liteidex/src/3rdparty/cplusplus/gotypes.cpp ================================================ #include "Lexer.h" #include "Token.h" namespace CPlusPlus { static inline int golangTypes3(const char *s) { if (s[0] == 'a') { if (s[1] == 'n') { if (s[2] == 'y') { return T_GO_ANY; } } } else if (s[0] == 'i') { if (s[1] == 'n') { if (s[2] == 't') { return T_GO_INT; } } } return T_IDENTIFIER; } static inline int golangTypes4(const char *s) { if (s[0] == 'b') { if (s[1] == 'o') { if (s[2] == 'o') { if (s[3] == 'l') { return T_GO_BOOL; } } } else if (s[1] == 'y') { if (s[2] == 't') { if (s[3] == 'e') { return T_GO_BYTE; } } } } else if (s[0] == 'i') { if (s[1] == 'n') { if (s[2] == 't') { if (s[3] == '8') { return T_GO_INT8; } } } } else if (s[0] == 'r') { if (s[1] == 'u') { if (s[2] == 'n') { if (s[3] == 'e') { return T_GO_RUNE; } } } } else if (s[0] == 'u') { if (s[1] == 'i') { if (s[2] == 'n') { if (s[3] == 't') { return T_GO_UINT; } } } } return T_IDENTIFIER; } static inline int golangTypes5(const char *s) { if (s[0] == 'e') { if (s[1] == 'r') { if (s[2] == 'r') { if (s[3] == 'o') { if (s[4] == 'r') { return T_GO_ERROR; } } } } } else if (s[0] == 'i') { if (s[1] == 'n') { if (s[2] == 't') { if (s[3] == '1') { if (s[4] == '6') { return T_GO_INT16; } } else if (s[3] == '3') { if (s[4] == '2') { return T_GO_INT32; } } else if (s[3] == '6') { if (s[4] == '4') { return T_GO_INT64; } } } } } else if (s[0] == 'u') { if (s[1] == 'i') { if (s[2] == 'n') { if (s[3] == 't') { if (s[4] == '8') { return T_GO_UINT8; } } } } } return T_IDENTIFIER; } static inline int golangTypes6(const char *s) { if (s[0] == 's') { if (s[1] == 't') { if (s[2] == 'r') { if (s[3] == 'i') { if (s[4] == 'n') { if (s[5] == 'g') { return T_GO_STRING; } } } } } } else if (s[0] == 'u') { if (s[1] == 'i') { if (s[2] == 'n') { if (s[3] == 't') { if (s[4] == '1') { if (s[5] == '6') { return T_GO_UINT16; } } else if (s[4] == '3') { if (s[5] == '2') { return T_GO_UINT32; } } else if (s[4] == '6') { if (s[5] == '4') { return T_GO_UINT64; } } } } } } return T_IDENTIFIER; } static inline int golangTypes7(const char *s) { if (s[0] == 'f') { if (s[1] == 'l') { if (s[2] == 'o') { if (s[3] == 'a') { if (s[4] == 't') { if (s[5] == '3') { if (s[6] == '2') { return T_GO_FLOAT32; } } else if (s[5] == '6') { if (s[6] == '4') { return T_GO_FLOAT64; } } } } } } } else if (s[0] == 'u') { if (s[1] == 'i') { if (s[2] == 'n') { if (s[3] == 't') { if (s[4] == 'p') { if (s[5] == 't') { if (s[6] == 'r') { return T_GO_UINTPTR; } } } } } } } return T_IDENTIFIER; } static inline int golangTypes9(const char *s) { if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'm') { if (s[3] == 'p') { if (s[4] == 'l') { if (s[5] == 'e') { if (s[6] == 'x') { if (s[7] == '6') { if (s[8] == '4') { return T_GO_COMPLEX64; } } } } } } } } } return T_IDENTIFIER; } static inline int golangTypes10(const char *s) { if (s[0] == 'c') { if (s[1] == 'o') { if (s[2] == 'm') { if (s[3] == 'p') { if (s[4] == 'a') { if (s[5] == 'r') { if (s[6] == 'a') { if (s[7] == 'b') { if (s[8] == 'l') { if (s[9] == 'e') { return T_GO_COMPARABLE; } } } } } } else if (s[4] == 'l') { if (s[5] == 'e') { if (s[6] == 'x') { if (s[7] == '1') { if (s[8] == '2') { if (s[9] == '8') { return T_GO_COMPLEX128; } } } } } } } } } } return T_IDENTIFIER; } int Lexer::golangTypes(const char *s, int n) { switch (n) { case 3: return golangTypes3(s); case 4: return golangTypes4(s); case 5: return golangTypes5(s); case 6: return golangTypes6(s); case 7: return golangTypes7(s); case 9: return golangTypes9(s); case 10: return golangTypes10(s); default: return T_IDENTIFIER; } // switch } } ================================================ FILE: liteidex/src/3rdparty/cplusplus/gotypes.kwgen ================================================ #include "Lexer.h" #include "Token.h" %token-prefix=T_GO_ %toupper %no-enums %namespace=CPlusPlus %lexer-class=Lexer %classify_prefix=golangTypes %identifier=T_IDENTIFIER %% bool uint8 uint16 uint32 uint64 int8 int16 int32 int64 float32 float64 complex64 complex128 byte rune string uint int uintptr error any comparable ================================================ FILE: liteidex/src/3rdparty/diff_match_patch/README.txt ================================================ Diff, Match and Patch Library http://code.google.com/p/google-diff-match-patch/ Neil Fraser Java: * diff_match_patch.java * diff_match_patch_test.java JavaScript: * diff_match_patch.js This file has been compressed using Google's internal JavaScript compressor. External hackers are recommended to use http://dean.edwards.name/packer/ * diff_match_patch_uncompressed.js * diff_match_patch_test.html Python: * diff_match_patch.py * diff_match_patch_test.py Lua: (ported by Duncan Cross) * diff_match_patch.lua * diff_match_patch_test.lua C++: (ported by Mike Slemmer) * diff_match_patch.pro * diff_match_patch.h * diff_match_patch.cpp * diff_match_patch_test.h * diff_match_patch_test.cpp C#: (ported by Matthaeus G. Chajdas) * DiffMatchPatch.cs * DiffMatchPatchTest.cs Demos: (in JavaScript) * demo_diff.html * demo_match.html * demo_patch.html ================================================ FILE: liteidex/src/3rdparty/diff_match_patch/diff_match_patch.cpp ================================================ /* * Copyright 2008 Google Inc. All Rights Reserved. * Author: fraser@google.com (Neil Fraser) * Author: mikeslemmer@gmail.com (Mike Slemmer) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Diff Match and Patch * http://code.google.com/p/google-diff-match-patch/ */ // Code known to compile and run with Qt 4.3.3 and Qt 4.4.0. #include #include "liteapi/liteqt.h" #include "diff_match_patch.h" ////////////////////////// // // Diff Class // ////////////////////////// /** * Constructor. Initializes the diff with the provided values. * @param operation One of INSERT, DELETE or EQUAL * @param text The text being applied */ Diff::Diff(Operation _operation, const QString &_text) : operation(_operation), text(_text) { // Construct a diff with the specified operation and text. } Diff::Diff() { } QString Diff::strOperation(Operation op) { switch (op) { case INSERT: return "INSERT"; case DELETE: return "DELETE"; case EQUAL: return "EQUAL"; } throw "Invalid operation."; } /** * Display a human-readable version of this Diff. * @return text version */ QString Diff::toString() const { QString prettyText = text; // Replace linebreaks with Pilcrow signs. prettyText.replace('\n', L'\u00b6'); //qDebug(qPrintable(QString("Diff(") + strOperation(operation) + QString(",\"") // + prettyText + QString("\")"))); return QString("Diff(") + strOperation(operation) + QString(",\"") + prettyText + QString("\")"); } /** * Is this Diff equivalent to another Diff? * @param d Another Diff to compare against * @return true or false */ bool Diff::operator==(const Diff &d) const { return (d.operation == this->operation) && (d.text == this->text); } bool Diff::operator!=(const Diff &d) const { return !(operator == (d)); } ///////////////////////////////////////////// // // Patch Class // ///////////////////////////////////////////// /** * Constructor. Initializes with an empty list of diffs. */ Patch::Patch() : start1(0), start2(0), length1(0), length2(0) { } bool Patch::isNull() const { if (start1 == 0 && start2 == 0 && length1 == 0 && length2 == 0 && diffs.size() == 0) { return true; } return false; } /** * Emmulate GNU diff's format. * Header: @@ -382,8 +481,9 @@ * Indicies are printed as 1-based, not 0-based. * @return The GNU diff string */ QString Patch::toString() { QString coords1, coords2; if (length1 == 0) { coords1 = QString::number(start1) + QString(",0"); } else if (length1 == 1) { coords1 = QString::number(start1 + 1); } else { coords1 = QString::number(start1 + 1) + QString(",") + QString::number(length1); } if (length2 == 0) { coords2 = QString::number(start2) + QString(",0"); } else if (length2 == 1) { coords2 = QString::number(start2 + 1); } else { coords2 = QString::number(start2 + 1) + QString(",") + QString::number(length2); } QString text; text = QString("@@ -") + coords1 + QString(" +") + coords2 + QString(" @@\n"); // Escape the body of the patch with %xx notation. foreach (Diff aDiff, diffs) { switch (aDiff.operation) { case INSERT: text += QString('+'); break; case DELETE: text += QString('-'); break; case EQUAL: text += QString(' '); break; } text += QString(QUrl::toPercentEncoding(aDiff.text, " !~*'();/?:@&=+$,#")) + QString("\n"); } return text; } ///////////////////////////////////////////// // // diff_match_patch Class // ///////////////////////////////////////////// diff_match_patch::diff_match_patch() : Diff_Timeout(1.0f), Diff_EditCost(4), Diff_DualThreshold(32), Match_Threshold(0.5f), Match_Distance(1000), Patch_DeleteThreshold(0.5f), Patch_Margin(4), Match_MaxBits(32) { } QList diff_match_patch::diff_main(const QString &text1, const QString &text2) { return diff_main(text1, text2, true); } QList diff_match_patch::diff_main(const QString &text1, const QString &text2, bool checklines) { // Check for equality (speedup) QList diffs; if (text1 == text2) { diffs.append(Diff(EQUAL, text1)); return diffs; } // Trim off common prefix (speedup) int commonlength = diff_commonPrefix(text1, text2); const QString &commonprefix = text1.left(commonlength); QString textChopped1 = text1.mid(commonlength); QString textChopped2 = text2.mid(commonlength); // Trim off common suffix (speedup) commonlength = diff_commonSuffix(textChopped1, textChopped2); const QString &commonsuffix = textChopped1.right(commonlength); textChopped1 = textChopped1.left(textChopped1.length() - commonlength); textChopped2 = textChopped2.left(textChopped2.length() - commonlength); // Compute the diff on the middle block diffs = diff_compute(textChopped1, textChopped2, checklines); // Restore the prefix and suffix if (!commonprefix.isEmpty()) { diffs.prepend(Diff(EQUAL, commonprefix)); } if (!commonsuffix.isEmpty()) { diffs.append(Diff(EQUAL, commonsuffix)); } diff_cleanupMerge(diffs); return diffs; } QList diff_match_patch::diff_compute(QString text1, QString text2, bool checklines) { QList diffs; if (text1.isEmpty()) { // Just add some text (speedup) diffs.append(Diff(INSERT, text2)); return diffs; } if (text2.isEmpty()) { // Just delete some text (speedup) diffs.append(Diff(DELETE, text1)); return diffs; } { const QString longtext = text1.length() > text2.length() ? text1 : text2; const QString shorttext = text1.length() > text2.length() ? text2 : text1; const int i = longtext.indexOf(shorttext); if (i != -1) { // Shorter text is inside the longer text (speedup) const Operation op = (text1.length() > text2.length()) ? DELETE : INSERT; diffs.append(Diff(op, longtext.left(i))); diffs.append(Diff(EQUAL, shorttext)); diffs.append(Diff(op, longtext.mid(i + shorttext.length()))); return diffs; } // Garbage collect longtext and shorttext by scoping out. } // Check to see if the problem can be split in two. const QStringList hm = diff_halfMatch(text1, text2); if (hm.count() > 0) { // A half-match was found, sort out the return data. const QString text1_a = hm[0]; const QString text1_b = hm[1]; const QString text2_a = hm[2]; const QString text2_b = hm[3]; const QString mid_common = hm[4]; // Send both pairs off for separate processing. const QList diffs_a = diff_main(text1_a, text2_a, checklines); const QList diffs_b = diff_main(text1_b, text2_b, checklines); // Merge the results. diffs = diffs_a; diffs.append(Diff(EQUAL, mid_common)); diffs += diffs_b; return diffs; } // Perform a real diff. if (checklines && (text1.length() < 100 || text2.length() < 100)) { // checklines = false; // Too trivial for the overhead. } QStringList linearray; if (checklines) { // Scan the text on a line-by-line basis first. const QList b = diff_linesToChars(text1, text2); text1 = b[0].toString(); text2 = b[1].toString(); linearray = b[2].toStringList(); } diffs = diff_map(text1, text2); if (diffs.isEmpty()) { // No acceptable result. diffs = QList(); diffs.append(Diff(DELETE, text1)); diffs.append(Diff(INSERT, text2)); } if (checklines) { // Convert the diff back to original text. diff_charsToLines(diffs, linearray); // Eliminate freak matches (e.g. blank lines) diff_cleanupSemantic(diffs); // Rediff any replacement blocks, this time character-by-character. // Add a dummy entry at the end. diffs.append(Diff(EQUAL, "")); int count_delete = 0; int count_insert = 0; QString text_delete = ""; QString text_insert = ""; QMutableListIterator pointer(diffs); Diff *thisDiff = pointer.hasNext() ? &pointer.next() : NULL; while (thisDiff != NULL) { switch (thisDiff->operation) { case INSERT: count_insert++; text_insert += thisDiff->text; break; case DELETE: count_delete++; text_delete += thisDiff->text; break; case EQUAL: // Upon reaching an equality, check for prior redundancies. if (count_delete >= 1 && count_insert >= 1) { // Delete the offending records and add the merged ones. pointer.previous(); for (int j = 0; j < count_delete + count_insert; j++) { pointer.previous(); pointer.remove(); } foreach(Diff newDiff, diff_main(text_delete, text_insert, false)) { pointer.insert(newDiff); } } count_insert = 0; count_delete = 0; text_delete = ""; text_insert = ""; break; } thisDiff = pointer.hasNext() ? &pointer.next() : NULL; } diffs.removeLast(); // Remove the dummy entry at the end. } return diffs; } QList diff_match_patch::diff_linesToChars(const QString &text1, const QString &text2) { QStringList lineArray; QMap lineHash; // e.g. linearray[4] == "Hello\n" // e.g. linehash.get("Hello\n") == 4 // "\x00" is a valid character, but various debuggers don't like it. // So we'll insert a junk entry to avoid generating a null character. lineArray.append(""); const QString chars1 = diff_linesToCharsMunge(text1, lineArray, lineHash); const QString chars2 = diff_linesToCharsMunge(text2, lineArray, lineHash); QList listRet; listRet.append(QVariant::fromValue(chars1)); listRet.append(QVariant::fromValue(chars2)); listRet.append(QVariant::fromValue(lineArray)); return listRet; } QString diff_match_patch::diff_linesToCharsMunge(const QString &text, QStringList &lineArray, QMap &lineHash) { int lineStart = 0; int lineEnd = -1; QString line; QString chars; // Walk the text, pulling out a substring for each line. // text.split('\n') would would temporarily double our memory footprint. // Modifying text would create many large strings to garbage collect. while (lineEnd < text.length() - 1) { lineEnd = text.indexOf('\n', lineStart); if (lineEnd == -1) { lineEnd = text.length() - 1; } line = text.mid(lineStart, lineEnd + 1 - lineStart); lineStart = lineEnd + 1; if (lineHash.contains(line)) { chars += QChar(static_cast(lineHash.value(line))); } else { lineArray.append(line); lineHash.insert(line, lineArray.size() - 1); chars += QChar(static_cast(lineArray.size() - 1)); } } return chars; } void diff_match_patch::diff_charsToLines(QList &diffs, const QStringList &lineArray) { // Qt has no mutable foreach construct. QMutableListIterator i(diffs); while (i.hasNext()) { Diff &diff = i.next(); QString text; for (int y = 0; y < diff.text.length(); y++) { text += lineArray.value(static_cast(diff.text[y].unicode())); } diff.text = text; } } QList diff_match_patch::diff_map(const QString &text1, const QString &text2) { QTime ms_end = QTime::currentTime() .addMSecs(static_cast (Diff_Timeout * 1000)); // Cache the text lengths to prevent multiple calls. const int text1_length = text1.length(); const int text2_length = text2.length(); const int max_d = text1_length + text2_length - 1; const bool doubleEnd = Diff_DualThreshold * 2 < max_d; QList > > v_map1; QList > > v_map2; QMap v1; QMap v2; v1.insert(1, 0); v2.insert(1, 0); int x, y; QPair footstep; // Used to track overlapping paths. QMap, int> footsteps; bool done = false; // If the total number of characters is odd, then the front path will // collide with the reverse path. const bool front = ((text1_length + text2_length) % 2 == 1); for (int d = 0; d < max_d; d++) { // Bail out if timeout reached. if (Diff_Timeout > 0 && QTime::currentTime() > ms_end) { return QList(); } // Walk the front path one step. v_map1.append(QSet >()); // Adds at index 'd'. for (int k = -d; k <= d; k += 2) { if (k == -d || (k != d && v1.value(k - 1) < v1.value(k + 1))) { x = v1.value(k + 1); } else { x = v1.value(k - 1) + 1; } y = x - k; if (doubleEnd) { footstep = QPair(x, y); if (front && (footsteps.contains(footstep))) { done = true; } if (!front) { footsteps.insert(footstep, d); } } while (!done && x < text1_length && y < text2_length && text1[x] == text2[y]) { x++; y++; if (doubleEnd) { footstep = QPair(x, y); if (front && (footsteps.contains(footstep))) { done = true; } if (!front) { footsteps.insert(footstep, d); } } } v1.insert(k, x); v_map1[d].insert(QPair(x, y)); if (x == text1_length && y == text2_length) { // Reached the end in single-path mode. return diff_path1(v_map1, text1, text2); } else if (done) { // Front path ran over reverse path. v_map2 = v_map2.mid(0, footsteps.value(footstep) + 1); QList a = diff_path1(v_map1, text1.left(x), text2.left(y)); a += diff_path2(v_map2, text1.mid(x), text2.mid(y)); return a; } } if (doubleEnd) { // Walk the reverse path one step. v_map2.append(QSet >()); // Adds at index 'd'. for (int k = -d; k <= d; k += 2) { if (k == -d || (k != d && v2.value(k - 1) < v2.value(k + 1))) { x = v2.value(k + 1); } else { x = v2.value(k - 1) + 1; } y = x - k; footstep = QPair(text1_length - x, text2_length - y); if (!front && (footsteps.contains(footstep))) { done = true; } if (front) { footsteps.insert(footstep, d); } while (!done && x < text1_length && y < text2_length && text1[text1_length - x - 1] == text2[text2_length - y - 1]) { x++; y++; footstep = QPair(text1_length - x, text2_length - y); if (!front && (footsteps.contains(footstep))) { done = true; } if (front) { footsteps.insert(footstep, d); } } v2.insert(k, x); v_map2[d].insert(QPair(x, y)); if (done) { // Reverse path ran over front path. v_map1 = v_map1.mid(0, footsteps.value(footstep) + 1); QList a = diff_path1(v_map1, text1.left(text1_length - x), text2.left(text2_length - y)); a += diff_path2(v_map2, text1.right(x), text2.right(y)); return a; } } } } // Number of diffs equals number of characters, no commonality at all. return QList(); } QList diff_match_patch::diff_path1( const QList > > &v_map, const QString &text1, const QString &text2) { QList path; int x = text1.length(); int y = text2.length(); Operation last_op = EQUAL; bool first = true; for (int d = v_map.size() - 2; d >= 0; d--) { while (true) { if (v_map.value(d).contains(QPair(x - 1, y))) { x--; if (last_op == DELETE) { path.front().text = text1[x] + path.front().text; } else { path.prepend(Diff(DELETE, text1.mid(x, 1))); } last_op = DELETE; break; } else if (v_map.value(d).contains(QPair(x, y - 1))) { y--; if (last_op == INSERT) { path.front().text = text2[y] + path.front().text; } else { path.prepend(Diff(INSERT, text2.mid(y, 1))); } last_op = INSERT; break; } else { x--; y--; if (text1[x] != text2[y]) { throw "No diagonal. Can't happen. (diff_path1)"; } if (last_op == EQUAL && !first) { path.front().text = text1[x] + path.front().text; } else { path.prepend(Diff(EQUAL, text1.mid(x, 1))); } last_op = EQUAL; } first = false; } } return path; } QList diff_match_patch::diff_path2( const QList > > &v_map, const QString &text1, const QString &text2) { QList path; int x = text1.length(); int y = text2.length(); Operation last_op = EQUAL; bool first = true; for (int d = v_map.size() - 2; d >= 0; d--) { while (true) { if (v_map.value(d).contains(QPair(x - 1, y))) { x--; if (last_op == DELETE) { path.back().text += text1[text1.length() - x - 1]; } else { path.append(Diff(DELETE, text1.mid(text1.length() - x - 1, 1))); } last_op = DELETE; break; } else if (v_map.value(d).contains(QPair(x, y - 1))) { y--; if (last_op == INSERT) { path.back().text += text2[text2.length() - y - 1]; } else { path.append(Diff(INSERT, text2.mid(text2.length() - y - 1, 1))); } last_op = INSERT; break; } else { x--; y--; if (text1[text1.length() - x - 1] != text2[text2.length() - y - 1]) { throw "No diagonal. Can't happen. (diff_path2)"; } if (last_op == EQUAL && !first) { path.back().text += text1[text1.length() - x - 1]; } else { path.append(Diff(EQUAL, text1.mid(text1.length() - x - 1, 1))); } last_op = EQUAL; } } first = false; } return path; } int diff_match_patch::diff_commonPrefix(const QString &text1, const QString &text2) { // Performance analysis: http://neil.fraser.name/news/2007/10/09/ const int n = qMin(text1.length(), text2.length()); for (int i = 0; i < n; i++) { if (text1[i] != text2[i]) { return i; } } return n; } int diff_match_patch::diff_commonSuffix(const QString &text1, const QString &text2) { // Performance analysis: http://neil.fraser.name/news/2007/10/09/ const int text1_length = text1.length(); const int text2_length = text2.length(); const int n = qMin(text1_length, text2_length); for (int i = 1; i <= n; i++) { if (text1[text1_length - i] != text2[text2_length - i]) { return i - 1; } } return n; } QStringList diff_match_patch::diff_halfMatch(const QString &text1, const QString &text2) { const QString longtext = text1.length() > text2.length() ? text1 : text2; const QString shorttext = text1.length() > text2.length() ? text2 : text1; if (longtext.length() < 10 || shorttext.length() < 1) { return QStringList(); // Pointless. } // First check if the second quarter is the seed for a half-match. const QStringList hm1 = diff_halfMatchI(longtext, shorttext, (longtext.length() + 3) / 4); // Check again based on the third quarter. const QStringList hm2 = diff_halfMatchI(longtext, shorttext, (longtext.length() + 1) / 2); QStringList hm; if (hm1.isEmpty() && hm2.isEmpty()) { return QStringList(); } else if (hm2.isEmpty()) { hm = hm1; } else if (hm1.isEmpty()) { hm = hm2; } else { // Both matched. Select the longest. hm = hm1[4].length() > hm2[4].length() ? hm1 : hm2; } // A half-match was found, sort out the return data. if (text1.length() > text2.length()) { return hm; } else { QStringList listRet; listRet << hm[2] << hm[3] << hm[0] << hm[1] << hm[4]; return listRet; } } QStringList diff_match_patch::diff_halfMatchI(const QString &longtext, const QString &shorttext, int i) { // Start with a 1/4 length substring at position i as a seed. const QString seed = longtext.mid(i, longtext.length() / 4); int j = -1; QString best_common; QString best_longtext_a, best_longtext_b; QString best_shorttext_a, best_shorttext_b; while ((j = shorttext.indexOf(seed, j + 1)) != -1) { const int prefixLength = diff_commonPrefix(longtext.mid(i), shorttext.mid(j)); const int suffixLength = diff_commonSuffix(longtext.left(i), shorttext.left(j)); if (best_common.length() < suffixLength + prefixLength) { best_common = shorttext.mid(j - suffixLength, suffixLength) + shorttext.mid(j, prefixLength); best_longtext_a = longtext.left(i - suffixLength); best_longtext_b = longtext.mid(i + prefixLength); best_shorttext_a = shorttext.left(j - suffixLength); best_shorttext_b = shorttext.mid(j + prefixLength); } } if (best_common.length() >= longtext.length() / 2) { QStringList listRet; listRet << best_longtext_a << best_longtext_b << best_shorttext_a << best_shorttext_b << best_common; return listRet; } else { return QStringList(); } } void diff_match_patch::diff_cleanupSemantic(QList &diffs) { if (diffs.isEmpty()) { return; } bool changes = false; QStack equalities; // Stack of equalities. QString lastequality; // Always equal to equalities.lastElement().text QMutableListIterator pointer(diffs); // Number of characters that changed prior to the equality. int length_changes1 = 0; // Number of characters that changed after the equality. int length_changes2 = 0; Diff *thisDiff = pointer.hasNext() ? &pointer.next() : NULL; while (thisDiff != NULL) { if (thisDiff->operation == EQUAL) { // equality found equalities.push(*thisDiff); length_changes1 = length_changes2; length_changes2 = 0; lastequality = thisDiff->text; } else { // an insertion or deletion length_changes2 += thisDiff->text.length(); if (!lastequality.isNull() && (lastequality.length() <= length_changes1) && (lastequality.length() <= length_changes2)) { // System.out.println("Splitting: '" + lastequality + "'"); // Walk back to offending equality. while (*thisDiff != equalities.top()) { thisDiff = &pointer.previous(); } pointer.next(); // Replace equality with a delete. pointer.setValue(Diff(DELETE, lastequality)); // Insert a corresponding an insert. pointer.insert(Diff(INSERT, lastequality)); equalities.pop(); // Throw away the equality we just deleted. if (!equalities.isEmpty()) { // Throw away the previous equality (it needs to be reevaluated). equalities.pop(); } if (equalities.isEmpty()) { // There are no previous equalities, walk back to the start. while (pointer.hasPrevious()) { pointer.previous(); } } else { // There is a safe equality we can fall back to. thisDiff = &equalities.top(); while (*thisDiff != pointer.previous()) { // Intentionally empty loop. } } length_changes1 = 0; // Reset the counters. length_changes2 = 0; lastequality = QString(); changes = true; } } thisDiff = pointer.hasNext() ? &pointer.next() : NULL; } if (changes) { diff_cleanupMerge(diffs); } diff_cleanupSemanticLossless(diffs); } void diff_match_patch::diff_cleanupSemanticLossless(QList &diffs) { QString equality1, edit, equality2; QString commonString; int commonOffset; int score, bestScore; QString bestEquality1, bestEdit, bestEquality2; // Create a new iterator at the start. QMutableListIterator pointer(diffs); Diff *prevDiff = pointer.hasNext() ? &pointer.next() : NULL; Diff *thisDiff = pointer.hasNext() ? &pointer.next() : NULL; Diff *nextDiff = pointer.hasNext() ? &pointer.next() : NULL; // Intentionally ignore the first and last element (don't need checking). while (nextDiff != NULL) { if (prevDiff->operation == EQUAL && nextDiff->operation == EQUAL) { // This is a single edit surrounded by equalities. equality1 = prevDiff->text; edit = thisDiff->text; equality2 = nextDiff->text; // First, shift the edit as far left as possible. commonOffset = diff_commonSuffix(equality1, edit); if (commonOffset != 0) { commonString = edit.mid(edit.length() - commonOffset); equality1 = equality1.left(equality1.length() - commonOffset); edit = commonString + edit.left(edit.length() - commonOffset); equality2 = commonString + equality2; } // Second, step character by character right, looking for the best fit. bestEquality1 = equality1; bestEdit = edit; bestEquality2 = equality2; bestScore = diff_cleanupSemanticScore(equality1, edit) + diff_cleanupSemanticScore(edit, equality2); while (!edit.isEmpty() && !equality2.isEmpty() && edit[0] == equality2[0]) { equality1 += edit[0]; edit = edit.mid(1) + equality2[0]; equality2 = equality2.mid(1); score = diff_cleanupSemanticScore(equality1, edit) + diff_cleanupSemanticScore(edit, equality2); // The >= encourages trailing rather than leading whitespace on edits. if (score >= bestScore) { bestScore = score; bestEquality1 = equality1; bestEdit = edit; bestEquality2 = equality2; } } if (prevDiff->text != bestEquality1) { // We have an improvement, save it back to the diff. if (!bestEquality1.isEmpty()) { prevDiff->text = bestEquality1; } else { pointer.previous(); // Walk past nextDiff. pointer.previous(); // Walk past thisDiff. pointer.previous(); // Walk past prevDiff. pointer.remove(); // Delete prevDiff. pointer.next(); // Walk past thisDiff. pointer.next(); // Walk past nextDiff. } thisDiff->text = bestEdit; if (!bestEquality2.isEmpty()) { nextDiff->text = bestEquality2; } else { pointer.remove(); // Delete nextDiff. nextDiff = thisDiff; thisDiff = prevDiff; } } } prevDiff = thisDiff; thisDiff = nextDiff; nextDiff = pointer.hasNext() ? &pointer.next() : NULL; } } int diff_match_patch::diff_cleanupSemanticScore(const QString &one, const QString &two) { if (one.isEmpty() || two.isEmpty()) { // Edges are the best. return 10; } // Each port of this function behaves slightly differently due to // subtle differences in each language's definition of things like // 'whitespace'. Since this function's purpose is largely cosmetic, // the choice has been made to use each language's native features // rather than force total conformity. int score = 0; // One point for non-alphanumeric. if (!one[one.length() - 1].isLetterOrNumber() || !two[0].isLetterOrNumber()) { score++; // Two points for whitespace. if (one[one.length() - 1].isSpace() || two[0].isSpace()) { score++; // Three points for line breaks. if (one[one.length() - 1].category() == QChar::Other_Control || two[0].category() == QChar::Other_Control) { score++; // Four points for blank lines. QRegExp blankLineEnd("\\n\\r?\\n$"); QRegExp blankLineStart("^\\r?\\n\\r?\\n"); if (blankLineEnd.indexIn(one) != -1 || blankLineStart.indexIn(two) != -1) { score++; } } } } return score; } void diff_match_patch::diff_cleanupEfficiency(QList &diffs) { if (diffs.isEmpty()) { return; } bool changes = false; QStack equalities; // Stack of equalities. QString lastequality; // Always equal to equalities.lastElement().text QMutableListIterator pointer(diffs); // Is there an insertion operation before the last equality. bool pre_ins = false; // Is there a deletion operation before the last equality. bool pre_del = false; // Is there an insertion operation after the last equality. bool post_ins = false; // Is there a deletion operation after the last equality. bool post_del = false; Diff *thisDiff = pointer.hasNext() ? &pointer.next() : NULL; Diff *safeDiff = thisDiff; while (thisDiff != NULL) { if (thisDiff->operation == EQUAL) { // equality found if (thisDiff->text.length() < Diff_EditCost && (post_ins || post_del)) { // Candidate found. equalities.push(*thisDiff); pre_ins = post_ins; pre_del = post_del; lastequality = thisDiff->text; } else { // Not a candidate, and can never become one. equalities.clear(); lastequality = QString(); safeDiff = thisDiff; } post_ins = post_del = false; } else { // an insertion or deletion if (thisDiff->operation == DELETE) { post_del = true; } else { post_ins = true; } /* * Five types to be split: * ABXYCD * AXCD * ABXC * AXCD * ABXC */ if (!lastequality.isNull() && ((pre_ins && pre_del && post_ins && post_del) || ((lastequality.length() < Diff_EditCost / 2) && ((pre_ins ? 1 : 0) + (pre_del ? 1 : 0) + (post_ins ? 1 : 0) + (post_del ? 1 : 0)) == 3))) { // System.out.println("Splitting: '" + lastequality + "'"); // Walk back to offending equality. while (*thisDiff != equalities.top()) { thisDiff = &pointer.previous(); } pointer.next(); // Replace equality with a delete. pointer.setValue(Diff(DELETE, lastequality)); // Insert a corresponding an insert. pointer.insert(Diff(INSERT, lastequality)); thisDiff = &pointer.previous(); pointer.next(); equalities.pop(); // Throw away the equality we just deleted. lastequality = QString(); if (pre_ins && pre_del) { // No changes made which could affect previous entry, keep going. post_ins = post_del = true; equalities.clear(); safeDiff = thisDiff; } else { if (!equalities.isEmpty()) { // Throw away the previous equality (it needs to be reevaluated). equalities.pop(); } if (equalities.isEmpty()) { // There are no previous questionable equalities, // walk back to the last known safe diff. thisDiff = safeDiff; } else { // There is an equality we can fall back to. thisDiff = &equalities.top(); } while (*thisDiff != pointer.previous()) { // Intentionally empty loop. } post_ins = post_del = false; } changes = true; } } thisDiff = pointer.hasNext() ? &pointer.next() : NULL; } if (changes) { diff_cleanupMerge(diffs); } } void diff_match_patch::diff_cleanupMerge(QList &diffs) { diffs.append(Diff(EQUAL, "")); // Add a dummy entry at the end. QMutableListIterator pointer(diffs); int count_delete = 0; int count_insert = 0; QString text_delete = ""; QString text_insert = ""; Diff *thisDiff = pointer.hasNext() ? &pointer.next() : NULL; Diff *prevEqual = NULL; int commonlength; while (thisDiff != NULL) { switch (thisDiff->operation) { case INSERT: count_insert++; text_insert += thisDiff->text; prevEqual = NULL; break; case DELETE: count_delete++; text_delete += thisDiff->text; prevEqual = NULL; break; case EQUAL: if (count_delete != 0 || count_insert != 0) { // Delete the offending records. pointer.previous(); // Reverse direction. while (count_delete-- > 0) { pointer.previous(); pointer.remove(); } while (count_insert-- > 0) { pointer.previous(); pointer.remove(); } if (count_delete != 0 && count_insert != 0) { // Factor out any common prefixies. commonlength = diff_commonPrefix(text_insert, text_delete); if (commonlength != 0) { if (pointer.hasPrevious()) { thisDiff = &pointer.previous(); if (thisDiff->operation != EQUAL) { throw "Previous diff should have been an equality."; } thisDiff->text += text_insert.left(commonlength); pointer.next(); } else { pointer.insert(Diff(EQUAL, text_insert.left(commonlength))); } text_insert = text_insert.mid(commonlength); text_delete = text_delete.mid(commonlength); } // Factor out any common suffixies. commonlength = diff_commonSuffix(text_insert, text_delete); if (commonlength != 0) { thisDiff = &pointer.next(); thisDiff->text = text_insert.mid(text_insert.length() - commonlength) + thisDiff->text; text_insert = text_insert.left(text_insert.length() - commonlength); text_delete = text_delete.left(text_delete.length() - commonlength); pointer.previous(); } } // Insert the merged records. if (!text_delete.isEmpty()) { pointer.insert(Diff(DELETE, text_delete)); } if (!text_insert.isEmpty()) { pointer.insert(Diff(INSERT, text_insert)); } // Step forward to the equality. thisDiff = pointer.hasNext() ? &pointer.next() : NULL; } else if (prevEqual != NULL) { // Merge this equality with the previous one. prevEqual->text += thisDiff->text; pointer.remove(); thisDiff = &pointer.previous(); pointer.next(); // Forward direction } count_insert = 0; count_delete = 0; text_delete = ""; text_insert = ""; prevEqual = thisDiff; break; } thisDiff = pointer.hasNext() ? &pointer.next() : NULL; } // System.out.println(diff); if (diffs.back().text.isEmpty()) { diffs.removeLast(); // Remove the dummy entry at the end. } /* * Second pass: look for single edits surrounded on both sides by equalities * which can be shifted sideways to eliminate an equality. * e.g: ABAC -> ABAC */ bool changes = false; // Create a new iterator at the start. // (As opposed to walking the current one back.) pointer.toFront(); Diff *prevDiff = pointer.hasNext() ? &pointer.next() : NULL; thisDiff = pointer.hasNext() ? &pointer.next() : NULL; Diff *nextDiff = pointer.hasNext() ? &pointer.next() : NULL; // Intentionally ignore the first and last element (don't need checking). while (nextDiff != NULL) { if (prevDiff->operation == EQUAL && nextDiff->operation == EQUAL) { // This is a single edit surrounded by equalities. if (thisDiff->text.endsWith(prevDiff->text)) { // Shift the edit over the previous equality. thisDiff->text = prevDiff->text + thisDiff->text.left(thisDiff->text.length() - prevDiff->text.length()); nextDiff->text = prevDiff->text + nextDiff->text; pointer.previous(); // Walk past nextDiff. pointer.previous(); // Walk past thisDiff. pointer.previous(); // Walk past prevDiff. pointer.remove(); // Delete prevDiff. pointer.next(); // Walk past thisDiff. thisDiff = &pointer.next(); // Walk past nextDiff. nextDiff = pointer.hasNext() ? &pointer.next() : NULL; changes = true; } else if (thisDiff->text.startsWith(nextDiff->text)) { // Shift the edit over the next equality. prevDiff->text += nextDiff->text; thisDiff->text = thisDiff->text.mid(nextDiff->text.length()) + nextDiff->text; pointer.remove(); // Delete nextDiff. nextDiff = pointer.hasNext() ? &pointer.next() : NULL; changes = true; } } prevDiff = thisDiff; thisDiff = nextDiff; nextDiff = pointer.hasNext() ? &pointer.next() : NULL; } // If shifts were made, the diff needs reordering and another shift sweep. if (changes) { diff_cleanupMerge(diffs); } } int diff_match_patch::diff_xIndex(const QList &diffs, int loc) { int chars1 = 0; int chars2 = 0; int last_chars1 = 0; int last_chars2 = 0; Diff lastDiff; foreach(Diff aDiff, diffs) { if (aDiff.operation != INSERT) { // Equality or deletion. chars1 += aDiff.text.length(); } if (aDiff.operation != DELETE) { // Equality or insertion. chars2 += aDiff.text.length(); } if (chars1 > loc) { // Overshot the location. lastDiff = aDiff; break; } last_chars1 = chars1; last_chars2 = chars2; } if (lastDiff.operation == DELETE) { // The location was deleted. return last_chars2; } // Add the remaining character length. return last_chars2 + (loc - last_chars1); } QString diff_match_patch::diff_prettyHtml(const QList &diffs) { QString html; QString text; int i = 0; foreach(Diff aDiff, diffs) { text = aDiff.text; text.replace("&", "&").replace("<", "<") .replace(">", ">").replace("\n", "¶
"); switch (aDiff.operation) { case INSERT: html += QString("") + text + QString(""); break; case DELETE: html += QString("") + text + QString(""); break; case EQUAL: html += QString("") + text + QString(""); break; } if (aDiff.operation != DELETE) { i += aDiff.text.length(); } } return html; } QString diff_match_patch::diff_text1(const QList &diffs) { QString text; foreach(Diff aDiff, diffs) { if (aDiff.operation != INSERT) { text += aDiff.text; } } return text; } QString diff_match_patch::diff_text2(const QList &diffs) { QString text; foreach(Diff aDiff, diffs) { if (aDiff.operation != DELETE) { text += aDiff.text; } } return text; } int diff_match_patch::diff_levenshtein(const QList &diffs) { int levenshtein = 0; int insertions = 0; int deletions = 0; foreach(Diff aDiff, diffs) { switch (aDiff.operation) { case INSERT: insertions += aDiff.text.length(); break; case DELETE: deletions += aDiff.text.length(); break; case EQUAL: // A deletion and an insertion is one substitution. levenshtein += qMax(insertions, deletions); insertions = 0; deletions = 0; break; } } levenshtein += qMax(insertions, deletions); return levenshtein; } QString diff_match_patch::diff_toDelta(const QList &diffs) { QString text; foreach(Diff aDiff, diffs) { switch (aDiff.operation) { case INSERT: { QString encoded = QString(QUrl::toPercentEncoding(aDiff.text, " !~*'();/?:@&=+$,#")); text += QString("+") + encoded + QString("\t"); break; } case DELETE: text += QString("-") + QString::number(aDiff.text.length()) + QString("\t"); break; case EQUAL: text += QString("=") + QString::number(aDiff.text.length()) + QString("\t"); break; } } if (!text.isEmpty()) { // Strip off trailing tab character. text = text.left(text.length() - 1); } return text; } QList diff_match_patch::diff_fromDelta(const QString &text1, const QString &delta) { QList diffs; int pointer = 0; // Cursor in text1 QStringList tokens = delta.split("\t"); foreach(QString token, tokens) { if (token.isEmpty()) { // Blank tokens are ok (from a trailing \t). continue; } // Each token begins with a one character parameter which specifies the // operation of this token (delete, insert, equality). QString param = token.mid(1); switch (token[0].toLatin1()) { case '+': param = QUrl::fromPercentEncoding(qPrintable(param)); diffs.append(Diff(INSERT, param)); break; case '-': // Fall through. case '=': { int n; n = param.toInt(); if (n < 0) { throw QString("Negative number in diff_fromDelta: %1").arg(param); } QString text; text = text1.mid(pointer, n); pointer += n; if (token[0] == QChar('=')) { diffs.append(Diff(EQUAL, text)); } else { diffs.append(Diff(DELETE, text)); } break; } default: throw QString("Invalid diff operation in diff_fromDelta: %1") .arg(token[0]); } } if (pointer != text1.length()) { throw QString("Delta length (%1) smaller than source text length (%2)") .arg(pointer).arg(text1.length()); } return diffs; } // MATCH FUNCTIONS int diff_match_patch::match_main(const QString &text, const QString &pattern, int loc) { loc = qMax(0, qMin(loc, text.length())); if (text == pattern) { // Shortcut (potentially not guaranteed by the algorithm) return 0; } else if (text.isEmpty()) { // Nothing to match. return -1; } else if (loc + pattern.length() <= text.length() && text.mid(loc, pattern.length()) == pattern) { // Perfect match at the perfect spot! (Includes case of null pattern) return loc; } else { // Do a fuzzy compare. return match_bitap(text, pattern, loc); } } int diff_match_patch::match_bitap(const QString &text, const QString &pattern, int loc) { if (!(Match_MaxBits == 0 || pattern.length() <= Match_MaxBits)) { throw "Pattern too long for this application."; } // Initialise the alphabet. QMap s = match_alphabet(pattern); // Highest score beyond which we give up. double score_threshold = Match_Threshold; // Is there a nearby exact match? (speedup) int best_loc = text.indexOf(pattern, loc); if (best_loc != -1) { score_threshold = qMin(match_bitapScore(0, best_loc, loc, pattern), score_threshold); // What about in the other direction? (speedup) best_loc = text.lastIndexOf(pattern, loc + pattern.length()); if (best_loc != -1) { score_threshold = qMin(match_bitapScore(0, best_loc, loc, pattern), score_threshold); } } // Initialise the bit arrays. int matchmask = 1 << (pattern.length() - 1); best_loc = -1; int bin_min, bin_mid; int bin_max = pattern.length() + text.length(); int *rd = NULL; int *last_rd = NULL; for (int d = 0; d < pattern.length(); d++) { // Scan for the best match; each iteration allows for one more error. // Run a binary search to determine how far from 'loc' we can stray at // this error level. bin_min = 0; bin_mid = bin_max; while (bin_min < bin_mid) { if (match_bitapScore(d, loc + bin_mid, loc, pattern) <= score_threshold) { bin_min = bin_mid; } else { bin_max = bin_mid; } bin_mid = (bin_max - bin_min) / 2 + bin_min; } // Use the result from this iteration as the maximum for the next. bin_max = bin_mid; int start = qMax(1, loc - bin_mid + 1); int finish = qMin(loc + bin_mid, text.length()) + pattern.length(); rd = new int[finish + 2]; rd[finish + 1] = (1 << d) - 1; for (int j = finish; j >= start; j--) { int charMatch; if (text.length() <= j - 1) { // Out of range. charMatch = 0; } else { charMatch = s.value(text[j - 1], 0); } if (d == 0) { // First pass: exact match. rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; } else { // Subsequent passes: fuzzy match. rd[j] = ((rd[j + 1] << 1) | 1) & charMatch | (((last_rd[j + 1] | last_rd[j]) << 1) | 1) | last_rd[j + 1]; } if ((rd[j] & matchmask) != 0) { double score = match_bitapScore(d, j - 1, loc, pattern); // This match will almost certainly be better than any existing // match. But check anyway. if (score <= score_threshold) { // Told you so. score_threshold = score; best_loc = j - 1; if (best_loc > loc) { // When passing loc, don't exceed our current distance from loc. start = qMax(1, 2 * loc - best_loc); } else { // Already passed loc, downhill from here on in. break; } } } } if (match_bitapScore(d + 1, loc, loc, pattern) > score_threshold) { // No hope for a (better) match at greater error levels. break; } delete [] last_rd; last_rd = rd; } delete [] last_rd; delete [] rd; return best_loc; } double diff_match_patch::match_bitapScore(int e, int x, int loc, const QString &pattern) { const float accuracy = static_cast (e) / pattern.length(); const int proximity = qAbs(loc - x); if (Match_Distance == 0) { // Dodge divide by zero error. return proximity == 0 ? accuracy : 1.0; } return accuracy + (proximity / static_cast (Match_Distance)); } QMap diff_match_patch::match_alphabet(const QString &pattern) { QMap s; int i; for (i = 0; i < pattern.length(); i++) { QChar c = pattern[i]; s.insert(c, 0); } for (i = 0; i < pattern.length(); i++) { QChar c = pattern[i]; s.insert(c, s.value(c) | (1 << (pattern.length() - i - 1))); } return s; } // PATCH FUNCTIONS void diff_match_patch::patch_addContext(Patch &patch, const QString &text) { if (text.isEmpty()) { return; } QString pattern = text.mid(patch.start2, patch.length1); int padding = 0; // Look for the first and last matches of pattern in text. If two different // matches are found, increase the pattern length. while (text.indexOf(pattern) != text.lastIndexOf(pattern) && pattern.length() < Match_MaxBits - Patch_Margin - Patch_Margin) { padding += Patch_Margin; pattern = text.mid(qMax(0, patch.start2 - padding), qMin(text.length(), patch.start2 + patch.length1 + padding) - qMax(0, patch.start2 - padding)); } // Add one chunk for good luck. padding += Patch_Margin; // Add the prefix. QString prefix = text.mid(qMax(0, patch.start2 - padding), patch.start2 - qMax(0, patch.start2 - padding)); if (!prefix.isEmpty()) { patch.diffs.prepend(Diff(EQUAL, prefix)); } // Add the suffix. QString suffix = text.mid(patch.start2 + patch.length1, qMin(text.length(), patch.start2 + patch.length1 + padding) - (patch.start2 + patch.length1)); if (!suffix.isEmpty()) { patch.diffs.append(Diff(EQUAL, suffix)); } // Roll back the start points. patch.start1 -= prefix.length(); patch.start2 -= prefix.length(); // Extend the lengths. patch.length1 += prefix.length() + suffix.length(); patch.length2 += prefix.length() + suffix.length(); } QList diff_match_patch::patch_make(const QString &text1, const QString &text2) { // No diffs provided, compute our own. QList diffs = diff_main(text1, text2, true); if (diffs.size() > 2) { diff_cleanupSemantic(diffs); diff_cleanupEfficiency(diffs); } return patch_make(text1, diffs); } QList diff_match_patch::patch_make(const QList &diffs) { // No origin string provided, compute our own. const QString text1 = diff_text1(diffs); return patch_make(text1, diffs); } QList diff_match_patch::patch_make(const QString &text1, const QString &text2, const QList &diffs) { // text2 is entirely unused. return patch_make(text1, diffs); Q_UNUSED(text2) } QList diff_match_patch::patch_make(const QString &text1, const QList &diffs) { QList patches; if (diffs.isEmpty()) { return patches; // Get rid of the null case. } Patch patch; int char_count1 = 0; // Number of characters into the text1 string. int char_count2 = 0; // Number of characters into the text2 string. // Start with text1 (prepatch_text) and apply the diffs until we arrive at // text2 (postpatch_text). We recreate the patches one by one to determine // context info. QString prepatch_text = text1; QString postpatch_text = text1; foreach(Diff aDiff, diffs) { if (patch.diffs.isEmpty() && aDiff.operation != EQUAL) { // A new patch starts here. patch.start1 = char_count1; patch.start2 = char_count2; } switch (aDiff.operation) { case INSERT: patch.diffs.append(aDiff); patch.length2 += aDiff.text.length(); postpatch_text = postpatch_text.left(char_count2) + aDiff.text + postpatch_text.mid(char_count2); break; case DELETE: patch.length1 += aDiff.text.length(); patch.diffs.append(aDiff); postpatch_text = postpatch_text.left(char_count2) + postpatch_text.mid(char_count2 + aDiff.text.length()); break; case EQUAL: if (aDiff.text.length() <= 2 * Patch_Margin && !patch.diffs.isEmpty() && !(aDiff == diffs.back())) { // Small equality inside a patch. patch.diffs.append(aDiff); patch.length1 += aDiff.text.length(); patch.length2 += aDiff.text.length(); } if (aDiff.text.length() >= 2 * Patch_Margin) { // Time for a new patch. if (!patch.diffs.isEmpty()) { patch_addContext(patch, prepatch_text); patches.append(patch); patch = Patch(); // Unlike Unidiff, our patch lists have a rolling context. // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff // Update prepatch text & pos to reflect the application of the // just completed patch. prepatch_text = postpatch_text; char_count1 = char_count2; } } break; } // Update the current character count. if (aDiff.operation != INSERT) { char_count1 += aDiff.text.length(); } if (aDiff.operation != DELETE) { char_count2 += aDiff.text.length(); } } // Pick up the leftover patch if not empty. if (!patch.diffs.isEmpty()) { patch_addContext(patch, prepatch_text); patches.append(patch); } return patches; } QList diff_match_patch::patch_deepCopy(QList &patches) { QList patchesCopy; foreach(Patch aPatch, patches) { Patch patchCopy = Patch(); foreach(Diff aDiff, aPatch.diffs) { Diff diffCopy = Diff(aDiff.operation, aDiff.text); patchCopy.diffs.append(diffCopy); } patchCopy.start1 = aPatch.start1; patchCopy.start2 = aPatch.start2; patchCopy.length1 = aPatch.length1; patchCopy.length2 = aPatch.length2; patchesCopy.append(patchCopy); } return patchesCopy; } QPair > diff_match_patch::patch_apply( QList &patches, const QString &sourceText) { QString text = sourceText; // Copy to preserve original. if (patches.isEmpty()) { return QPair >(text, QVector(0)); } // Deep copy the patches so that no changes are made to originals. QList patchesCopy = patch_deepCopy(patches); QString nullPadding = patch_addPadding(patchesCopy); text = nullPadding + text + nullPadding; patch_splitMax(patchesCopy); int x = 0; // delta keeps track of the offset between the expected and actual location // of the previous patch. If there are patches expected at positions 10 and // 20, but the first patch was found at 12, delta is 2 and the second patch // has an effective expected position of 22. int delta = 0; QVector results(patchesCopy.size()); foreach(Patch aPatch, patchesCopy) { int expected_loc = aPatch.start2 + delta; QString text1 = diff_text1(aPatch.diffs); int start_loc; int end_loc = -1; if (text1.length() > Match_MaxBits) { // patch_splitMax will only provide an oversized pattern in the case of // a monster delete. start_loc = match_main(text, text1.left(Match_MaxBits), expected_loc); if (start_loc != -1) { end_loc = match_main(text, text1.right(Match_MaxBits), expected_loc + text1.length() - Match_MaxBits); if (end_loc == -1 || start_loc >= end_loc) { // Can't find valid trailing context. Drop this patch. start_loc = -1; } } } else { start_loc = match_main(text, text1, expected_loc); } if (start_loc == -1) { // No match found. :( results[x] = false; // Subtract the delta for this failed patch from subsequent patches. delta -= aPatch.length2 - aPatch.length1; } else { // Found a match. :) results[x] = true; delta = start_loc - expected_loc; QString text2; if (end_loc == -1) { text2 = text.mid(start_loc, text1.length()); } else { text2 = text.mid(start_loc, end_loc + Match_MaxBits - start_loc); } if (text1 == text2) { // Perfect match, just shove the replacement text in. text = text.left(start_loc) + diff_text2(aPatch.diffs) + text.mid(start_loc + text1.length()); } else { // Imperfect match. Run a diff to get a framework of equivalent // indices. QList diffs = diff_main(text1, text2, false); if (text1.length() > Match_MaxBits && diff_levenshtein(diffs) / static_cast (text1.length()) > Patch_DeleteThreshold) { // The end points match, but the content is unacceptably bad. results[x] = false; } else { diff_cleanupSemanticLossless(diffs); int index1 = 0; foreach(Diff aDiff, aPatch.diffs) { if (aDiff.operation != EQUAL) { int index2 = diff_xIndex(diffs, index1); if (aDiff.operation == INSERT) { // Insertion text = text.left(start_loc + index2) + aDiff.text + text.mid(start_loc + index2); } else if (aDiff.operation == DELETE) { // Deletion text = text.left(start_loc + index2) + text.mid(start_loc + diff_xIndex(diffs, index1 + aDiff.text.length())); } } if (aDiff.operation != DELETE) { index1 += aDiff.text.length(); } } } } } x++; } // Strip the padding off. text = text.mid(nullPadding.length(), text.length() - 2 * nullPadding.length()); return QPair >(text, results); } QString diff_match_patch::patch_addPadding(QList &patches) { int paddingLength = Patch_Margin; QString nullPadding = ""; for (int x = 1; x <= paddingLength; x++) { nullPadding += QChar((ushort)x); } // Bump all the patches forward. QMutableListIterator pointer(patches); while (pointer.hasNext()) { Patch &aPatch = pointer.next(); aPatch.start1 += paddingLength; aPatch.start2 += paddingLength; } // Add some padding on start of first diff. Patch &firstPatch = patches.first(); QList &firstPatchDiffs = firstPatch.diffs; if (firstPatchDiffs.empty() || firstPatchDiffs.first().operation != EQUAL) { // Add nullPadding equality. firstPatchDiffs.prepend(Diff(EQUAL, nullPadding)); firstPatch.start1 -= paddingLength; // Should be 0. firstPatch.start2 -= paddingLength; // Should be 0. firstPatch.length1 += paddingLength; firstPatch.length2 += paddingLength; } else if (paddingLength > firstPatchDiffs.first().text.length()) { // Grow first equality. Diff &firstDiff = firstPatchDiffs.first(); int extraLength = paddingLength - firstDiff.text.length(); firstDiff.text = nullPadding.mid(firstDiff.text.length(), paddingLength - firstDiff.text.length()) + firstDiff.text; firstPatch.start1 -= extraLength; firstPatch.start2 -= extraLength; firstPatch.length1 += extraLength; firstPatch.length2 += extraLength; } // Add some padding on end of last diff. Patch &lastPatch = patches.first(); QList &lastPatchDiffs = lastPatch.diffs; if (lastPatchDiffs.empty() || lastPatchDiffs.last().operation != EQUAL) { // Add nullPadding equality. lastPatchDiffs.append(Diff(EQUAL, nullPadding)); lastPatch.length1 += paddingLength; lastPatch.length2 += paddingLength; } else if (paddingLength > lastPatchDiffs.last().text.length()) { // Grow last equality. Diff &lastDiff = lastPatchDiffs.last(); int extraLength = paddingLength - lastDiff.text.length(); lastDiff.text += nullPadding.left(extraLength); lastPatch.length1 += extraLength; lastPatch.length2 += extraLength; } return nullPadding; } void diff_match_patch::patch_splitMax(QList &patches) { int patch_size; QString precontext, postcontext; Patch patch; int start1, start2; bool empty; Operation diff_type; QString diff_text; QMutableListIterator pointer(patches); Patch bigpatch; if (pointer.hasNext()) { bigpatch = pointer.next(); } while (!bigpatch.isNull()) { if (bigpatch.length1 <= Match_MaxBits) { bigpatch = pointer.hasNext() ? pointer.next() : Patch(); continue; } // Remove the big old patch. pointer.remove(); patch_size = Match_MaxBits; start1 = bigpatch.start1; start2 = bigpatch.start2; precontext = ""; while (!bigpatch.diffs.isEmpty()) { // Create one of several smaller patches. patch = Patch(); empty = true; patch.start1 = start1 - precontext.length(); patch.start2 = start2 - precontext.length(); if (!precontext.isEmpty()) { patch.length1 = patch.length2 = precontext.length(); patch.diffs.append(Diff(EQUAL, precontext)); } while (!bigpatch.diffs.isEmpty() && patch.length1 < patch_size - Patch_Margin) { diff_type = bigpatch.diffs.front().operation; diff_text = bigpatch.diffs.front().text; if (diff_type == INSERT) { // Insertions are harmless. patch.length2 += diff_text.length(); start2 += diff_text.length(); patch.diffs.append(bigpatch.diffs.front()); bigpatch.diffs.removeFirst(); empty = false; } else if (diff_type == DELETE && patch.diffs.size() == 1 && patch.diffs.front().operation == EQUAL && diff_text.length() > 2 * patch_size) { // This is a large deletion. Let it pass in one chunk. patch.length1 += diff_text.length(); start1 += diff_text.length(); empty = false; patch.diffs.append(Diff(diff_type, diff_text)); bigpatch.diffs.removeFirst(); } else { // Deletion or equality. Only take as much as we can stomach. diff_text = diff_text.left(qMin(diff_text.length(), patch_size - patch.length1 - Patch_Margin)); patch.length1 += diff_text.length(); start1 += diff_text.length(); if (diff_type == EQUAL) { patch.length2 += diff_text.length(); start2 += diff_text.length(); } else { empty = false; } patch.diffs.append(Diff(diff_type, diff_text)); if (diff_text == bigpatch.diffs.front().text) { bigpatch.diffs.removeFirst(); } else { bigpatch.diffs.front().text = bigpatch.diffs.front().text .mid(diff_text.length()); } } } // Compute the head context for the next patch. precontext = diff_text2(patch.diffs); precontext = precontext.mid(precontext.length() - Patch_Margin); // Append the end context for this patch. if (diff_text1(bigpatch.diffs).length() > Patch_Margin) { postcontext = diff_text1(bigpatch.diffs).left(Patch_Margin); } else { postcontext = diff_text1(bigpatch.diffs); } if (!postcontext.isEmpty()) { patch.length1 += postcontext.length(); patch.length2 += postcontext.length(); if (!patch.diffs.isEmpty() && patch.diffs.back().operation == EQUAL) { patch.diffs.back().text += postcontext; } else { patch.diffs.append(Diff(EQUAL, postcontext)); } } if (!empty) { pointer.insert(patch); } } bigpatch = pointer.hasNext() ? pointer.next() : Patch(); } } QString diff_match_patch::patch_toText(const QList &patches) { QString text; foreach(Patch aPatch, patches) { text.append(aPatch.toString()); } return text; } QList diff_match_patch::patch_fromText(const QString &textline) { QList patches; if (textline.isEmpty()) { return patches; } QStringList text = textline.split("\n", qtSkipEmptyParts); Patch patch; QRegExp patchHeader("^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$"); char sign; QString line; while (!text.isEmpty()) { if (!patchHeader.exactMatch(text.front())) { throw QString("Invalid patch string: %1").arg(text.front()); } patch = Patch(); patch.start1 = patchHeader.cap(1).toInt(); if (patchHeader.cap(2).isEmpty()) { patch.start1--; patch.length1 = 1; } else if (patchHeader.cap(2) == "0") { patch.length1 = 0; } else { patch.start1--; patch.length1 = patchHeader.cap(2).toInt(); } patch.start2 = patchHeader.cap(3).toInt(); if (patchHeader.cap(4).isEmpty()) { patch.start2--; patch.length2 = 1; } else if (patchHeader.cap(4) == "0") { patch.length2 = 0; } else { patch.start2--; patch.length2 = patchHeader.cap(4).toInt(); } text.removeFirst(); while (!text.isEmpty()) { if (text.front().isEmpty()) { text.removeFirst(); continue; } sign = text.front()[0].toLatin1(); line = text.front().mid(1); line = line.replace("+", "%2B"); // decode would change all "+" to " " line = QUrl::fromPercentEncoding(qPrintable(line)); if (sign == '-') { // Deletion. patch.diffs.append(Diff(DELETE, line)); } else if (sign == '+') { // Insertion. patch.diffs.append(Diff(INSERT, line)); } else if (sign == ' ') { // Minor equality. patch.diffs.append(Diff(EQUAL, line)); } else if (sign == '@') { // Start of next patch. break; } else { // WTF? throw QString("Invalid patch mode '%1' in: %2").arg(sign).arg(line); return QList(); } text.removeFirst(); } patches.append(patch); } return patches; } ================================================ FILE: liteidex/src/3rdparty/diff_match_patch/diff_match_patch.h ================================================ /* * Copyright 2008 Google Inc. All Rights Reserved. * Author: fraser@google.com (Neil Fraser) * Author: mikeslemmer@gmail.com (Mike Slemmer) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Diff Match and Patch * http://code.google.com/p/google-diff-match-patch/ */ #ifndef DIFF_MATCH_PATCH_H #define DIFF_MATCH_PATCH_H /* * Functions for diff, match and patch. * Computes the difference between two texts to create a patch. * Applies the patch onto another text, allowing for errors. * * @author fraser@google.com (Neil Fraser) * * Qt/C++ port by mikeslemmer@gmail.com (Mike Slemmer): * * Code compiles and runs with Qt 4.3.3. * * Here is a trivial sample program which works properly when linked with this library: * #include #include "diff_match_patch.h" int main(int argc, char **argv) { diff_match_patch dmp; QString str1 = QString("First string in diff"); QString str2 = QString("Second string in diff"); QString strPatch = dmp.patch_toText(dmp.patch_make(str1, str2)); QPair > out = dmp.patch_apply(dmp.patch_fromText(strPatch), str1); QString strResult = out.first; // here, strResult will equal str2 above. return 0; } */ /**- * The data structure representing a diff is a Linked list of Diff objects: * {Diff(Operation.DELETE, "Hello"), Diff(Operation.INSERT, "Goodbye"), * Diff(Operation.EQUAL, " world.")} * which means: delete "Hello", add "Goodbye" and keep " world." */ enum Operation { DELETE, INSERT, EQUAL }; /** * Class representing one diff operation. */ class Diff { public: Operation operation; // One of: INSERT, DELETE or EQUAL. QString text; // The text associated with this diff operation. /** * Constructor. Initializes the diff with the provided values. * @param operation One of INSERT, DELETE or EQUAL. * @param text The text being applied. */ Diff(Operation _operation, const QString &_text); Diff(); inline bool isNull() const; QString toString() const; bool operator==(const Diff &d) const; bool operator!=(const Diff &d) const; static QString strOperation(Operation op); }; /** * Class representing one patch operation. */ class Patch { public: QList diffs; int start1; int start2; int length1; int length2; /** * Constructor. Initializes with an empty list of diffs. */ Patch(); bool isNull() const; QString toString(); }; /** * Class containing the diff, match and patch methods. * Also contains the behaviour settings. */ class diff_match_patch { friend class diff_match_patch_test; public: // Defaults. // Set these on your diff_match_patch instance to override the defaults. // Number of seconds to map a diff before giving up (0 for infinity). float Diff_Timeout; // Cost of an empty edit operation in terms of edit characters. short Diff_EditCost; // The size beyond which the double-ended diff activates. // Double-ending is twice as fast, but less accurate. short Diff_DualThreshold; // At what point is no match declared (0.0 = perfection, 1.0 = very loose). float Match_Threshold; // How far to search for a match (0 = exact location, 1000+ = broad match). // A match this many characters away from the expected location will add // 1.0 to the score (0.0 is a perfect match). int Match_Distance; // When deleting a large block of text (over ~64 characters), how close does // the contents have to match the expected contents. (0.0 = perfection, // 1.0 = very loose). Note that Match_Threshold controls how closely the // end points of a delete need to match. float Patch_DeleteThreshold; // Chunk size for context length. short Patch_Margin; // The number of bits in an int. int Match_MaxBits; public: diff_match_patch(); // DIFF FUNCTIONS /** * Find the differences between two texts. * Run a faster slightly less optimal diff * This method allows the 'checklines' of diff_main() to be optional. * Most of the time checklines is wanted, so default to true. * @param text1 Old string to be diffed. * @param text2 New string to be diffed. * @return Linked List of Diff objects. */ QList diff_main(const QString &text1, const QString &text2); /** * Find the differences between two texts. Simplifies the problem by * stripping any common prefix or suffix off the texts before diffing. * @param text1 Old string to be diffed. * @param text2 New string to be diffed. * @param checklines Speedup flag. If false, then don't run a * line-level diff first to identify the changed areas. * If true, then run a faster slightly less optimal diff * @return Linked List of Diff objects. */ QList diff_main(const QString &text1, const QString &text2, bool checklines); /** * Find the differences between two texts. Assumes that the texts do not * have any common prefix or suffix. * @param text1 Old string to be diffed. * @param text2 New string to be diffed. * @param checklines Speedup flag. If false, then don't run a * line-level diff first to identify the changed areas. * If true, then run a faster slightly less optimal diff * @return Linked List of Diff objects. */ protected: QList diff_compute(QString text1, QString text2, bool checklines); /** * Split two texts into a list of strings. Reduce the texts to a string of * hashes where each Unicode character represents one line. * @param text1 First string. * @param text2 Second string. * @return Three element Object array, containing the encoded text1, the * encoded text2 and the List of unique strings. The zeroth element * of the List of unique strings is intentionally blank. */ protected: QList diff_linesToChars(const QString &text1, const QString &text2); // return elems 0 and 1 are QString, elem 2 is QStringList /** * Split a text into a list of strings. Reduce the texts to a string of * hashes where each Unicode character represents one line. * @param text String to encode. * @param lineArray List of unique strings. * @param lineHash Map of strings to indices. * @return Encoded string. */ private: QString diff_linesToCharsMunge(const QString &text, QStringList &lineArray, QMap &lineHash); /** * Rehydrate the text in a diff from a string of line hashes to real lines of * text. * @param diffs LinkedList of Diff objects. * @param lineArray List of unique strings. */ private: void diff_charsToLines(QList &diffs, const QStringList &lineArray); /** * Explore the intersection points between the two texts. * @param text1 Old string to be diffed. * @param text2 New string to be diffed. * @return LinkedList of Diff objects or null if no diff available. */ protected: QList diff_map(const QString &text1, const QString &text2); /** * Work from the middle back to the start to determine the path. * @param v_map List of path sets. * @param text1 Old string fragment to be diffed. * @param text2 New string fragment to be diffed. * @return LinkedList of Diff objects. */ protected: QList diff_path1(const QList > > &v_map, const QString &text1, const QString &text2); /** * Work from the middle back to the end to determine the path. * @param v_map List of path sets. * @param text1 Old string fragment to be diffed. * @param text2 New string fragment to be diffed. * @return LinkedList of Diff objects. */ protected: QList diff_path2(const QList > > &v_map, const QString &text1, const QString &text2); /** * Determine the common prefix of two strings * @param text1 First string. * @param text2 Second string. * @return The number of characters common to the start of each string. */ public: int diff_commonPrefix(const QString &text1, const QString &text2); /** * Determine the common suffix of two strings * @param text1 First string. * @param text2 Second string. * @return The number of characters common to the end of each string. */ public: int diff_commonSuffix(const QString &text1, const QString &text2); /** * Do the two texts share a substring which is at least half the length of * the longer text? * @param text1 First string. * @param text2 Second string. * @return Five element String array, containing the prefix of text1, the * suffix of text1, the prefix of text2, the suffix of text2 and the * common middle. Or null if there was no match. */ protected: QStringList diff_halfMatch(const QString &text1, const QString &text2); /** * Does a substring of shorttext exist within longtext such that the * substring is at least half the length of longtext? * @param longtext Longer string. * @param shorttext Shorter string. * @param i Start index of quarter length substring within longtext. * @return Five element String array, containing the prefix of longtext, the * suffix of longtext, the prefix of shorttext, the suffix of shorttext * and the common middle. Or null if there was no match. */ private: QStringList diff_halfMatchI(const QString &longtext, const QString &shorttext, int i); /** * Reduce the number of edits by eliminating semantically trivial equalities. * @param diffs LinkedList of Diff objects. */ public: void diff_cleanupSemantic(QList &diffs); /** * Look for single edits surrounded on both sides by equalities * which can be shifted sideways to align the edit to a word boundary. * e.g: The cat came. -> The cat came. * @param diffs LinkedList of Diff objects. */ public: void diff_cleanupSemanticLossless(QList &diffs); /** * Given two strings, compute a score representing whether the internal * boundary falls on logical boundaries. * Scores range from 5 (best) to 0 (worst). * @param one First string. * @param two Second string. * @return The score. */ private: int diff_cleanupSemanticScore(const QString &one, const QString &two); /** * Reduce the number of edits by eliminating operationally trivial equalities. * @param diffs LinkedList of Diff objects. */ public: void diff_cleanupEfficiency(QList &diffs); /** * Reorder and merge like edit sections. Merge equalities. * Any edit section can move as long as it doesn't cross an equality. * @param diffs LinkedList of Diff objects. */ public: void diff_cleanupMerge(QList &diffs); /** * loc is a location in text1, compute and return the equivalent location in * text2. * e.g. "The cat" vs "The big cat", 1->1, 5->8 * @param diffs LinkedList of Diff objects. * @param loc Location within text1. * @return Location within text2. */ public: int diff_xIndex(const QList &diffs, int loc); /** * Convert a Diff list into a pretty HTML report. * @param diffs LinkedList of Diff objects. * @return HTML representation. */ public: QString diff_prettyHtml(const QList &diffs); /** * Compute and return the source text (all equalities and deletions). * @param diffs LinkedList of Diff objects. * @return Source text. */ public: QString diff_text1(const QList &diffs); /** * Compute and return the destination text (all equalities and insertions). * @param diffs LinkedList of Diff objects. * @return Destination text. */ public: QString diff_text2(const QList &diffs); /** * Compute the Levenshtein distance; the number of inserted, deleted or * substituted characters. * @param diffs LinkedList of Diff objects. * @return Number of changes. */ public: int diff_levenshtein(const QList &diffs); /** * Crush the diff into an encoded string which describes the operations * required to transform text1 into text2. * E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'. * Operations are tab-separated. Inserted text is escaped using %xx notation. * @param diffs Array of diff tuples. * @return Delta text. */ public: QString diff_toDelta(const QList &diffs); /** * Given the original text1, and an encoded string which describes the * operations required to transform text1 into text2, compute the full diff. * @param text1 Source string for the diff. * @param delta Delta text. * @return Array of diff tuples or null if invalid. * @throws QString If invalid input. */ public: QList diff_fromDelta(const QString &text1, const QString &delta); // MATCH FUNCTIONS /** * Locate the best instance of 'pattern' in 'text' near 'loc'. * Returns -1 if no match found. * @param text The text to search. * @param pattern The pattern to search for. * @param loc The location to search around. * @return Best match index or -1. */ public: int match_main(const QString &text, const QString &pattern, int loc); /** * Locate the best instance of 'pattern' in 'text' near 'loc' using the * Bitap algorithm. Returns -1 if no match found. * @param text The text to search. * @param pattern The pattern to search for. * @param loc The location to search around. * @return Best match index or -1. */ protected: int match_bitap(const QString &text, const QString &pattern, int loc); /** * Compute and return the score for a match with e errors and x location. * @param e Number of errors in match. * @param x Location of match. * @param loc Expected location of match. * @param pattern Pattern being sought. * @return Overall score for match (0.0 = good, 1.0 = bad). */ private: double match_bitapScore(int e, int x, int loc, const QString &pattern); /** * Initialise the alphabet for the Bitap algorithm. * @param pattern The text to encode. * @return Hash of character locations. */ protected: QMap match_alphabet(const QString &pattern); // PATCH FUNCTIONS /** * Increase the context until it is unique, * but don't let the pattern expand beyond Match_MaxBits. * @param patch The patch to grow. * @param text Source text. */ protected: void patch_addContext(Patch &patch, const QString &text); /** * Compute a list of patches to turn text1 into text2. * A set of diffs will be computed. * @param text1 Old text. * @param text2 New text. * @return LinkedList of Patch objects. */ public: QList patch_make(const QString &text1, const QString &text2); /** * Compute a list of patches to turn text1 into text2. * text1 will be derived from the provided diffs. * @param diffs Array of diff tuples for text1 to text2. * @return LinkedList of Patch objects. */ public: QList patch_make(const QList &diffs); /** * Compute a list of patches to turn text1 into text2. * text2 is ignored, diffs are the delta between text1 and text2. * @param text1 Old text. * @param text2 Ignored. * @param diffs Array of diff tuples for text1 to text2. * @return LinkedList of Patch objects. * @deprecated Prefer patch_make(const QString &text1, const QList &diffs). */ public: QList patch_make(const QString &text1, const QString &text2, const QList &diffs); /** * Compute a list of patches to turn text1 into text2. * text2 is not provided, diffs are the delta between text1 and text2. * @param text1 Old text. * @param diffs Array of diff tuples for text1 to text2. * @return LinkedList of Patch objects. */ public: QList patch_make(const QString &text1, const QList &diffs); /** * Given an array of patches, return another array that is identical. * @param patches Array of patch objects. * @return Array of patch objects. */ public: QList patch_deepCopy(QList &patches); /** * Merge a set of patches onto the text. Return a patched text, as well * as an array of true/false values indicating which patches were applied. * @param patches Array of patch objects. * @param text Old text. * @return Two element Object array, containing the new text and an array of * boolean values. */ public: QPair > patch_apply(QList &patches, const QString &text); /** * Add some padding on text start and end so that edges can match something. * Intended to be called only from within patch_apply. * @param patches Array of patch objects. * @return The padding string added to each side. */ public: QString patch_addPadding(QList &patches); /** * Look through the patches and break up any which are longer than the * maximum limit of the match algorithm. * @param patches LinkedList of Patch objects. */ public: void patch_splitMax(QList &patches); /** * Take a list of patches and return a textual representation. * @param patches List of Patch objects. * @return Text representation of patches. */ public: QString patch_toText(const QList &patches); /** * Parse a textual representation of patches and return a List of Patch * objects. * @param textline Text representation of patches. * @return List of Patch objects. * @throws QString If invalid input. */ public: QList patch_fromText(const QString &textline); }; #endif // DIFF_MATCH_PATCH_H ================================================ FILE: liteidex/src/3rdparty/diff_match_patch/diff_match_patch.pri ================================================ LIBS *= -l$$qtLibraryName(diff_match_pitch) ================================================ FILE: liteidex/src/3rdparty/diff_match_patch/diff_match_patch.pro ================================================ TARGET = diff_match_pitch TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += \ diff_match_patch.h SOURCES += \ diff_match_patch.cpp RESOURCES += ================================================ FILE: liteidex/src/3rdparty/diff_match_patch/diff_match_patch_test.cpp ================================================ /* * Copyright 2008 Google Inc. All Rights Reserved. * Author: fraser@google.com (Neil Fraser) * Author: mikeslemmer@gmail.com (Mike Slemmer) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Diff Match and Patch -- Test Harness * http://code.google.com/p/google-diff-match-patch/ */ // Code known to compile and run with Qt 4.3.3 and Qt 4.4.0. #include #include "diff_match_patch.h" #include "diff_match_patch_test.h" int main(int argc, char **argv) { diff_match_patch_test dmp_test; qDebug("Starting diff_match_patch unit tests."); dmp_test.run_all_tests(); qDebug("Done."); return 0; Q_UNUSED(argc) Q_UNUSED(argv) } diff_match_patch_test::diff_match_patch_test() { } void diff_match_patch_test::run_all_tests() { QTime t; t.start(); try { testDiffCommonPrefix(); testDiffCommonSuffix(); testDiffHalfmatch(); testDiffLinesToChars(); testDiffCharsToLines(); testDiffCleanupMerge(); testDiffCleanupSemanticLossless(); testDiffCleanupSemantic(); testDiffCleanupEfficiency(); testDiffPrettyHtml(); testDiffText(); testDiffDelta(); testDiffXIndex(); testDiffPath(); testDiffMain(); testMatchAlphabet(); testMatchBitap(); testMatchMain(); testPatchObj(); testPatchFromText(); testPatchToText(); testPatchAddContext(); testPatchMake(); testPatchSplitMax(); testPatchAddPadding(); testPatchApply(); qDebug("All tests passed."); } catch (QString strCase) { qDebug(qPrintable(QString("Test failed: %1").arg(strCase))); } qDebug("Total time: %d ms", t.elapsed()); } // DIFF TEST FUNCTIONS void diff_match_patch_test::testDiffCommonPrefix() { // Detect and remove any common prefix. assertEquals("diff_commonPrefix: Null case.", 0, dmp.diff_commonPrefix("abc", "xyz")); assertEquals("diff_commonPrefix: Non-null case.", 4, dmp.diff_commonPrefix("1234abcdef", "1234xyz")); assertEquals("diff_commonPrefix: Whole case.", 4, dmp.diff_commonPrefix("1234", "1234xyz")); } void diff_match_patch_test::testDiffCommonSuffix() { // Detect and remove any common suffix. assertEquals("diff_commonSuffix: Null case.", 0, dmp.diff_commonSuffix("abc", "xyz")); assertEquals("diff_commonSuffix: Non-null case.", 4, dmp.diff_commonSuffix("abcdef1234", "xyz1234")); assertEquals("diff_commonSuffix: Whole case.", 4, dmp.diff_commonSuffix("1234", "xyz1234")); } void diff_match_patch_test::testDiffHalfmatch() { // Detect a halfmatch. assertNull("diff_halfMatch: No match.", dmp.diff_halfMatch("1234567890", "abcdef")); assertEquals("diff_halfMatch: Single Match #1.", QString("12,90,a,z,345678").split(","), dmp.diff_halfMatch("1234567890", "a345678z")); assertEquals("diff_halfMatch: Single Match #2.", QString("a,z,12,90,345678").split(","), dmp.diff_halfMatch("a345678z", "1234567890")); assertEquals("diff_halfMatch: Multiple Matches #1.", QString("12123,123121,a,z,1234123451234").split(","), dmp.diff_halfMatch("121231234123451234123121", "a1234123451234z")); assertEquals("diff_halfMatch: Multiple Matches #2.", QString(",-=-=-=-=-=,x,,x-=-=-=-=-=-=-=").split(","), dmp.diff_halfMatch("x-=-=-=-=-=-=-=-=-=-=-=-=", "xx-=-=-=-=-=-=-=")); assertEquals("diff_halfMatch: Multiple Matches #3.", QString("-=-=-=-=-=,,,y,-=-=-=-=-=-=-=y").split(","), dmp.diff_halfMatch("-=-=-=-=-=-=-=-=-=-=-=-=y", "-=-=-=-=-=-=-=yy")); } void diff_match_patch_test::testDiffLinesToChars() { // Convert lines down to characters. QStringList tmpVector; QList tmpVarList; tmpVector.append(""); tmpVector.append("alpha\n"); tmpVector.append("beta\n"); tmpVarList << QVariant::fromValue(QString() + QChar((ushort)1) + QChar((ushort)2) + QChar((ushort)1)); //(("\u0001\u0002\u0001")); tmpVarList << QVariant::fromValue(QString() + QChar((ushort)2) + QChar((ushort)1) + QChar((ushort)2)); // (("\u0002\u0001\u0002")); tmpVarList << QVariant::fromValue(tmpVector); assertEquals("diff_linesToChars:", tmpVarList, dmp.diff_linesToChars("alpha\nbeta\nalpha\n", "beta\nalpha\nbeta\n")); tmpVector.clear(); tmpVarList.clear(); tmpVector.append(""); tmpVector.append("alpha\r\n"); tmpVector.append("beta\r\n"); tmpVector.append("\r\n"); tmpVarList << QVariant::fromValue(QString("")); tmpVarList << QVariant::fromValue(QString() + QChar((ushort)1) + QChar((ushort)2) + QChar((ushort)3) + QChar((ushort)3)); // (("\u0001\u0002\u0003\u0003")); tmpVarList << QVariant::fromValue(tmpVector); assertEquals("diff_linesToChars:", tmpVarList, dmp.diff_linesToChars("", "alpha\r\nbeta\r\n\r\n\r\n")); tmpVector.clear(); tmpVarList.clear(); tmpVector.append(""); tmpVector.append("a"); tmpVector.append("b"); tmpVarList << QVariant::fromValue(QString() + QChar((ushort)1)); // (("\u0001")); tmpVarList << QVariant::fromValue(QString() + QChar((ushort)2)); // (("\u0002")); tmpVarList << QVariant::fromValue(tmpVector); assertEquals("diff_linesToChars:", tmpVarList, dmp.diff_linesToChars("a", "b")); // More than 256 to reveal any 8-bit limitations. int n = 300; tmpVector.clear(); tmpVarList.clear(); QString lines; QString chars; for (int x = 1; x < n + 1; x++) { tmpVector.append(QString::number(x) + "\n"); lines += QString::number(x) + "\n"; chars += QChar(static_cast(x)); } assertEquals("diff_linesToChars: More than 256 (setup).", n, tmpVector.size()); assertEquals("diff_linesToChars: More than 256 (setup).", n, chars.length()); tmpVector.prepend(""); tmpVarList << QVariant::fromValue(chars); tmpVarList << QVariant::fromValue(QString("")); tmpVarList << QVariant::fromValue(tmpVector); assertEquals("diff_linesToChars: More than 256.", tmpVarList, dmp.diff_linesToChars(lines, "")); } void diff_match_patch_test::testDiffCharsToLines() { // First check that Diff equality works. assertTrue("diff_charsToLines:", Diff(EQUAL, "a") == Diff(EQUAL, "a")); assertEquals("diff_charsToLines:", Diff(EQUAL, "a"), Diff(EQUAL, "a")); // Convert chars up to lines. QList diffs; diffs << Diff(EQUAL, QString() + QChar((ushort)1) + QChar((ushort)2) + QChar((ushort)1)); // ("\u0001\u0002\u0001"); diffs << Diff(INSERT, QString() + QChar((ushort)2) + QChar((ushort)1) + QChar((ushort)2)); // ("\u0002\u0001\u0002"); QStringList tmpVector; tmpVector.append(""); tmpVector.append("alpha\n"); tmpVector.append("beta\n"); dmp.diff_charsToLines(diffs, tmpVector); assertEquals("diff_charsToLines:", diffList(Diff(EQUAL, "alpha\nbeta\nalpha\n"), Diff(INSERT, "beta\nalpha\nbeta\n")), diffs); // More than 256 to reveal any 8-bit limitations. int n = 300; tmpVector.clear(); QList tmpVarList; QString lines; QString chars; for (int x = 1; x < n + 1; x++) { tmpVector.append(QString::number(x) + "\n"); lines += QString::number(x) + "\n"; chars += QChar(static_cast(x)); } assertEquals("diff_linesToChars: More than 256 (setup).", n, tmpVector.size()); assertEquals("diff_linesToChars: More than 256 (setup).", n, chars.length()); tmpVector.prepend(""); diffs = diffList(Diff(DELETE, chars)); dmp.diff_charsToLines(diffs, tmpVector); assertEquals("diff_charsToLines: More than 256.", diffList(Diff(DELETE, lines)), diffs); } void diff_match_patch_test::testDiffCleanupMerge() { // Cleanup a messy diff. QList diffs; dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Null case.", diffList(), diffs); diffs = diffList(Diff(EQUAL, "a"), Diff(DELETE, "b"), Diff(INSERT, "c")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: No change case.", diffList(Diff(EQUAL, "a"), Diff(DELETE, "b"), Diff(INSERT, "c")), diffs); diffs = diffList(Diff(EQUAL, "a"), Diff(EQUAL, "b"), Diff(EQUAL, "c")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Merge equalities.", diffList(Diff(EQUAL, "abc")), diffs); diffs = diffList(Diff(DELETE, "a"), Diff(DELETE, "b"), Diff(DELETE, "c")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Merge deletions.", diffList(Diff(DELETE, "abc")), diffs); diffs = diffList(Diff(INSERT, "a"), Diff(INSERT, "b"), Diff(INSERT, "c")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Merge insertions.", diffList(Diff(INSERT, "abc")), diffs); diffs = diffList(Diff(DELETE, "a"), Diff(INSERT, "b"), Diff(DELETE, "c"), Diff(INSERT, "d"), Diff(EQUAL, "e"), Diff(EQUAL, "f")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Merge interweave.", diffList(Diff(DELETE, "ac"), Diff(INSERT, "bd"), Diff(EQUAL, "ef")), diffs); diffs = diffList(Diff(DELETE, "a"), Diff(INSERT, "abc"), Diff(DELETE, "dc")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Prefix and suffix detection.", diffList(Diff(EQUAL, "a"), Diff(DELETE, "d"), Diff(INSERT, "b"), Diff(EQUAL, "c")), diffs); diffs = diffList(Diff(EQUAL, "a"), Diff(INSERT, "ba"), Diff(EQUAL, "c")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Slide edit left.", diffList(Diff(INSERT, "ab"), Diff(EQUAL, "ac")), diffs); diffs = diffList(Diff(EQUAL, "c"), Diff(INSERT, "ab"), Diff(EQUAL, "a")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Slide edit right.", diffList(Diff(EQUAL, "ca"), Diff(INSERT, "ba")), diffs); diffs = diffList(Diff(EQUAL, "a"), Diff(DELETE, "b"), Diff(EQUAL, "c"), Diff(DELETE, "ac"), Diff(EQUAL, "x")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Slide edit left recursive.", diffList(Diff(DELETE, "abc"), Diff(EQUAL, "acx")), diffs); diffs = diffList(Diff(EQUAL, "x"), Diff(DELETE, "ca"), Diff(EQUAL, "c"), Diff(DELETE, "b"), Diff(EQUAL, "a")); dmp.diff_cleanupMerge(diffs); assertEquals("diff_cleanupMerge: Slide edit right recursive.", diffList(Diff(EQUAL, "xca"), Diff(DELETE, "cba")), diffs); } void diff_match_patch_test::testDiffCleanupSemanticLossless() { // Slide diffs to match logical boundaries. QList diffs = diffList(); dmp.diff_cleanupSemanticLossless(diffs); assertEquals("diff_cleanupSemantic: Null case.", diffList(), diffs); diffs = diffList(Diff(EQUAL, "AAA\r\n\r\nBBB"), Diff(INSERT, "\r\nDDD\r\n\r\nBBB"), Diff(EQUAL, "\r\nEEE")); dmp.diff_cleanupSemanticLossless(diffs); assertEquals("diff_cleanupSemanticLossless: Blank lines.", diffList(Diff(EQUAL, "AAA\r\n\r\n"), Diff(INSERT, "BBB\r\nDDD\r\n\r\n"), Diff(EQUAL, "BBB\r\nEEE")), diffs); diffs = diffList(Diff(EQUAL, "AAA\r\nBBB"), Diff(INSERT, " DDD\r\nBBB"), Diff(EQUAL, " EEE")); dmp.diff_cleanupSemanticLossless(diffs); assertEquals("diff_cleanupSemanticLossless: Line boundaries.", diffList(Diff(EQUAL, "AAA\r\n"), Diff(INSERT, "BBB DDD\r\n"), Diff(EQUAL, "BBB EEE")), diffs); diffs = diffList(Diff(EQUAL, "The c"), Diff(INSERT, "ow and the c"), Diff(EQUAL, "at.")); dmp.diff_cleanupSemanticLossless(diffs); assertEquals("diff_cleanupSemantic: Word boundaries.", diffList(Diff(EQUAL, "The "), Diff(INSERT, "cow and the "), Diff(EQUAL, "cat.")), diffs); diffs = diffList(Diff(EQUAL, "The-c"), Diff(INSERT, "ow-and-the-c"), Diff(EQUAL, "at.")); dmp.diff_cleanupSemanticLossless(diffs); assertEquals("diff_cleanupSemantic: Alphanumeric boundaries.", diffList(Diff(EQUAL, "The-"), Diff(INSERT, "cow-and-the-"), Diff(EQUAL, "cat.")), diffs); diffs = diffList(Diff(EQUAL, "a"), Diff(DELETE, "a"), Diff(EQUAL, "ax")); dmp.diff_cleanupSemanticLossless(diffs); assertEquals("diff_cleanupSemantic: Hitting the start.", diffList(Diff(DELETE, "a"), Diff(EQUAL, "aax")), diffs); diffs = diffList(Diff(EQUAL, "xa"), Diff(DELETE, "a"), Diff(EQUAL, "a")); dmp.diff_cleanupSemanticLossless(diffs); assertEquals("diff_cleanupSemantic: Hitting the end.", diffList(Diff(EQUAL, "xaa"), Diff(DELETE, "a")), diffs); } void diff_match_patch_test::testDiffCleanupSemantic() { // Cleanup semantically trivial equalities. QList diffs = diffList(); dmp.diff_cleanupSemantic(diffs); assertEquals("diff_cleanupSemantic: Null case.", diffList(), diffs); diffs = diffList(Diff(DELETE, "a"), Diff(INSERT, "b"), Diff(EQUAL, "cd"), Diff(DELETE, "e")); dmp.diff_cleanupSemantic(diffs); assertEquals("diff_cleanupSemantic: No elimination.", diffList(Diff(DELETE, "a"), Diff(INSERT, "b"), Diff(EQUAL, "cd"), Diff(DELETE, "e")), diffs); diffs = diffList(Diff(DELETE, "a"), Diff(EQUAL, "b"), Diff(DELETE, "c")); dmp.diff_cleanupSemantic(diffs); assertEquals("diff_cleanupSemantic: Simple elimination.", diffList(Diff(DELETE, "abc"), Diff(INSERT, "b")), diffs); diffs = diffList(Diff(DELETE, "ab"), Diff(EQUAL, "cd"), Diff(DELETE, "e"), Diff(EQUAL, "f"), Diff(INSERT, "g")); dmp.diff_cleanupSemantic(diffs); assertEquals("diff_cleanupSemantic: Backpass elimination.", diffList(Diff(DELETE, "abcdef"), Diff(INSERT, "cdfg")), diffs); diffs = diffList(Diff(INSERT, "1"), Diff(EQUAL, "A"), Diff(DELETE, "B"), Diff(INSERT, "2"), Diff(EQUAL, "_"), Diff(INSERT, "1"), Diff(EQUAL, "A"), Diff(DELETE, "B"), Diff(INSERT, "2")); dmp.diff_cleanupSemantic(diffs); assertEquals("diff_cleanupSemantic: Multiple elimination.", diffList(Diff(DELETE, "AB_AB"), Diff(INSERT, "1A2_1A2")), diffs); diffs = diffList(Diff(EQUAL, "The c"), Diff(DELETE, "ow and the c"), Diff(EQUAL, "at.")); dmp.diff_cleanupSemantic(diffs); assertEquals("diff_cleanupSemantic: Word boundaries.", diffList(Diff(EQUAL, "The "), Diff(DELETE, "cow and the "), Diff(EQUAL, "cat.")), diffs); } void diff_match_patch_test::testDiffCleanupEfficiency() { // Cleanup operationally trivial equalities. dmp.Diff_EditCost = 4; QList diffs = diffList(); dmp.diff_cleanupEfficiency(diffs); assertEquals("diff_cleanupEfficiency: Null case.", diffList(), diffs); diffs = diffList(Diff(DELETE, "ab"), Diff(INSERT, "12"), Diff(EQUAL, "wxyz"), Diff(DELETE, "cd"), Diff(INSERT, "34")); dmp.diff_cleanupEfficiency(diffs); assertEquals("diff_cleanupEfficiency: No elimination.", diffList(Diff(DELETE, "ab"), Diff(INSERT, "12"), Diff(EQUAL, "wxyz"), Diff(DELETE, "cd"), Diff(INSERT, "34")), diffs); diffs = diffList(Diff(DELETE, "ab"), Diff(INSERT, "12"), Diff(EQUAL, "xyz"), Diff(DELETE, "cd"), Diff(INSERT, "34")); dmp.diff_cleanupEfficiency(diffs); assertEquals("diff_cleanupEfficiency: Four-edit elimination.", diffList(Diff(DELETE, "abxyzcd"), Diff(INSERT, "12xyz34")), diffs); diffs = diffList(Diff(INSERT, "12"), Diff(EQUAL, "x"), Diff(DELETE, "cd"), Diff(INSERT, "34")); dmp.diff_cleanupEfficiency(diffs); assertEquals("diff_cleanupEfficiency: Three-edit elimination.", diffList(Diff(DELETE, "xcd"), Diff(INSERT, "12x34")), diffs); diffs = diffList(Diff(DELETE, "ab"), Diff(INSERT, "12"), Diff(EQUAL, "xy"), Diff(INSERT, "34"), Diff(EQUAL, "z"), Diff(DELETE, "cd"), Diff(INSERT, "56")); dmp.diff_cleanupEfficiency(diffs); assertEquals("diff_cleanupEfficiency: Backpass elimination.", diffList(Diff(DELETE, "abxyzcd"), Diff(INSERT, "12xy34z56")), diffs); dmp.Diff_EditCost = 5; diffs = diffList(Diff(DELETE, "ab"), Diff(INSERT, "12"), Diff(EQUAL, "wxyz"), Diff(DELETE, "cd"), Diff(INSERT, "34")); dmp.diff_cleanupEfficiency(diffs); assertEquals("diff_cleanupEfficiency: High cost elimination.", diffList(Diff(DELETE, "abwxyzcd"), Diff(INSERT, "12wxyz34")), diffs); dmp.Diff_EditCost = 4; } void diff_match_patch_test::testDiffPrettyHtml() { // Pretty print. QList diffs = diffList(Diff(EQUAL, "a\n"), Diff(DELETE, "b"), Diff(INSERT, "c&d")); assertEquals("diff_prettyHtml:", "
<B>b</B>c&d", dmp.diff_prettyHtml(diffs)); } void diff_match_patch_test::testDiffText() { // Compute the source and destination texts. QList diffs = diffList(Diff(EQUAL, "jump"), Diff(DELETE, "s"), Diff(INSERT, "ed"), Diff(EQUAL, " over "), Diff(DELETE, "the"), Diff(INSERT, "a"), Diff(EQUAL, " lazy")); assertEquals("diff_text1:", "jumps over the lazy", dmp.diff_text1(diffs)); assertEquals("diff_text2:", "jumped over a lazy", dmp.diff_text2(diffs)); } void diff_match_patch_test::testDiffDelta() { // Convert a diff into delta string. QList diffs = diffList(Diff(EQUAL, "jump"), Diff(DELETE, "s"), Diff(INSERT, "ed"), Diff(EQUAL, " over "), Diff(DELETE, "the"), Diff(INSERT, "a"), Diff(EQUAL, " lazy"), Diff(INSERT, "old dog")); QString text1 = dmp.diff_text1(diffs); assertEquals("diff_text1: Base text.", "jumps over the lazy", text1); QString delta = dmp.diff_toDelta(diffs); assertEquals("diff_toDelta:", "=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog", delta); // Convert delta string into a diff. assertEquals("diff_fromDelta: Normal.", diffs, dmp.diff_fromDelta(text1, delta)); // Generates error (19 < 20). try { dmp.diff_fromDelta(text1 + "x", delta); throw "diff_fromDelta: Too long."; } catch (QString ex) { // Exception expected. } // Generates error (19 > 18). try { dmp.diff_fromDelta(text1.mid(1), delta); throw "diff_fromDelta: Too short."; } catch (QString ex) { // Exception expected. } // Generates error (%c3%xy invalid Unicode). /* This test does not work because QUrl::fromPercentEncoding("%xy") -> "?" try { dmp.diff_fromDelta("", "+%c3%xy"); throw "diff_fromDelta: Invalid character."; } catch (QString ex) { // Exception expected. } */ // Test deltas with special characters. diffs = diffList(Diff(EQUAL, QString::fromWCharArray((const wchar_t*) L"\u0680 \000 \t %", 7)), Diff(DELETE, QString::fromWCharArray((const wchar_t*) L"\u0681 \001 \n ^", 7)), Diff(INSERT, QString::fromWCharArray((const wchar_t*) L"\u0682 \002 \\ |", 7))); text1 = dmp.diff_text1(diffs); assertEquals("diff_text1: Unicode text.", QString::fromWCharArray((const wchar_t*) L"\u0680 \000 \t %\u0681 \001 \n ^", 14), text1); delta = dmp.diff_toDelta(diffs); assertEquals("diff_toDelta: Unicode.", "=7\t-7\t+%DA%82 %02 %5C %7C", delta); assertEquals("diff_fromDelta: Unicode.", diffs, dmp.diff_fromDelta(text1, delta)); // Verify pool of unchanged characters. diffs = diffList(Diff(INSERT, "A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , # ")); QString text2 = dmp.diff_text2(diffs); assertEquals("diff_text2: Unchanged characters.", "A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", text2); delta = dmp.diff_toDelta(diffs); assertEquals("diff_toDelta: Unchanged characters.", "+A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", delta); // Convert delta string into a diff. assertEquals("diff_fromDelta: Unchanged characters.", diffs, dmp.diff_fromDelta("", delta)); } void diff_match_patch_test::testDiffXIndex() { // Translate a location in text1 to text2. QList diffs = diffList(Diff(DELETE, "a"), Diff(INSERT, "1234"), Diff(EQUAL, "xyz")); assertEquals("diff_xIndex: Translation on equality.", 5, dmp.diff_xIndex(diffs, 2)); diffs = diffList(Diff(EQUAL, "a"), Diff(DELETE, "1234"), Diff(EQUAL, "xyz")); assertEquals("diff_xIndex: Translation on deletion.", 1, dmp.diff_xIndex(diffs, 3)); } void diff_match_patch_test::testDiffLevenshtein() { QList diffs = diffList(Diff(DELETE, "abc"), Diff(INSERT, "1234"), Diff(EQUAL, "xyz")); assertEquals("Levenshtein with trailing equality.", 4, dmp.diff_levenshtein(diffs)); diffs = diffList(Diff(EQUAL, "xyz"), Diff(DELETE, "abc"), Diff(INSERT, "1234")); assertEquals("Levenshtein with leading equality.", 4, dmp.diff_levenshtein(diffs)); diffs = diffList(Diff(DELETE, "abc"), Diff(EQUAL, "xyz"), Diff(INSERT, "1234")); assertEquals("Levenshtein with middle equality.", 7, dmp.diff_levenshtein(diffs)); } void diff_match_patch_test::testDiffPath() { // Single letters. // Trace a path from back to front. QList > > v_map; QSet > row_set; { row_set = QSet >(); row_set.insert(QPair(0, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 1)); row_set.insert(QPair(1, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 2)); row_set.insert(QPair(2, 0)); row_set.insert(QPair(2, 2)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 3)); row_set.insert(QPair(2, 3)); row_set.insert(QPair(3, 0)); row_set.insert(QPair(4, 3)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 4)); row_set.insert(QPair(2, 4)); row_set.insert(QPair(4, 0)); row_set.insert(QPair(4, 4)); row_set.insert(QPair(5, 3)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 5)); row_set.insert(QPair(2, 5)); row_set.insert(QPair(4, 5)); row_set.insert(QPair(5, 0)); row_set.insert(QPair(6, 3)); row_set.insert(QPair(6, 5)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 6)); row_set.insert(QPair(2, 6)); row_set.insert(QPair(4, 6)); row_set.insert(QPair(6, 6)); row_set.insert(QPair(7, 5)); v_map.append(row_set); } QList diffs = diffList(Diff(INSERT, "W"), Diff(DELETE, "A"), Diff(EQUAL, "1"), Diff(DELETE, "B"), Diff(EQUAL, "2"), Diff(INSERT, "X"), Diff(DELETE, "C"), Diff(EQUAL, "3"), Diff(DELETE, "D")); assertEquals("diff_path1: Single letters.", diffs, dmp.diff_path1(v_map, "A1B2C3D", "W12X3")); // Trace a path from front to back. v_map.removeAt(v_map.size() - 1); diffs = diffList(Diff(EQUAL, "4"), Diff(DELETE, "E"), Diff(INSERT, "Y"), Diff(EQUAL, "5"), Diff(DELETE, "F"), Diff(EQUAL, "6"), Diff(DELETE, "G"), Diff(INSERT, "Z")); assertEquals("diff_path2: Single letters.", diffs, dmp.diff_path2(v_map, "4E5F6G", "4Y56Z")); // Double letters. // Trace a path from back to front. v_map = QList > >(); { row_set = QSet >(); row_set.insert(QPair(0, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 1)); row_set.insert(QPair(1, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 2)); row_set.insert(QPair(1, 1)); row_set.insert(QPair(2, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 3)); row_set.insert(QPair(1, 2)); row_set.insert(QPair(2, 1)); row_set.insert(QPair(3, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 4)); row_set.insert(QPair(1, 3)); row_set.insert(QPair(3, 1)); row_set.insert(QPair(4, 0)); row_set.insert(QPair(4, 4)); v_map.append(row_set); } diffs = diffList(Diff(INSERT, "WX"), Diff(DELETE, "AB"), Diff(EQUAL, "12")); assertEquals("diff_path1: Double letters.", diffs, dmp.diff_path1(v_map, "AB12", "WX12")); // Trace a path from front to back. v_map = QList > >(); { row_set = QSet >(); row_set.insert(QPair(0, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(0, 1)); row_set.insert(QPair(1, 0)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(1, 1)); row_set.insert(QPair(2, 0)); row_set.insert(QPair(2, 4)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(2, 1)); row_set.insert(QPair(2, 5)); row_set.insert(QPair(3, 0)); row_set.insert(QPair(3, 4)); v_map.append(row_set); row_set = QSet >(); row_set.insert(QPair(2, 6)); row_set.insert(QPair(3, 5)); row_set.insert(QPair(4, 4)); v_map.append(row_set); } diffs = diffList(Diff(DELETE, "CD"), Diff(EQUAL, "34"), Diff(INSERT, "YZ")); assertEquals("diff_path2: Double letters.", diffs, dmp.diff_path2(v_map, "CD34", "34YZ")); } void diff_match_patch_test::testDiffMain() { // Perform a trivial diff. QList diffs = diffList(Diff(EQUAL, "abc")); assertEquals("diff_main: Null case.", diffs, dmp.diff_main("abc", "abc", false)); diffs = diffList(Diff(EQUAL, "ab"), Diff(INSERT, "123"), Diff(EQUAL, "c")); assertEquals("diff_main: Simple insertion.", diffs, dmp.diff_main("abc", "ab123c", false)); diffs = diffList(Diff(EQUAL, "a"), Diff(DELETE, "123"), Diff(EQUAL, "bc")); assertEquals("diff_main: Simple deletion.", diffs, dmp.diff_main("a123bc", "abc", false)); diffs = diffList(Diff(EQUAL, "a"), Diff(INSERT, "123"), Diff(EQUAL, "b"), Diff(INSERT, "456"), Diff(EQUAL, "c")); assertEquals("diff_main: Two insertions.", diffs, dmp.diff_main("abc", "a123b456c", false)); diffs = diffList(Diff(EQUAL, "a"), Diff(DELETE, "123"), Diff(EQUAL, "b"), Diff(DELETE, "456"), Diff(EQUAL, "c")); assertEquals("diff_main: Two deletions.", diffs, dmp.diff_main("a123b456c", "abc", false)); // Perform a real diff. // Switch off the timeout. dmp.Diff_Timeout = 0; dmp.Diff_DualThreshold = 32; diffs = diffList(Diff(DELETE, "a"), Diff(INSERT, "b")); assertEquals("diff_main: Simple case #1.", diffs, dmp.diff_main("a", "b", false)); diffs = diffList(Diff(DELETE, "Apple"), Diff(INSERT, "Banana"), Diff(EQUAL, "s are a"), Diff(INSERT, "lso"), Diff(EQUAL, " fruit.")); assertEquals("diff_main: Simple case #2.", diffs, dmp.diff_main("Apples are a fruit.", "Bananas are also fruit.", false)); diffs = diffList(Diff(DELETE, "a"), Diff(INSERT, QString::fromWCharArray((const wchar_t*) L"\u0680", 1)), Diff(EQUAL, "x"), Diff(DELETE, "\t"), Diff(INSERT, QString::fromWCharArray((const wchar_t*) L"\000", 1))); assertEquals("diff_main: Simple case #3.", diffs, dmp.diff_main("ax\t", QString::fromWCharArray((const wchar_t*) L"\u0680x\000", 3), false)); diffs = diffList(Diff(DELETE, "1"), Diff(EQUAL, "a"), Diff(DELETE, "y"), Diff(EQUAL, "b"), Diff(DELETE, "2"), Diff(INSERT, "xab")); assertEquals("diff_main: Overlap #1.", diffs, dmp.diff_main("1ayb2", "abxab", false)); diffs = diffList(Diff(INSERT, "xaxcx"), Diff(EQUAL, "abc"), Diff(DELETE, "y")); assertEquals("diff_main: Overlap #2.", diffs, dmp.diff_main("abcy", "xaxcxabc", false)); // Sub-optimal double-ended diff. dmp.Diff_DualThreshold = 2; diffs = diffList(Diff(INSERT, "x"), Diff(EQUAL, "a"), Diff(DELETE, "b"), Diff(INSERT, "x"), Diff(EQUAL, "c"), Diff(DELETE, "y"), Diff(INSERT, "xabc")); assertEquals("diff_main: Overlap #3.", diffs, dmp.diff_main("abcy", "xaxcxabc", false)); dmp.Diff_DualThreshold = 32; dmp.Diff_Timeout = 0.001f; // 1ms // This test may 'fail' on extremely fast computers. If so, just increase the text lengths. QString a = "`Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.\n"; QString b = "I am the very model of a modern major general,\nI've information vegetable, animal, and mineral,\nI know the kings of England, and I quote the fights historical,\nFrom Marathon to Waterloo, in order categorical.\n"; // Increase the text lengths by 1024 times to ensure a timeout. for (int x = 0; x < 10; x++) { a = a + a; b = b + b; } assertNull("diff_main: Timeout.", dmp.diff_map(a, b)); dmp.Diff_Timeout = 0; // Test the linemode speedup. // Must be long to pass the 200 char cutoff. a = "1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n"; b = "abcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\n"; assertEquals("diff_main: Simple.", dmp.diff_main(a, b, true), dmp.diff_main(a, b, false)); a = "1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n"; b = "abcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n"; QStringList texts_linemode = diff_rebuildtexts(dmp.diff_main(a, b, true)); QStringList texts_textmode = diff_rebuildtexts(dmp.diff_main(a, b, false)); assertEquals("diff_main: Overlap.", texts_textmode, texts_linemode); } // MATCH TEST FUNCTIONS void diff_match_patch_test::testMatchAlphabet() { // Initialise the bitmasks for Bitap. QMap bitmask; bitmask.insert('a', 4); bitmask.insert('b', 2); bitmask.insert('c', 1); assertEquals("match_alphabet: Unique.", bitmask, dmp.match_alphabet("abc")); bitmask = QMap(); bitmask.insert('a', 37); bitmask.insert('b', 18); bitmask.insert('c', 8); assertEquals("match_alphabet: Duplicates.", bitmask, dmp.match_alphabet("abcaba")); } void diff_match_patch_test::testMatchBitap() { // Bitap algorithm. dmp.Match_Distance = 100; dmp.Match_Threshold = 0.5f; assertEquals("match_bitap: Exact match #1.", 5, dmp.match_bitap("abcdefghijk", "fgh", 5)); assertEquals("match_bitap: Exact match #2.", 5, dmp.match_bitap("abcdefghijk", "fgh", 0)); assertEquals("match_bitap: Fuzzy match #1.", 4, dmp.match_bitap("abcdefghijk", "efxhi", 0)); assertEquals("match_bitap: Fuzzy match #2.", 2, dmp.match_bitap("abcdefghijk", "cdefxyhijk", 5)); assertEquals("match_bitap: Fuzzy match #3.", -1, dmp.match_bitap("abcdefghijk", "bxy", 1)); assertEquals("match_bitap: Overflow.", 2, dmp.match_bitap("123456789xx0", "3456789x0", 2)); assertEquals("match_bitap: Before start match.", 0, dmp.match_bitap("abcdef", "xxabc", 4)); assertEquals("match_bitap: Beyond end match.", 3, dmp.match_bitap("abcdef", "defyy", 4)); assertEquals("match_bitap: Oversized pattern.", 0, dmp.match_bitap("abcdef", "xabcdefy", 0)); dmp.Match_Threshold = 0.4f; assertEquals("match_bitap: Threshold #1.", 4, dmp.match_bitap("abcdefghijk", "efxyhi", 1)); dmp.Match_Threshold = 0.3f; assertEquals("match_bitap: Threshold #2.", -1, dmp.match_bitap("abcdefghijk", "efxyhi", 1)); dmp.Match_Threshold = 0.0f; assertEquals("match_bitap: Threshold #3.", 1, dmp.match_bitap("abcdefghijk", "bcdef", 1)); dmp.Match_Threshold = 0.5f; assertEquals("match_bitap: Multiple select #1.", 0, dmp.match_bitap("abcdexyzabcde", "abccde", 3)); assertEquals("match_bitap: Multiple select #2.", 8, dmp.match_bitap("abcdexyzabcde", "abccde", 5)); dmp.Match_Distance = 10; // Strict location. assertEquals("match_bitap: Distance test #1.", -1, dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdefg", 24)); assertEquals("match_bitap: Distance test #2.", 0, dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdxxefg", 1)); dmp.Match_Distance = 1000; // Loose location. assertEquals("match_bitap: Distance test #3.", 0, dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdefg", 24)); } void diff_match_patch_test::testMatchMain() { // Full match. assertEquals("match_main: Equality.", 0, dmp.match_main("abcdef", "abcdef", 1000)); assertEquals("match_main: Null text.", -1, dmp.match_main("", "abcdef", 1)); assertEquals("match_main: Null pattern.", 3, dmp.match_main("abcdef", "", 3)); assertEquals("match_main: Exact match.", 3, dmp.match_main("abcdef", "de", 3)); dmp.Match_Threshold = 0.7f; assertEquals("match_main: Complex match.", 4, dmp.match_main("I am the very model of a modern major general.", " that berry ", 5)); dmp.Match_Threshold = 0.5f; } // PATCH TEST FUNCTIONS void diff_match_patch_test::testPatchObj() { // Patch Object. Patch p; p.start1 = 20; p.start2 = 21; p.length1 = 18; p.length2 = 17; p.diffs = diffList(Diff(EQUAL, "jump"), Diff(DELETE, "s"), Diff(INSERT, "ed"), Diff(EQUAL, " over "), Diff(DELETE, "the"), Diff(INSERT, "a"), Diff(EQUAL, "\nlaz")); QString strp = "@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n %0Alaz\n"; assertEquals("Patch: toString.", strp, p.toString()); } void diff_match_patch_test::testPatchFromText() { assertTrue("patch_fromText: #0.", dmp.patch_fromText("").isEmpty()); QString strp = "@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n %0Alaz\n"; assertEquals("patch_fromText: #1.", strp, dmp.patch_fromText(strp).value(0).toString()); assertEquals("patch_fromText: #2.", "@@ -1 +1 @@\n-a\n+b\n", dmp.patch_fromText("@@ -1 +1 @@\n-a\n+b\n").value(0).toString()); assertEquals("patch_fromText: #3.", "@@ -1,3 +0,0 @@\n-abc\n", dmp.patch_fromText("@@ -1,3 +0,0 @@\n-abc\n").value(0).toString()); assertEquals("patch_fromText: #4.", "@@ -0,0 +1,3 @@\n+abc\n", dmp.patch_fromText("@@ -0,0 +1,3 @@\n+abc\n").value(0).toString()); // Generates error. try { dmp.patch_fromText("Bad\nPatch\n"); throw "patch_fromText: #5"; } catch (QString ex) { // Exception expected. } } void diff_match_patch_test::testPatchToText() { QString strp = "@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n laz\n"; QList patches; patches = dmp.patch_fromText(strp); assertEquals("patch_toText: Single", strp, dmp.patch_toText(patches)); strp = "@@ -1,9 +1,9 @@\n-f\n+F\n oo+fooba\n@@ -7,9 +7,9 @@\n obar\n-,\n+.\n tes\n"; patches = dmp.patch_fromText(strp); assertEquals("patch_toText: Dual", strp, dmp.patch_toText(patches)); } void diff_match_patch_test::testPatchAddContext() { dmp.Patch_Margin = 4; Patch p; p = dmp.patch_fromText("@@ -21,4 +21,10 @@\n-jump\n+somersault\n").value(0); dmp.patch_addContext(p, "The quick brown fox jumps over the lazy dog."); assertEquals("patch_addContext: Simple case.", "@@ -17,12 +17,18 @@\n fox \n-jump\n+somersault\n s ov\n", p.toString()); p = dmp.patch_fromText("@@ -21,4 +21,10 @@\n-jump\n+somersault\n").value(0); dmp.patch_addContext(p, "The quick brown fox jumps."); assertEquals("patch_addContext: Not enough trailing context.", "@@ -17,10 +17,16 @@\n fox \n-jump\n+somersault\n s.\n", p.toString()); p = dmp.patch_fromText("@@ -3 +3,2 @@\n-e\n+at\n").value(0); dmp.patch_addContext(p, "The quick brown fox jumps."); assertEquals("patch_addContext: Not enough leading context.", "@@ -1,7 +1,8 @@\n Th\n-e\n+at\n qui\n", p.toString()); p = dmp.patch_fromText("@@ -3 +3,2 @@\n-e\n+at\n").value(0); dmp.patch_addContext(p, "The quick brown fox jumps. The quick brown fox crashes."); assertEquals("patch_addContext: Ambiguity.", "@@ -1,27 +1,28 @@\n Th\n-e\n+at\n quick brown fox jumps. \n", p.toString()); } void diff_match_patch_test::testPatchMake() { QList patches; QString text1 = "The quick brown fox jumps over the lazy dog."; QString text2 = "That quick brown fox jumped over a lazy dog."; QString expectedPatch = "@@ -1,8 +1,7 @@\n Th\n-at\n+e\n qui\n@@ -21,17 +21,18 @@\n jump\n-ed\n+s\n over \n-a\n+the\n laz\n"; // The second patch must be "-21,17 +21,18", not "-22,17 +21,18" due to rolling context. patches = dmp.patch_make(text2, text1); assertEquals("patch_make: Text2+Text1 inputs", expectedPatch, dmp.patch_toText(patches)); expectedPatch = "@@ -1,11 +1,12 @@\n Th\n-e\n+at\n quick b\n@@ -22,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n laz\n"; patches = dmp.patch_make(text1, text2); assertEquals("patch_make: Text1+Text2 inputs", expectedPatch, dmp.patch_toText(patches)); QList diffs = dmp.diff_main(text1, text2, false); patches = dmp.patch_make(diffs); assertEquals("patch_make: Diff input", expectedPatch, dmp.patch_toText(patches)); patches = dmp.patch_make(text1, diffs); assertEquals("patch_make: Text1+Diff inputs", expectedPatch, dmp.patch_toText(patches)); patches = dmp.patch_make(text1, text2, diffs); assertEquals("patch_make: Text1+Text2+Diff inputs (deprecated)", expectedPatch, dmp.patch_toText(patches)); patches = dmp.patch_make("`1234567890-=[]\\;',./", "~!@#$%^&*()_+{}|:\"<>?"); assertEquals("patch_toText: Character encoding.", "@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;',./\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n", dmp.patch_toText(patches)); diffs = diffList(Diff(DELETE, "`1234567890-=[]\\;',./"), Diff(INSERT, "~!@#$%^&*()_+{}|:\"<>?")); assertEquals("patch_fromText: Character decoding.", diffs, dmp.patch_fromText("@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;',./\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n").value(0).diffs); text1 = ""; for (int x = 0; x < 100; x++) { text1 += "abcdef"; } text2 = text1 + "123"; expectedPatch = "@@ -573,28 +573,31 @@\n cdefabcdefabcdefabcdefabcdef\n+123\n"; patches = dmp.patch_make(text1, text2); assertEquals("patch_make: Long string with repeats.", expectedPatch, dmp.patch_toText(patches)); } void diff_match_patch_test::testPatchSplitMax() { // Assumes that Match_MaxBits is 32. QList patches; patches = dmp.patch_make("abcdefghijklmnopqrstuvwxyz01234567890", "XabXcdXefXghXijXklXmnXopXqrXstXuvXwxXyzX01X23X45X67X89X0"); dmp.patch_splitMax(patches); assertEquals("patch_splitMax: #1.", "@@ -1,32 +1,46 @@\n+X\n ab\n+X\n cd\n+X\n ef\n+X\n gh\n+X\n ij\n+X\n kl\n+X\n mn\n+X\n op\n+X\n qr\n+X\n st\n+X\n uv\n+X\n wx\n+X\n yz\n+X\n 012345\n@@ -25,13 +39,18 @@\n zX01\n+X\n 23\n+X\n 45\n+X\n 67\n+X\n 89\n+X\n 0\n", dmp.patch_toText(patches)); patches = dmp.patch_make("abcdef1234567890123456789012345678901234567890123456789012345678901234567890uvwxyz", "abcdefuvwxyz"); QString oldToText = dmp.patch_toText(patches); dmp.patch_splitMax(patches); assertEquals("patch_splitMax: #2.", oldToText, dmp.patch_toText(patches)); patches = dmp.patch_make("1234567890123456789012345678901234567890123456789012345678901234567890", "abc"); dmp.patch_splitMax(patches); assertEquals("patch_splitMax: #3.", "@@ -1,32 +1,4 @@\n-1234567890123456789012345678\n 9012\n@@ -29,32 +1,4 @@\n-9012345678901234567890123456\n 7890\n@@ -57,14 +1,3 @@\n-78901234567890\n+abc\n", dmp.patch_toText(patches)); patches = dmp.patch_make("abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1", "abcdefghij , h : 1 , t : 1 abcdefghij , h : 1 , t : 1 abcdefghij , h : 0 , t : 1"); dmp.patch_splitMax(patches); assertEquals("patch_splitMax: #4.", "@@ -2,32 +2,32 @@\n bcdefghij , h : \n-0\n+1\n , t : 1 abcdef\n@@ -29,32 +29,32 @@\n bcdefghij , h : \n-0\n+1\n , t : 1 abcdef\n", dmp.patch_toText(patches)); } void diff_match_patch_test::testPatchAddPadding() { QList patches; patches = dmp.patch_make("", "test"); assertEquals("patch_addPadding: Both edges full.", "@@ -0,0 +1,4 @@\n+test\n", dmp.patch_toText(patches)); dmp.patch_addPadding(patches); assertEquals("patch_addPadding: Both edges full.", "@@ -1,8 +1,12 @@\n %01%02%03%04\n+test\n %01%02%03%04\n", dmp.patch_toText(patches)); patches = dmp.patch_make("XY", "XtestY"); assertEquals("patch_addPadding: Both edges partial.", "@@ -1,2 +1,6 @@\n X\n+test\n Y\n", dmp.patch_toText(patches)); dmp.patch_addPadding(patches); assertEquals("patch_addPadding: Both edges partial.", "@@ -2,8 +2,12 @@\n %02%03%04X\n+test\n Y%01%02%03\n", dmp.patch_toText(patches)); patches = dmp.patch_make("XXXXYYYY", "XXXXtestYYYY"); assertEquals("patch_addPadding: Both edges none.", "@@ -1,8 +1,12 @@\n XXXX\n+test\n YYYY\n", dmp.patch_toText(patches)); dmp.patch_addPadding(patches); assertEquals("patch_addPadding: Both edges none.", "@@ -5,8 +5,12 @@\n XXXX\n+test\n YYYY\n", dmp.patch_toText(patches)); } void diff_match_patch_test::testPatchApply() { dmp.Match_Distance = 1000; dmp.Match_Threshold = 0.5f; dmp.Patch_DeleteThreshold = 0.5f; QList patches; patches = dmp.patch_make("The quick brown fox jumps over the lazy dog.", "That quick brown fox jumped over a lazy dog."); QPair > results = dmp.patch_apply(patches, "The quick brown fox jumps over the lazy dog."); QVector boolArray = results.second; QString resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false") + "\t" + (boolArray[1] ? "true" : "false"); assertEquals("patch_apply: Exact match.", "That quick brown fox jumped over a lazy dog.\ttrue\ttrue", resultStr); results = dmp.patch_apply(patches, "The quick red rabbit jumps over the tired tiger."); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false") + "\t" + (boolArray[1] ? "true" : "false"); assertEquals("patch_apply: Partial match.", "That quick red rabbit jumped over a tired tiger.\ttrue\ttrue", resultStr); results = dmp.patch_apply(patches, "I am the very model of a modern major general."); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false") + "\t" + (boolArray[1] ? "true" : "false"); assertEquals("patch_apply: Failed match.", "I am the very model of a modern major general.\tfalse\tfalse", resultStr); patches = dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy"); results = dmp.patch_apply(patches, "x123456789012345678901234567890-----++++++++++-----123456789012345678901234567890y"); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false") + "\t" + (boolArray[1] ? "true" : "false"); assertEquals("patch_apply: Big delete, small change.", "xabcy\ttrue\ttrue", resultStr); patches = dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy"); results = dmp.patch_apply(patches, "x12345678901234567890---------------++++++++++---------------12345678901234567890y"); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false") + "\t" + (boolArray[1] ? "true" : "false"); assertEquals("patch_apply: Big delete, large change 1.", "xabc12345678901234567890---------------++++++++++---------------12345678901234567890y\tfalse\ttrue", resultStr); dmp.Patch_DeleteThreshold = 0.6f; patches = dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy"); results = dmp.patch_apply(patches, "x12345678901234567890---------------++++++++++---------------12345678901234567890y"); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false") + "\t" + (boolArray[1] ? "true" : "false"); assertEquals("patch_apply: Big delete, large change 2.", "xabcy\ttrue\ttrue", resultStr); dmp.Patch_DeleteThreshold = 0.5f; dmp.Match_Threshold = 0.0f; dmp.Match_Distance = 0; patches = dmp.patch_make("abcdefghijklmnopqrstuvwxyz--------------------1234567890", "abcXXXXXXXXXXdefghijklmnopqrstuvwxyz--------------------1234567YYYYYYYYYY890"); results = dmp.patch_apply(patches, "ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567890"); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false") + "\t" + (boolArray[1] ? "true" : "false"); assertEquals("Compensate for failed patch.", "ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567YYYYYYYYYY890\tfalse\ttrue", resultStr); dmp.Match_Threshold = 0.5f; dmp.Match_Distance = 1000; patches = dmp.patch_make("", "test"); QString patchStr = dmp.patch_toText(patches); dmp.patch_apply(patches, ""); assertEquals("patch_apply: No side effects.", patchStr, dmp.patch_toText(patches)); patches = dmp.patch_make("The quick brown fox jumps over the lazy dog.", "Woof"); patchStr = dmp.patch_toText(patches); dmp.patch_apply(patches, "The quick brown fox jumps over the lazy dog."); assertEquals("patch_apply: No side effects with major delete.", patchStr, dmp.patch_toText(patches)); patches = dmp.patch_make("", "test"); results = dmp.patch_apply(patches, ""); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false"); assertEquals("patch_apply: Edge exact match.", "test\ttrue", resultStr); patches = dmp.patch_make("XY", "XtestY"); results = dmp.patch_apply(patches, "XY"); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false"); assertEquals("patch_apply: Near edge exact match.", "XtestY\ttrue", resultStr); patches = dmp.patch_make("y", "y123"); results = dmp.patch_apply(patches, "x"); boolArray = results.second; resultStr = results.first + "\t" + (boolArray[0] ? "true" : "false"); assertEquals("patch_apply: Edge partial match.", "x123\ttrue", resultStr); } void diff_match_patch_test::assertEquals(const QString &strCase, int n1, int n2) { if (n1 != n2) { qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, QString::number(n1), QString::number(n2)))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertEquals(const QString &strCase, const QString &s1, const QString &s2) { if (s1 != s2) { qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, s1, s2))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertEquals(const QString &strCase, const Diff &d1, const Diff &d2) { if (d1 != d2) { qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, d1.toString(), d2.toString()))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertEquals(const QString &strCase, const QList &list1, const QList &list2) { bool fail = false; if (list1.count() == list2.count()) { int i = 0; foreach(Diff d1, list1) { Diff d2 = list2.value(i); if (d1 != d2) { fail = true; break; } i++; } } else { fail = true; } if (fail) { // Build human readable description of both lists. QString listString1 = "("; bool first = true; foreach(Diff d1, list1) { if (!first) { listString1 += ", "; } listString1 += d1.toString(); first = false; } listString1 += ")"; QString listString2 = "("; first = true; foreach(Diff d2, list2) { if (!first) { listString2 += ", "; } listString2 += d2.toString(); first = false; } listString2 += ")"; qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, listString1, listString2))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertEquals(const QString &strCase, const QList &list1, const QList &list2) { bool fail = false; if (list1.count() == list2.count()) { int i = 0; foreach(QVariant q1, list1) { QVariant q2 = list2.value(i); if (q1 != q2) { fail = true; break; } i++; } } else { fail = true; } if (fail) { // Build human readable description of both lists. QString listString1 = "("; bool first = true; foreach(QVariant q1, list1) { if (!first) { listString1 += ", "; } listString1 += q1.toString(); first = false; } listString1 += ")"; QString listString2 = "("; first = true; foreach(QVariant q2, list2) { if (!first) { listString2 += ", "; } listString2 += q2.toString(); first = false; } listString2 += ")"; qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, listString1, listString2))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertEquals(const QString &strCase, const QVariant &var1, const QVariant &var2) { if (var1 != var2) { qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, var1.toString(), var2.toString()))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertEquals(const QString &strCase, const QMap &m1, const QMap &m2) { QMapIterator i1(m1), i2(m2); while (i1.hasNext() && i2.hasNext()) { i1.next(); i2.next(); if (i1.key() != i2.key() || i1.value() != i2.value()) { qDebug(qPrintable(QString("%1 FAIL\nExpected: (%2, %3)\nActual: (%4, %5)") .arg(strCase, QString(i1.key()), QString::number(i1.value()), QString(i2.key()), QString::number(i2.value())))); throw strCase; } } if (i1.hasNext()) { i1.next(); qDebug(qPrintable(QString("%1 FAIL\nExpected: (%2, %3)\nActual: none") .arg(strCase, QString(i1.key()), QString::number(i1.value())))); throw strCase; } if (i2.hasNext()) { i2.next(); qDebug(qPrintable(QString("%1 FAIL\nExpected: none\nActual: (%2, %3)") .arg(strCase, QString(i2.key()), QString::number(i2.value())))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertEquals(const QString &strCase, const QStringList &list1, const QStringList &list2) { if (list1 != list2) { qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, list1.join(","), list2.join(",")))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertTrue(const QString &strCase, bool value) { if (!value) { qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, "true", "false"))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } void diff_match_patch_test::assertFalse(const QString &strCase, bool value) { if (value) { qDebug(qPrintable(QString("%1 FAIL\nExpected: %2\nActual: %3") .arg(strCase, "false", "true"))); throw strCase; } qDebug(qPrintable(QString("%1 OK").arg(strCase))); } // Construct the two texts which made up the diff originally. QStringList diff_match_patch_test::diff_rebuildtexts(QList diffs) { QStringList text; text << QString("") << QString(""); foreach (Diff myDiff, diffs) { if (myDiff.operation != INSERT) { text[0] += myDiff.text; } if (myDiff.operation != DELETE) { text[1] += myDiff.text; } } return text; } void diff_match_patch_test::assertNull(const QString &strCase, const QStringList &list) { if (!list.isEmpty()) { throw strCase; } } void diff_match_patch_test::assertNull(const QString &strCase, const QList &list) { if (!list.isEmpty()) { throw strCase; } } // Private function for quickly building lists of diffs. QList diff_match_patch_test::diffList(Diff d1, Diff d2, Diff d3, Diff d4, Diff d5, Diff d6, Diff d7, Diff d8, Diff d9, Diff d10) { QList listRet; if (d1.operation == EQUAL && d1.text == NULL) { return listRet; } listRet << d1; if (d2.operation == EQUAL && d2.text == NULL) { return listRet; } listRet << d2; if (d3.operation == EQUAL && d3.text == NULL) { return listRet; } listRet << d3; if (d4.operation == EQUAL && d4.text == NULL) { return listRet; } listRet << d4; if (d5.operation == EQUAL && d5.text == NULL) { return listRet; } listRet << d5; if (d6.operation == EQUAL && d6.text == NULL) { return listRet; } listRet << d6; if (d7.operation == EQUAL && d7.text == NULL) { return listRet; } listRet << d7; if (d8.operation == EQUAL && d8.text == NULL) { return listRet; } listRet << d8; if (d9.operation == EQUAL && d9.text == NULL) { return listRet; } listRet << d9; if (d10.operation == EQUAL && d10.text == NULL) { return listRet; } listRet << d10; return listRet; } /* Compile instructions for MinGW and QT4 on Windows: qmake -project qmake mingw32-make g++ -o diff_match_patch_test debug\diff_match_patch_test.o debug\diff_match_patch.o \qt4\lib\libQtCore4.a diff_match_patch_test.exe */ ================================================ FILE: liteidex/src/3rdparty/diff_match_patch/diff_match_patch_test.h ================================================ /* * Copyright 2008 Google Inc. All Rights Reserved. * Author: fraser@google.com (Neil Fraser) * Author: mikeslemmer@gmail.com (Mike Slemmer) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Diff Match and Patch -- Test Harness * http://code.google.com/p/google-diff-match-patch/ */ #ifndef DIFF_MATCH_PATCH_TEST_H #define DIFF_MATCH_PATCH_TEST_H class diff_match_patch_test { public: diff_match_patch_test(); void run_all_tests(); // DIFF TEST FUNCTIONS void testDiffCommonPrefix(); void testDiffCommonSuffix(); void testDiffHalfmatch(); void testDiffLinesToChars(); void testDiffCharsToLines(); void testDiffCleanupMerge(); void testDiffCleanupSemanticLossless(); void testDiffCleanupSemantic(); void testDiffCleanupEfficiency(); void testDiffPrettyHtml(); void testDiffText(); void testDiffDelta(); void testDiffXIndex(); void testDiffLevenshtein(); void testDiffPath(); void testDiffMain(); // MATCH TEST FUNCTIONS void testMatchAlphabet(); void testMatchBitap(); void testMatchMain(); // PATCH TEST FUNCTIONS void testPatchObj(); void testPatchFromText(); void testPatchToText(); void testPatchAddContext(); void testPatchMake(); void testPatchSplitMax(); void testPatchAddPadding(); void testPatchApply(); private: diff_match_patch dmp; // Define equality. void assertEquals(const QString &strCase, int n1, int n2); void assertEquals(const QString &strCase, const QString &s1, const QString &s2); void assertEquals(const QString &strCase, const Diff &d1, const Diff &d2); void assertEquals(const QString &strCase, const QList &list1, const QList &list2); void assertEquals(const QString &strCase, const QList &list1, const QList &list2); void assertEquals(const QString &strCase, const QVariant &var1, const QVariant &var2); void assertEquals(const QString &strCase, const QMap &m1, const QMap &m2); void assertEquals(const QString &strCase, const QStringList &list1, const QStringList &list2); void assertTrue(const QString &strCase, bool value); void assertFalse(const QString &strCase, bool value); void assertNull(const QString &strCase, const QStringList &list); void assertNull(const QString &strCase, const QList &list); // Construct the two texts which made up the diff originally. QStringList diff_rebuildtexts(QList diffs); // Private function for quickly building lists of diffs. QList diffList( Diff d1 = Diff(EQUAL, NULL), Diff d2 = Diff(EQUAL, NULL), Diff d3 = Diff(EQUAL, NULL), Diff d4 = Diff(EQUAL, NULL), Diff d5 = Diff(EQUAL, NULL), Diff d6 = Diff(EQUAL, NULL), Diff d7 = Diff(EQUAL, NULL), Diff d8 = Diff(EQUAL, NULL), Diff d9 = Diff(EQUAL, NULL), Diff d10 = Diff(EQUAL, NULL)); }; #endif // DIFF_MATCH_PATCH_TEST_H ================================================ FILE: liteidex/src/3rdparty/elidedlabel/elidedlabel.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ** the names of its contributors may be used to endorse or promote ** products derived from this software without specific prior written ** permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "elidedlabel.h" #include #include #include ElidedLabel::ElidedLabel(QWidget *parent) : QFrame(parent), elided(false), m_elideMode(Qt::ElideRight) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); } //! [0] ElidedLabel::ElidedLabel(const QString &text, QWidget *parent) : QFrame(parent) , elided(false) , content(text) , m_elideMode(Qt::ElideRight) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); } //! [0] //! [1] void ElidedLabel::setText(const QString &newText) { content = newText; update(); } void ElidedLabel::setElideMode(Qt::TextElideMode mode) { m_elideMode = mode; update(); } Qt::TextElideMode ElidedLabel::elideMode() const { return m_elideMode; } //! [1] //! [2] void ElidedLabel::paintEvent(QPaintEvent *event) { QFrame::paintEvent(event); QPainter painter(this); QFontMetrics fontMetrics = painter.fontMetrics(); bool didElide = false; int lineSpacing = fontMetrics.lineSpacing(); int y = (this->height()-lineSpacing)/2; QTextLayout textLayout(content, painter.font()); textLayout.beginLayout(); forever { QTextLine line = textLayout.createLine(); if (!line.isValid()) break; line.setLineWidth(width()); int nextLineY = y + lineSpacing; if (height() >= nextLineY + lineSpacing) { line.draw(&painter, QPoint(0, y)); y = nextLineY; //! [2] //! [3] } else { QString lastLine = content.mid(line.textStart()); QString elidedLastLine = fontMetrics.elidedText(lastLine, m_elideMode, width()); painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine); line = textLayout.createLine(); didElide = line.isValid(); break; } } textLayout.endLayout(); //! [3] //! [4] if (didElide != elided) { elided = didElide; emit elisionChanged(didElide); } } //! [4] ================================================ FILE: liteidex/src/3rdparty/elidedlabel/elidedlabel.h ================================================ /**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ** the names of its contributors may be used to endorse or promote ** products derived from this software without specific prior written ** permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef ELIDEDLABEL_H #define ELIDEDLABEL_H #include #include #include #include #include //! [0] class ElidedLabel : public QFrame { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText) Q_PROPERTY(bool isElided READ isElided) public: ElidedLabel(QWidget *parent = 0); ElidedLabel(const QString &text, QWidget *parent = 0); void setText(const QString &text); const QString & text() const { return content; } bool isElided() const { return elided; } void setElideMode(Qt::TextElideMode mode); Qt::TextElideMode elideMode() const; protected: void paintEvent(QPaintEvent *event); signals: void elisionChanged(bool elided); private: bool elided; QString content; Qt::TextElideMode m_elideMode; }; //! [0] #endif // TEXTWRAPPINGWIDGET_H ================================================ FILE: liteidex/src/3rdparty/elidedlabel/elidedlabel.pri ================================================ LIBS *= -l$$qtLibraryName(elidedlabel) ================================================ FILE: liteidex/src/3rdparty/elidedlabel/elidedlabel.pro ================================================ TARGET = elidedlabel TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += \ elidedlabel.h SOURCES += \ elidedlabel.cpp RESOURCES += ================================================ FILE: liteidex/src/3rdparty/fakevim/.gitignore ================================================ fakevim_python.pro *.so.* sip* # Created by https://www.gitignore.io ### C++ ### # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app ### Qt ### # C++ objects and libs *.slo *.lo *.o *.a *.la *.lai *.so *.dll *.dylib # Qt-es /.qmake.cache /.qmake.stash *.pro.user *.pro.user.* *.moc moc_*.cpp qrc_*.cpp ui_*.h Makefile* *-build-* # QtCreator *.autosave #QtCtreator Qml *.qmlproject.user *.qmlproject.user.* ### Python ### # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # PyBuilder target/ ================================================ FILE: liteidex/src/3rdparty/fakevim/LGPL_EXCEPTION.TXT ================================================ Digia Qt LGPL Exception version 1.1 As an additional permission to the GNU Lesser General Public License version 2.1, the object code form of a "work that uses the Library" may incorporate material from a header file that is part of the Library. You may distribute such object code under terms of your choice, provided that: (i) the header files of the Library have not been modified; and (ii) the incorporated material is limited to numerical parameters, data structure layouts, accessors, macros, inline functions and templates; and (iii) you comply with the terms of Section 6 of the GNU Lesser General Public License version 2.1. Moreover, you may apply this exception to a modified version of the Library, provided that such modification does not involve copying material from the Library into the modified Library's header files unless such material is limited to (i) numerical parameters; (ii) data structure layouts; (iii) accessors; and (iv) small macros, templates and inline functions of five lines or less in length. Furthermore, you are not required to apply this additional permission to a modified version of the Library. ================================================ FILE: liteidex/src/3rdparty/fakevim/LICENSE.LGPL ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: liteidex/src/3rdparty/fakevim/README.md ================================================ FakeVim ======= FakeVim is library to emulate Vim in QTextEdit, QPlainTextEdit and possibly other Qt widgets. Build ----- To build the library and simple example editor (in `test` directory), run following commands. qmake make Supported Features ------------------ Most of supported commands can be followed by motion command or executed in visual mode, work with registers or can be prefixed with number of repetitions. Here is list of emulated commands with description where it can diverge from Vim in functionality. ### Modes * normal * insert and replace * visual * command line (`:`) ### Normal and Visual Modes * basic movement -- `h`/`j`/`k`/`l`, ``, ``, ``, ``, `gg`, `G`, `0`, `^`, `$` etc. * word movement -- `w`, `e`, `b` etc. * "inner/a" movement -- `ciw`, `3daw`, `ya{` etc. * `f`, `t` movement * `[`, `]` movement * `{`, `}` -- paragraph movement * delete/change/yank/paste with register * undo/redo * ``, `` -- increase or decrease number in decimal/octal/hexadecimal format (e.g. `128` on or before "0x0ff" changes it to "0x17f") * `.` -- repeat last change * `/search`, `?search`, `*`, `#`, `n`, `N` -- most of regular expression syntax used in Vim except `\<` and `\>` just is the same as `\b` in QRegExp * `@`, `q` (macro recording, execution) -- special keys are saved as `` * marks * `gv` -- last visual selection; can differ if text is edited around it * indentation -- `=`, `<<`, `>>` etc. with movement, count and in visual mode * "to upper/lower" -- `~`, `gU`, `gu` etc. * `i`, `a`, `o`, `I`, `A`, `O` -- enter insert mode * scroll window -- `zt`, `zb`, `zz` etc. * wrap line movement -- `gj`, `gk`, `g0`, `g^`, `g$` ### Command Line Mode * `:map`, `:unmap`, `:inoremap` etc. * `:source` -- very basic line-by-line sourcing of vimrc files * `:substitute` -- substitute expression in range * `:'<,'>!cmd` -- filter through an external command (e.g. sort lines in file with `:%!sort`) * `:.!cmd` -- insert standard output of an external command * `:read` * `:yank`, `:delete`, `:change` * `:move`, `:join` * `:20` -- go to address * `:history` * `:registers`, `:display` * `:nohlsearch` * `:undo`, `:redo` * `:normal` * `:<`, `:>` ### Insert Mode * `` -- execute single command and return to insert mode * `` -- insert raw character * `` -- toggle replace mode ### Options (:set ...) * `autoindent` * `clipboard` * `backspace` * `expandtab` * `hlsearch` * `ignorecase` * `incsearch` * `indent` * `iskeyword` * `scrolloff` * `shiftwidth` * `showcmd` * `smartcase` * `smartindent` * `smarttab` * `startofline` * `tabstop` * `tildeop` * `wrapscan` Example Vimrc ------------- " highlight matched set hlsearch " case insensitive search set ignorecase set smartcase " search while typing set incsearch " wrap-around when searching set wrapscan " show pressed keys in lower right corner set showcmd " tab -> spaces set expandtab set tabstop=4 set shiftwidth=4 " keep a 5 line buffer for the cursor from top/bottom of window set scrolloff=5 " X11 clipboard set clipboard=unnamed " use ~ with movement set tildeop " mappings nnoremap ; : inoremap jj " clear highlighted search term on space noremap :nohls " reselect visual block after indent vnoremap < >gv " MOVE LINE/BLOCK nnoremap :m+== nnoremap :m-2== inoremap :m+==gi inoremap :m-2==gi vnoremap :m'>+gv=gv vnoremap :m-2gv=gv Implementation -------------- There are appropriate signals emitted for command which has to be processed by the underlying editor widget (folds, windows, tabs, command line, messages etc.). See example in `test/` directory or implementation of FakeVim plugin in Qt Creator IDE. ================================================ FILE: liteidex/src/3rdparty/fakevim/fakevim/fakevim.pri ================================================ include($$PWD/utils/utils.pri) DEFINES += FAKEVIM_STANDALONE INCLUDEPATH += $$PWD SOURCES += $$PWD/fakevimhandler.cpp \ $$PWD/fakevimactions.cpp HEADERS += $$PWD/fakevimhandler.h \ $$PWD/fakevimactions.h CONFIG += qt QT += core gui ================================================ FILE: liteidex/src/3rdparty/fakevim/fakevim/fakevim.pro ================================================ TARGET = fakevim TEMPLATE = lib CONFIG += staticlib include(../../../liteideutils.pri) include(fakevim.pri) ================================================ FILE: liteidex/src/3rdparty/fakevim/fakevim/fakevimactions.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "fakevimactions.h" #include "fakevimhandler.h" // Please do not add any direct dependencies to other Qt Creator code here. // Instead emit signals and let the FakeVimPlugin channel the information to // Qt Creator. The idea is to keep this file here in a "clean" state that // allows easy reuse with any QTextEdit or QPlainTextEdit derived class. #include #include #include #include #ifdef FAKEVIM_STANDALONE using namespace FakeVim::Internal::Utils; #else using namespace Utils; #endif /////////////////////////////////////////////////////////////////////// // // FakeVimSettings // /////////////////////////////////////////////////////////////////////// namespace FakeVim { namespace Internal { typedef QLatin1String _; #ifdef FAKEVIM_STANDALONE namespace Utils { SavedAction::SavedAction(QObject *parent) : QObject(parent) { } void SavedAction::setValue(const QVariant &value) { m_value = value; } QVariant SavedAction::value() const { return m_value; } void SavedAction::setDefaultValue(const QVariant &value) { m_defaultValue = value; } QVariant SavedAction::defaultValue() const { return m_defaultValue; } void SavedAction::setSettingsKey(const QString &key) { m_settingsKey = key; } QString SavedAction::settingsKey() const { return m_settingsKey; } } // namespace Utils #endif // FAKEVIM_STANDALONE FakeVimSettings::FakeVimSettings() {} FakeVimSettings::~FakeVimSettings() { qDeleteAll(m_items); } void FakeVimSettings::insertItem(int code, SavedAction *item, const QString &longName, const QString &shortName) { QTC_ASSERT(!m_items.contains(code), qDebug() << code; return); m_items[code] = item; if (!longName.isEmpty()) { m_nameToCode[longName] = code; m_codeToName[code] = longName; } if (!shortName.isEmpty()) m_nameToCode[shortName] = code; } #ifndef FAKEVIM_STANDALONE void FakeVimSettings::readSettings(QSettings *settings) { foreach (SavedAction *item, m_items) item->readSettings(settings); } void FakeVimSettings::writeSettings(QSettings *settings) { foreach (SavedAction *item, m_items) item->writeSettings(settings); } #endif // FAKEVIM_STANDALONE SavedAction *FakeVimSettings::item(int code) { QTC_ASSERT(m_items.value(code, 0), qDebug() << "CODE: " << code; return 0); return m_items.value(code, 0); } SavedAction *FakeVimSettings::item(const QString &name) { return m_items.value(m_nameToCode.value(name, -1), 0); } QString FakeVimSettings::trySetValue(const QString &name, const QString &value) { int code = m_nameToCode.value(name, -1); if (code == -1) return FakeVimHandler::tr("Unknown option: %1").arg(name); if (code == ConfigTabStop || code == ConfigShiftWidth) { if (value.toInt() <= 0) return FakeVimHandler::tr("Argument must be positive: %1=%2") .arg(name).arg(value); } SavedAction *act = item(code); if (!act) return FakeVimHandler::tr("Unknown option: %1").arg(name); act->setValue(value); return QString(); } SavedAction *createAction(FakeVimSettings *instance, int code, const QVariant &value, const QString &settingsKey = QString(), const QString &shortKey = QString()) { SavedAction *item = new SavedAction(instance); item->setValue(value); #ifndef FAKEVIM_STANDALONE item->setSettingsKey(_("FakeVim"), settingsKey); item->setDefaultValue(value); item->setCheckable( value.canConvert() ); #endif instance->insertItem(code, item, settingsKey.toLower(), shortKey); return item; } FakeVimSettings *theFakeVimSettings() { static FakeVimSettings *s = 0; if (s) return s; s = new FakeVimSettings; // Specific FakeVim settings createAction(s, ConfigReadVimRc, false, _("ReadVimRc")); createAction(s, ConfigVimRcPath, QString(), _("VimRcPath")); #ifndef FAKEVIM_STANDALONE createAction(s, ConfigUseFakeVim, false, _("UseFakeVim")); s->item(ConfigUseFakeVim)->setText(QCoreApplication::translate("FakeVim::Internal", "Use Vim-style Editing")); s->item(ConfigReadVimRc)->setText(QCoreApplication::translate("FakeVim::Internal", "Read .vimrc")); s->item(ConfigVimRcPath)->setText(QCoreApplication::translate("FakeVim::Internal", "Path to .vimrc")); #endif createAction(s, ConfigShowMarks, false, _("ShowMarks"), _("sm")); createAction(s, ConfigPassControlKey, false, _("PassControlKey"), _("pck")); createAction(s, ConfigPassKeys, true, _("PassKeys"), _("pk")); // Emulated Vim setting createAction(s, ConfigStartOfLine, true, _("StartOfLine"), _("sol")); createAction(s, ConfigTabStop, 8, _("TabStop"), _("ts")); createAction(s, ConfigSmartTab, false, _("SmartTab"), _("sta")); createAction(s, ConfigHlSearch, true, _("HlSearch"), _("hls")); createAction(s, ConfigShiftWidth, 8, _("ShiftWidth"), _("sw")); createAction(s, ConfigExpandTab, false, _("ExpandTab"), _("et")); createAction(s, ConfigAutoIndent, false, _("AutoIndent"), _("ai")); createAction(s, ConfigSmartIndent, false, _("SmartIndent"), _("si")); createAction(s, ConfigIncSearch, true, _("IncSearch"), _("is")); createAction(s, ConfigUseCoreSearch, false, _("UseCoreSearch"), _("ucs")); createAction(s, ConfigSmartCase, false, _("SmartCase"), _("scs")); createAction(s, ConfigIgnoreCase, false, _("IgnoreCase"), _("ic")); createAction(s, ConfigWrapScan, true, _("WrapScan"), _("ws")); createAction(s, ConfigTildeOp, false, _("TildeOp"), _("top")); createAction(s, ConfigShowCmd, true, _("ShowCmd"), _("sc")); createAction(s, ConfigRelativeNumber, false, _("RelativeNumber"),_("rnu")); createAction(s, ConfigScrollOff, 0, _("ScrollOff"), _("so")); createAction(s, ConfigBackspace, _("indent,eol,start"), _("ConfigBackspace"), _("bs")); createAction(s, ConfigIsKeyword, _("@,48-57,_,192-255,a-z,A-Z"), _("IsKeyword"), _("isk")); createAction(s, ConfigClipboard, QString(), _("Clipboard"), _("cb")); return s; } SavedAction *theFakeVimSetting(int code) { return theFakeVimSettings()->item(code); } } // namespace Internal } // namespace FakeVim ================================================ FILE: liteidex/src/3rdparty/fakevim/fakevim/fakevimactions.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef FAKEVIM_ACTIONS_H #define FAKEVIM_ACTIONS_H #ifndef FAKEVIM_STANDALONE # include #endif #include #include #include #include namespace FakeVim { namespace Internal { #ifdef FAKEVIM_STANDALONE namespace Utils { class SavedAction : public QObject { Q_OBJECT public: SavedAction(QObject *parent); void setValue(const QVariant &value); QVariant value() const; void setDefaultValue(const QVariant &value); QVariant defaultValue() const; void setSettingsKey(const QString &key); QString settingsKey() const; QVariant m_value; QVariant m_defaultValue; QString m_settingsKey; }; } // namespace Utils #endif // FAKEVIM_STANDALONE enum FakeVimSettingsCode { ConfigUseFakeVim, ConfigReadVimRc, ConfigVimRcPath, ConfigStartOfLine, ConfigHlSearch, ConfigTabStop, ConfigSmartTab, ConfigShiftWidth, ConfigExpandTab, ConfigAutoIndent, ConfigSmartIndent, ConfigIncSearch, ConfigUseCoreSearch, ConfigSmartCase, ConfigIgnoreCase, ConfigWrapScan, // command ~ behaves as g~ ConfigTildeOp, // indent allow backspacing over autoindent // eol allow backspacing over line breaks (join lines) // start allow backspacing over the start of insert; CTRL-W and CTRL-U // stop once at the start of insert. ConfigBackspace, // @,48-57,_,192-255 ConfigIsKeyword, // other actions ConfigShowMarks, ConfigPassControlKey, ConfigPassKeys, ConfigClipboard, ConfigShowCmd, ConfigScrollOff, ConfigRelativeNumber }; class FakeVimSettings : public QObject { Q_OBJECT public: FakeVimSettings(); ~FakeVimSettings(); void insertItem(int code, Utils::SavedAction *item, const QString &longname = QString(), const QString &shortname = QString()); Utils::SavedAction *item(int code); Utils::SavedAction *item(const QString &name); QString trySetValue(const QString &name, const QString &value); #ifndef FAKEVIM_STANDALONE void readSettings(QSettings *settings); void writeSettings(QSettings *settings); #endif private: QHash m_items; QHash m_nameToCode; QHash m_codeToName; }; FakeVimSettings *theFakeVimSettings(); Utils::SavedAction *theFakeVimSetting(int code); } // namespace Internal } // namespace FakeVim #endif // FAKEVIM_ACTTIONS_H ================================================ FILE: liteidex/src/3rdparty/fakevim/fakevim/fakevimhandler.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // // ATTENTION: // // 1 Please do not add any direct dependencies to other Qt Creator code here. // Instead emit signals and let the FakeVimPlugin channel the information to // Qt Creator. The idea is to keep this file here in a "clean" state that // allows easy reuse with any QTextEdit or QPlainTextEdit derived class. // // 2 There are a few auto tests located in ../../../tests/auto/fakevim. // Commands that are covered there are marked as "// tested" below. // // 3 Some conventions: // // Use 1 based line numbers and 0 based column numbers. Even though // the 1 based line are not nice it matches vim's and QTextEdit's 'line' // concepts. // // Do not pass QTextCursor etc around unless really needed. Convert // early to line/column. // // A QTextCursor is always between characters, whereas vi's cursor is always // over a character. FakeVim interprets the QTextCursor to be over the character // to the right of the QTextCursor's position(). // // A current "region of interest" // spans between anchor(), (i.e. the character below anchor()), and // position(). The character below position() is not included // if the last movement command was exclusive (MoveExclusive). // #include "fakevimhandler.h" #include "fakevimactions.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define DEBUG_KEY 1 #if DEBUG_KEY # define KEY_DEBUG(s) qDebug() << s #else # define KEY_DEBUG(s) #endif //#define DEBUG_UNDO 1 #if DEBUG_UNDO # define UNDO_DEBUG(s) qDebug() << "REV" << revision() << s #else # define UNDO_DEBUG(s) #endif using namespace Utils; #ifdef FAKEVIM_STANDALONE using namespace FakeVim::Internal::Utils; #endif namespace FakeVim { namespace Internal { /////////////////////////////////////////////////////////////////////// // // FakeVimHandler // /////////////////////////////////////////////////////////////////////// #define StartOfLine QTextCursor::StartOfLine #define EndOfLine QTextCursor::EndOfLine #define MoveAnchor QTextCursor::MoveAnchor #define KeepAnchor QTextCursor::KeepAnchor #define Up QTextCursor::Up #define Down QTextCursor::Down #define Right QTextCursor::Right #define Left QTextCursor::Left #define EndOfDocument QTextCursor::End #define StartOfDocument QTextCursor::Start #define NextBlock QTextCursor::NextBlock #define ParagraphSeparator QChar::ParagraphSeparator #define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s) #define MetaModifier // Use HostOsInfo::controlModifier() instead #define ControlModifier // Use HostOsInfo::controlModifier() instead typedef QLatin1String _; /* Clipboard MIME types used by Vim. */ static const QString vimMimeText = _("_VIM_TEXT"); static const QString vimMimeTextEncoded = _("_VIMENC_TEXT"); using namespace Qt; /*! A \e Mode represents one of the basic modes of operation of FakeVim. */ enum Mode { InsertMode, ReplaceMode, CommandMode, ExMode }; enum BlockInsertMode { NoneBlockInsertMode, AppendBlockInsertMode, AppendToEndOfLineBlockInsertMode, InsertBlockInsertMode, ChangeBlockInsertMode }; /*! A \e SubMode is used for things that require one more data item and are 'nested' behind a \l Mode. */ enum SubMode { NoSubMode, ChangeSubMode, // Used for c DeleteSubMode, // Used for d FilterSubMode, // Used for ! IndentSubMode, // Used for = RegisterSubMode, // Used for " ShiftLeftSubMode, // Used for < ShiftRightSubMode, // Used for > InvertCaseSubMode, // Used for g~ DownCaseSubMode, // Used for gu UpCaseSubMode, // Used for gU WindowSubMode, // Used for Ctrl-w YankSubMode, // Used for y ZSubMode, // Used for z CapitalZSubMode, // Used for Z ReplaceSubMode, // Used for r MacroRecordSubMode, // Used for q MacroExecuteSubMode, // Used for @ CtrlVSubMode // Used for Ctrl-v in insert mode }; /*! A \e SubSubMode is used for things that require one more data item and are 'nested' behind a \l SubMode. */ enum SubSubMode { NoSubSubMode, FtSubSubMode, // Used for f, F, t, T. MarkSubSubMode, // Used for m. BackTickSubSubMode, // Used for `. TickSubSubMode, // Used for '. TextObjectSubSubMode, // Used for thing like iw, aW, as etc. ZSubSubMode, // Used for zj, zk OpenSquareSubSubMode, // Used for [{, {(, [z CloseSquareSubSubMode, // Used for ]}, ]), ]z SearchSubSubMode, CtrlVUnicodeSubSubMode // Used for Ctrl-v based unicode input }; enum VisualMode { NoVisualMode, VisualCharMode, VisualLineMode, VisualBlockMode }; enum MoveType { MoveExclusive, MoveInclusive, MoveLineWise }; /*! \enum RangeMode The \e RangeMode serves as a means to define how the "Range" between the \l cursor and the \l anchor position is to be interpreted. \value RangeCharMode Entered by pressing \key v. The range includes all characters between cursor and anchor. \value RangeLineMode Entered by pressing \key V. The range includes all lines between the line of the cursor and the line of the anchor. \value RangeLineModeExclusice Like \l RangeLineMode, but keeps one newline when deleting. \value RangeBlockMode Entered by pressing \key Ctrl-v. The range includes all characters with line and column coordinates between line and columns coordinates of cursor and anchor. \value RangeBlockAndTailMode Like \l RangeBlockMode, but also includes all characters in the affected lines up to the end of these lines. */ enum EventResult { EventHandled, EventUnhandled, EventCancelled, // Event is handled but a sub mode was cancelled. EventPassedToCore }; struct CursorPosition { CursorPosition() : line(-1), column(-1) {} CursorPosition(int block, int column) : line(block), column(column) {} explicit CursorPosition(const QTextCursor &tc) : line(tc.block().blockNumber()), column(tc.positionInBlock()) {} CursorPosition(const QTextDocument *document, int position) { QTextBlock block = document->findBlock(position); line = block.blockNumber(); column = position - block.position(); } bool isValid() const { return line >= 0 && column >= 0; } bool operator>(const CursorPosition &other) const { return line > other.line || column > other.column; } bool operator==(const CursorPosition &other) const { return line == other.line && column == other.column; } bool operator!=(const CursorPosition &other) const { return !operator==(other); } int line; // Line in document (from 0, folded lines included). int column; // Position on line. }; QDebug operator<<(QDebug ts, const CursorPosition &pos) { return ts << "(line: " << pos.line << ", column: " << pos.column << ")"; } class Mark { public: Mark(const CursorPosition &pos = CursorPosition(), const QString &fileName = QString()) : m_position(pos), m_fileName(fileName) {} bool isValid() const { return m_position.isValid(); } bool isLocal(const QString &localFileName) const { return m_fileName.isEmpty() || m_fileName == localFileName; } /* Return position of mark within given document. * If saved line number is too big, mark position is at the end of document. * If line number is in document but column is too big, mark position is at the end of line. */ CursorPosition position(const QTextDocument *document) const { QTextBlock block = document->findBlockByNumber(m_position.line); CursorPosition pos; if (block.isValid()) { pos.line = m_position.line; pos.column = qMax(0, qMin(m_position.column, block.length() - 2)); } else if (document->isEmpty()) { pos.line = 0; pos.column = 0; } else { pos.line = document->blockCount() - 1; pos.column = qMax(0, document->lastBlock().length() - 2); } return pos; } const QString &fileName() const { return m_fileName; } private: CursorPosition m_position; QString m_fileName; }; typedef QHash Marks; typedef QHashIterator MarksIterator; struct State { State() : revision(-1), position(), marks(), lastVisualMode(NoVisualMode), lastVisualModeInverted(false) {} State(int revision, const CursorPosition &position, const Marks &marks, VisualMode lastVisualMode, bool lastVisualModeInverted) : revision(revision), position(position), marks(marks), lastVisualMode(lastVisualMode), lastVisualModeInverted(lastVisualModeInverted) {} bool isValid() const { return position.isValid(); } int revision; CursorPosition position; Marks marks; VisualMode lastVisualMode; bool lastVisualModeInverted; }; struct Column { Column(int p, int l) : physical(p), logical(l) {} int physical; // Number of characters in the data. int logical; // Column on screen. }; QDebug operator<<(QDebug ts, const Column &col) { return ts << "(p: " << col.physical << ", l: " << col.logical << ")"; } struct Register { Register() : rangemode(RangeCharMode) {} Register(const QString &c) : contents(c), rangemode(RangeCharMode) {} Register(const QString &c, RangeMode m) : contents(c), rangemode(m) {} QString contents; RangeMode rangemode; }; QDebug operator<<(QDebug ts, const Register ®) { return ts << reg.contents; } struct SearchData { SearchData() { forward = true; highlightMatches = true; } QString needle; bool forward; bool highlightMatches; }; // If string begins with given prefix remove it with trailing spaces and return true. static bool eatString(const char *prefix, QString *str) { if (!str->startsWith(_(prefix))) return false; *str = str->mid(strlen(prefix)).trimmed(); return true; } static QRegExp vimPatternToQtPattern(QString needle, bool ignoreCaseOption, bool smartCaseOption) { /* Transformations (Vim regexp -> QRegExp): * \a -> [A-Za-z] * \A -> [^A-Za-z] * \h -> [A-Za-z_] * \H -> [^A-Za-z_] * \l -> [a-z] * \L -> [^a-z] * \o -> [0-7] * \O -> [^0-7] * \u -> [A-Z] * \U -> [^A-Z] * \x -> [0-9A-Fa-f] * \X -> [^0-9A-Fa-f] * * \< -> \b * \> -> \b * [] -> \[\] * \= -> ? * * (...) <-> \(...\) * {...} <-> \{...\} * | <-> \| * ? <-> \? * + <-> \+ * \{...} -> {...} * * \c - set ignorecase for rest * \C - set noignorecase for rest */ // FIXME: Option smartcase should be used only if search was typed by user. bool ignorecase = ignoreCaseOption && !(smartCaseOption && needle.contains(QRegExp(_("[A-Z]")))); QString pattern; pattern.reserve(2 * needle.size()); bool escape = false; bool brace = false; bool embraced = false; bool range = false; bool curly = false; foreach (const QChar &c, needle) { if (brace) { brace = false; if (c == QLatin1Char(']')) { pattern.append(_("\\[\\]")); continue; } pattern.append(QLatin1Char('[')); escape = true; embraced = true; } if (embraced) { if (range) { QChar c2 = pattern[pattern.size() - 2]; pattern.remove(pattern.size() - 2, 2); pattern.append(c2.toUpper() + QLatin1Char('-') + c.toUpper()); pattern.append(c2.toLower() + QLatin1Char('-') + c.toLower()); range = false; } else if (escape) { escape = false; pattern.append(c); } else if (c == QLatin1Char('\\')) { escape = true; } else if (c == QLatin1Char(']')) { pattern.append(QLatin1Char(']')); embraced = false; } else if (c == QLatin1Char('-')) { range = ignorecase && pattern[pattern.size() - 1].isLetter(); pattern.append(QLatin1Char('-')); } else if (c.isLetter() && ignorecase) { pattern.append(c.toLower()).append(c.toUpper()); } else { pattern.append(c); } } else if (QString::fromLatin1("(){}+|?").indexOf(c) != -1) { if (c == QLatin1Char('{')) { curly = escape; } else if (c == QLatin1Char('}') && curly) { curly = false; escape = true; } if (escape) escape = false; else pattern.append(QLatin1Char('\\')); pattern.append(c); } else if (escape) { // escape expression escape = false; if (c == QLatin1Char('<') || c == QLatin1Char('>')) pattern.append(_("\\b")); else if (c == QLatin1Char('a')) pattern.append(_("[a-zA-Z]")); else if (c == QLatin1Char('A')) pattern.append(_("[^a-zA-Z]")); else if (c == QLatin1Char('h')) pattern.append(_("[A-Za-z_]")); else if (c == QLatin1Char('H')) pattern.append(_("[^A-Za-z_]")); else if (c == QLatin1Char('c') || c == QLatin1Char('C')) ignorecase = (c == QLatin1Char('c')); else if (c == QLatin1Char('l')) pattern.append(_("[a-z]")); else if (c == QLatin1Char('L')) pattern.append(_("[^a-z]")); else if (c == QLatin1Char('o')) pattern.append(_("[0-7]")); else if (c == QLatin1Char('O')) pattern.append(_("[^0-7]")); else if (c == QLatin1Char('u')) pattern.append(_("[A-Z]")); else if (c == QLatin1Char('U')) pattern.append(_("[^A-Z]")); else if (c == QLatin1Char('x')) pattern.append(_("[0-9A-Fa-f]")); else if (c == QLatin1Char('X')) pattern.append(_("[^0-9A-Fa-f]")); else if (c == QLatin1Char('=')) pattern.append(_("?")); else pattern.append(QLatin1Char('\\') + c); } else { // unescaped expression if (c == QLatin1Char('\\')) escape = true; else if (c == QLatin1Char('[')) brace = true; else if (c.isLetter() && ignorecase) pattern.append(QLatin1Char('[') + c.toLower() + c.toUpper() + QLatin1Char(']')); else pattern.append(c); } } if (escape) pattern.append(QLatin1Char('\\')); else if (brace) pattern.append(QLatin1Char('[')); return QRegExp(pattern); } static bool afterEndOfLine(const QTextDocument *doc, int position) { return doc->characterAt(position) == ParagraphSeparator && doc->findBlock(position).length() > 1; } static void searchForward(QTextCursor *tc, QRegExp &needleExp, int *repeat) { const QTextDocument *doc = tc->document(); const int startPos = tc->position(); // Search from beginning of line so that matched text is the same. tc->movePosition(StartOfLine); // forward to current position *tc = doc->find(needleExp, *tc); while (!tc->isNull() && tc->anchor() < startPos) { if (!tc->hasSelection()) tc->movePosition(Right); if (tc->atBlockEnd()) tc->movePosition(NextBlock); *tc = doc->find(needleExp, *tc); } if (tc->isNull()) return; --*repeat; while (*repeat > 0) { if (!tc->hasSelection()) tc->movePosition(Right); if (tc->atBlockEnd()) tc->movePosition(NextBlock); *tc = doc->find(needleExp, *tc); if (tc->isNull()) return; --*repeat; } if (!tc->isNull() && afterEndOfLine(doc, tc->anchor())) tc->movePosition(Left); } static void searchBackward(QTextCursor *tc, QRegExp &needleExp, int *repeat) { // Search from beginning of line so that matched text is the same. QTextBlock block = tc->block(); QString line = block.text(); int i = line.indexOf(needleExp, 0); while (i != -1 && i < tc->positionInBlock()) { --*repeat; i = line.indexOf(needleExp, i + qMax(1, needleExp.matchedLength())); if (i == line.size()) i = -1; } if (i == tc->positionInBlock()) --*repeat; while (*repeat > 0) { block = block.previous(); if (!block.isValid()) break; line = block.text(); i = line.indexOf(needleExp, 0); while (i != -1) { --*repeat; i = line.indexOf(needleExp, i + qMax(1, needleExp.matchedLength())); if (i == line.size()) i = -1; } } if (!block.isValid()) { *tc = QTextCursor(); return; } i = line.indexOf(needleExp, 0); while (*repeat < 0) { i = line.indexOf(needleExp, i + qMax(1, needleExp.matchedLength())); ++*repeat; } tc->setPosition(block.position() + i); tc->setPosition(tc->position() + needleExp.matchedLength(), KeepAnchor); } // Commands [[, [] static void bracketSearchBackward(QTextCursor *tc, const QString &needleExp, int repeat) { QRegExp re(needleExp); QTextCursor tc2 = *tc; tc2.setPosition(tc2.position() - 1); searchBackward(&tc2, re, &repeat); if (repeat <= 1) tc->setPosition(tc2.isNull() ? 0 : tc2.position(), KeepAnchor); } // Commands ][, ]] // When ]] is used after an operator, then also stops below a '}' in the first column. static void bracketSearchForward(QTextCursor *tc, const QString &needleExp, int repeat, bool searchWithCommand) { QRegExp re(searchWithCommand ? QString(_("^\\}|^\\{")) : needleExp); QTextCursor tc2 = *tc; tc2.setPosition(tc2.position() + 1); searchForward(&tc2, re, &repeat); if (repeat <= 1) { if (tc2.isNull()) { tc->setPosition(tc->document()->characterCount() - 1, KeepAnchor); } else { tc->setPosition(tc2.position() - 1, KeepAnchor); if (searchWithCommand && tc->document()->characterAt(tc->position()).unicode() == '}') { QTextBlock block = tc->block().next(); if (block.isValid()) tc->setPosition(block.position(), KeepAnchor); } } } } static bool substituteText(QString *text, QRegExp &pattern, const QString &replacement, bool global) { bool substituted = false; int pos = 0; int right = -1; while (true) { pos = pattern.indexIn(*text, pos, QRegExp::CaretAtZero); if (pos == -1) break; // ensure that substitution is advancing towards end of line if (right == text->size() - pos) { ++pos; if (pos == text->size()) break; continue; } right = text->size() - pos; substituted = true; QString matched = text->mid(pos, pattern.cap(0).size()); QString repl; bool escape = false; // insert captured texts for (int i = 0; i < replacement.size(); ++i) { const QChar &c = replacement[i]; if (escape) { escape = false; if (c.isDigit()) { if (c.digitValue() <= pattern.captureCount()) repl += pattern.cap(c.digitValue()); } else { repl += c; } } else { if (c == QLatin1Char('\\')) escape = true; else if (c == QLatin1Char('&')) repl += pattern.cap(0); else repl += c; } } text->replace(pos, matched.size(), repl); pos += (repl.isEmpty() && matched.isEmpty()) ? 1 : repl.size(); if (pos >= text->size() || !global) break; } return substituted; } static int findUnescaped(QChar c, const QString &line, int from) { for (int i = from; i < line.size(); ++i) { if (line.at(i) == c && (i == 0 || line.at(i - 1) != QLatin1Char('\\'))) return i; } return -1; } static void setClipboardData(const QString &content, RangeMode mode, QClipboard::Mode clipboardMode) { QClipboard *clipboard = QApplication::clipboard(); char vimRangeMode = mode; QByteArray bytes1; bytes1.append(vimRangeMode); bytes1.append(content.toUtf8()); QByteArray bytes2; bytes2.append(vimRangeMode); bytes2.append("utf-8"); bytes2.append('\0'); bytes2.append(content.toUtf8()); QMimeData *data = new QMimeData; data->setText(content); data->setData(vimMimeText, bytes1); data->setData(vimMimeTextEncoded, bytes2); clipboard->setMimeData(data, clipboardMode); } static QByteArray toLocalEncoding(const QString &text) { return HostOsInfo::isWindowsHost() ? QString(text).replace(_("\n"), _("\r\n")).toLocal8Bit() : text.toLocal8Bit(); } static QString fromLocalEncoding(const QByteArray &data) { return HostOsInfo::isWindowsHost() ? QString::fromLocal8Bit(data).replace(_("\n"), _("\r\n")) : QString::fromLocal8Bit(data); } static QString getProcessOutput(const QString &command, const QString &input) { QProcess proc; proc.start(command); proc.waitForStarted(); proc.write(toLocalEncoding(input)); proc.closeWriteChannel(); // FIXME: Process should be interruptable by user. // Solution is to create a QObject for each process and emit finished state. proc.waitForFinished(); return fromLocalEncoding(proc.readAllStandardOutput()); } static const QMap &vimKeyNames() { static QMap k; if (!k.isEmpty()) return k; // FIXME: Should be value of mapleader. k.insert(_("LEADER"), Key_Backslash); k.insert(_("SPACE"), Key_Space); k.insert(_("TAB"), Key_Tab); k.insert(_("NL"), Key_Return); k.insert(_("NEWLINE"), Key_Return); k.insert(_("LINEFEED"), Key_Return); k.insert(_("LF"), Key_Return); k.insert(_("CR"), Key_Return); k.insert(_("RETURN"), Key_Return); k.insert(_("ENTER"), Key_Return); k.insert(_("BS"), Key_Backspace); k.insert(_("BACKSPACE"), Key_Backspace); k.insert(_("ESC"), Key_Escape); k.insert(_("BAR"), Key_Bar); k.insert(_("BSLASH"), Key_Backslash); k.insert(_("DEL"), Key_Delete); k.insert(_("DELETE"), Key_Delete); k.insert(_("KDEL"), Key_Delete); k.insert(_("UP"), Key_Up); k.insert(_("DOWN"), Key_Down); k.insert(_("LEFT"), Key_Left); k.insert(_("RIGHT"), Key_Right); k.insert(_("LT"), Key_Less); k.insert(_("GT"), Key_Greater); k.insert(_("F1"), Key_F1); k.insert(_("F2"), Key_F2); k.insert(_("F3"), Key_F3); k.insert(_("F4"), Key_F4); k.insert(_("F5"), Key_F5); k.insert(_("F6"), Key_F6); k.insert(_("F7"), Key_F7); k.insert(_("F8"), Key_F8); k.insert(_("F9"), Key_F9); k.insert(_("F10"), Key_F10); k.insert(_("F11"), Key_F11); k.insert(_("F12"), Key_F12); k.insert(_("F13"), Key_F13); k.insert(_("F14"), Key_F14); k.insert(_("F15"), Key_F15); k.insert(_("F16"), Key_F16); k.insert(_("F17"), Key_F17); k.insert(_("F18"), Key_F18); k.insert(_("F19"), Key_F19); k.insert(_("F20"), Key_F20); k.insert(_("F21"), Key_F21); k.insert(_("F22"), Key_F22); k.insert(_("F23"), Key_F23); k.insert(_("F24"), Key_F24); k.insert(_("F25"), Key_F25); k.insert(_("F26"), Key_F26); k.insert(_("F27"), Key_F27); k.insert(_("F28"), Key_F28); k.insert(_("F29"), Key_F29); k.insert(_("F30"), Key_F30); k.insert(_("F31"), Key_F31); k.insert(_("F32"), Key_F32); k.insert(_("F33"), Key_F33); k.insert(_("F34"), Key_F34); k.insert(_("F35"), Key_F35); k.insert(_("INSERT"), Key_Insert); k.insert(_("INS"), Key_Insert); k.insert(_("KINSERT"), Key_Insert); k.insert(_("HOME"), Key_Home); k.insert(_("END"), Key_End); k.insert(_("PAGEUP"), Key_PageUp); k.insert(_("PAGEDOWN"), Key_PageDown); k.insert(_("KPLUS"), Key_Plus); k.insert(_("KMINUS"), Key_Minus); k.insert(_("KDIVIDE"), Key_Slash); k.insert(_("KMULTIPLY"), Key_Asterisk); k.insert(_("KENTER"), Key_Enter); k.insert(_("KPOINT"), Key_Period); return k; } static bool isOnlyControlModifier(const Qt::KeyboardModifiers &mods) { return (mods ^ HostOsInfo::controlModifier()) == Qt::NoModifier; } Range::Range() : beginPos(-1), endPos(-1), rangemode(RangeCharMode) {} Range::Range(int b, int e, RangeMode m) : beginPos(qMin(b, e)), endPos(qMax(b, e)), rangemode(m) {} QString Range::toString() const { return QString::fromLatin1("%1-%2 (mode: %3)").arg(beginPos).arg(endPos) .arg(rangemode); } bool Range::isValid() const { return beginPos >= 0 && endPos >= 0; } QDebug operator<<(QDebug ts, const Range &range) { return ts << '[' << range.beginPos << ',' << range.endPos << ']'; } ExCommand::ExCommand(const QString &c, const QString &a, const Range &r) : cmd(c), hasBang(false), args(a), range(r), count(1) {} bool ExCommand::matches(const QString &min, const QString &full) const { return cmd.startsWith(min) && full.startsWith(cmd); } QDebug operator<<(QDebug ts, const ExCommand &cmd) { return ts << cmd.cmd << ' ' << cmd.args << ' ' << cmd.range; } QDebug operator<<(QDebug ts, const QList &sels) { foreach (const QTextEdit::ExtraSelection &sel, sels) ts << "SEL: " << sel.cursor.anchor() << sel.cursor.position(); return ts; } QString quoteUnprintable(const QString &ba) { QString res; for (int i = 0, n = ba.size(); i != n; ++i) { const QChar c = ba.at(i); const int cc = c.unicode(); if (c.isPrint()) res += c; else if (cc == QLatin1Char('\n')) res += _(""); else res += QString::fromLatin1("\\x%1").arg(c.unicode(), 2, 16, QLatin1Char('0')); } return res; } static bool startsWithWhitespace(const QString &str, int col) { QTC_ASSERT(str.size() >= col, return false); for (int i = 0; i < col; ++i) { uint u = str.at(i).unicode(); if (u != QLatin1Char(' ') && u != QLatin1Char('\t')) return false; } return true; } inline QString msgMarkNotSet(const QString &text) { return FakeVimHandler::tr("Mark \"%1\" not set.").arg(text); } class Input { public: // Remove some extra "information" on Mac. static Qt::KeyboardModifiers cleanModifier(Qt::KeyboardModifiers m) { return m & ~Qt::KeypadModifier; } Input() : m_key(0), m_xkey(0), m_modifiers(0) {} explicit Input(QChar x) : m_key(x.unicode()), m_xkey(x.unicode()), m_modifiers(0), m_text(x) { if (x.isUpper()) m_modifiers = Qt::ShiftModifier; else if (x.isLower()) m_key = x.toUpper().unicode(); } Input(int k, Qt::KeyboardModifiers m, const QString &t = QString()) : m_key(k), m_modifiers(cleanModifier(m)), m_text(t) { if (m_text.size() == 1) { QChar x = m_text.at(0); // On Mac, QKeyEvent::text() returns non-empty strings for // cursor keys. This breaks some of the logic later on // relying on text() being empty for "special" keys. // FIXME: Check the real conditions. if (x.unicode() < ' ') m_text.clear(); else if (x.isLetter()) m_key = x.toUpper().unicode(); } // Set text only if input is ascii key without control modifier. if (m_text.isEmpty() && k >= 0 && k <= 0x7f && (m & HostOsInfo::controlModifier()) == 0) { QChar c = QChar::fromLatin1(k); if (c.isLetter()) m_text = QString(isShift() ? c.toUpper() : c); else if (!isShift()) m_text = c; } // Normalize . if (m_key == Qt::Key_Backtab) { m_key = Qt::Key_Tab; m_modifiers |= Qt::ShiftModifier; } // m_xkey is only a cache. m_xkey = (m_text.size() == 1 ? m_text.at(0).unicode() : m_key); } bool isValid() const { return m_key != 0 || !m_text.isNull(); } bool isDigit() const { return m_xkey >= '0' && m_xkey <= '9'; } bool isKey(int c) const { return !m_modifiers && m_key == c; } bool isBackspace() const { return m_key == Key_Backspace || isControl('h'); } bool isReturn() const { return m_key == QLatin1Char('\n') || m_key == Key_Return || m_key == Key_Enter; } bool isEscape() const { return isKey(Key_Escape) || isKey(27) || isControl('c') || isControl(Key_BracketLeft); } bool is(int c) const { return m_xkey == c && !isControl(); } bool isControl() const { return isOnlyControlModifier(m_modifiers); } bool isControl(int c) const { return isControl() && (m_xkey == c || m_xkey + 32 == c || m_xkey + 64 == c || m_xkey + 96 == c); } bool isShift() const { return m_modifiers & Qt::ShiftModifier; } bool isShift(int c) const { return isShift() && m_xkey == c; } bool operator<(const Input &a) const { if (m_key != a.m_key) return m_key < a.m_key; // Text for some mapped key cannot be determined (e.g. ) so if text is not set for // one of compared keys ignore it. if (!m_text.isEmpty() && !a.m_text.isEmpty() && m_text != _(" ")) return m_text < a.m_text; return m_modifiers < a.m_modifiers; } bool operator==(const Input &a) const { return !(*this < a || a < *this); } bool operator!=(const Input &a) const { return !operator==(a); } QString text() const { return m_text; } QChar asChar() const { return (m_text.size() == 1 ? m_text.at(0) : QChar()); } int toInt(bool *ok, int base) const { const int uc = asChar().unicode(); int res; if ('0' <= uc && uc <= '9') res = uc -'0'; else if ('a' <= uc && uc <= 'z') res = 10 + uc - 'a'; else if ('A' <= uc && uc <= 'Z') res = 10 + uc - 'A'; else res = base; *ok = res < base; return *ok ? res : 0; } int key() const { return m_key; } Qt::KeyboardModifiers modifiers() const { return m_modifiers; } // Return raw character for macro recording or dot command. QChar raw() const { if (m_key == Key_Tab) return QLatin1Char('\t'); if (m_key == Key_Return) return QLatin1Char('\n'); if (m_key == Key_Escape) return QChar(27); return m_xkey; } QString toString() const { QString key = vimKeyNames().key(m_key); bool namedKey = !key.isEmpty(); if (!namedKey) { if (m_xkey == '<') key = _(""); else if (m_xkey == '>') key = _(""); else key = QChar(m_xkey); } bool shift = isShift(); bool ctrl = isControl(); if (shift) key.prepend(_("S-")); if (ctrl) key.prepend(_("C-")); if (namedKey || shift || ctrl) { key.prepend(QLatin1Char('<')); key.append(QLatin1Char('>')); } return key; } QDebug dump(QDebug ts) const { return ts << m_key << '-' << m_modifiers << '-' << quoteUnprintable(m_text); } private: int m_key; int m_xkey; Qt::KeyboardModifiers m_modifiers; QString m_text; }; // mapping to (do nothing) static const Input Nop(-1, Qt::KeyboardModifiers(-1), QString()); QDebug operator<<(QDebug ts, const Input &input) { return input.dump(ts); } class Inputs : public QVector { public: Inputs() : m_noremap(true), m_silent(false) {} explicit Inputs(const QString &str, bool noremap = true, bool silent = false) : m_noremap(noremap), m_silent(silent) { parseFrom(str); squeeze(); } bool noremap() const { return m_noremap; } bool silent() const { return m_silent; } private: void parseFrom(const QString &str); bool m_noremap; bool m_silent; }; static Input parseVimKeyName(const QString &keyName) { if (keyName.length() == 1) return Input(keyName.at(0)); const QStringList keys = keyName.split(QLatin1Char('-')); const int len = keys.length(); if (len == 1 && keys.at(0).toUpper() == _("NOP")) return Nop; Qt::KeyboardModifiers mods = NoModifier; for (int i = 0; i < len - 1; ++i) { const QString &key = keys[i].toUpper(); if (key == _("S")) mods |= Qt::ShiftModifier; else if (key == _("C")) mods |= HostOsInfo::controlModifier(); else return Input(); } if (!keys.isEmpty()) { const QString key = keys.last(); if (key.length() == 1) { // simple character QChar c = key.at(0).toUpper(); return Input(c.unicode(), mods); } // find key name QMap::ConstIterator it = vimKeyNames().constFind(key.toUpper()); if (it != vimKeyNames().end()) return Input(*it, mods); } return Input(); } void Inputs::parseFrom(const QString &str) { const int n = str.size(); for (int i = 0; i < n; ++i) { ushort c = str.at(i).unicode(); if (c == '<') { int j = str.indexOf(QLatin1Char('>'), i); Input input; if (j != -1) { const QString key = str.mid(i+1, j - i - 1); if (!key.contains(QLatin1Char('<'))) input = parseVimKeyName(key); } if (input.isValid()) { append(input); i = j; } else { append(Input(c)); } } else { append(Input(c)); } } } class History { public: History() : m_items(QString()), m_index(0) {} void append(const QString &item); const QString &move(const QStringRef &prefix, int skip); const QString ¤t() const { return m_items[m_index]; } const QStringList &items() const { return m_items; } void restart() { m_index = m_items.size() - 1; } private: // Last item is always empty or current search prefix. QStringList m_items; int m_index; }; void History::append(const QString &item) { if (item.isEmpty()) return; m_items.pop_back(); m_items.removeAll(item); m_items << item << QString(); restart(); } const QString &History::move(const QStringRef &prefix, int skip) { if (!current().startsWith(prefix)) restart(); if (m_items.last() != prefix) m_items[m_items.size() - 1] = prefix.toString(); int i = m_index + skip; if (!prefix.isEmpty()) for (; i >= 0 && i < m_items.size() && !m_items[i].startsWith(prefix); i += skip) ; if (i >= 0 && i < m_items.size()) m_index = i; return current(); } // Command line buffer with prompt (i.e. :, / or ? characters), text contents and cursor position. class CommandBuffer { public: CommandBuffer() : m_pos(0), m_anchor(0), m_userPos(0), m_historyAutoSave(true) {} void setPrompt(const QChar &prompt) { m_prompt = prompt; } void setContents(const QString &s) { m_buffer = s; m_anchor = m_pos = s.size(); } void setContents(const QString &s, int pos, int anchor = -1) { m_buffer = s; m_pos = m_userPos = pos; m_anchor = anchor >= 0 ? anchor : pos; } QStringRef userContents() const { return m_buffer.leftRef(m_userPos); } const QChar &prompt() const { return m_prompt; } const QString &contents() const { return m_buffer; } bool isEmpty() const { return m_buffer.isEmpty(); } int cursorPos() const { return m_pos; } int anchorPos() const { return m_anchor; } bool hasSelection() const { return m_pos != m_anchor; } void insertChar(QChar c) { m_buffer.insert(m_pos++, c); m_anchor = m_userPos = m_pos; } void insertText(const QString &s) { m_buffer.insert(m_pos, s); m_anchor = m_userPos = m_pos = m_pos + s.size(); } void deleteChar() { if (m_pos) m_buffer.remove(--m_pos, 1); m_anchor = m_userPos = m_pos; } void moveLeft() { if (m_pos) m_userPos = --m_pos; } void moveRight() { if (m_pos < m_buffer.size()) m_userPos = ++m_pos; } void moveStart() { m_userPos = m_pos = 0; } void moveEnd() { m_userPos = m_pos = m_buffer.size(); } void setHistoryAutoSave(bool autoSave) { m_historyAutoSave = autoSave; } void historyDown() { setContents(m_history.move(userContents(), 1)); } void historyUp() { setContents(m_history.move(userContents(), -1)); } const QStringList &historyItems() const { return m_history.items(); } void historyPush(const QString &item = QString()) { m_history.append(item.isNull() ? contents() : item); } void clear() { if (m_historyAutoSave) historyPush(); m_buffer.clear(); m_anchor = m_userPos = m_pos = 0; } QString display() const { QString msg(m_prompt); for (int i = 0; i != m_buffer.size(); ++i) { const QChar c = m_buffer.at(i); if (c.unicode() < 32) { msg += QLatin1Char('^'); msg += QChar(c.unicode() + 64); } else { msg += c; } } return msg; } void deleteSelected() { if (m_pos < m_anchor) { m_buffer.remove(m_pos, m_anchor - m_pos); m_anchor = m_pos; } else { m_buffer.remove(m_anchor, m_pos - m_anchor); m_pos = m_anchor; } } bool handleInput(const Input &input) { if (input.isShift(Key_Left)) { moveLeft(); } else if (input.isShift(Key_Right)) { moveRight(); } else if (input.isShift(Key_Home)) { moveStart(); } else if (input.isShift(Key_End)) { moveEnd(); } else if (input.isKey(Key_Left)) { moveLeft(); m_anchor = m_pos; } else if (input.isKey(Key_Right)) { moveRight(); m_anchor = m_pos; } else if (input.isKey(Key_Home)) { moveStart(); m_anchor = m_pos; } else if (input.isKey(Key_End)) { moveEnd(); m_anchor = m_pos; } else if (input.isKey(Key_Up) || input.isKey(Key_PageUp)) { historyUp(); } else if (input.isKey(Key_Down) || input.isKey(Key_PageDown)) { historyDown(); } else if (input.isKey(Key_Delete)) { if (hasSelection()) { deleteSelected(); } else { if (m_pos < m_buffer.size()) m_buffer.remove(m_pos, 1); else deleteChar(); } } else if (!input.text().isEmpty()) { if (hasSelection()) deleteSelected(); insertText(input.text()); } else { return false; } return true; } private: QString m_buffer; QChar m_prompt; History m_history; int m_pos; int m_anchor; int m_userPos; // last position of inserted text (for retrieving history items) bool m_historyAutoSave; // store items to history on clear()? }; // Mappings for a specific mode (trie structure) class ModeMapping : public QMap { public: const Inputs &value() const { return m_value; } void setValue(const Inputs &value) { m_value = value; } private: Inputs m_value; }; // Mappings for all modes typedef QHash Mappings; // Iterator for mappings class MappingsIterator : public QVector { public: MappingsIterator(Mappings *mappings, char mode = -1, const Inputs &inputs = Inputs()) : m_parent(mappings) , m_lastValid(-1) , m_mode(0) { reset(mode); walk(inputs); } // Reset iterator state. Keep previous mode if 0. void reset(char mode = 0) { clear(); m_lastValid = -1; m_currentInputs.clear(); if (mode != 0) { m_mode = mode; if (mode != -1) m_modeMapping = m_parent->find(mode); } } bool isValid() const { return !empty(); } // Return true if mapping can be extended. bool canExtend() const { return isValid() && !last()->empty(); } // Return true if this mapping can be used. bool isComplete() const { return m_lastValid != -1; } // Return size of current map. int mapLength() const { return m_lastValid + 1; } bool walk(const Input &input) { m_currentInputs.append(input); if (m_modeMapping == m_parent->end()) return false; ModeMapping::Iterator it; if (isValid()) { it = last()->find(input); if (it == last()->end()) return false; } else { it = m_modeMapping->find(input); if (it == m_modeMapping->end()) return false; } if (!it->value().isEmpty()) m_lastValid = size(); append(it); return true; } bool walk(const Inputs &inputs) { foreach (const Input &input, inputs) { if (!walk(input)) return false; } return true; } // Return current mapped value. Iterator must be valid. const Inputs &inputs() const { return at(m_lastValid)->value(); } void remove() { if (isValid()) { if (canExtend()) { last()->setValue(Inputs()); } else { if (size() > 1) { while (last()->empty()) { at(size() - 2)->erase(last()); pop_back(); if (size() == 1 || !last()->value().isEmpty()) break; } if (last()->empty() && last()->value().isEmpty()) m_modeMapping->erase(last()); } else if (last()->empty() && !last()->value().isEmpty()) { m_modeMapping->erase(last()); } } } } void setInputs(const Inputs &key, const Inputs &inputs, bool unique = false) { ModeMapping *current = &(*m_parent)[m_mode]; foreach (const Input &input, key) current = &(*current)[input]; if (!unique || current->value().isEmpty()) current->setValue(inputs); } const Inputs ¤tInputs() const { return m_currentInputs; } private: Mappings *m_parent; Mappings::Iterator m_modeMapping; int m_lastValid; char m_mode; Inputs m_currentInputs; }; // state of current mapping struct MappingState { MappingState() : noremap(false), silent(false), editBlock(false) {} MappingState(bool noremap, bool silent, bool editBlock) : noremap(noremap), silent(silent), editBlock(editBlock) {} bool noremap; bool silent; bool editBlock; }; class FakeVimHandler::Private : public QObject { Q_OBJECT public: Private(FakeVimHandler *parent, QWidget *widget); EventResult handleEvent(QKeyEvent *ev); bool wantsOverride(QKeyEvent *ev); bool parseExCommmand(QString *line, ExCommand *cmd); bool parseLineRange(QString *line, ExCommand *cmd); int parseLineAddress(QString *cmd); void parseRangeCount(const QString &line, Range *range) const; void handleCommand(const QString &cmd); // Sets m_tc + handleExCommand void handleExCommand(const QString &cmd); void installEventFilter(); void removeEventFilter(); void passShortcuts(bool enable); void setupWidget(); void restoreWidget(int tabSize); friend class FakeVimHandler; void init(); void focus(); // Call before any FakeVim processing (import cursor position from editor) void enterFakeVim(); // Call after any FakeVim processing // (if needUpdate is true, export cursor position to editor and scroll) void leaveFakeVim(bool needUpdate = true); EventResult handleKey(const Input &input); EventResult handleDefaultKey(const Input &input); EventResult handleCurrentMapAsDefault(); void prependInputs(const QVector &inputs); // Handle inputs. void prependMapping(const Inputs &inputs); // Handle inputs as mapping. bool expandCompleteMapping(); // Return false if current mapping is not complete. bool extendMapping(const Input &input); // Return false if no suitable mappig found. void endMapping(); bool canHandleMapping(); void clearPendingInput(); void waitForMapping(); EventResult stopWaitForMapping(bool hasInput); EventResult handleInsertOrReplaceMode(const Input &); void handleInsertMode(const Input &); void handleReplaceMode(const Input &); void finishInsertMode(); EventResult handleCommandMode(const Input &); // return true only if input in current mode and sub-mode was correctly handled bool handleEscape(); bool handleNoSubMode(const Input &); bool handleChangeDeleteSubModes(const Input &); bool handleReplaceSubMode(const Input &); bool handleFilterSubMode(const Input &); bool handleRegisterSubMode(const Input &); bool handleShiftSubMode(const Input &); bool handleChangeCaseSubMode(const Input &); bool handleWindowSubMode(const Input &); bool handleYankSubMode(const Input &); bool handleZSubMode(const Input &); bool handleCapitalZSubMode(const Input &); bool handleMacroRecordSubMode(const Input &); bool handleMacroExecuteSubMode(const Input &); bool handleCount(const Input &); // Handle count for commands (return false if input isn't count). bool handleMovement(const Input &); EventResult handleExMode(const Input &); EventResult handleSearchSubSubMode(const Input &); bool handleCommandSubSubMode(const Input &); void fixSelection(); // Fix selection according to current range, move and command modes. bool finishSearch(); void finishMovement(const QString &dotCommandMovement = QString()); void resetCommandMode(); void clearCommandMode(); QTextCursor search(const SearchData &sd, int startPos, int count, bool showMessages); void search(const SearchData &sd, bool showMessages = true); bool searchNext(bool forward = true); void searchBalanced(bool forward, QChar needle, QChar other); void highlightMatches(const QString &needle); void stopIncrementalFind(); void updateFind(bool isComplete); void resetCount(); bool isInputCount(const Input &) const; // Return true if input can be used as count for commands. int mvCount() const { return qMax(1, g.mvcount); } int opCount() const { return qMax(1, g.opcount); } int count() const { return mvCount() * opCount(); } QTextBlock block() const { return m_cursor.block(); } int leftDist() const { return position() - block().position(); } int rightDist() const { return block().length() - leftDist() - (isVisualCharMode() ? 0 : 1); } bool atBlockStart() const { return m_cursor.atBlockStart(); } bool atBlockEnd() const { return m_cursor.atBlockEnd(); } bool atEndOfLine() const { return atBlockEnd() && block().length() > 1; } bool atDocumentEnd() const { return position() >= lastPositionInDocument(true); } bool atDocumentStart() const { return m_cursor.atStart(); } bool atEmptyLine(const QTextCursor &tc = QTextCursor()) const; bool atBoundary(bool end, bool simple, bool onlyWords = false, const QTextCursor &tc = QTextCursor()) const; bool atWordBoundary(bool end, bool simple, const QTextCursor &tc = QTextCursor()) const; bool atWordStart(bool simple, const QTextCursor &tc = QTextCursor()) const; bool atWordEnd(bool simple, const QTextCursor &tc = QTextCursor()) const; bool isFirstNonBlankOnLine(int pos); int lastPositionInDocument(bool ignoreMode = false) const; // Returns last valid position in doc. int firstPositionInLine(int line, bool onlyVisibleLines = true) const; // 1 based line, 0 based pos int lastPositionInLine(int line, bool onlyVisibleLines = true) const; // 1 based line, 0 based pos int lineForPosition(int pos) const; // 1 based line, 0 based pos QString lineContents(int line) const; // 1 based line QString textAt(int from, int to) const; void setLineContents(int line, const QString &contents); // 1 based line int blockBoundary(const QString &left, const QString &right, bool end, int count) const; // end or start position of current code block int lineNumber(const QTextBlock &block) const; QTextBlock nextLine(const QTextBlock &block) const; // following line (respects wrapped parts) QTextBlock previousLine(const QTextBlock &block) const; // previous line (respects wrapped parts) int linesOnScreen() const; int linesInDocument() const; // The following use all zero-based counting. int cursorLineOnScreen() const; int cursorLine() const; int cursorBlockNumber() const; // "." address int physicalCursorColumn() const; // as stored in the data int logicalCursorColumn() const; // as visible on screen int physicalToLogicalColumn(int physical, const QString &text) const; int logicalToPhysicalColumn(int logical, const QString &text) const; int windowScrollOffset() const; // return scrolloffset but max half the current window height Column cursorColumn() const; // as visible on screen void updateFirstVisibleLine(); int firstVisibleLine() const; int lastVisibleLine() const; int lineOnTop(int count = 1) const; // [count]-th line from top reachable without scrolling int lineOnBottom(int count = 1) const; // [count]-th line from bottom reachable without scrolling void scrollToLine(int line); void scrollUp(int count); void scrollDown(int count) { scrollUp(-count); } void updateScrollOffset(); void alignViewportToCursor(Qt::AlignmentFlag align, int line = -1, bool moveToNonBlank = false); int lineToBlockNumber(int line) const; void setCursorPosition(const CursorPosition &p); void setCursorPosition(QTextCursor *tc, const CursorPosition &p); // Helper functions for indenting/ bool isElectricCharacter(QChar c) const; void indentSelectedText(QChar lastTyped = QChar()); void indentText(const Range &range, QChar lastTyped = QChar()); void shiftRegionLeft(int repeat = 1); void shiftRegionRight(int repeat = 1); void moveToFirstNonBlankOnLine(); void moveToFirstNonBlankOnLine(QTextCursor *tc); void moveToFirstNonBlankOnLineVisually(); void moveToNonBlankOnLine(QTextCursor *tc); void moveToTargetColumn(); void setTargetColumn(); void moveToMatchingParanthesis(); void moveToBoundary(bool simple, bool forward = true); void moveToNextBoundary(bool end, int count, bool simple, bool forward); void moveToNextBoundaryStart(int count, bool simple, bool forward = true); void moveToNextBoundaryEnd(int count, bool simple, bool forward = true); void moveToBoundaryStart(int count, bool simple, bool forward = true); void moveToBoundaryEnd(int count, bool simple, bool forward = true); void moveToNextWord(bool end, int count, bool simple, bool forward, bool emptyLines); void moveToNextWordStart(int count, bool simple, bool forward = true, bool emptyLines = true); void moveToNextWordEnd(int count, bool simple, bool forward = true, bool emptyLines = true); void moveToWordStart(int count, bool simple, bool forward = true, bool emptyLines = true); void moveToWordEnd(int count, bool simple, bool forward = true, bool emptyLines = true); // Convenience wrappers to reduce line noise. void moveToStartOfLine(); void moveToStartOfLineVisually(); void moveToEndOfLine(); void moveToEndOfLineVisually(); void moveToEndOfLineVisually(QTextCursor *tc); void moveBehindEndOfLine(); void moveUp(int n = 1) { moveDown(-n); } void moveDown(int n = 1); void moveUpVisually(int n = 1) { moveDownVisually(-n); } void moveDownVisually(int n = 1); void movePageDown(int count = 1); void movePageUp(int count = 1) { movePageDown(-count); } void dump(const char *msg) const { qDebug() << msg << "POS: " << anchor() << position() << "EXT: " << m_oldExternalAnchor << m_oldExternalPosition << "INT: " << m_oldInternalAnchor << m_oldInternalPosition << "VISUAL: " << g.visualMode; } void moveRight(int n = 1) { //dump("RIGHT 1"); if (isVisualCharMode()) { const QTextBlock currentBlock = block(); const int max = currentBlock.position() + currentBlock.length() - 1; const int pos = position() + n; setPosition(qMin(pos, max)); } else { m_cursor.movePosition(Right, KeepAnchor, n); } if (atEndOfLine()) emit q->fold(1, false); //dump("RIGHT 2"); } void moveLeft(int n = 1) { m_cursor.movePosition(Left, KeepAnchor, n); } void setAnchor() { m_cursor.setPosition(position(), MoveAnchor); } void setAnchor(int position) { m_cursor.setPosition(position, KeepAnchor); } void setPosition(int position) { m_cursor.setPosition(position, KeepAnchor); } void setAnchorAndPosition(int anchor, int position) { m_cursor.setPosition(anchor, MoveAnchor); m_cursor.setPosition(position, KeepAnchor); } // Set cursor in text editor widget. void commitCursor() { if (isVisualBlockMode()) { emit q->requestSetBlockSelection(m_cursor); } else { emit q->requestDisableBlockSelection(); if (editor()) EDITOR(setTextCursor(m_cursor)); } } // Restore cursor from editor widget. void pullCursor() { if (isVisualBlockMode()) q->requestBlockSelection(&m_cursor); else if (editor()) m_cursor = EDITOR(textCursor()); } // Values to save when starting FakeVim processing. int m_firstVisibleLine; QTextCursor m_cursor; bool moveToPreviousParagraph(int count) { return moveToNextParagraph(-count); } bool moveToNextParagraph(int count); bool handleFfTt(const QString &key, bool repeats = false); void enterVisualInsertMode(QChar command); void enterReplaceMode(); void enterInsertMode(); void enterInsertOrReplaceMode(Mode mode); void enterCommandMode(Mode returnToMode = CommandMode); void enterExMode(const QString &contents = QString()); void showMessage(MessageLevel level, const QString &msg); void clearMessage() { showMessage(MessageInfo, QString()); } void notImplementedYet(); void updateMiniBuffer(); void updateSelection(); void updateHighlights(); void updateCursorShape(); QWidget *editor() const; QTextDocument *document() const { return EDITOR(document()); } QChar characterAtCursor() const { return document()->characterAt(position()); } void joinPreviousEditBlock(); void beginEditBlock(bool largeEditBlock = false); void beginLargeEditBlock() { beginEditBlock(true); } void endEditBlock(); void breakEditBlock() { m_buffer->breakEditBlock = true; } Q_SLOT void onContentsChanged(int position, int charsRemoved, int charsAdded); Q_SLOT void onUndoCommandAdded(); bool isInsertMode() const { return g.mode == InsertMode || g.mode == ReplaceMode; } // Waiting for movement operator. bool isOperatorPending() const { return g.submode == ChangeSubMode || g.submode == DeleteSubMode || g.submode == FilterSubMode || g.submode == IndentSubMode || g.submode == ShiftLeftSubMode || g.submode == ShiftRightSubMode || g.submode == InvertCaseSubMode || g.submode == DownCaseSubMode || g.submode == UpCaseSubMode || g.submode == YankSubMode; } bool isVisualMode() const { return g.visualMode != NoVisualMode; } bool isNoVisualMode() const { return g.visualMode == NoVisualMode; } bool isVisualCharMode() const { return g.visualMode == VisualCharMode; } bool isVisualLineMode() const { return g.visualMode == VisualLineMode; } bool isVisualBlockMode() const { return g.visualMode == VisualBlockMode; } char currentModeCode() const; void updateEditor(); void selectTextObject(bool simple, bool inner); void selectWordTextObject(bool inner); void selectWORDTextObject(bool inner); void selectSentenceTextObject(bool inner); void selectParagraphTextObject(bool inner); bool changeNumberTextObject(int count); // return true only if cursor is in a block delimited with correct characters bool selectBlockTextObject(bool inner, char left, char right); bool selectQuotedStringTextObject(bool inner, const QString "e); Q_SLOT void importSelection(); void exportSelection(); void commitInsertState(); void invalidateInsertState(); bool isInsertStateValid() const; void clearLastInsertion(); void ensureCursorVisible(); void insertInInsertMode(const QString &text); // Macro recording bool startRecording(const Input &input); void record(const Input &input); void stopRecording(); bool executeRegister(int reg); public: QTextEdit *m_textedit; QPlainTextEdit *m_plaintextedit; bool m_wasReadOnly; // saves read-only state of document bool m_inFakeVim; // true if currently processing a key press or a command FakeVimHandler *q; int m_oldExternalPosition; // copy from last event to check for external changes int m_oldExternalAnchor; int m_oldInternalPosition; // copy from last event to check for external changes int m_oldInternalAnchor; int m_register; BlockInsertMode m_visualBlockInsert; bool m_fakeEnd; bool m_anchorPastEnd; bool m_positionPastEnd; // '$' & 'l' in visual mode can move past eol QString m_currentFileName; int m_findStartPosition; int anchor() const { return m_cursor.anchor(); } int position() const { return m_cursor.position(); } struct TransformationData { TransformationData(const QString &s, const QVariant &d) : from(s), extraData(d) {} QString from; QString to; QVariant extraData; }; typedef void (Private::*Transformation)(TransformationData *td); void transformText(const Range &range, Transformation transformation, const QVariant &extraData = QVariant()); void insertText(QTextCursor &tc, const QString &text); void insertText(const Register ®); void removeText(const Range &range); void removeTransform(TransformationData *td); void invertCase(const Range &range); void invertCaseTransform(TransformationData *td); void upCase(const Range &range); void upCaseTransform(TransformationData *td); void downCase(const Range &range); void downCaseTransform(TransformationData *td); void replaceText(const Range &range, const QString &str); void replaceByStringTransform(TransformationData *td); void replaceByCharTransform(TransformationData *td); QString selectText(const Range &range) const; void setCurrentRange(const Range &range); Range currentRange() const { return Range(position(), anchor(), g.rangemode); } void yankText(const Range &range, int toregister); void pasteText(bool afterCursor); void joinLines(int count, bool preserveSpace = false); void insertNewLine(); bool handleInsertInEditor(const Input &input); bool passEventToEditor(QEvent &event); // Pass event to editor widget without filtering. Returns true if event was processed. // undo handling int revision() const { return document()->availableUndoSteps(); } void undoRedo(bool undo); void undo(); void redo(); void pushUndoState(bool overwrite = true); // extra data for '.' void replay(const QString &text, int repeat = 1); void setDotCommand(const QString &cmd) { g.dotCommand = cmd; } void setDotCommand(const QString &cmd, int n) { g.dotCommand = cmd.arg(n); } QString visualDotCommand() const; // visual modes void toggleVisualMode(VisualMode visualMode); void leaveVisualMode(); // marks Mark mark(QChar code) const; void setMark(QChar code, CursorPosition position); // jump to valid mark return true if mark is valid and local bool jumpToMark(QChar mark, bool backTickMode); // update marks on undo/redo void updateMarks(const Marks &newMarks); CursorPosition markLessPosition() const { return mark(QLatin1Char('<')).position(document()); } CursorPosition markGreaterPosition() const { return mark(QLatin1Char('>')).position(document()); } // vi style configuration QVariant config(int code) const { return theFakeVimSetting(code)->value(); } bool hasConfig(int code) const { return config(code).toBool(); } bool hasConfig(int code, const char *value) const // FIXME { return config(code).toString().contains(_(value)); } int m_targetColumn; // -1 if past end of line int m_visualTargetColumn; // 'l' can move past eol in visual mode only int m_targetColumnWrapped; // column in current part of wrapped line // auto-indent QString tabExpand(int len) const; Column indentation(const QString &line) const; void insertAutomaticIndentation(bool goingDown, bool forceAutoIndent = false); // number of autoindented characters void handleStartOfLine(); // register handling QString registerContents(int reg) const; void setRegister(int reg, const QString &contents, RangeMode mode); RangeMode registerRangeMode(int reg) const; void getRegisterType(int reg, bool *isClipboard, bool *isSelection) const; void recordJump(int position = -1); void jump(int distance); QList m_extraSelections; QTextCursor m_searchCursor; int m_searchStartPosition; int m_searchFromScreenLine; QString m_highlighted; // currently highlighted text bool handleExCommandHelper(ExCommand &cmd); // Returns success. bool handleExPluginCommand(const ExCommand &cmd); // Handled by plugin? bool handleExBangCommand(const ExCommand &cmd); bool handleExYankDeleteCommand(const ExCommand &cmd); bool handleExChangeCommand(const ExCommand &cmd); bool handleExMoveCommand(const ExCommand &cmd); bool handleExJoinCommand(const ExCommand &cmd); bool handleExGotoCommand(const ExCommand &cmd); bool handleExHistoryCommand(const ExCommand &cmd); bool handleExRegisterCommand(const ExCommand &cmd); bool handleExMapCommand(const ExCommand &cmd); bool handleExNohlsearchCommand(const ExCommand &cmd); bool handleExNormalCommand(const ExCommand &cmd); bool handleExReadCommand(const ExCommand &cmd); bool handleExUndoRedoCommand(const ExCommand &cmd); bool handleExSetCommand(const ExCommand &cmd); bool handleExShiftCommand(const ExCommand &cmd); bool handleExSourceCommand(const ExCommand &cmd); bool handleExSubstituteCommand(const ExCommand &cmd); bool handleExWriteCommand(const ExCommand &cmd); bool handleExEchoCommand(const ExCommand &cmd); void timerEvent(QTimerEvent *ev); void setupCharClass(); int charClass(QChar c, bool simple) const; signed char m_charClass[256]; int m_ctrlVAccumulator; int m_ctrlVLength; int m_ctrlVBase; void miniBufferTextEdited(const QString &text, int cursorPos, int anchorPos); // Data shared among editors with same document. struct BufferData { BufferData() : lastRevision(0) , editBlockLevel(0) , breakEditBlock(false) , lastVisualMode(NoVisualMode) , lastVisualModeInverted(false) {} QStack undo; QStack redo; State undoState; int lastRevision; int editBlockLevel; // current level of edit blocks bool breakEditBlock; // if true, joinPreviousEditBlock() starts new edit block QStack jumpListUndo; QStack jumpListRedo; CursorPosition lastChangePosition; VisualMode lastVisualMode; bool lastVisualModeInverted; Marks marks; // Insert state to get last inserted text. struct InsertState { int pos1; int pos2; int backspaces; int deletes; QSet spaces; bool insertingSpaces; QString textBeforeCursor; bool newLineBefore; bool newLineAfter; } insertState; QString lastInsertion; }; typedef QSharedPointer BufferDataPtr; void pullOrCreateBufferData(); BufferDataPtr m_buffer; // Data shared among all editors. static struct GlobalData { GlobalData() : passing(false) , mode(CommandMode) , submode(NoSubMode) , subsubmode(NoSubSubMode) , visualMode(NoVisualMode) , mvcount(0) , opcount(0) , movetype(MoveInclusive) , rangemode(RangeCharMode) , gflag(false) , mappings() , currentMap(&mappings) , inputTimer(-1) , mapDepth(0) , currentMessageLevel(MessageInfo) , lastSearchForward(false) , highlightsCleared(false) , findPending(false) , returnToMode(CommandMode) , currentRegister(0) , lastExecutedRegister(0) { commandBuffer.setPrompt(QLatin1Char(':')); } // Current state. bool passing; // let the core see the next event Mode mode; SubMode submode; SubSubMode subsubmode; Input subsubdata; VisualMode visualMode; // [count] for current command, 0 if no [count] available int mvcount; int opcount; MoveType movetype; RangeMode rangemode; bool gflag; // whether current command started with 'g' // Extra data for ';'. Input semicolonType; // 'f', 'F', 't', 'T' QString semicolonKey; // Repetition. QString dotCommand; QHash registers; // All mappings. Mappings mappings; // Input. QList pendingInput; MappingsIterator currentMap; int inputTimer; QStack mapStates; int mapDepth; // Command line buffers. CommandBuffer commandBuffer; CommandBuffer searchBuffer; // Current mini buffer message. QString currentMessage; MessageLevel currentMessageLevel; QString currentCommand; // Search state. QString lastSearch; // last search expression as entered by user QString lastNeedle; // last search expression translated with vimPatternToQtPattern() bool lastSearchForward; // last search command was '/' or '*' bool highlightsCleared; // ':nohlsearch' command is active until next search bool findPending; // currently searching using external tool (until editor is focused again) // Last substitution command. QString lastSubstituteFlags; QString lastSubstitutePattern; QString lastSubstituteReplacement; // Global marks. Marks marks; // Return to insert/replace mode after single command (). Mode returnToMode; // Currently recorded macro (not recording if null string). QString recording; int currentRegister; int lastExecutedRegister; } g; }; FakeVimHandler::Private::GlobalData FakeVimHandler::Private::g; FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget) { q = parent; m_textedit = qobject_cast(widget); m_plaintextedit = qobject_cast(widget); init(); if (editor()) { connect(EDITOR(document()), SIGNAL(contentsChange(int,int,int)), SLOT(onContentsChanged(int,int,int))); connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded())); m_buffer->lastRevision = revision(); } } void FakeVimHandler::Private::init() { m_inFakeVim = false; m_findStartPosition = -1; m_visualBlockInsert = NoneBlockInsertMode; m_fakeEnd = false; m_positionPastEnd = false; m_anchorPastEnd = false; m_register = '"'; m_targetColumn = 0; m_visualTargetColumn = 0; m_targetColumnWrapped = 0; m_oldInternalAnchor = -1; m_oldInternalPosition = -1; m_oldExternalAnchor = -1; m_oldExternalPosition = -1; m_searchStartPosition = 0; m_searchFromScreenLine = 0; m_firstVisibleLine = 0; m_ctrlVAccumulator = 0; m_ctrlVLength = 0; m_ctrlVBase = 0; pullOrCreateBufferData(); setupCharClass(); } void FakeVimHandler::Private::focus() { enterFakeVim(); stopIncrementalFind(); if (!isInsertMode()) { if (g.subsubmode == SearchSubSubMode) { setPosition(m_searchStartPosition); scrollToLine(m_searchFromScreenLine); setTargetColumn(); setAnchor(); commitCursor(); } else if (g.submode != NoSubMode || g.mode == ExMode) { leaveVisualMode(); setPosition(qMin(position(), anchor())); setTargetColumn(); setAnchor(); commitCursor(); } bool exitCommandLine = (g.subsubmode == SearchSubSubMode || g.mode == ExMode); resetCommandMode(); if (exitCommandLine) updateMiniBuffer(); } updateCursorShape(); if (g.mode != CommandMode) updateMiniBuffer(); updateHighlights(); leaveFakeVim(false); } void FakeVimHandler::Private::enterFakeVim() { QTC_ASSERT(!m_inFakeVim, qDebug() << "enterFakeVim() shouldn't be called recursively!"; return); pullOrCreateBufferData(); pullCursor(); if (m_cursor.isNull()) m_cursor = QTextCursor(document()); m_inFakeVim = true; removeEventFilter(); updateFirstVisibleLine(); importSelection(); // Position changed externally, e.g. by code completion. if (position() != m_oldInternalPosition) { // record external jump to different line if (m_oldInternalPosition != -1 && lineForPosition(m_oldInternalPosition) != lineForPosition(position())) recordJump(m_oldInternalPosition); setTargetColumn(); if (atEndOfLine() && !isVisualMode() && !isInsertMode()) moveLeft(); } if (m_fakeEnd) moveRight(); } void FakeVimHandler::Private::leaveFakeVim(bool needUpdate) { QTC_ASSERT(m_inFakeVim, qDebug() << "enterFakeVim() not called before leaveFakeVim()!"; return); // The command might have destroyed the editor. if (m_textedit || m_plaintextedit) { // We fake vi-style end-of-line behaviour m_fakeEnd = atEndOfLine() && g.mode == CommandMode && !isVisualBlockMode() && !isVisualCharMode(); //QTC_ASSERT(g.mode == InsertMode || g.mode == ReplaceMode // || !atBlockEnd() || block().length() <= 1, // qDebug() << "Cursor at EOL after key handler"); if (m_fakeEnd) moveLeft(); if (hasConfig(ConfigShowMarks)) updateSelection(); exportSelection(); updateCursorShape(); if (needUpdate) { commitCursor(); // Move cursor line to middle of screen if it's not visible. const int line = cursorLine(); if (line < firstVisibleLine() || line > firstVisibleLine() + linesOnScreen()) scrollToLine(qMax(0, line - linesOnScreen() / 2)); else scrollToLine(firstVisibleLine()); updateScrollOffset(); } installEventFilter(); } m_inFakeVim = false; } bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev) { const int key = ev->key(); const Qt::KeyboardModifiers mods = ev->modifiers(); KEY_DEBUG("SHORTCUT OVERRIDE" << key << " PASSING: " << g.passing); if (key == Key_Escape) { if (g.subsubmode == SearchSubSubMode) return true; // Not sure this feels good. People often hit Esc several times. if (isNoVisualMode() && g.mode == CommandMode && g.submode == NoSubMode && g.currentCommand.isEmpty() && g.returnToMode == CommandMode) return false; return true; } // We are interested in overriding most Ctrl key combinations. if (isOnlyControlModifier(mods) && !config(ConfigPassControlKey).toBool() && ((key >= Key_A && key <= Key_Z && key != Key_K) || key == Key_BracketLeft || key == Key_BracketRight)) { // Ctrl-K is special as it is the Core's default notion of Locator if (g.passing) { KEY_DEBUG(" PASSING CTRL KEY"); // We get called twice on the same key //g.passing = false; return false; } KEY_DEBUG(" NOT PASSING CTRL KEY"); //updateMiniBuffer(); return true; } // Let other shortcuts trigger. return false; } EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev) { const int key = ev->key(); const Qt::KeyboardModifiers mods = ev->modifiers(); if (key == Key_Shift || key == Key_Alt || key == Key_Control || key == Key_AltGr || key == Key_Meta) { KEY_DEBUG("PLAIN MODIFIER"); return EventUnhandled; } if (g.passing) { passShortcuts(false); KEY_DEBUG("PASSING PLAIN KEY..." << ev->key() << ev->text()); //if (input.is(',')) { // use ',,' to leave, too. // qDebug() << "FINISHED..."; // return EventHandled; //} g.passing = false; updateMiniBuffer(); KEY_DEBUG(" PASS TO CORE"); return EventPassedToCore; } #ifndef FAKEVIM_STANDALONE bool inSnippetMode = false; QMetaObject::invokeMethod(editor(), "inSnippetMode", Q_ARG(bool *, &inSnippetMode)); if (inSnippetMode) return EventPassedToCore; #endif // Fake "End of line" //m_tc = m_cursor; //bool hasBlock = false; //emit q->requestHasBlockSelection(&hasBlock); //qDebug() << "IMPORT BLOCK 2:" << hasBlock; //if (0 && hasBlock) { // (pos > anc) ? --pos : --anc; //if ((mods & RealControlModifier) != 0) { // if (key >= Key_A && key <= Key_Z) // key = shift(key); // make it lower case // key = control(key); //} else if (key >= Key_A && key <= Key_Z && (mods & Qt::ShiftModifier) == 0) { // key = shift(key); //} //QTC_ASSERT(g.mode == InsertMode || g.mode == ReplaceMode // || !atBlockEnd() || block().length() <= 1, // qDebug() << "Cursor at EOL before key handler"); enterFakeVim(); EventResult result = handleKey(Input(key, mods, ev->text())); leaveFakeVim(result == EventHandled); return result; } void FakeVimHandler::Private::installEventFilter() { EDITOR(viewport()->installEventFilter(q)); EDITOR(installEventFilter(q)); } void FakeVimHandler::Private::removeEventFilter() { EDITOR(viewport()->removeEventFilter(q)); EDITOR(removeEventFilter(q)); } void FakeVimHandler::Private::setupWidget() { enterFakeVim(); resetCommandMode(); m_wasReadOnly = EDITOR(isReadOnly()); updateEditor(); importSelection(); updateMiniBuffer(); updateCursorShape(); recordJump(); setTargetColumn(); if (atEndOfLine() && !isVisualMode() && !isInsertMode()) moveLeft(); leaveFakeVim(); } void FakeVimHandler::Private::exportSelection() { int pos = position(); int anc = isVisualMode() ? anchor() : position(); m_oldInternalPosition = pos; m_oldInternalAnchor = anc; if (isVisualMode()) { if (g.visualMode == VisualBlockMode) { const int col1 = anc - document()->findBlock(anc).position(); const int col2 = pos - document()->findBlock(pos).position(); if (col1 > col2) ++anc; else if (!atBlockEnd()) ++pos; // FIXME: After '$' command (i.e. m_visualTargetColumn == -1), end of selected lines // should be selected. setAnchorAndPosition(anc, pos); commitCursor(); } else if (g.visualMode == VisualLineMode) { const int posLine = lineForPosition(pos); const int ancLine = lineForPosition(anc); if (anc < pos) { pos = lastPositionInLine(posLine); anc = firstPositionInLine(ancLine); } else { pos = firstPositionInLine(posLine); anc = lastPositionInLine(ancLine) + 1; } // putting cursor on folded line will unfold the line, so move the cursor a bit if (!document()->findBlock(pos).isVisible()) ++pos; setAnchorAndPosition(anc, pos); } else if (g.visualMode == VisualCharMode) { if (anc > pos) ++anc; } else { QTC_CHECK(false); } setAnchorAndPosition(anc, pos); setMark(QLatin1Char('<'), markLessPosition()); setMark(QLatin1Char('>'), markGreaterPosition()); } else { if (g.subsubmode == SearchSubSubMode && !m_searchCursor.isNull()) m_cursor = m_searchCursor; else setAnchorAndPosition(pos, pos); } m_oldExternalPosition = position(); m_oldExternalAnchor = anchor(); } void FakeVimHandler::Private::commitInsertState() { if (!isInsertStateValid()) return; QString &lastInsertion = m_buffer->lastInsertion; BufferData::InsertState &insertState = m_buffer->insertState; // Get raw inserted text. lastInsertion = textAt(insertState.pos1, insertState.pos2); // Escape special characters and spaces inserted by user (not by auto-indentation). for (int i = lastInsertion.size() - 1; i >= 0; --i) { const int pos = insertState.pos1 + i; const ushort c = document()->characterAt(pos).unicode(); if (c == '<') lastInsertion.replace(i, 1, _("")); else if ((c == ' ' || c == '\t') && insertState.spaces.contains(pos)) lastInsertion.replace(i, 1, _(c == ' ' ? "" : "")); } // Remove unnecessary backspaces. while (insertState.backspaces > 0 && !lastInsertion.isEmpty() && lastInsertion[0].isSpace()) --insertState.backspaces; // backspaces in front of inserted text lastInsertion.prepend(QString(_("")).repeated(insertState.backspaces)); // deletes after inserted text lastInsertion.prepend(QString(_("")).repeated(insertState.deletes)); // Remove indentation. lastInsertion.replace(QRegExp(_("(^|\n)[\\t ]+")), _("\\1")); } void FakeVimHandler::Private::invalidateInsertState() { m_oldInternalPosition = position(); BufferData::InsertState &insertState = m_buffer->insertState; insertState.pos1 = -1; insertState.pos2 = m_oldInternalPosition; insertState.backspaces = 0; insertState.deletes = 0; insertState.spaces.clear(); insertState.insertingSpaces = false; insertState.textBeforeCursor = textAt(document()->findBlock(m_oldInternalPosition).position(), m_oldInternalPosition); insertState.newLineBefore = false; insertState.newLineAfter = false; } bool FakeVimHandler::Private::isInsertStateValid() const { return m_buffer->insertState.pos1 != -1; } void FakeVimHandler::Private::clearLastInsertion() { invalidateInsertState(); m_buffer->lastInsertion.clear(); m_buffer->insertState.pos1 = m_buffer->insertState.pos2; } void FakeVimHandler::Private::ensureCursorVisible() { int pos = position(); int anc = isVisualMode() ? anchor() : position(); // fix selection so it is outside folded block int start = qMin(pos, anc); int end = qMax(pos, anc) + 1; QTextBlock block = document()->findBlock(start); QTextBlock block2 = document()->findBlock(end); if (!block.isVisible() || !block2.isVisible()) { // FIXME: Moving cursor left/right or unfolding block immediately after block is folded // should restore cursor position inside block. // Changing cursor position after folding is not Vim behavior so at least record the jump. if (block.isValid() && !block.isVisible()) recordJump(); pos = start; while (block.isValid() && !block.isVisible()) block = block.previous(); if (block.isValid()) pos = block.position() + qMin(m_targetColumn, block.length() - 2); if (isVisualMode()) { anc = end; while (block2.isValid() && !block2.isVisible()) { anc = block2.position() + block2.length() - 2; block2 = block2.next(); } } setAnchorAndPosition(anc, pos); } } void FakeVimHandler::Private::importSelection() { if (position() == m_oldExternalPosition && anchor() == m_oldExternalAnchor) { // Undo drawing correction. setAnchorAndPosition(m_oldInternalAnchor, m_oldInternalPosition); } else { // Import new selection. Qt::KeyboardModifiers mods = QApplication::keyboardModifiers(); if (m_cursor.hasSelection()) { if (mods & HostOsInfo::controlModifier()) g.visualMode = VisualBlockMode; else if (mods & Qt::AltModifier) g.visualMode = VisualBlockMode; else if (mods & Qt::ShiftModifier) g.visualMode = VisualLineMode; else g.visualMode = VisualCharMode; m_buffer->lastVisualMode = g.visualMode; } else { g.visualMode = NoVisualMode; } } } void FakeVimHandler::Private::updateEditor() { const int charWidth = QFontMetrics(EDITOR(font())).width(QLatin1Char(' ')); EDITOR(setTabStopWidth(charWidth * config(ConfigTabStop).toInt())); setupCharClass(); } void FakeVimHandler::Private::restoreWidget(int tabSize) { //clearMessage(); //updateMiniBuffer(); //EDITOR(removeEventFilter(q)); //EDITOR(setReadOnly(m_wasReadOnly)); const int charWidth = QFontMetrics(EDITOR(font())).width(QLatin1Char(' ')); EDITOR(setTabStopWidth(charWidth * tabSize)); g.visualMode = NoVisualMode; // Force "ordinary" cursor. EDITOR(setOverwriteMode(false)); updateSelection(); updateHighlights(); } EventResult FakeVimHandler::Private::handleKey(const Input &input) { KEY_DEBUG("HANDLE INPUT: " << input << " MODE: " << mode); bool hasInput = input.isValid(); // Waiting on input to complete mapping? EventResult r = stopWaitForMapping(hasInput); if (hasInput) { record(input); g.pendingInput.append(input); } // Process pending input. // Note: Pending input is global state and can be extended by: // 1. handling a user input (though handleKey() is not called recursively), // 2. expanding a user mapping or // 3. executing a register. while (!g.pendingInput.isEmpty() && r == EventHandled) { const Input in = g.pendingInput.takeFirst(); // invalid input is used to pop mapping state if (!in.isValid()) { endMapping(); } else { // Handle user mapping. if (canHandleMapping()) { if (extendMapping(in)) { if (!hasInput || !g.currentMap.canExtend()) expandCompleteMapping(); } else if (!expandCompleteMapping()) { r = handleCurrentMapAsDefault(); } } else { r = handleDefaultKey(in); } } } if (g.currentMap.canExtend()) { waitForMapping(); return EventHandled; } if (r != EventHandled) clearPendingInput(); return r; } EventResult FakeVimHandler::Private::handleDefaultKey(const Input &input) { if (input == Nop) return EventHandled; else if (g.subsubmode == SearchSubSubMode) return handleSearchSubSubMode(input); else if (g.mode == CommandMode) return handleCommandMode(input); else if (g.mode == InsertMode || g.mode == ReplaceMode) return handleInsertOrReplaceMode(input); else if (g.mode == ExMode) return handleExMode(input); return EventUnhandled; } EventResult FakeVimHandler::Private::handleCurrentMapAsDefault() { // If mapping has failed take the first input from it and try default command. const Inputs &inputs = g.currentMap.currentInputs(); Input in = inputs.front(); if (inputs.size() > 1) prependInputs(inputs.mid(1)); g.currentMap.reset(); return handleDefaultKey(in); } void FakeVimHandler::Private::prependInputs(const QVector &inputs) { for (int i = inputs.size() - 1; i >= 0; --i) g.pendingInput.prepend(inputs[i]); } void FakeVimHandler::Private::prependMapping(const Inputs &inputs) { // FIXME: Implement Vim option maxmapdepth (default value is 1000). if (g.mapDepth >= 1000) { const int i = qMax(0, g.pendingInput.lastIndexOf(Input())); QList inputs = g.pendingInput.mid(i); clearPendingInput(); g.pendingInput.append(inputs); showMessage(MessageError, tr("Recursive mapping")); updateMiniBuffer(); return; } ++g.mapDepth; g.pendingInput.prepend(Input()); prependInputs(inputs); g.commandBuffer.setHistoryAutoSave(false); // start new edit block (undo/redo) only if necessary bool editBlock = m_buffer->editBlockLevel == 0 && !(isInsertMode() && isInsertStateValid()); if (editBlock) beginLargeEditBlock(); g.mapStates << MappingState(inputs.noremap(), inputs.silent(), editBlock); } bool FakeVimHandler::Private::expandCompleteMapping() { if (!g.currentMap.isComplete()) return false; const Inputs &inputs = g.currentMap.inputs(); int usedInputs = g.currentMap.mapLength(); prependInputs(g.currentMap.currentInputs().mid(usedInputs)); prependMapping(inputs); g.currentMap.reset(); return true; } bool FakeVimHandler::Private::extendMapping(const Input &input) { if (!g.currentMap.isValid()) g.currentMap.reset(currentModeCode()); return g.currentMap.walk(input); } void FakeVimHandler::Private::endMapping() { if (!g.currentMap.canExtend()) --g.mapDepth; if (g.mapStates.isEmpty()) return; if (g.mapStates.last().editBlock) endEditBlock(); g.mapStates.pop_back(); if (g.mapStates.isEmpty()) g.commandBuffer.setHistoryAutoSave(true); updateMiniBuffer(); } bool FakeVimHandler::Private::canHandleMapping() { // Don't handle user mapping in sub-modes that cannot be followed by movement and in "noremap". return g.subsubmode == NoSubSubMode && g.submode != RegisterSubMode && g.submode != WindowSubMode && g.submode != ZSubMode && g.submode != CapitalZSubMode && g.submode != ReplaceSubMode && g.submode != MacroRecordSubMode && g.submode != MacroExecuteSubMode && (g.mapStates.isEmpty() || !g.mapStates.last().noremap); } void FakeVimHandler::Private::clearPendingInput() { // Clear pending input on interrupt or bad mapping. g.pendingInput.clear(); g.mapStates.clear(); g.mapDepth = 0; // Clear all started edit blocks. while (m_buffer->editBlockLevel > 0) endEditBlock(); } void FakeVimHandler::Private::waitForMapping() { g.currentCommand.clear(); foreach (const Input &input, g.currentMap.currentInputs()) g.currentCommand.append(input.toString()); updateMiniBuffer(); // wait for user to press any key or trigger complete mapping after interval g.inputTimer = startTimer(1000); } EventResult FakeVimHandler::Private::stopWaitForMapping(bool hasInput) { if (g.inputTimer != -1) { killTimer(g.inputTimer); g.inputTimer = -1; g.currentCommand.clear(); if (!hasInput && !expandCompleteMapping()) { // Cannot complete mapping so handle the first input from it as default command. return handleCurrentMapAsDefault(); } } return EventHandled; } void FakeVimHandler::Private::timerEvent(QTimerEvent *ev) { if (ev->timerId() == g.inputTimer) { enterFakeVim(); EventResult result = handleKey(Input()); leaveFakeVim(result == EventHandled); } } void FakeVimHandler::Private::stopIncrementalFind() { if (g.findPending) { g.findPending = false; setAnchorAndPosition(m_findStartPosition, m_cursor.selectionStart()); finishMovement(); setAnchor(); } } void FakeVimHandler::Private::updateFind(bool isComplete) { if (!isComplete && !hasConfig(ConfigIncSearch)) return; g.currentMessage.clear(); const QString &needle = g.searchBuffer.contents(); if (isComplete) { setPosition(m_searchStartPosition); if (!needle.isEmpty()) recordJump(); } SearchData sd; sd.needle = needle; sd.forward = g.lastSearchForward; sd.highlightMatches = isComplete; search(sd, isComplete); } void FakeVimHandler::Private::resetCount() { g.mvcount = 0; g.opcount = 0; } bool FakeVimHandler::Private::isInputCount(const Input &input) const { return input.isDigit() && (!input.is('0') || g.mvcount > 0); } bool FakeVimHandler::Private::atEmptyLine(const QTextCursor &tc) const { if (tc.isNull()) return atEmptyLine(m_cursor); return tc.block().length() == 1; } bool FakeVimHandler::Private::atBoundary(bool end, bool simple, bool onlyWords, const QTextCursor &tc) const { if (tc.isNull()) return atBoundary(end, simple, onlyWords, m_cursor); if (atEmptyLine(tc)) return true; int pos = tc.position(); QChar c1 = document()->characterAt(pos); QChar c2 = document()->characterAt(pos + (end ? 1 : -1)); int thisClass = charClass(c1, simple); return (!onlyWords || thisClass != 0) && (c2.isNull() || c2 == ParagraphSeparator || thisClass != charClass(c2, simple)); } bool FakeVimHandler::Private::atWordBoundary(bool end, bool simple, const QTextCursor &tc) const { return atBoundary(end, simple, true, tc); } bool FakeVimHandler::Private::atWordStart(bool simple, const QTextCursor &tc) const { return atWordBoundary(false, simple, tc); } bool FakeVimHandler::Private::atWordEnd(bool simple, const QTextCursor &tc) const { return atWordBoundary(true, simple, tc); } bool FakeVimHandler::Private::isFirstNonBlankOnLine(int pos) { for (int i = document()->findBlock(pos).position(); i < pos; ++i) { if (!document()->characterAt(i).isSpace()) return false; } return true; } void FakeVimHandler::Private::pushUndoState(bool overwrite) { if (m_buffer->editBlockLevel != 0 && m_buffer->undoState.isValid()) return; // No need to save undo state for inner edit blocks. if (m_buffer->undoState.isValid() && !overwrite) return; UNDO_DEBUG("PUSH UNDO"); int pos = position(); if (!isInsertMode()) { if (isVisualMode() || g.submode == DeleteSubMode || (g.submode == ChangeSubMode && g.movetype != MoveLineWise)) { pos = qMin(pos, anchor()); if (isVisualLineMode()) pos = firstPositionInLine(lineForPosition(pos)); } else if (g.movetype == MoveLineWise && hasConfig(ConfigStartOfLine)) { QTextCursor tc = m_cursor; if (g.submode == ShiftLeftSubMode || g.submode == ShiftRightSubMode || g.submode == IndentSubMode) { pos = qMin(pos, anchor()); } tc.setPosition(pos); moveToFirstNonBlankOnLine(&tc); pos = qMin(pos, tc.position()); } } m_buffer->redo.clear(); m_buffer->lastChangePosition = CursorPosition(document(), pos); if (isVisualMode()) { setMark(QLatin1Char('<'), markLessPosition()); setMark(QLatin1Char('>'), markGreaterPosition()); } m_buffer->undoState = State(revision(), m_buffer->lastChangePosition, m_buffer->marks, m_buffer->lastVisualMode, m_buffer->lastVisualModeInverted); } void FakeVimHandler::Private::moveDown(int n) { if (n == 0) return; QTextBlock block = m_cursor.block(); const int col = position() - block.position(); int lines = qAbs(n); int position = 0; while (block.isValid()) { position = block.position() + qMax(0, qMin(block.length() - 2, col)); if (block.isVisible()) { --lines; if (lines < 0) break; } block = n > 0 ? nextLine(block) : previousLine(block); } setPosition(position); moveToTargetColumn(); updateScrollOffset(); } void FakeVimHandler::Private::moveDownVisually(int n) { const QTextCursor::MoveOperation moveOperation = (n > 0) ? Down : Up; int count = qAbs(n); int oldPos = m_cursor.position(); while (count > 0) { m_cursor.movePosition(moveOperation, KeepAnchor, 1); if (oldPos == m_cursor.position()) break; oldPos = m_cursor.position(); QTextBlock block = m_cursor.block(); if (block.isVisible()) --count; } QTextCursor tc = m_cursor; tc.movePosition(StartOfLine); const int minPos = tc.position(); moveToEndOfLineVisually(&tc); const int maxPos = tc.position(); if (m_targetColumn == -1) { setPosition(maxPos); } else { setPosition(qMin(maxPos, minPos + m_targetColumnWrapped)); const int targetColumn = m_targetColumnWrapped; setTargetColumn(); m_targetColumnWrapped = targetColumn; } updateScrollOffset(); } void FakeVimHandler::Private::movePageDown(int count) { const int scrollOffset = windowScrollOffset(); const int screenLines = linesOnScreen(); const int offset = count > 0 ? scrollOffset - 2 : screenLines - scrollOffset + 2; const int value = count * screenLines - cursorLineOnScreen() + offset; moveDown(value); if (count > 0) scrollToLine(cursorLine()); else scrollToLine(qMax(0, cursorLine() - screenLines + 1)); } bool FakeVimHandler::Private::moveToNextParagraph(int count) { const bool forward = count > 0; int repeat = forward ? count : -count; int pos = position(); QTextBlock block = this->block(); if (block.isValid() && block.length() == 1) ++repeat; for (; block.isValid(); block = forward ? block.next() : block.previous()) { if (block.length() == 1) { if (--repeat == 0) break; while (block.isValid() && block.length() == 1) block = forward ? block.next() : block.previous(); } } if (repeat == 0) setPosition(block.position()); else if (repeat == 1) setPosition(forward ? lastPositionInDocument() : 0); else return false; recordJump(pos); setTargetColumn(); g.movetype = MoveExclusive; return true; } void FakeVimHandler::Private::moveToEndOfLine() { // Additionally select (in visual mode) or apply current command on hidden lines following // the current line. bool onlyVisibleLines = isVisualMode() || g.submode != NoSubMode; const int id = onlyVisibleLines ? lineNumber(block()) : block().blockNumber() + 1; setPosition(lastPositionInLine(id, onlyVisibleLines)); setTargetColumn(); } void FakeVimHandler::Private::moveToEndOfLineVisually() { moveToEndOfLineVisually(&m_cursor); setTargetColumn(); } void FakeVimHandler::Private::moveToEndOfLineVisually(QTextCursor *tc) { // Moving to end of line ends up on following line if the line is wrapped. tc->movePosition(StartOfLine); const int minPos = tc->position(); tc->movePosition(EndOfLine); int maxPos = tc->position(); tc->movePosition(StartOfLine); if (minPos != tc->position()) --maxPos; tc->setPosition(maxPos); } void FakeVimHandler::Private::moveBehindEndOfLine() { emit q->fold(1, false); int pos = qMin(block().position() + block().length() - 1, lastPositionInDocument() + 1); setPosition(pos); } void FakeVimHandler::Private::moveToStartOfLine() { setPosition(block().position()); setTargetColumn(); } void FakeVimHandler::Private::moveToStartOfLineVisually() { m_cursor.movePosition(StartOfLine, KeepAnchor); setTargetColumn(); } void FakeVimHandler::Private::fixSelection() { if (g.rangemode == RangeBlockMode) return; if (g.movetype == MoveInclusive) { // If position or anchor is after end of non-empty line, include line break in selection. if (document()->characterAt(position()) == ParagraphSeparator) { if (!atEmptyLine()) { setPosition(position() + 1); return; } } else if (document()->characterAt(anchor()) == ParagraphSeparator) { QTextCursor tc = m_cursor; tc.setPosition(anchor()); if (!atEmptyLine(tc)) { setAnchorAndPosition(anchor() + 1, position()); return; } } } if (g.movetype == MoveExclusive && g.subsubmode == NoSubSubMode) { if (anchor() < position() && atBlockStart()) { // Exclusive motion ending at the beginning of line // becomes inclusive and end is moved to end of previous line. g.movetype = MoveInclusive; moveToStartOfLine(); moveLeft(); // Exclusive motion ending at the beginning of line and // starting at or before first non-blank on a line becomes linewise. if (anchor() < block().position() && isFirstNonBlankOnLine(anchor())) g.movetype = MoveLineWise; } } if (g.movetype == MoveLineWise) g.rangemode = (g.submode == ChangeSubMode) ? RangeLineModeExclusive : RangeLineMode; if (g.movetype == MoveInclusive) { if (anchor() <= position()) { if (!atBlockEnd()) setPosition(position() + 1); // correction // Omit first character in selection if it's line break on non-empty line. int start = anchor(); int end = position(); if (afterEndOfLine(document(), start) && start > 0) { start = qMin(start + 1, end); if (g.submode == DeleteSubMode && !atDocumentEnd()) setAnchorAndPosition(start, end + 1); else setAnchorAndPosition(start, end); } // If more than one line is selected and all are selected completely // movement becomes linewise. if (start < block().position() && isFirstNonBlankOnLine(start) && atBlockEnd()) { if (g.submode != ChangeSubMode) { moveRight(); if (atEmptyLine()) moveRight(); } g.movetype = MoveLineWise; } } else if (!m_anchorPastEnd) { setAnchorAndPosition(anchor() + 1, position()); } } if (m_positionPastEnd) { moveBehindEndOfLine(); moveRight(); setAnchorAndPosition(anchor(), position()); } if (m_anchorPastEnd) { const int pos = position(); setPosition(anchor()); moveBehindEndOfLine(); moveRight(); setAnchorAndPosition(position(), pos); } } bool FakeVimHandler::Private::finishSearch() { if (g.lastSearch.isEmpty() || (!g.currentMessage.isEmpty() && g.currentMessageLevel == MessageError)) { return false; } if (g.submode != NoSubMode) setAnchorAndPosition(m_searchStartPosition, position()); return true; } void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement) { //dump("FINISH MOVEMENT"); if (g.submode == FilterSubMode) { int beginLine = lineForPosition(anchor()); int endLine = lineForPosition(position()); setPosition(qMin(anchor(), position())); enterExMode(QString::fromLatin1(".,+%1!").arg(qAbs(endLine - beginLine))); return; } if (g.submode == ChangeSubMode || g.submode == DeleteSubMode || g.submode == YankSubMode || g.submode == InvertCaseSubMode || g.submode == DownCaseSubMode || g.submode == UpCaseSubMode) { fixSelection(); if (g.submode != InvertCaseSubMode && g.submode != DownCaseSubMode && g.submode != UpCaseSubMode) { yankText(currentRange(), m_register); if (g.movetype == MoveLineWise) setRegister(m_register, registerContents(m_register), RangeLineMode); } m_positionPastEnd = m_anchorPastEnd = false; } QString dotCommand; if (g.submode == ChangeSubMode) { pushUndoState(false); beginEditBlock(); removeText(currentRange()); dotCommand = _("c"); if (g.movetype == MoveLineWise) insertAutomaticIndentation(true); endEditBlock(); setTargetColumn(); } else if (g.submode == DeleteSubMode) { pushUndoState(false); beginEditBlock(); const int pos = position(); // Always delete something (e.g. 'dw' on an empty line deletes the line). if (pos == anchor() && g.movetype == MoveInclusive) removeText(Range(pos, pos + 1)); else removeText(currentRange()); dotCommand = _("d"); if (g.movetype == MoveLineWise) handleStartOfLine(); if (atEndOfLine()) moveLeft(); else setTargetColumn(); endEditBlock(); } else if (g.submode == YankSubMode) { bool isVisualModeYank = isVisualMode(); leaveVisualMode(); const QTextCursor tc = m_cursor; if (g.rangemode == RangeBlockMode) { const int pos1 = tc.block().position(); const int pos2 = document()->findBlock(tc.anchor()).position(); const int col = qMin(tc.position() - pos1, tc.anchor() - pos2); setPosition(qMin(pos1, pos2) + col); } else { setPosition(qMin(position(), anchor())); if (g.rangemode == RangeLineMode) { if (isVisualModeYank) moveToStartOfLine(); } } setTargetColumn(); } else if (g.submode == InvertCaseSubMode || g.submode == UpCaseSubMode || g.submode == DownCaseSubMode) { beginEditBlock(); if (g.submode == InvertCaseSubMode) { invertCase(currentRange()); dotCommand = QString::fromLatin1("g~"); } else if (g.submode == DownCaseSubMode) { downCase(currentRange()); dotCommand = QString::fromLatin1("gu"); } else if (g.submode == UpCaseSubMode) { upCase(currentRange()); dotCommand = QString::fromLatin1("gU"); } if (g.movetype == MoveLineWise) handleStartOfLine(); endEditBlock(); } else if (g.submode == IndentSubMode || g.submode == ShiftRightSubMode || g.submode == ShiftLeftSubMode) { recordJump(); pushUndoState(false); if (g.submode == IndentSubMode) { indentSelectedText(); dotCommand = _("="); } else if (g.submode == ShiftRightSubMode) { shiftRegionRight(1); dotCommand = _(">"); } else if (g.submode == ShiftLeftSubMode) { shiftRegionLeft(1); dotCommand = _("<"); } } if (!dotCommand.isEmpty() && !dotCommandMovement.isEmpty()) setDotCommand(dotCommand + dotCommandMovement); // Change command continues in insert mode. if (g.submode == ChangeSubMode) { clearCommandMode(); enterInsertMode(); } else { resetCommandMode(); } } void FakeVimHandler::Private::resetCommandMode() { if (g.returnToMode == CommandMode) { enterCommandMode(); } else { clearCommandMode(); const QString lastInsertion = m_buffer->lastInsertion; if (g.returnToMode == InsertMode) enterInsertMode(); else enterReplaceMode(); moveToTargetColumn(); invalidateInsertState(); m_buffer->lastInsertion = lastInsertion; } if (isNoVisualMode()) setAnchor(); } void FakeVimHandler::Private::clearCommandMode() { g.submode = NoSubMode; g.subsubmode = NoSubSubMode; g.movetype = MoveInclusive; g.gflag = false; m_register = '"'; g.rangemode = RangeCharMode; g.currentCommand.clear(); resetCount(); } void FakeVimHandler::Private::updateSelection() { QList selections = m_extraSelections; if (hasConfig(ConfigShowMarks)) { for (MarksIterator it(m_buffer->marks); it.hasNext(); ) { it.next(); QTextEdit::ExtraSelection sel; sel.cursor = m_cursor; setCursorPosition(&sel.cursor, it.value().position(document())); sel.cursor.setPosition(sel.cursor.position(), MoveAnchor); sel.cursor.movePosition(Right, KeepAnchor); sel.format = m_cursor.blockCharFormat(); sel.format.setForeground(Qt::blue); sel.format.setBackground(Qt::green); selections.append(sel); } } //qDebug() << "SELECTION: " << selections; emit q->selectionChanged(selections); } void FakeVimHandler::Private::updateHighlights() { if (hasConfig(ConfigUseCoreSearch) || !hasConfig(ConfigHlSearch) || g.highlightsCleared) { if (m_highlighted.isEmpty()) return; m_highlighted.clear(); } else if (m_highlighted != g.lastNeedle) { m_highlighted = g.lastNeedle; } else { return; } emit q->highlightMatches(m_highlighted); } void FakeVimHandler::Private::updateMiniBuffer() { if (!m_textedit && !m_plaintextedit) return; QString msg; int cursorPos = -1; int anchorPos = -1; MessageLevel messageLevel = MessageMode; if (!g.mapStates.isEmpty() && g.mapStates.last().silent && g.currentMessageLevel < MessageInfo) g.currentMessage.clear(); if (g.passing) { msg = _("PASSING"); } else if (g.subsubmode == SearchSubSubMode) { msg = g.searchBuffer.display(); if (g.mapStates.isEmpty()) { cursorPos = g.searchBuffer.cursorPos() + 1; anchorPos = g.searchBuffer.anchorPos() + 1; } } else if (g.mode == ExMode) { msg = g.commandBuffer.display(); if (g.mapStates.isEmpty()) { cursorPos = g.commandBuffer.cursorPos() + 1; anchorPos = g.commandBuffer.anchorPos() + 1; } } else if (!g.currentMessage.isEmpty()) { msg = g.currentMessage; g.currentMessage.clear(); messageLevel = g.currentMessageLevel; } else if (!g.mapStates.isEmpty() && !g.mapStates.last().silent) { // Do not reset previous message when after running a mapped command. return; } else if (g.mode == CommandMode && !g.currentCommand.isEmpty() && hasConfig(ConfigShowCmd)) { msg = g.currentCommand; messageLevel = MessageShowCmd; } else if (g.mode == CommandMode && isVisualMode()) { if (isVisualCharMode()) msg = _("-- VISUAL --"); else if (isVisualLineMode()) msg = _("-- VISUAL LINE --"); else if (isVisualBlockMode()) msg = _("VISUAL BLOCK"); } else if (g.mode == InsertMode) { msg = _("-- INSERT --"); } else if (g.mode == ReplaceMode) { msg = _("-- REPLACE --"); } else { QTC_CHECK(g.mode == CommandMode && g.subsubmode != SearchSubSubMode); if (g.returnToMode == CommandMode) msg = _("-- COMMAND --"); else if (g.returnToMode == InsertMode) msg = _("-- (insert) --"); else msg = _("-- (replace) --"); } if (!g.recording.isNull() && msg.startsWith(_("--"))) msg.append(_("recording")); emit q->commandBufferChanged(msg, cursorPos, anchorPos, messageLevel, q); int linesInDoc = linesInDocument(); int l = cursorLine(); QString status; const QString pos = QString::fromLatin1("%1,%2") .arg(l + 1).arg(physicalCursorColumn() + 1); // FIXME: physical "-" logical if (linesInDoc != 0) status = FakeVimHandler::tr("%1%2%").arg(pos, -10).arg(l * 100 / linesInDoc, 4); else status = FakeVimHandler::tr("%1All").arg(pos, -10); emit q->statusDataChanged(status); } void FakeVimHandler::Private::showMessage(MessageLevel level, const QString &msg) { //qDebug() << "MSG: " << msg; g.currentMessage = msg; g.currentMessageLevel = level; } void FakeVimHandler::Private::notImplementedYet() { qDebug() << "Not implemented in FakeVim"; showMessage(MessageError, FakeVimHandler::tr("Not implemented in FakeVim.")); } void FakeVimHandler::Private::passShortcuts(bool enable) { g.passing = enable; updateMiniBuffer(); if (enable) QCoreApplication::instance()->installEventFilter(q); else QCoreApplication::instance()->removeEventFilter(q); } bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input) { //const int key = input.key; bool handled = true; if (g.subsubmode == FtSubSubMode) { g.semicolonType = g.subsubdata; g.semicolonKey = input.text(); bool valid = handleFfTt(g.semicolonKey); g.subsubmode = NoSubSubMode; if (!valid) { g.submode = NoSubMode; resetCommandMode(); handled = false; } else { finishMovement(QString::fromLatin1("%1%2%3") .arg(count()) .arg(g.semicolonType.text()) .arg(g.semicolonKey)); } } else if (g.subsubmode == TextObjectSubSubMode) { bool ok = true; if (input.is('w')) selectWordTextObject(g.subsubdata.is('i')); else if (input.is('W')) selectWORDTextObject(g.subsubdata.is('i')); else if (input.is('s')) selectSentenceTextObject(g.subsubdata.is('i')); else if (input.is('p')) selectParagraphTextObject(g.subsubdata.is('i')); else if (input.is('[') || input.is(']')) ok = selectBlockTextObject(g.subsubdata.is('i'), '[', ']'); else if (input.is('(') || input.is(')') || input.is('b')) ok = selectBlockTextObject(g.subsubdata.is('i'), '(', ')'); else if (input.is('<') || input.is('>')) ok = selectBlockTextObject(g.subsubdata.is('i'), '<', '>'); else if (input.is('{') || input.is('}') || input.is('B')) ok = selectBlockTextObject(g.subsubdata.is('i'), '{', '}'); else if (input.is('"') || input.is('\'') || input.is('`')) ok = selectQuotedStringTextObject(g.subsubdata.is('i'), input.asChar()); else ok = false; g.subsubmode = NoSubSubMode; if (ok) { finishMovement(QString::fromLatin1("%1%2%3") .arg(count()) .arg(g.subsubdata.text()) .arg(input.text())); } else { resetCommandMode(); handled = false; } } else if (g.subsubmode == MarkSubSubMode) { setMark(input.asChar(), CursorPosition(m_cursor)); g.subsubmode = NoSubSubMode; } else if (g.subsubmode == BackTickSubSubMode || g.subsubmode == TickSubSubMode) { if (jumpToMark(input.asChar(), g.subsubmode == BackTickSubSubMode)) { finishMovement(); } else { resetCommandMode(); handled = false; } g.subsubmode = NoSubSubMode; } else if (g.subsubmode == ZSubSubMode) { handled = false; if (input.is('j') || input.is('k')) { int pos = position(); emit q->foldGoTo(input.is('j') ? count() : -count(), false); if (pos != position()) { handled = true; finishMovement(QString::fromLatin1("%1z%2") .arg(count()) .arg(input.text())); } } } else if (g.subsubmode == OpenSquareSubSubMode || g.subsubmode == CloseSquareSubSubMode) { int pos = position(); if (input.is('{') && g.subsubmode == OpenSquareSubSubMode) searchBalanced(false, QLatin1Char('{'), QLatin1Char('}')); else if (input.is('}') && g.subsubmode == CloseSquareSubSubMode) searchBalanced(true, QLatin1Char('}'), QLatin1Char('{')); else if (input.is('(') && g.subsubmode == OpenSquareSubSubMode) searchBalanced(false, QLatin1Char('('), QLatin1Char(')')); else if (input.is(')') && g.subsubmode == CloseSquareSubSubMode) searchBalanced(true, QLatin1Char(')'), QLatin1Char('(')); else if (input.is('[') && g.subsubmode == OpenSquareSubSubMode) bracketSearchBackward(&m_cursor, _("^\\{"), count()); else if (input.is('[') && g.subsubmode == CloseSquareSubSubMode) bracketSearchForward(&m_cursor, _("^\\}"), count(), false); else if (input.is(']') && g.subsubmode == OpenSquareSubSubMode) bracketSearchBackward(&m_cursor, _("^\\}"), count()); else if (input.is(']') && g.subsubmode == CloseSquareSubSubMode) bracketSearchForward(&m_cursor, _("^\\{"), count(), g.submode != NoSubMode); else if (input.is('z')) emit q->foldGoTo(g.subsubmode == OpenSquareSubSubMode ? -count() : count(), true); handled = pos != position(); if (handled) { if (lineForPosition(pos) != lineForPosition(position())) recordJump(pos); finishMovement(QString::fromLatin1("%1%2%3") .arg(count()) .arg(g.subsubmode == OpenSquareSubSubMode ? '[' : ']') .arg(input.text())); } } else { handled = false; } return handled; } bool FakeVimHandler::Private::handleCount(const Input &input) { if (!isInputCount(input)) return false; g.mvcount = g.mvcount * 10 + input.text().toInt(); return true; } bool FakeVimHandler::Private::handleMovement(const Input &input) { bool handled = true; QString movement; int count = this->count(); if (handleCount(input)) { return true; } else if (input.is('0')) { g.movetype = MoveExclusive; if (g.gflag) moveToStartOfLineVisually(); else moveToStartOfLine(); count = 1; } else if (input.is('a') || input.is('i')) { g.subsubmode = TextObjectSubSubMode; g.subsubdata = input; } else if (input.is('^') || input.is('_')) { if (g.gflag) moveToFirstNonBlankOnLineVisually(); else moveToFirstNonBlankOnLine(); g.movetype = MoveExclusive; } else if (0 && input.is(',')) { // FIXME: fakevim uses ',' by itself, so it is incompatible g.subsubmode = FtSubSubMode; // HACK: toggle 'f' <-> 'F', 't' <-> 'T' //g.subsubdata = g.semicolonType ^ 32; handleFfTt(g.semicolonKey, true); g.subsubmode = NoSubSubMode; } else if (input.is(';')) { g.subsubmode = FtSubSubMode; g.subsubdata = g.semicolonType; handleFfTt(g.semicolonKey, true); g.subsubmode = NoSubSubMode; } else if (input.is('/') || input.is('?')) { g.lastSearchForward = input.is('/'); if (hasConfig(ConfigUseCoreSearch)) { // re-use the core dialog. g.findPending = true; m_findStartPosition = position(); g.movetype = MoveExclusive; setAnchor(); // clear selection: otherwise, search is restricted to selection emit q->findRequested(!g.lastSearchForward); } else { // FIXME: make core find dialog sufficiently flexible to // produce the "default vi" behaviour too. For now, roll our own. g.currentMessage.clear(); g.movetype = MoveExclusive; g.subsubmode = SearchSubSubMode; g.searchBuffer.setPrompt(g.lastSearchForward ? QLatin1Char('/') : QLatin1Char('?')); m_searchStartPosition = position(); m_searchFromScreenLine = firstVisibleLine(); m_searchCursor = QTextCursor(); g.searchBuffer.clear(); } } else if (input.is('`')) { g.subsubmode = BackTickSubSubMode; } else if (input.is('#') || input.is('*')) { // FIXME: That's not proper vim behaviour QString needle; QTextCursor tc = m_cursor; tc.select(QTextCursor::WordUnderCursor); needle = QRegExp::escape(tc.selection().toPlainText()); if (!g.gflag) needle = _("\\<") + needle + _("\\>"); setAnchorAndPosition(tc.position(), tc.anchor()); g.searchBuffer.historyPush(needle); g.lastSearch = needle; g.lastSearchForward = input.is('*'); handled = searchNext(); } else if (input.is('\'')) { g.subsubmode = TickSubSubMode; if (g.submode != NoSubMode) g.movetype = MoveLineWise; } else if (input.is('|')) { moveToStartOfLine(); moveRight(qMin(count, rightDist()) - 1); setTargetColumn(); } else if (input.is('}')) { handled = moveToNextParagraph(count); } else if (input.is('{')) { handled = moveToPreviousParagraph(count); } else if (input.isReturn()) { moveToStartOfLine(); moveDown(); moveToFirstNonBlankOnLine(); g.movetype = MoveLineWise; } else if (input.is('-')) { moveToStartOfLine(); moveUp(count); moveToFirstNonBlankOnLine(); g.movetype = MoveLineWise; } else if (input.is('+')) { moveToStartOfLine(); moveDown(count); moveToFirstNonBlankOnLine(); g.movetype = MoveLineWise; } else if (input.isKey(Key_Home)) { moveToStartOfLine(); setTargetColumn(); movement = _(""); } else if (input.is('$') || input.isKey(Key_End)) { if (g.gflag) { if (count > 1) moveDownVisually(count - 1); moveToEndOfLineVisually(); } else { if (count > 1) moveDown(count - 1); moveToEndOfLine(); } g.movetype = atEmptyLine() ? MoveExclusive : MoveInclusive; setTargetColumn(); if (g.submode == NoSubMode) m_targetColumn = -1; if (isVisualMode()) m_visualTargetColumn = -1; movement = _("$"); } else if (input.is('%')) { recordJump(); if (g.mvcount == 0) { moveToMatchingParanthesis(); g.movetype = MoveInclusive; } else { // set cursor position in percentage - formula taken from Vim help setPosition(firstPositionInLine((count * linesInDocument() + 99) / 100)); moveToTargetColumn(); handleStartOfLine(); g.movetype = MoveLineWise; } } else if (input.is('b') || input.isShift(Key_Left)) { g.movetype = MoveExclusive; moveToNextWordStart(count, false, false); setTargetColumn(); movement = _("b"); } else if (input.is('B')) { g.movetype = MoveExclusive; moveToNextWordStart(count, true, false); setTargetColumn(); } else if (input.is('e') && g.gflag) { g.movetype = MoveInclusive; moveToNextWordEnd(count, false, false); setTargetColumn(); } else if (input.is('e') || input.isShift(Key_Right)) { g.movetype = MoveInclusive; moveToNextWordEnd(count, false, true, false); setTargetColumn(); movement = _("e"); } else if (input.is('E') && g.gflag) { g.movetype = MoveInclusive; moveToNextWordEnd(count, true, false); setTargetColumn(); } else if (input.is('E')) { g.movetype = MoveInclusive; moveToNextWordEnd(count, true, true, false); setTargetColumn(); } else if (input.isControl('e')) { // FIXME: this should use the "scroll" option, and "count" if (cursorLineOnScreen() == 0) moveDown(1); scrollDown(1); movement = _(""); } else if (input.is('f')) { g.subsubmode = FtSubSubMode; g.movetype = MoveInclusive; g.subsubdata = input; } else if (input.is('F')) { g.subsubmode = FtSubSubMode; g.movetype = MoveExclusive; g.subsubdata = input; } else if (!g.gflag && input.is('g')) { g.gflag = true; return true; } else if (input.is('g') || input.is('G')) { QString dotCommand = QString::fromLatin1("%1G").arg(count); recordJump(); if (input.is('G') && g.mvcount == 0) dotCommand = QString(QLatin1Char('G')); int n = (input.is('g')) ? 1 : linesInDocument(); n = g.mvcount == 0 ? n : count; if (g.submode == NoSubMode || g.submode == ZSubMode || g.submode == CapitalZSubMode || g.submode == RegisterSubMode) { setPosition(firstPositionInLine(n, false)); handleStartOfLine(); } else { g.movetype = MoveLineWise; g.rangemode = RangeLineMode; setAnchor(); setPosition(firstPositionInLine(n, false)); } setTargetColumn(); updateScrollOffset(); } else if (input.is('h') || input.isKey(Key_Left) || input.isBackspace()) { g.movetype = MoveExclusive; int n = qMin(count, leftDist()); if (m_fakeEnd && block().length() > 1) ++n; moveLeft(n); setTargetColumn(); movement = _("h"); } else if (input.is('H')) { const CursorPosition pos(lineToBlockNumber(lineOnTop(count)), 0); setCursorPosition(&m_cursor, pos); handleStartOfLine(); } else if (input.is('j') || input.isKey(Key_Down) || input.isControl('j') || input.isControl('n')) { if (g.gflag) { g.movetype = MoveExclusive; moveDownVisually(count); movement = _("gj"); } else { g.movetype = MoveLineWise; moveDown(count); movement = _("j"); } } else if (input.is('k') || input.isKey(Key_Up) || input.isControl('p')) { if (g.gflag) { g.movetype = MoveExclusive; moveUpVisually(count); movement = _("gk"); } else { g.movetype = MoveLineWise; moveUp(count); movement = _("k"); } } else if (input.is('l') || input.isKey(Key_Right) || input.is(' ')) { g.movetype = MoveExclusive; bool pastEnd = count >= rightDist() - 1; moveRight(qMax(0, qMin(count, rightDist() - (g.submode == NoSubMode)))); setTargetColumn(); if (pastEnd && isVisualMode()) m_visualTargetColumn = -1; } else if (input.is('L')) { const CursorPosition pos(lineToBlockNumber(lineOnBottom(count)), 0); setCursorPosition(&m_cursor, pos); handleStartOfLine(); } else if (g.gflag && input.is('m')) { const QPoint pos(EDITOR(viewport()->width()) / 2, EDITOR(cursorRect(m_cursor)).y()); QTextCursor tc = EDITOR(cursorForPosition(pos)); if (!tc.isNull()) { m_cursor = tc; setTargetColumn(); } } else if (input.is('M')) { m_cursor = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()) / 2))); handleStartOfLine(); } else if (input.is('n') || input.is('N')) { if (hasConfig(ConfigUseCoreSearch)) { bool forward = (input.is('n')) ? g.lastSearchForward : !g.lastSearchForward; int pos = position(); emit q->findNextRequested(!forward); if (forward && pos == m_cursor.selectionStart()) { // if cursor is already positioned at the start of a find result, this is returned emit q->findNextRequested(false); } setPosition(m_cursor.selectionStart()); } else { handled = searchNext(input.is('n')); } } else if (input.is('t')) { g.movetype = MoveInclusive; g.subsubmode = FtSubSubMode; g.subsubdata = input; } else if (input.is('T')) { g.movetype = MoveExclusive; g.subsubmode = FtSubSubMode; g.subsubdata = input; } else if (input.is('w') || input.is('W')) { // tested // Special case: "cw" and "cW" work the same as "ce" and "cE" if the // cursor is on a non-blank - except if the cursor is on the last // character of a word: only the current word will be changed bool simple = input.is('W'); if (g.submode == ChangeSubMode && !document()->characterAt(position()).isSpace()) { moveToWordEnd(count, simple, true); g.movetype = MoveInclusive; } else { moveToNextWordStart(count, simple, true); // Command 'dw' deletes to the next word on the same line or to end of line. if (g.submode == DeleteSubMode && count == 1) { const QTextBlock currentBlock = document()->findBlock(anchor()); setPosition(qMin(position(), currentBlock.position() + currentBlock.length())); } g.movetype = MoveExclusive; } setTargetColumn(); } else if (input.is('z')) { g.movetype = MoveLineWise; g.subsubmode = ZSubSubMode; } else if (input.is('[')) { g.subsubmode = OpenSquareSubSubMode; } else if (input.is(']')) { g.subsubmode = CloseSquareSubSubMode; } else if (input.isKey(Key_PageDown) || input.isControl('f')) { movePageDown(count); handleStartOfLine(); movement = _("f"); } else if (input.isKey(Key_PageUp) || input.isControl('b')) { movePageUp(count); handleStartOfLine(); movement = _("b"); } else { handled = false; } if (handled && g.subsubmode == NoSubSubMode) { if (g.submode == NoSubMode) { resetCommandMode(); } else { // finish movement for sub modes const QString dotMovement = (count > 1 ? QString::number(count) : QString()) + _(g.gflag ? "g" : "") + (movement.isNull() ? QString(input.asChar()) : movement); finishMovement(dotMovement); setTargetColumn(); } } return handled; } EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) { bool handled = false; bool clearGflag = g.gflag; bool clearRegister = g.submode != RegisterSubMode; bool clearCount = g.submode != RegisterSubMode && !isInputCount(input); // Process input for a sub-mode. if (input.isEscape()) { handled = handleEscape(); } else if (g.subsubmode != NoSubSubMode) { handled = handleCommandSubSubMode(input); } else if (g.submode == NoSubMode) { handled = handleNoSubMode(input); } else if (g.submode == ChangeSubMode || g.submode == DeleteSubMode) { handled = handleChangeDeleteSubModes(input); } else if (g.submode == ReplaceSubMode) { handled = handleReplaceSubMode(input); } else if (g.submode == FilterSubMode) { handled = handleFilterSubMode(input); } else if (g.submode == RegisterSubMode) { handled = handleRegisterSubMode(input); } else if (g.submode == WindowSubMode) { handled = handleWindowSubMode(input); } else if (g.submode == YankSubMode) { handled = handleYankSubMode(input); } else if (g.submode == ZSubMode) { handled = handleZSubMode(input); } else if (g.submode == CapitalZSubMode) { handled = handleCapitalZSubMode(input); } else if (g.submode == MacroRecordSubMode) { handled = handleMacroRecordSubMode(input); } else if (g.submode == MacroExecuteSubMode) { handled = handleMacroExecuteSubMode(input); } else if (g.submode == ShiftLeftSubMode || g.submode == ShiftRightSubMode || g.submode == IndentSubMode) { handled = handleShiftSubMode(input); } else if (g.submode == InvertCaseSubMode || g.submode == DownCaseSubMode || g.submode == UpCaseSubMode) { handled = handleChangeCaseSubMode(input); } if (!handled && isOperatorPending()) handled = handleMovement(input); // Clear state and display incomplete command if necessary. if (handled) { bool noMode = (g.mode == CommandMode && g.submode == NoSubMode && g.subsubmode == NoSubSubMode); clearCount = clearCount && noMode && !g.gflag; if (clearCount && clearRegister) { resetCommandMode(); } else { // Use gflag only for next input. if (clearGflag) g.gflag = false; // Clear [count] and [register] if its no longer needed. if (clearCount) resetCount(); // Show or clear current command on minibuffer (showcmd). if (input.isEscape() || g.mode != CommandMode || clearCount) g.currentCommand.clear(); else g.currentCommand.append(input.toString()); } } else { resetCommandMode(); //qDebug() << "IGNORED IN COMMAND MODE: " << key << text // << " VISUAL: " << g.visualMode; // if a key which produces text was pressed, don't mark it as unhandled // - otherwise the text would be inserted while being in command mode if (input.text().isEmpty()) handled = false; } updateMiniBuffer(); m_positionPastEnd = (m_visualTargetColumn == -1) && isVisualMode() && !atEmptyLine(); return handled ? EventHandled : EventCancelled; } bool FakeVimHandler::Private::handleEscape() { if (isVisualMode()) leaveVisualMode(); resetCommandMode(); return true; } bool FakeVimHandler::Private::handleNoSubMode(const Input &input) { bool handled = true; if (input.is('&')) { handleExCommand(g.gflag ? _("%s//~/&") : _("s")); } else if (input.is(':')) { enterExMode(); } else if (input.is('!') && isNoVisualMode()) { g.submode = FilterSubMode; } else if (input.is('!') && isVisualMode()) { enterExMode(QString::fromLatin1("!")); } else if (input.is('"')) { g.submode = RegisterSubMode; } else if (input.is(',')) { passShortcuts(true); } else if (input.is('.')) { //qDebug() << "REPEATING" << quoteUnprintable(g.dotCommand) << count() // << input; QString savedCommand = g.dotCommand; g.dotCommand.clear(); beginLargeEditBlock(); replay(savedCommand); endEditBlock(); resetCommandMode(); g.dotCommand = savedCommand; } else if (input.is('<') || input.is('>') || input.is('=')) { if (isNoVisualMode()) { if (input.is('<')) g.submode = ShiftLeftSubMode; else if (input.is('>')) g.submode = ShiftRightSubMode; else g.submode = IndentSubMode; setAnchor(); } else { leaveVisualMode(); const int lines = qAbs(lineForPosition(position()) - lineForPosition(anchor())) + 1; const int repeat = count(); if (input.is('<')) shiftRegionLeft(repeat); else if (input.is('>')) shiftRegionRight(repeat); else indentSelectedText(); const QString selectDotCommand = (lines > 1) ? QString::fromLatin1("V%1j").arg(lines - 1): QString(); setDotCommand(selectDotCommand + QString::fromLatin1("%1%2%2").arg(repeat).arg(input.raw())); } } else if ((!isVisualMode() && input.is('a')) || (isVisualMode() && input.is('A'))) { if (isVisualMode()) { enterVisualInsertMode(QLatin1Char('A')); } else { setDotCommand(_("%1a"), count()); moveRight(qMin(rightDist(), 1)); breakEditBlock(); enterInsertMode(); } } else if (input.is('A')) { breakEditBlock(); moveBehindEndOfLine(); setAnchor(); enterInsertMode(); setTargetColumn(); setDotCommand(_("%1A"), count()); } else if (input.isControl('a')) { if (changeNumberTextObject(count())) setDotCommand(_("%1"), count()); } else if ((input.is('c') || input.is('d')) && isNoVisualMode()) { setAnchor(); g.opcount = g.mvcount; g.mvcount = 0; g.rangemode = RangeCharMode; g.movetype = MoveExclusive; g.submode = input.is('c') ? ChangeSubMode : DeleteSubMode; } else if ((input.is('c') || input.is('C') || input.is('s') || input.is('R')) && (isVisualCharMode() || isVisualLineMode())) { setDotCommand(visualDotCommand() + input.asChar()); leaveVisualMode(); g.submode = ChangeSubMode; finishMovement(); } else if ((input.is('c') || input.is('s')) && isVisualBlockMode()) { resetCount(); enterVisualInsertMode(input.asChar()); } else if (input.is('C')) { setAnchor(); moveToEndOfLine(); g.rangemode = RangeCharMode; g.submode = ChangeSubMode; setDotCommand(QString(QLatin1Char('C'))); finishMovement(); } else if (input.isControl('c')) { if (isNoVisualMode()) showMessage(MessageInfo, tr("Type Alt-V, Alt-V to quit FakeVim mode.")); else leaveVisualMode(); } else if ((input.is('d') || input.is('x') || input.isKey(Key_Delete)) && isVisualMode()) { pushUndoState(); setDotCommand(visualDotCommand() + QLatin1Char('x')); if (isVisualCharMode()) { leaveVisualMode(); g.submode = DeleteSubMode; finishMovement(); } else if (isVisualLineMode()) { leaveVisualMode(); yankText(currentRange(), m_register); removeText(currentRange()); handleStartOfLine(); } else if (isVisualBlockMode()) { leaveVisualMode(); yankText(currentRange(), m_register); removeText(currentRange()); setPosition(qMin(position(), anchor())); } } else if (input.is('D') && isNoVisualMode()) { pushUndoState(); if (atEndOfLine()) moveLeft(); g.submode = DeleteSubMode; g.movetype = MoveInclusive; setAnchorAndPosition(position(), lastPositionInLine(cursorLine() + count())); setDotCommand(QString(QLatin1Char('D'))); finishMovement(); setTargetColumn(); } else if ((input.is('D') || input.is('X')) && (isVisualCharMode() || isVisualLineMode())) { setDotCommand(visualDotCommand() + QLatin1Char('X')); leaveVisualMode(); g.rangemode = RangeLineMode; g.submode = NoSubMode; yankText(currentRange(), m_register); removeText(currentRange()); moveToFirstNonBlankOnLine(); } else if ((input.is('D') || input.is('X')) && isVisualBlockMode()) { setDotCommand(visualDotCommand() + QLatin1Char('X')); leaveVisualMode(); g.rangemode = RangeBlockAndTailMode; yankText(currentRange(), m_register); removeText(currentRange()); setPosition(qMin(position(), anchor())); } else if (input.isControl('d')) { const int scrollOffset = windowScrollOffset(); int sline = cursorLine() < scrollOffset ? scrollOffset : cursorLineOnScreen(); // FIXME: this should use the "scroll" option, and "count" moveDown(linesOnScreen() / 2); handleStartOfLine(); scrollToLine(cursorLine() - sline); } else if (!g.gflag && input.is('g')) { g.gflag = true; } else if (!isVisualMode() && (input.is('i') || input.isKey(Key_Insert))) { setDotCommand(_("%1i"), count()); breakEditBlock(); enterInsertMode(); if (atEndOfLine()) moveLeft(); } else if (input.is('I')) { if (isVisualMode()) { enterVisualInsertMode(QLatin1Char('I')); } else { if (g.gflag) { setDotCommand(_("%1gI"), count()); moveToStartOfLine(); } else { setDotCommand(_("%1I"), count()); moveToFirstNonBlankOnLine(); } breakEditBlock(); enterInsertMode(); } } else if (input.isControl('i')) { jump(count()); } else if (input.is('J')) { pushUndoState(); moveBehindEndOfLine(); beginEditBlock(); if (g.submode == NoSubMode) joinLines(count(), g.gflag); endEditBlock(); setDotCommand(_("%1J"), count()); } else if (input.isControl('l')) { // screen redraw. should not be needed } else if (!g.gflag && input.is('m')) { g.subsubmode = MarkSubSubMode; } else if (isVisualMode() && (input.is('o') || input.is('O'))) { int pos = position(); setAnchorAndPosition(pos, anchor()); std::swap(m_positionPastEnd, m_anchorPastEnd); setTargetColumn(); if (m_positionPastEnd) m_visualTargetColumn = -1; } else if (input.is('o') || input.is('O')) { bool insertAfter = input.is('o'); setDotCommand(_(insertAfter ? "%1o" : "%1O"), count()); pushUndoState(); // Prepend line only if on the first line and command is 'O'. bool appendLine = true; if (!insertAfter) { if (block().blockNumber() == 0) appendLine = false; else moveUp(); } const int line = lineNumber(block()); beginEditBlock(); enterInsertMode(); setPosition(appendLine ? lastPositionInLine(line) : firstPositionInLine(line)); clearLastInsertion(); setAnchor(); insertNewLine(); if (appendLine) { m_buffer->insertState.newLineBefore = true; } else { moveUp(); m_oldInternalPosition = position(); m_buffer->insertState.pos1 = m_oldInternalPosition; m_buffer->insertState.newLineAfter = true; } setTargetColumn(); endEditBlock(); // Close accidentally opened block. if (block().blockNumber() > 0) { moveUp(); if (line != lineNumber(block())) emit q->fold(1, true); moveDown(); } } else if (input.isControl('o')) { jump(-count()); } else if (input.is('p') || input.is('P') || input.isShift(Qt::Key_Insert)) { pasteText(!input.is('P')); setTargetColumn(); setDotCommand(_("%1p"), count()); finishMovement(); } else if (input.is('q')) { if (g.recording.isNull()) { // Recording shouldn't work in mapping or while executing register. handled = g.mapStates.empty(); if (handled) g.submode = MacroRecordSubMode; } else { // Stop recording. stopRecording(); } } else if (input.is('r')) { g.submode = ReplaceSubMode; } else if (!isVisualMode() && input.is('R')) { pushUndoState(); breakEditBlock(); enterReplaceMode(); } else if (input.isControl('r')) { int repeat = count(); while (--repeat >= 0) redo(); } else if (input.is('s')) { pushUndoState(); leaveVisualMode(); if (atEndOfLine()) moveLeft(); setAnchor(); moveRight(qMin(count(), rightDist())); setDotCommand(_("%1s"), count()); g.submode = ChangeSubMode; g.movetype = MoveExclusive; finishMovement(); } else if (input.is('S')) { g.movetype = MoveLineWise; pushUndoState(); if (!isVisualMode()) { const int line = cursorLine() + 1; const int anc = firstPositionInLine(line); const int pos = lastPositionInLine(line + count() - 1); setAnchorAndPosition(anc, pos); } setDotCommand(_("%1S"), count()); g.submode = ChangeSubMode; finishMovement(); } else if (g.gflag && input.is('t')) { handleExCommand(_("tabnext")); } else if (g.gflag && input.is('T')) { handleExCommand(_("tabprev")); } else if (input.isControl('t')) { handleExCommand(_("pop")); } else if (!g.gflag && input.is('u') && !isVisualMode()) { int repeat = count(); while (--repeat >= 0) undo(); } else if (input.isControl('u')) { int sline = cursorLineOnScreen(); // FIXME: this should use the "scroll" option, and "count" moveUp(linesOnScreen() / 2); handleStartOfLine(); scrollToLine(cursorLine() - sline); } else if (g.gflag && input.is('v')) { if (m_buffer->lastVisualMode != NoVisualMode) { CursorPosition from = markLessPosition(); CursorPosition to = markGreaterPosition(); toggleVisualMode(m_buffer->lastVisualMode); setCursorPosition(m_buffer->lastVisualModeInverted ? to : from); setAnchor(); setCursorPosition(m_buffer->lastVisualModeInverted ? from : to); setTargetColumn(); } } else if (input.is('v')) { toggleVisualMode(VisualCharMode); } else if (input.is('V')) { toggleVisualMode(VisualLineMode); } else if (input.isControl('v')) { toggleVisualMode(VisualBlockMode); } else if (input.isControl('w')) { g.submode = WindowSubMode; } else if (input.is('x') && isNoVisualMode()) { // = _("dl") g.movetype = MoveExclusive; g.submode = DeleteSubMode; const int n = qMin(count(), rightDist()); setAnchorAndPosition(position(), position() + n); setDotCommand(_("%1x"), count()); finishMovement(); } else if (input.isControl('x')) { if (changeNumberTextObject(-count())) setDotCommand(_("%1"), count()); } else if (input.is('X')) { if (leftDist() > 0) { setAnchor(); moveLeft(qMin(count(), leftDist())); yankText(currentRange(), m_register); removeText(currentRange()); } } else if (input.is('Y') && isNoVisualMode()) { handleYankSubMode(Input(QLatin1Char('y'))); } else if (input.isControl('y')) { // FIXME: this should use the "scroll" option, and "count" if (cursorLineOnScreen() == linesOnScreen() - 1) moveUp(1); scrollUp(1); } else if (input.is('y') && isNoVisualMode()) { setAnchor(); g.rangemode = RangeCharMode; g.movetype = MoveExclusive; g.submode = YankSubMode; } else if (input.is('y') && isVisualCharMode()) { g.rangemode = RangeCharMode; g.movetype = MoveInclusive; g.submode = YankSubMode; finishMovement(); } else if ((input.is('y') && isVisualLineMode()) || (input.is('Y') && isVisualLineMode()) || (input.is('Y') && isVisualCharMode())) { g.rangemode = RangeLineMode; g.movetype = MoveLineWise; g.submode = YankSubMode; finishMovement(); } else if ((input.is('y') || input.is('Y')) && isVisualBlockMode()) { g.rangemode = RangeBlockMode; g.movetype = MoveInclusive; g.submode = YankSubMode; finishMovement(); } else if (input.is('z')) { g.submode = ZSubMode; } else if (input.is('Z')) { g.submode = CapitalZSubMode; } else if ((input.is('~') || input.is('u') || input.is('U'))) { g.movetype = MoveExclusive; pushUndoState(); if (isVisualMode()) { setDotCommand(visualDotCommand() + QString::number(count()) + input.raw()); if (isVisualLineMode()) g.rangemode = RangeLineMode; else if (isVisualBlockMode()) g.rangemode = RangeBlockMode; leaveVisualMode(); if (input.is('~')) g.submode = InvertCaseSubMode; else if (input.is('u')) g.submode = DownCaseSubMode; else if (input.is('U')) g.submode = UpCaseSubMode; finishMovement(); } else if (g.gflag || (input.is('~') && hasConfig(ConfigTildeOp))) { if (atEndOfLine()) moveLeft(); setAnchor(); if (input.is('~')) g.submode = InvertCaseSubMode; else if (input.is('u')) g.submode = DownCaseSubMode; else if (input.is('U')) g.submode = UpCaseSubMode; } else { beginEditBlock(); if (atEndOfLine()) moveLeft(); setAnchor(); moveRight(qMin(count(), rightDist())); if (input.is('~')) { const int pos = position(); invertCase(currentRange()); setPosition(pos); } else if (input.is('u')) { downCase(currentRange()); } else if (input.is('U')) { upCase(currentRange()); } setDotCommand(QString::fromLatin1("%1%2").arg(count()).arg(input.raw())); endEditBlock(); } } else if (input.is('@')) { g.submode = MacroExecuteSubMode; } else if (input.isKey(Key_Delete)) { setAnchor(); moveRight(qMin(1, rightDist())); removeText(currentRange()); if (atEndOfLine()) moveLeft(); } else if (input.isControl(Key_BracketRight)) { handleExCommand(_("tag")); } else if (handleMovement(input)) { // movement handled } else { handled = false; } return handled; } bool FakeVimHandler::Private::handleChangeDeleteSubModes(const Input &input) { bool handled = false; if ((g.submode == ChangeSubMode && input.is('c')) || (g.submode == DeleteSubMode && input.is('d'))) { g.movetype = MoveLineWise; pushUndoState(); const int anc = firstPositionInLine(cursorLine() + 1); moveDown(count() - 1); const int pos = lastPositionInLine(cursorLine() + 1); setAnchorAndPosition(anc, pos); if (g.submode == ChangeSubMode) setDotCommand(_("%1cc"), count()); else setDotCommand(_("%1dd"), count()); finishMovement(); g.submode = NoSubMode; handled = true; } return handled; } bool FakeVimHandler::Private::handleReplaceSubMode(const Input &input) { bool handled = true; setDotCommand(visualDotCommand() + QLatin1Char('r') + input.asChar()); if (isVisualMode()) { pushUndoState(); if (isVisualLineMode()) g.rangemode = RangeLineMode; else if (isVisualBlockMode()) g.rangemode = RangeBlockMode; else g.rangemode = RangeCharMode; leaveVisualMode(); Range range = currentRange(); if (g.rangemode == RangeCharMode) ++range.endPos; Transformation tr = &FakeVimHandler::Private::replaceByCharTransform; transformText(range, tr, input.asChar()); } else if (count() <= rightDist()) { pushUndoState(); setAnchor(); moveRight(count()); Range range = currentRange(); if (input.isReturn()) { beginEditBlock(); replaceText(range, QString()); insertText(QString::fromLatin1("\n")); endEditBlock(); } else { replaceText(range, QString(count(), input.asChar())); moveRight(count() - 1); } setTargetColumn(); setDotCommand(_("%1r") + input.text(), count()); } else { handled = false; } g.submode = NoSubMode; finishMovement(); return handled; } bool FakeVimHandler::Private::handleFilterSubMode(const Input &) { return false; } bool FakeVimHandler::Private::handleRegisterSubMode(const Input &input) { bool handled = false; QChar reg = input.asChar(); if (QString::fromLatin1("*+.%#:-\"").contains(reg) || reg.isLetterOrNumber()) { m_register = reg.unicode(); g.rangemode = RangeLineMode; handled = true; } g.submode = NoSubMode; return handled; } bool FakeVimHandler::Private::handleShiftSubMode(const Input &input) { bool handled = false; if ((g.submode == ShiftLeftSubMode && input.is('<')) || (g.submode == ShiftRightSubMode && input.is('>')) || (g.submode == IndentSubMode && input.is('='))) { g.movetype = MoveLineWise; pushUndoState(); moveDown(count() - 1); setDotCommand(QString::fromLatin1("%2%1%1").arg(input.asChar()), count()); finishMovement(); handled = true; g.submode = NoSubMode; } return handled; } bool FakeVimHandler::Private::handleChangeCaseSubMode(const Input &input) { bool handled = false; if ((g.submode == InvertCaseSubMode && input.is('~')) || (g.submode == DownCaseSubMode && input.is('u')) || (g.submode == UpCaseSubMode && input.is('U'))) { if (!isFirstNonBlankOnLine(position())) { moveToStartOfLine(); moveToFirstNonBlankOnLine(); } setTargetColumn(); pushUndoState(); setAnchor(); setPosition(lastPositionInLine(cursorLine() + count()) + 1); finishMovement(QString::fromLatin1("%1%2").arg(count()).arg(input.raw())); handled = true; g.submode = NoSubMode; } return handled; } bool FakeVimHandler::Private::handleWindowSubMode(const Input &input) { if (handleCount(input)) return true; leaveVisualMode(); emit q->windowCommandRequested(input.toString(), count()); g.submode = NoSubMode; return true; } bool FakeVimHandler::Private::handleYankSubMode(const Input &input) { bool handled = false; if (input.is('y')) { g.movetype = MoveLineWise; int endPos = firstPositionInLine(lineForPosition(position()) + count() - 1); Range range(position(), endPos, RangeLineMode); yankText(range, m_register); g.submode = NoSubMode; handled = true; } return handled; } bool FakeVimHandler::Private::handleZSubMode(const Input &input) { bool handled = true; bool foldMaybeClosed = false; if (input.isReturn() || input.is('t') || input.is('-') || input.is('b') || input.is('.') || input.is('z')) { // Cursor line to top/center/bottom of window. Qt::AlignmentFlag align; if (input.isReturn() || input.is('t')) align = Qt::AlignTop; else if (input.is('.') || input.is('z')) align = Qt::AlignVCenter; else align = Qt::AlignBottom; const bool moveToNonBlank = (input.is('.') || input.isReturn() || input.is('-')); const int line = g.mvcount == 0 ? -1 : firstPositionInLine(count()); alignViewportToCursor(align, line, moveToNonBlank); } else if (input.is('o') || input.is('c')) { // Open/close current fold. foldMaybeClosed = input.is('c'); emit q->fold(count(), foldMaybeClosed); } else if (input.is('O') || input.is('C')) { // Recursively open/close current fold. foldMaybeClosed = input.is('C'); emit q->fold(-1, foldMaybeClosed); } else if (input.is('a') || input.is('A')) { // Toggle current fold. foldMaybeClosed = true; emit q->foldToggle(input.is('a') ? count() : -1); } else if (input.is('R') || input.is('M')) { // Open/close all folds in document. foldMaybeClosed = input.is('M'); emit q->foldAll(foldMaybeClosed); } else if (input.is('j') || input.is('k')) { emit q->foldGoTo(input.is('j') ? count() : -count(), false); } else { handled = false; } if (foldMaybeClosed) ensureCursorVisible(); g.submode = NoSubMode; return handled; } bool FakeVimHandler::Private::handleCapitalZSubMode(const Input &input) { // Recognize ZZ and ZQ as aliases for ":x" and ":q!". bool handled = true; if (input.is('Z')) handleExCommand(QString(QLatin1Char('x'))); else if (input.is('Q')) handleExCommand(_("q!")); else handled = false; g.submode = NoSubMode; return handled; } bool FakeVimHandler::Private::handleMacroRecordSubMode(const Input &input) { g.submode = NoSubMode; return startRecording(input); } bool FakeVimHandler::Private::handleMacroExecuteSubMode(const Input &input) { g.submode = NoSubMode; bool result = true; int repeat = count(); while (result && --repeat >= 0) result = executeRegister(input.asChar().unicode()); return result; } EventResult FakeVimHandler::Private::handleInsertOrReplaceMode(const Input &input) { if (position() < m_buffer->insertState.pos1 || position() > m_buffer->insertState.pos2) { commitInsertState(); invalidateInsertState(); } if (g.mode == InsertMode) handleInsertMode(input); else handleReplaceMode(input); if (!m_textedit && !m_plaintextedit) return EventHandled; if (!isInsertMode() || m_buffer->breakEditBlock || position() < m_buffer->insertState.pos1 || position() > m_buffer->insertState.pos2) { commitInsertState(); invalidateInsertState(); breakEditBlock(); m_visualBlockInsert = NoneBlockInsertMode; } else if (m_oldInternalPosition == position()) { setTargetColumn(); } updateMiniBuffer(); // We don't want fancy stuff in insert mode. return EventHandled; } void FakeVimHandler::Private::handleReplaceMode(const Input &input) { if (input.isEscape()) { commitInsertState(); moveLeft(qMin(1, leftDist())); enterCommandMode(); g.dotCommand.append(m_buffer->lastInsertion + _("")); } else if (input.isKey(Key_Left)) { moveLeft(); setTargetColumn(); } else if (input.isKey(Key_Right)) { moveRight(); setTargetColumn(); } else if (input.isKey(Key_Up)) { moveUp(); } else if (input.isKey(Key_Down)) { moveDown(); } else if (input.isKey(Key_Insert)) { g.mode = InsertMode; } else if (input.isControl('o')) { enterCommandMode(ReplaceMode); } else { joinPreviousEditBlock(); if (!atEndOfLine()) { setAnchor(); moveRight(); removeText(currentRange()); } const QString text = input.text(); setAnchor(); insertText(text); endEditBlock(); } } void FakeVimHandler::Private::finishInsertMode() { bool newLineAfter = m_buffer->insertState.newLineAfter; bool newLineBefore = m_buffer->insertState.newLineBefore; // Repeat insertion [count] times. // One instance was already physically inserted while typing. if (!m_buffer->breakEditBlock && isInsertStateValid()) { commitInsertState(); QString text = m_buffer->lastInsertion; const QString dotCommand = g.dotCommand; const int repeat = count() - 1; m_buffer->lastInsertion.clear(); joinPreviousEditBlock(); if (newLineAfter) { text.chop(1); text.prepend(_("\n")); } else if (newLineBefore) { text.prepend(_("")); } replay(text, repeat); if (m_visualBlockInsert != NoneBlockInsertMode && !text.contains(QLatin1Char('\n'))) { const CursorPosition lastAnchor = markLessPosition(); const CursorPosition lastPosition = markGreaterPosition(); bool change = m_visualBlockInsert == ChangeBlockInsertMode; const int insertColumn = (m_visualBlockInsert == InsertBlockInsertMode || change) ? qMin(lastPosition.column, lastAnchor.column) : qMax(lastPosition.column, lastAnchor.column) + 1; CursorPosition pos(lastAnchor.line, insertColumn); if (change) pos.column = m_buffer->insertState.pos1 - document()->findBlock(m_buffer->insertState.pos1).position(); // Cursor position after block insert is on the first selected line, // last selected column for 's' command, otherwise first selected column. const int endColumn = change ? qMax(0, m_cursor.positionInBlock() - 1) : qMin(lastPosition.column, lastAnchor.column); while (pos.line < lastPosition.line) { ++pos.line; setCursorPosition(&m_cursor, pos); if (m_visualBlockInsert == AppendToEndOfLineBlockInsertMode) { moveToEndOfLine(); } else if (m_visualBlockInsert == AppendBlockInsertMode) { // Prepend spaces if necessary. int spaces = pos.column - m_cursor.positionInBlock(); if (spaces > 0) { setAnchor(); m_cursor.insertText(QString(_(" ")).repeated(spaces)); } } else if (m_cursor.positionInBlock() != pos.column) { continue; } replay(text, repeat + 1); } setCursorPosition(CursorPosition(lastAnchor.line, endColumn)); } else { moveLeft(qMin(1, leftDist())); } endEditBlock(); breakEditBlock(); m_buffer->lastInsertion = text; g.dotCommand = dotCommand; } else { moveLeft(qMin(1, leftDist())); } if (newLineBefore || newLineAfter) m_buffer->lastInsertion.remove(0, m_buffer->lastInsertion.indexOf(QLatin1Char('\n')) + 1); g.dotCommand.append(m_buffer->lastInsertion + _("")); enterCommandMode(); setTargetColumn(); } void FakeVimHandler::Private::handleInsertMode(const Input &input) { if (input.isEscape()) { finishInsertMode(); } else if (g.submode == CtrlVSubMode) { if (g.subsubmode == NoSubSubMode) { g.subsubmode = CtrlVUnicodeSubSubMode; m_ctrlVAccumulator = 0; if (input.is('x') || input.is('X')) { // ^VXnn or ^Vxnn with 00 <= nn <= FF // BMP Unicode codepoints ^Vunnnn with 0000 <= nnnn <= FFFF // any Unicode codepoint ^VUnnnnnnnn with 00000000 <= nnnnnnnn <= 7FFFFFFF // ^Vnnn with 000 <= nnn <= 255 // ^VOnnn or ^Vonnn with 000 <= nnn <= 377 m_ctrlVLength = 2; m_ctrlVBase = 16; } else if (input.is('O') || input.is('o')) { m_ctrlVLength = 3; m_ctrlVBase = 8; } else if (input.is('u')) { m_ctrlVLength = 4; m_ctrlVBase = 16; } else if (input.is('U')) { m_ctrlVLength = 8; m_ctrlVBase = 16; } else if (input.isDigit()) { bool ok; m_ctrlVAccumulator = input.toInt(&ok, 10); m_ctrlVLength = 2; m_ctrlVBase = 10; } else { insertInInsertMode(input.raw()); g.submode = NoSubMode; g.subsubmode = NoSubSubMode; } } else { bool ok; int current = input.toInt(&ok, m_ctrlVBase); if (ok) m_ctrlVAccumulator = m_ctrlVAccumulator * m_ctrlVBase + current; --m_ctrlVLength; if (m_ctrlVLength == 0 || !ok) { QString s; if (QChar::requiresSurrogates(m_ctrlVAccumulator)) { s.append(QChar(QChar::highSurrogate(m_ctrlVAccumulator))); s.append(QChar(QChar::lowSurrogate(m_ctrlVAccumulator))); } else { s.append(QChar(m_ctrlVAccumulator)); } insertInInsertMode(s); g.submode = NoSubMode; g.subsubmode = NoSubSubMode; // Try again without Ctrl-V interpretation. if (!ok) handleInsertMode(input); } } } else if (input.isControl('o')) { enterCommandMode(InsertMode); } else if (input.isControl('v')) { g.submode = CtrlVSubMode; g.subsubmode = NoSubSubMode; } else if (input.isControl('w')) { const int blockNumber = m_cursor.blockNumber(); const int endPos = position(); moveToNextWordStart(1, false, false); if (blockNumber != m_cursor.blockNumber()) moveToEndOfLine(); const int beginPos = position(); Range range(beginPos, endPos, RangeCharMode); removeText(range); } else if (input.isKey(Key_Insert)) { g.mode = ReplaceMode; } else if (input.isKey(Key_Left)) { moveLeft(); setTargetColumn(); } else if (input.isControl(Key_Left)) { moveToNextWordStart(1, false, false); setTargetColumn(); } else if (input.isKey(Key_Down)) { g.submode = NoSubMode; moveDown(); } else if (input.isKey(Key_Up)) { g.submode = NoSubMode; moveUp(); } else if (input.isKey(Key_Right)) { moveRight(); setTargetColumn(); } else if (input.isControl(Key_Right)) { moveToNextWordStart(1, false, true); moveRight(); // we need one more move since we are in insert mode setTargetColumn(); } else if (input.isKey(Key_Home)) { moveToStartOfLine(); setTargetColumn(); } else if (input.isKey(Key_End)) { moveBehindEndOfLine(); setTargetColumn(); m_targetColumn = -1; } else if (input.isReturn() || input.isControl('j') || input.isControl('m')) { if (!input.isReturn() || !handleInsertInEditor(input)) { joinPreviousEditBlock(); g.submode = NoSubMode; insertNewLine(); endEditBlock(); } } else if (input.isBackspace()) { if (!handleInsertInEditor(input)) { joinPreviousEditBlock(); if (!m_buffer->lastInsertion.isEmpty() || hasConfig(ConfigBackspace, "start") || hasConfig(ConfigBackspace, "2")) { const int line = cursorLine() + 1; const Column col = cursorColumn(); QString data = lineContents(line); const Column ind = indentation(data); if (col.logical <= ind.logical && col.logical && startsWithWhitespace(data, col.physical)) { const int ts = config(ConfigTabStop).toInt(); const int newl = col.logical - 1 - (col.logical - 1) % ts; const QString prefix = tabExpand(newl); setLineContents(line, prefix + data.mid(col.physical)); moveToStartOfLine(); moveRight(prefix.size()); } else { setAnchor(); m_cursor.deletePreviousChar(); } } endEditBlock(); } } else if (input.isKey(Key_Delete)) { if (!handleInsertInEditor(input)) { joinPreviousEditBlock(); m_cursor.deleteChar(); endEditBlock(); } } else if (input.isKey(Key_PageDown) || input.isControl('f')) { movePageDown(); } else if (input.isKey(Key_PageUp) || input.isControl('b')) { movePageUp(); } else if (input.isKey(Key_Tab)) { m_buffer->insertState.insertingSpaces = true; if (hasConfig(ConfigExpandTab)) { const int ts = config(ConfigTabStop).toInt(); const int col = logicalCursorColumn(); QString str = QString(ts - col % ts, QLatin1Char(' ')); insertText(str); } else { insertInInsertMode(input.raw()); } m_buffer->insertState.insertingSpaces = false; } else if (input.isControl('d')) { // remove one level of indentation from the current line int shift = config(ConfigShiftWidth).toInt(); int tab = config(ConfigTabStop).toInt(); int line = cursorLine() + 1; int pos = firstPositionInLine(line); QString text = lineContents(line); int amount = 0; int i = 0; for (; i < text.size() && amount < shift; ++i) { if (text.at(i) == QLatin1Char(' ')) ++amount; else if (text.at(i) == QLatin1Char('\t')) amount += tab; // FIXME: take position into consideration else break; } removeText(Range(pos, pos+i)); } else if (input.isControl('p') || input.isControl('n')) { QTextCursor tc = m_cursor; moveToNextWordStart(1, false, false); QString str = selectText(Range(position(), tc.position())); m_cursor = tc; emit q->simpleCompletionRequested(str, input.isControl('n')); } else if (input.isShift(Qt::Key_Insert)) { // Insert text from clipboard. QClipboard *clipboard = QApplication::clipboard(); const QMimeData *data = clipboard->mimeData(); if (data && data->hasText()) insertInInsertMode(data->text()); } else { m_buffer->insertState.insertingSpaces = input.isKey(Key_Space); if (!handleInsertInEditor(input)) { const QString toInsert = input.text(); if (toInsert.isEmpty()) return; insertInInsertMode(toInsert); } m_buffer->insertState.insertingSpaces = false; } } void FakeVimHandler::Private::insertInInsertMode(const QString &text) { joinPreviousEditBlock(); insertText(text); if (hasConfig(ConfigSmartIndent) && isElectricCharacter(text.at(0))) { const QString leftText = block().text() .left(position() - 1 - block().position()); if (leftText.simplified().isEmpty()) { Range range(position(), position(), g.rangemode); indentText(range, text.at(0)); } } setTargetColumn(); endEditBlock(); g.submode = NoSubMode; } bool FakeVimHandler::Private::startRecording(const Input &input) { QChar reg = input.asChar(); if (reg == QLatin1Char('"') || reg.isLetterOrNumber()) { g.currentRegister = reg.unicode(); g.recording = QLatin1String(""); return true; } return false; } void FakeVimHandler::Private::record(const Input &input) { if ( !g.recording.isNull() ) g.recording.append(input.toString()); } void FakeVimHandler::Private::stopRecording() { // Remove q from end (stop recording command). g.recording.remove(g.recording.size() - 1, 1); setRegister(g.currentRegister, g.recording, g.rangemode); g.currentRegister = 0; g.recording = QString(); } bool FakeVimHandler::Private::executeRegister(int reg) { QChar regChar(reg); // TODO: Prompt for an expression to execute if register is '='. if (reg == '@' && g.lastExecutedRegister != 0) reg = g.lastExecutedRegister; else if (QString::fromLatin1("\".*+").contains(regChar) || regChar.isLetterOrNumber()) g.lastExecutedRegister = reg; else return false; // FIXME: In Vim it's possible to interrupt recursive macro with . // One solution may be to call QApplication::processEvents() and check if was // used when a mapping is active. // According to Vim, register is executed like mapping. prependMapping(Inputs(registerContents(reg), false, false)); return true; } EventResult FakeVimHandler::Private::handleExMode(const Input &input) { if (input.isEscape()) { g.commandBuffer.clear(); resetCommandMode(); g.submode = NoSubMode; } else if (g.submode == CtrlVSubMode) { g.commandBuffer.insertChar(input.raw()); g.submode = NoSubMode; } else if (input.isControl('v')) { g.submode = CtrlVSubMode; g.subsubmode = NoSubSubMode; return EventHandled; } else if (input.isBackspace()) { if (g.commandBuffer.isEmpty()) { leaveVisualMode(); resetCommandMode(); } else if (g.commandBuffer.hasSelection()) { g.commandBuffer.deleteSelected(); } else { g.commandBuffer.deleteChar(); } } else if (input.isKey(Key_Tab)) { // FIXME: Complete actual commands. g.commandBuffer.historyUp(); } else if (input.isReturn()) { showMessage(MessageCommand, g.commandBuffer.display()); handleExCommand(g.commandBuffer.contents()); g.commandBuffer.clear(); if (m_textedit || m_plaintextedit) leaveVisualMode(); } else if (!g.commandBuffer.handleInput(input)) { qDebug() << "IGNORED IN EX-MODE: " << input.key() << input.text(); return EventUnhandled; } updateMiniBuffer(); return EventHandled; } EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input) { EventResult handled = EventHandled; if (input.isEscape()) { g.currentMessage.clear(); setPosition(m_searchStartPosition); scrollToLine(m_searchFromScreenLine); } else if (input.isBackspace()) { if (g.searchBuffer.isEmpty()) resetCommandMode(); else g.searchBuffer.deleteChar(); } else if (input.isReturn()) { const QString &needle = g.searchBuffer.contents(); if (!needle.isEmpty()) g.lastSearch = needle; else g.searchBuffer.setContents(g.lastSearch); updateFind(true); if (finishSearch()) { if (g.submode != NoSubMode) finishMovement(g.searchBuffer.prompt() + g.lastSearch + QLatin1Char('\n')); if (g.currentMessage.isEmpty()) showMessage(MessageCommand, g.searchBuffer.display()); } else { handled = EventCancelled; // Not found so cancel mapping if any. } } else if (input.isKey(Key_Tab)) { g.searchBuffer.insertChar(QChar(9)); } else if (!g.searchBuffer.handleInput(input)) { //qDebug() << "IGNORED IN SEARCH MODE: " << input.key() << input.text(); return EventUnhandled; } if (input.isReturn() || input.isEscape()) { g.searchBuffer.clear(); resetCommandMode(); updateMiniBuffer(); } else { updateMiniBuffer(); updateFind(false); } return handled; } // This uses 0 based line counting (hidden lines included). int FakeVimHandler::Private::parseLineAddress(QString *cmd) { //qDebug() << "CMD: " << cmd; if (cmd->isEmpty()) return -1; int result = -1; QChar c = cmd->at(0); if (c == QLatin1Char('.')) { // current line result = cursorBlockNumber(); cmd->remove(0, 1); } else if (c == QLatin1Char('$')) { // last line result = document()->blockCount() - 1; cmd->remove(0, 1); } else if (c == QLatin1Char('\'')) { // mark cmd->remove(0, 1); if (cmd->isEmpty()) { showMessage(MessageError, msgMarkNotSet(QString())); return -1; } c = cmd->at(0); Mark m = mark(c); if (!m.isValid() || !m.isLocal(m_currentFileName)) { showMessage(MessageError, msgMarkNotSet(c)); return -1; } cmd->remove(0, 1); result = m.position(document()).line; } else if (c.isDigit()) { // line with given number result = 0; } else if (c == QLatin1Char('-') || c == QLatin1Char('+')) { // add or subtract from current line number result = cursorBlockNumber(); } else if (c == QLatin1Char('/') || c == QLatin1Char('?') || (c == QLatin1Char('\\') && cmd->size() > 1 && QString::fromLatin1("/?&").contains(cmd->at(1)))) { // search for expression SearchData sd; if (c == QLatin1Char('/') || c == QLatin1Char('?')) { const int end = findUnescaped(c, *cmd, 1); if (end == -1) return -1; sd.needle = cmd->mid(1, end - 1); cmd->remove(0, end + 1); } else { c = cmd->at(1); cmd->remove(0, 2); sd.needle = (c == QLatin1Char('&')) ? g.lastSubstitutePattern : g.lastSearch; } sd.forward = (c != QLatin1Char('?')); const QTextBlock b = block(); const int pos = b.position() + (sd.forward ? b.length() - 1 : 0); QTextCursor tc = search(sd, pos, 1, true); g.lastSearch = sd.needle; if (tc.isNull()) return -1; result = tc.block().blockNumber(); } else { return cursorBlockNumber(); } // basic arithmetic ("-3+5" or "++" means "+2" etc.) int n = 0; bool add = true; int i = 0; for (; i < cmd->size(); ++i) { c = cmd->at(i); if (c == QLatin1Char('-') || c == QLatin1Char('+')) { if (n != 0) result = result + (add ? n - 1 : -(n - 1)); add = c == QLatin1Char('+'); result = result + (add ? 1 : -1); n = 0; } else if (c.isDigit()) { n = n * 10 + c.digitValue(); } else if (!c.isSpace()) { break; } } if (n != 0) result = result + (add ? n - 1 : -(n - 1)); *cmd = cmd->mid(i).trimmed(); return result; } void FakeVimHandler::Private::setCurrentRange(const Range &range) { setAnchorAndPosition(range.beginPos, range.endPos); g.rangemode = range.rangemode; } bool FakeVimHandler::Private::parseExCommmand(QString *line, ExCommand *cmd) { *cmd = ExCommand(); if (line->isEmpty()) return false; // parse range first if (!parseLineRange(line, cmd)) return false; // get first command from command line QChar close; bool subst = false; int i = 0; for (; i < line->size(); ++i) { const QChar &c = line->at(i); if (c == QLatin1Char('\\')) { ++i; // skip escaped character } else if (close.isNull()) { if (c == QLatin1Char('|')) { // split on | break; } else if (c == QLatin1Char('/')) { subst = i > 0 && (line->at(i - 1) == QLatin1Char('s')); close = c; } else if (c == QLatin1Char('"') || c == QLatin1Char('\'')) { close = c; } } else if (c == close) { if (subst) subst = false; else close = QChar(); } } cmd->cmd = line->mid(0, i).trimmed(); // command arguments starts with first non-letter character cmd->args = cmd->cmd.section(QRegExp(_("(?=[^a-zA-Z])")), 1); if (!cmd->args.isEmpty()) { cmd->cmd.chop(cmd->args.size()); cmd->args = cmd->args.trimmed(); // '!' at the end of command cmd->hasBang = cmd->args.startsWith(QLatin1Char('!')); if (cmd->hasBang) cmd->args = cmd->args.mid(1).trimmed(); } // remove the first command from command line line->remove(0, i + 1); return true; } bool FakeVimHandler::Private::parseLineRange(QString *line, ExCommand *cmd) { // remove leading colons and spaces line->remove(QRegExp(_("^\\s*(:+\\s*)*"))); // special case ':!...' (use invalid range) if (line->startsWith(QLatin1Char('!'))) { cmd->range = Range(); return true; } // FIXME: that seems to be different for %w and %s if (line->startsWith(QLatin1Char('%'))) line->replace(0, 1, _("1,$")); int beginLine = parseLineAddress(line); int endLine; if (line->startsWith(QLatin1Char(','))) { *line = line->mid(1).trimmed(); endLine = parseLineAddress(line); } else { endLine = beginLine; } if (beginLine == -1 || endLine == -1) return false; const int beginPos = firstPositionInLine(qMin(beginLine, endLine) + 1, false); const int endPos = lastPositionInLine(qMax(beginLine, endLine) + 1, false); cmd->range = Range(beginPos, endPos, RangeLineMode); cmd->count = beginLine; return true; } void FakeVimHandler::Private::parseRangeCount(const QString &line, Range *range) const { bool ok; const int count = qAbs(line.trimmed().toInt(&ok)); if (ok) { const int beginLine = document()->findBlock(range->endPos).blockNumber() + 1; const int endLine = qMin(beginLine + count - 1, document()->blockCount()); range->beginPos = firstPositionInLine(beginLine, false); range->endPos = lastPositionInLine(endLine, false); } } // use handleExCommand for invoking commands that might move the cursor void FakeVimHandler::Private::handleCommand(const QString &cmd) { handleExCommand(cmd); } bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd) { // :substitute if (!cmd.matches(_("s"), _("substitute")) && !(cmd.cmd.isEmpty() && !cmd.args.isEmpty() && QString::fromLatin1("&~").contains(cmd.args[0]))) { return false; } int count = 1; QString line = cmd.args; const int countIndex = line.lastIndexOf(QRegExp(_("\\d+$"))); if (countIndex != -1) { count = line.mid(countIndex).toInt(); line = line.mid(0, countIndex).trimmed(); } if (cmd.cmd.isEmpty()) { // keep previous substitution flags on '&&' and '~&' if (line.size() > 1 && line[1] == QLatin1Char('&')) g.lastSubstituteFlags += line.mid(2); else g.lastSubstituteFlags = line.mid(1); if (line[0] == QLatin1Char('~')) g.lastSubstitutePattern = g.lastSearch; } else { if (line.isEmpty()) { g.lastSubstituteFlags.clear(); } else { // we have /{pattern}/{string}/[flags] now const QChar separator = line.at(0); int pos1 = findUnescaped(separator, line, 1); if (pos1 == -1) return false; int pos2 = findUnescaped(separator, line, pos1 + 1); if (pos2 == -1) pos2 = line.size(); g.lastSubstitutePattern = line.mid(1, pos1 - 1); g.lastSubstituteReplacement = line.mid(pos1 + 1, pos2 - pos1 - 1); g.lastSubstituteFlags = line.mid(pos2 + 1); } } count = qMax(1, count); QString needle = g.lastSubstitutePattern; if (g.lastSubstituteFlags.contains(QLatin1Char('i'))) needle.prepend(_("\\c")); QRegExp pattern = vimPatternToQtPattern(needle, hasConfig(ConfigIgnoreCase), hasConfig(ConfigSmartCase)); QTextBlock lastBlock; QTextBlock firstBlock; const bool global = g.lastSubstituteFlags.contains(QLatin1Char('g')); for (int a = 0; a != count; ++a) { for (QTextBlock block = document()->findBlock(cmd.range.endPos); block.isValid() && block.position() + block.length() > cmd.range.beginPos; block = block.previous()) { QString text = block.text(); if (substituteText(&text, pattern, g.lastSubstituteReplacement, global)) { firstBlock = block; if (!lastBlock.isValid()) { lastBlock = block; beginEditBlock(); } QTextCursor tc = m_cursor; const int pos = block.position(); const int anchor = pos + block.length() - 1; tc.setPosition(anchor); tc.setPosition(pos, KeepAnchor); tc.insertText(text); } } } if (lastBlock.isValid()) { m_buffer->undoState.position = CursorPosition(firstBlock.blockNumber(), 0); leaveVisualMode(); setPosition(lastBlock.position()); setAnchor(); moveToFirstNonBlankOnLine(); setTargetColumn(); endEditBlock(); } return true; } bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map { QByteArray modes; enum Type { Map, Noremap, Unmap } type; QByteArray cmd = cmd0.cmd.toLatin1(); // Strange formatting. But everything else is even uglier. if (cmd == "map") { modes = "nvo"; type = Map; } else if (cmd == "nm" || cmd == "nmap") { modes = "n"; type = Map; } else if (cmd == "vm" || cmd == "vmap") { modes = "v"; type = Map; } else if (cmd == "xm" || cmd == "xmap") { modes = "x"; type = Map; } else if (cmd == "smap") { modes = "s"; type = Map; } else if (cmd == "omap") { modes = "o"; type = Map; } else if (cmd == "map!") { modes = "ic"; type = Map; } else if (cmd == "im" || cmd == "imap") { modes = "i"; type = Map; } else if (cmd == "lm" || cmd == "lmap") { modes = "l"; type = Map; } else if (cmd == "cm" || cmd == "cmap") { modes = "c"; type = Map; } else if (cmd == "no" || cmd == "noremap") { modes = "nvo"; type = Noremap; } else if (cmd == "nn" || cmd == "nnoremap") { modes = "n"; type = Noremap; } else if (cmd == "vn" || cmd == "vnoremap") { modes = "v"; type = Noremap; } else if (cmd == "xn" || cmd == "xnoremap") { modes = "x"; type = Noremap; } else if (cmd == "snor" || cmd == "snoremap") { modes = "s"; type = Noremap; } else if (cmd == "ono" || cmd == "onoremap") { modes = "o"; type = Noremap; } else if (cmd == "no!" || cmd == "noremap!") { modes = "ic"; type = Noremap; } else if (cmd == "ino" || cmd == "inoremap") { modes = "i"; type = Noremap; } else if (cmd == "ln" || cmd == "lnoremap") { modes = "l"; type = Noremap; } else if (cmd == "cno" || cmd == "cnoremap") { modes = "c"; type = Noremap; } else if (cmd == "unm" || cmd == "unmap") { modes = "nvo"; type = Unmap; } else if (cmd == "nun" || cmd == "nunmap") { modes = "n"; type = Unmap; } else if (cmd == "vu" || cmd == "vunmap") { modes = "v"; type = Unmap; } else if (cmd == "xu" || cmd == "xunmap") { modes = "x"; type = Unmap; } else if (cmd == "sunm" || cmd == "sunmap") { modes = "s"; type = Unmap; } else if (cmd == "ou" || cmd == "ounmap") { modes = "o"; type = Unmap; } else if (cmd == "unm!" || cmd == "unmap!") { modes = "ic"; type = Unmap; } else if (cmd == "iu" || cmd == "iunmap") { modes = "i"; type = Unmap; } else if (cmd == "lu" || cmd == "lunmap") { modes = "l"; type = Unmap; } else if (cmd == "cu" || cmd == "cunmap") { modes = "c"; type = Unmap; } else return false; QString args = cmd0.args; bool silent = false; bool unique = false; forever { if (eatString("", &args)) { silent = true; } else if (eatString("", &args)) { continue; } else if (eatString("", &args)) { continue; } else if (eatString("", &args)) { notImplementedYet(); continue; } else if (eatString("

xterm.js + Pty-Qt + C++

================================================ FILE: liteidex/src/3rdparty/ptyqt/examples/xtermjs/style.css ================================================ body { font-family: helvetica, sans-serif, arial; font-size: 1em; color: #111; } h1 { text-align: center; } #terminal-container { width: 800px; height: 450px; margin: 0 auto; padding: 2px; } p { font-size: 0.9em; font-style: italic } #option-container { display: flex; justify-content: center; } .option-group { display: inline-block; padding-left: 20px; vertical-align: top; } ================================================ FILE: liteidex/src/3rdparty/ptyqt/examples/xtermjs/xtermjs.cpp ================================================ #include #include #include #include "ptyqt.h" #include #include #include #define PORT 4242 #define COLS 87 #define ROWS 26 int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); //start WebSockets server for receive connections from xterm.js QWebSocketServer wsServer("TestServer", QWebSocketServer::NonSecureMode); if (!wsServer.listen(QHostAddress::Any, PORT)) return 1; QMap sessions; //create new session on new connection QObject::connect(&wsServer, &QWebSocketServer::newConnection, [&wsServer, &sessions]() { //handle new connection QWebSocket *wSocket = wsServer.nextPendingConnection(); //use cmd.exe or bash, depends on target platform IPtyProcess::PtyType ptyType = IPtyProcess::WinPty; qint32 buildNumber = QSysInfo::kernelVersion().split(".").last().toInt(); if (buildNumber >= CONPTY_MINIMAL_WINDOWS_VERSION) { qDebug() << "Use ConPty instead of WinPty"; ptyType = IPtyProcess::ConPty; } //force select WinPty ptyType = IPtyProcess::WinPty; QString shellPath = "c:\\Windows\\system32\\cmd.exe"; //shellPath = "C:\\Program\ Files\\Git\\bin\\bash.exe"; #ifdef Q_OS_UNIX shellPath = "/bin/sh"; ptyType = IPtyProcess::UnixPty; #endif //create new Pty instance IPtyProcess *pty = PtyQt::createPtyProcess(ptyType); qDebug() << "New connection" << wSocket->peerAddress() << wSocket->peerPort() << pty->pid(); //start Pty process () pty->startProcess(shellPath, QProcessEnvironment::systemEnvironment().toStringList(), COLS, ROWS); if (!pty->lastError().isEmpty()) { qDebug() << pty->lastError(); delete pty; return; } //connect read channel from Pty process to write channel on websocket QObject::connect(pty->notifier(), &QIODevice::readyRead, [wSocket, pty]() { QByteArray data = pty->readAll(); //qDebug() << "< " << data; wSocket->sendTextMessage(data); }); //connect read channel of Websocket to write channel of Pty process QObject::connect(wSocket, &QWebSocket::textMessageReceived, [wSocket, pty](const QString &message) { //qDebug() << "> " << message.size() << message.at(0) << message << message.toUtf8() << QString::fromUtf8(message.toUtf8()); pty->write(message.toUtf8()); }); //for example handle disconnections, process crashes and stuff like that... auto endSessionHandler = [wSocket, &sessions]() { IPtyProcess *pty = sessions.value(wSocket); if (pty == 0) return; //because can be called twice sessions.remove(wSocket); qDebug() << "wSockMn" << wSocket << pty; if (wSocket->isValid()) wSocket->close(); wSocket->deleteLater(); pty->kill(); delete pty; }; QObject::connect(wSocket, &QWebSocket::disconnected, endSessionHandler); #ifdef Q_OS_UNIX QProcess *shellProcess = qobject_cast(pty->notifier()); QObject::connect(shellProcess, QOverload::of(&QProcess::finished), [endSessionHandler](int, QProcess::ExitStatus ) { endSessionHandler(); }); #else QLocalSocket *localSocket = qobject_cast(pty->notifier()); QObject::connect(localSocket, &QLocalSocket::disconnected, endSessionHandler); #endif //add connection to list of active connections sessions.insert(wSocket, pty); qDebug() << pty->size(); }); //stop eventloop if needed //QTimer::singleShot(5000, [](){ qApp->quit(); }); //exec eventloop bool res = app.exec(); QMapIterator it(sessions); while (it.hasNext()) { it.next(); it.key()->deleteLater(); delete it.value(); } sessions.clear(); return res; } ================================================ FILE: liteidex/src/3rdparty/ptyqt/ptyqt.pri ================================================ LIBS *= -l$$qtLibraryName(ptyqt) ================================================ FILE: liteidex/src/3rdparty/ptyqt/ptyqt.pro ================================================ TARGET = ptyqt TEMPLATE = lib CONFIG += staticlib include (../../liteideutils.pri) HEADERS += \ core/iptyprocess.h \ core/ptyqt.h SOURCES += \ core/ptyqt.cpp win32 { HEADERS += \ core/winpty.h \ core/winpty_constants.h QT += network } win32-g++ { HEADERS += \ core/winptyprocess.h SOURCES += \ core/winptyprocess.cpp } win32-msvc* { HEADERS += \ core/conptyprocess.h SOURCES += \ core/conptyprocess.cpp } unix { HEADERS += \ core/unixptyprocess.h SOURCES += \ core/unixptyprocess.cpp } ================================================ FILE: liteidex/src/3rdparty/ptyqt/tests/CMakeLists.txt ================================================ project(ptyqt-tests) enable_testing() find_package(Qt5Test REQUIRED) add_executable(ptyqt_tests ptyqt_tests.cpp) add_dependencies(ptyqt_tests ptyqt) add_test(ptyqt_tests ptyqt_tests) if (MSVC) if ("${PTYQT_DEBUG}") set(WINPTY_DEBUG_SERVER_PATH ${WINPTY_ROOT_DIR}/${TARGET_ARCH}/bin/winpty-debugserver.exe) add_definitions(-DWINPTY_DEBUG_SRV_PATH="${WINPTY_DEBUG_SERVER_PATH}") message("WinPty debug server path " ${WINPTY_DEBUG_SERVER_PATH}) endif() endif() target_link_libraries(ptyqt_tests ptyqt Qt5::Core Qt5::Test) if (MSVC) target_link_libraries(ptyqt_tests Qt5::Network ${WINPTY_LIBS}) endif() foreach( file_i ${WINPTY_DIST_FILES}) add_custom_command( TARGET ptyqt_tests POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy ${file_i} ${CMAKE_CURRENT_BINARY_DIR} ) endforeach( file_i ) #file(COPY ${WINPTY_DIST_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) ================================================ FILE: liteidex/src/3rdparty/ptyqt/tests/ptyqt_tests.cpp ================================================ #include #include "ptyqt.h" #include #include #ifdef Q_OS_WIN #include #include #endif #include #include #ifdef Q_OS_WIN #ifndef _WINDEF_ typedef unsigned long DWORD; #endif #endif #define WINPTY_DBG_SERVER_NAME "winpty-debugserver.exe" #define WINPTY_AGENT_NAME "winpty-agent.exe" //increase it for visual control each shell #define DEBUG_SLEEP_SEC 1 void sleepByEventLoop(int seconds) { QEventLoop sleepLoop; QTimer sleepTimer; QObject::connect(&sleepTimer, &QTimer::timeout, &sleepLoop, &QEventLoop::quit); sleepTimer.setInterval(seconds * 1000); sleepTimer.setSingleShot(true); sleepTimer.start(); sleepLoop.exec(); } #ifdef Q_OS_WIN DWORD findProcessId(const std::string& processName, int parentProcessId = 0) { PROCESSENTRY32 processInfo; processInfo.dwSize = sizeof(processInfo); HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (processesSnapshot == INVALID_HANDLE_VALUE) { return 0; } Process32First(processesSnapshot, &processInfo); if (!processName.compare(processInfo.szExeFile)) { if (parentProcessId == 0 || parentProcessId == processInfo.th32ParentProcessID) { CloseHandle(processesSnapshot); return processInfo.th32ProcessID; } } while (Process32Next(processesSnapshot, &processInfo)) { if (!processName.compare(processInfo.szExeFile)) { if (parentProcessId == 0 || parentProcessId == processInfo.th32ParentProcessID) { CloseHandle(processesSnapshot); return processInfo.th32ProcessID; } } } CloseHandle(processesSnapshot); return 0; } void killProcessByName(QString processName) { if (findProcessId(processName.toStdString())) { system(QString("taskkill /im %1 /f").arg(processName).toStdString().c_str()); sleepByEventLoop(1); } } QStringList getShells() { QString systemRoot = QProcessEnvironment::systemEnvironment().value("windir"); if (systemRoot.trimmed().isEmpty()) systemRoot = QProcessEnvironment::systemEnvironment().value("WINDIR"); if (systemRoot.trimmed().isEmpty()) systemRoot = "c:\\Windows"; QStringList possibleShells; possibleShells << (systemRoot + "\\system32\\cmd.exe"); //reversed slashes //possibleShells << ("C:/Windows/system32/cmd.exe"); //normal slashes //possibleShells << (systemRoot + "\\system32\\WindowsPowerShell\\v1.0\\powershell.exe"); //possibleShells << "C:\\Program\ Files\\Git\\bin\\bash.exe"; //possibleShells << "C:\\Python27\\python.exe"; //possibleShells << "C:/Python27/pythonw.exe"; QStringList shells; foreach (QString possibleShell, possibleShells) { if (QFile::exists(possibleShell)) shells << possibleShell; } return shells; } #endif class PtyQtTests : public QObject { Q_OBJECT private slots: //unix unit tests #ifdef Q_OS_UNIX void unixpty() { QString shellPath = "/bin/bash"; QScopedPointer unixPty(PtyQt::createPtyProcess(IPtyProcess::UnixPty)); QCOMPARE(unixPty->type(), IPtyProcess::UnixPty); QVERIFY(unixPty->isAvailable()); //start UnixPty agent and cmd.exe bool startResult = unixPty->startProcess(shellPath, QProcessEnvironment::systemEnvironment().toStringList(), 200, 80); #ifdef PTYQT_DEBUG if (!startResult) qDebug() << unixPty->lastError() << unixPty->dumpDebugInfo(); #endif QVERIFY(startResult); //check pid QVERIFY(unixPty->pid() != 0); //check shell welcome QEventLoop el; auto connection = QObject::connect(unixPty->notifier(), &QIODevice::readyRead, [&unixPty, &el]() { sleepByEventLoop(1); qDebug() << "unixPty.read" << unixPty->readAll(); el.quit(); }); el.exec(); unixPty->notifier()->disconnect(connection); //check shell read after write bool testRes = false; connection = QObject::connect(unixPty->notifier(), &QIODevice::readyRead, [&unixPty, &el, &testRes]() { sleepByEventLoop(1); QString res = QString::fromUtf8(unixPty->readAll()); //qDebug() << res; //for e.g. bash return empty strings after needed data if (res.isEmpty() && testRes) return; testRes = res.contains("ptyqt_tests"); testRes = testRes && res.contains("Makefile"); testRes = testRes && res.contains("cmake_install.cmake"); el.quit(); }); qDebug() << "ptyin:" << unixPty->write("ls\n"); el.exec(); QVERIFY(testRes); qDebug() << "ptyin:" << unixPty->write("ls -alh\n"); el.exec(); QVERIFY(testRes); unixPty->notifier()->disconnect(connection); //resize window sleepByEventLoop(1); QVERIFY(unixPty->resize(240, 90)); } #endif //windows unit tests #ifdef Q_OS_WIN //ConPty available only on Windows 10 released after 1903 (19H1) Windows release void conpty() { qint32 buildNumber = QSysInfo::kernelVersion().split(".").last().toInt(); if (buildNumber < CONPTY_MINIMAL_WINDOWS_VERSION) { qDebug() << QString("Your Windows version doesn't support ConPty. Minimal version: %1. Your version: %2").arg(CONPTY_MINIMAL_WINDOWS_VERSION).arg(buildNumber) << QSysInfo::kernelVersion(); return; } qsrand(QDateTime::currentMSecsSinceEpoch()); QStringList shells = getShells(); foreach (QString shellPath, shells) { qDebug() << "Test" << shellPath; IPtyProcess::PtyType ptyType = IPtyProcess::ConPty; QScopedPointer conPty(PtyQt::createPtyProcess(ptyType)); QCOMPARE(conPty->type(), ptyType); QVERIFY(conPty->isAvailable()); //check shell welcome QEventLoop el; auto connection = QObject::connect(conPty->notifier(), &QIODevice::readyRead, [&conPty, &el]() { sleepByEventLoop(1); //qDebug() << "conPty.read" << conPty->readAll(); conPty->readAll(); el.quit(); }); //start ConPty agent and cmd.exe bool startResult = conPty->startProcess(shellPath, QProcessEnvironment::systemEnvironment().toStringList(), 200, 80); #ifdef PTYQT_DEBUG if (!startResult) qDebug() << conPty->lastError() << conPty->dumpDebugInfo(); #endif QVERIFY(startResult); //check pid QVERIFY(conPty->pid() != 0); //check shell welcome el.exec(); conPty->notifier()->disconnect(connection); //check shell read after write bool testRes = false; connection = QObject::connect(conPty->notifier(), &QIODevice::readyRead, [&conPty, &el, &testRes]() { sleepByEventLoop(1); QString res = QString::fromUtf8(conPty->readAll()); //qDebug() << res; //for e.g. bash return empty strings after needed data if (res.isEmpty() && testRes) return; testRes = res.contains("winpty-agent.exe"); testRes = testRes && res.contains("winpty.dll"); testRes = testRes && res.contains("ptyqt_tests.exe"); el.quit(); }); qDebug() << conPty->write("dir\r\n\r\n"); //sleepByEventLoop(1); //qDebug() << conPty->readAll(); el.exec(); QVERIFY(testRes); conPty->notifier()->disconnect(connection); //resize window sleepByEventLoop(1); QVERIFY(conPty->resize(240, 90)); //kill shell process #ifdef PTYQT_DEBUG qDebug() << conPty->dumpDebugInfo(); sleepByEventLoop(DEBUG_SLEEP_SEC); #endif QVERIFY(conPty->kill()); sleepByEventLoop(1); } } void winpty() { //QVERIFY(false); //force quit #ifdef PTYQT_DEBUG //run debug server killProcessByName(WINPTY_DBG_SERVER_NAME); qint64 debugServerPid; QProcess::startDetached(QString(WINPTY_DEBUG_SRV_PATH), QStringList() << "--everyone", QCoreApplication::applicationDirPath(), &debugServerPid); QVERIFY(debugServerPid != 0); #endif QStringList shells = getShells(); foreach (QString shellPath, shells) { qDebug() << "Test" << shellPath; //create object QScopedPointer winPty(PtyQt::createPtyProcess(IPtyProcess::WinPty)); QCOMPARE(winPty->type(), IPtyProcess::WinPty); QVERIFY(winPty->isAvailable()); //prepare to check shell welcome QEventLoop el; auto connection = QObject::connect(winPty->notifier(), &QIODevice::readyRead, [&winPty, &el]() { sleepByEventLoop(1); //qDebug() << "winPty.read" << winPty->readAll(); winPty->readAll(); el.quit(); }); //start WinPty agent and cmd.exe bool startResult = winPty->startProcess(shellPath, QProcessEnvironment::systemEnvironment().toStringList(), 200, 80); #ifdef PTYQT_DEBUG if (!startResult) qDebug() << winPty->lastError() << winPty->dumpDebugInfo(); #endif QVERIFY(startResult); //check pid (winPty->pid() - PID of child process of winpty-agent.exe) QVERIFY(winPty->pid() != 0); //DWORD winPtyAgentPid = findProcessId(QString(WINPTY_AGENT_NAME).toStdString()); //DWORD winPtyShellPid = findProcessId(QFileInfo(shellPath).fileName().toStdString(), winPtyAgentPid); //QCOMPARE(winPty->pid(), winPtyShellPid); //check shell welcome el.exec(); winPty->notifier()->disconnect(connection); //check shell read after write bool testRes = false; connection = QObject::connect(winPty->notifier(), &QIODevice::readyRead, [&winPty, &el, &testRes]() { sleepByEventLoop(1); QString res = QString::fromUtf8(winPty->readAll()); //qDebug() << res; //for e.g. bash return empty strings after needed data if (res.isEmpty() && testRes) return; testRes = res.contains("winpty-agent.exe"); testRes = testRes && res.contains("winpty.dll"); testRes = testRes && res.contains("ptyqt_tests.exe"); el.quit(); }); winPty->write("dir\r\n"); el.exec(); QVERIFY(testRes); winPty->notifier()->disconnect(connection); //resize window sleepByEventLoop(1); QVERIFY(winPty->resize(240, 90)); //kill shell and winpty-agent processes #ifdef PTYQT_DEBUG qDebug() << winPty->dumpDebugInfo(); sleepByEventLoop(DEBUG_SLEEP_SEC); #endif QVERIFY(winPty->kill()); sleepByEventLoop(1); //QCOMPARE(findProcessId(QFileInfo(shellPath).fileName().toStdString(), winPtyAgentPid), 0); //QCOMPARE(findProcessId(QString(WINPTY_AGENT_NAME).toStdString()), 0); } #ifdef PTYQT_DEBUG killProcessByName(WINPTY_DBG_SERVER_NAME); #endif } #endif }; QTEST_MAIN(PtyQtTests) #include "ptyqt_tests.moc" ================================================ FILE: liteidex/src/3rdparty/qjson/.gitignore ================================================ lib Makefile ================================================ FILE: liteidex/src/3rdparty/qjson/CMakeLists.txt ================================================ PROJECT(qjson) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII" ) # Stop cmake 2.6 from whining CMAKE_MINIMUM_REQUIRED(VERSION 2.6) CMAKE_POLICY(SET CMP0003 NEW) set(CMAKE_INSTALL_NAME_DIR ${LIB_INSTALL_DIR}) # compile in debug mode IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel.") ENDIF(NOT CMAKE_BUILD_TYPE) IF("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*") ADD_DEFINITIONS("-DQT_NO_DEBUG_OUTPUT") ENDIF("${CMAKE_BUILD_TYPE}" MATCHES "^Rel.*") # Ability to disable verbose debug output IF(QJSON_VERBOSE_DEBUG_OUTPUT) ADD_DEFINITIONS("-DQJSON_VERBOSE_DEBUG_OUTPUT") endif(QJSON_VERBOSE_DEBUG_OUTPUT) OPTION(OSX_FRAMEWORK "Build a Mac OS X Framework") SET(FRAMEWORK_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/Library/Frameworks" CACHE PATH "Where to place qjson.framework if OSX_FRAMEWORK is selected") # Don't use absolute path in qjson-targets-*.cmake # (This will have no effect with CMake < 2.8) SET(QT_USE_IMPORTED_TARGETS TRUE) # Find Qt4 FIND_PACKAGE( Qt4 REQUIRED ) IF (NOT WIN32) SET( QT_DONT_USE_QTGUI TRUE ) ENDIF() # Include the cmake file needed to use qt4 INCLUDE( ${QT_USE_FILE} ) #add extra search paths for libraries and includes SET (LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) SET (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Directory where lib will install") SET (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The directory the headers are installed in") SET (CMAKECONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${CMAKE_PROJECT_NAME}" CACHE PATH "Directory where to install QJSONConfig.cmake") set(QJSON_LIB_MAJOR_VERSION "0") set(QJSON_LIB_MINOR_VERSION "7") set(QJSON_LIB_PATCH_VERSION "1") set(QJSON_LIB_VERSION_STRING "${QJSON_LIB_MAJOR_VERSION}.${QJSON_LIB_MINOR_VERSION}.${QJSON_LIB_PATCH_VERSION}") set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib" ) # pkg-config IF (NOT WIN32) CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/QJson.pc.in ${CMAKE_CURRENT_BINARY_DIR}/QJson.pc @ONLY) INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/QJson.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) ENDIF (NOT WIN32) # Subdirs ADD_SUBDIRECTORY(src) IF (KDE4_BUILD_TESTS OR QJSON_BUILD_TESTS) enable_testing() ADD_SUBDIRECTORY(tests) ENDIF (KDE4_BUILD_TESTS OR QJSON_BUILD_TESTS) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) INSTALL(EXPORT qjson-export DESTINATION ${CMAKECONFIG_INSTALL_DIR} FILE QJSONTargets.cmake) # figure out the relative path from the installed Config.cmake file to the install prefix (which may be at # runtime different from the chosen CMAKE_INSTALL_PREFIX if under Windows the package was installed anywhere) # This relative path will be configured into the QJSONConfig.cmake file(RELATIVE_PATH relInstallDir ${CMAKE_INSTALL_PREFIX}/${CMAKECONFIG_INSTALL_DIR} ${CMAKE_INSTALL_PREFIX} ) # cmake-modules CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/QJSONConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/QJSONConfig.cmake @ONLY) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/QJSONConfigVersion.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/QJSONConfigVersion.cmake @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/QJSONConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/QJSONConfigVersion.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}") ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ================================================ FILE: liteidex/src/3rdparty/qjson/COPYING.lib ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1, as published by the Free Software Foundation. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: liteidex/src/3rdparty/qjson/ChangeLog ================================================ Tue Jan 31 10:15:06 CET 2012 Flavio Castelli * Make possible to build qjson as an OS X framework. Fri Nov 04 16:50:56 CET 2011 Flavio Castelli * Make possible to set double precision during serialization. Wed Aug 24 17:58:56 CEST 2011 Flavio Castelli * Buildsystem adjustments, fix issues mentioned here: - http://lists.kde.org/?l=kde-buildsystem&m=130947194605100&w=3 - http://lists.kde.org/?l=kde-buildsystem&m=128835747626464&w=3 The biggest difference now is that FindQJSON.cmake is not provided anymore. Instead, QJSONConfig.cmake and QJSONConfigVersion.cmake are installed and can be used in find_package(QJSON) calls. Applications using QJson can write their own FindQJSON.cmake files if they need to. Fri Apr 23:04:29 CEST 2011 Flavio Castelli * Fixed QVariant de-serialization. QVariant properties were ignored during QVariant -> QObject conversion. Sun Dec 18:59:28 CET 2010 Flavio Castelli * It's now possible to indent the output produced by the Serializer. Mon Sep 06 18:53:02 CEST 2010 Flavio Castelli * 50% performance improvement when parsing numbers. Sun Jul 04 15:41:08 CEST 2010 Flavio Castelli * fix make install when not installing as root * provide "make uninstall" Tue Jun 15 13:16:57 CEST 2010 Flavio Castelli * Allow top level values ---------------------------------------------------------------------- Sat Mar 13 23:57:00 CEST 2009 - flavio@castelli.name * Merged the symbian branch into master, ---------------------------------------------------------------------- Sun Oct 11 19:18:00 CEST 2009 - flavio@castelli.name * Updated to 0.6.3: fixed a bug affecting ulonglong numbers serialization. ------------------------------------------------------------------- Wed Sep 15 19:21:00 CEST 2009 - flavio@castelli.name * Updated to 0.6.2: fixed a bug affecting ulonglong numbers parsing. ------------------------------------------------------------------- Wed Sep 09 09:55:00 CEST 2009 - flavio@castelli.name * Updated to 0.6.1: relevant bugs fixed. * Moved the SerializerRunnable class inside QJson namespace. * Fixed a bug in cmdline_tester. ------------------------------------------------------------------- Mon Jul 20 15:24:32 CEST 2009 - prusnak@suse.cz * Updated to 0.6.0 (KDE SVN rev 999750). ------------------------------------------------------------------- Mon Apr 07 00:00:00 UTC 2009 - flavio@castelli.name * Released 0.5.1 - added unicode support. ------------------------------------------------------------------- Mon Apr 03 00:00:00 UTC 2009 - flavio@castelli.name * First release. ================================================ FILE: liteidex/src/3rdparty/qjson/INSTALL ================================================ Installing QJson -------------- QJson requires: - Qt 4.0 or greater - cmake 2.6 or greater Some possible cmake options: -DCMAKE_BUILD_TYPE=DEBUG enables some debug output (other than making easier to debug the code) -DQJSON_BUILD_TESTS=yes or -DKDE4_BUILD_TESTS=yes builds the unit tests -DCMAKE_INSTALL_PREFIX=${HOME}/testinstall install qjson in a custom directory -DCMAKE_INCLUDE_PATH=${HOME}/testinstall/include include a custom include directory -DCMAKE_LIBRARY_PATH=${HOME}/testinstall/lib include a custom library directory -DLIB_DESTINATION=lib64 if you have a 64 bit system with separate libraries for 64 bit libraries -DQJSON_VERBOSE_DEBUG_OUTPUT:BOOL=ON more debugging statements are generated by the parser. It's useful only if you are trying to fix the bison grammar. For Unix/Linux/Mac: mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=_preferred_path_ .. make make install /sbin/ldconfig, if necessary For Mac: It's possible to build qjson as an OS X framework using the OSX_FRAMEWORK option. For Symbian: Read this page: http://qjson.sourceforge.net/get_it/symbian.html For Windows: Read this page: http://qjson.sourceforge.net/get_it/windows.html Please report problems to: https://lists.sourceforge.net/mailman/listinfo/qjson-devel ================================================ FILE: liteidex/src/3rdparty/qjson/QJSONConfig.cmake.in ================================================ GET_FILENAME_COMPONENT(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) SET(QJSON_LIBRARIES qjson) SET(QJSON_INCLUDE_DIR "@INCLUDE_INSTALL_DIR@") include(${myDir}/QJSONTargets.cmake) ================================================ FILE: liteidex/src/3rdparty/qjson/QJSONConfigVersion.cmake.in ================================================ SET(PACKAGE_VERSION "@QJSON_LIB_VERSION_STRING@") IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) SET(PACKAGE_VERSION_EXACT TRUE) ENDIF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) IF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) SET(PACKAGE_VERSION_COMPATIBLE TRUE) ELSE (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) SET(PACKAGE_VERSION_UNSUITABLE TRUE) ENDIF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) ================================================ FILE: liteidex/src/3rdparty/qjson/QJson.pc.in ================================================ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=@LIB_INSTALL_DIR@ includedir=@INCLUDE_INSTALL_DIR@ Name: QJson Description: QJson is a qt-based library that maps JSON data to QVariant objects Version: @QJSON_LIB_MAJOR_VERSION@.@QJSON_LIB_MINOR_VERSION@.@QJSON_LIB_PATCH_VERSION@ Requires: QtCore Libs: -L${libdir} -lqjson Cflags: -I${includedir} ================================================ FILE: liteidex/src/3rdparty/qjson/README ================================================ QJson ------------------------------------------------- Website: http://qjson.sourceforge.net/ Mailing List: https://lists.sourceforge.net/mailman/listinfo/qjson-devel Project Lead/Maintainer (2008-current): Flavio Castelli Install ------- For installation or compiling instructions, see the INSTALL file. License ------- This library is licensed under the Lesser GNU General Public License version 2.1. See the COPYING.lib file for more information. Description ----------- JSON (JavaScript Object Notation) is a lightweight data-interchange format. It can represents integer, real number, string, an ordered sequence of value, and a collection of name/value pairs. QJson is a qt-based library that maps JSON data to QVariant objects. JSON arrays will be mapped to QVariantList instances, while JSON's objects will be mapped to QVariantMap. Happy hacking Flavio ================================================ FILE: liteidex/src/3rdparty/qjson/cmake_uninstall.cmake.in ================================================ IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") ENDIF(NOT "${rm_retval}" STREQUAL 0) ENDFOREACH(file) ================================================ FILE: liteidex/src/3rdparty/qjson/doc/Doxyfile ================================================ # Doxyfile 1.5.6 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = QJson PROJECT_NUMBER = 0.7.0 OUTPUT_DIRECTORY = ./ CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = NO SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = ./qjson.dox \ ../src INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.f90 \ *.f \ *.vhd \ *.vhdl \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM \ *.PY \ *.F90 \ *.F \ *.VHD \ *.VHDL RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = ./header.html HTML_FOOTER = ./footer.html HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project HTML_DYNAMIC_SECTIONS = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = NO MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO DOT_FONTNAME = FreeSans DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = YES DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO ================================================ FILE: liteidex/src/3rdparty/qjson/doc/footer.html ================================================
SourceForge Logo hosts this site. Send comments to:
QJson Developers
================================================ FILE: liteidex/src/3rdparty/qjson/doc/header.html ================================================ QJson - a Qt based library for mapping JSON data to QVariant objects
QJson project page QJson home page

================================================ FILE: liteidex/src/3rdparty/qjson/doc/qjson.dox ================================================ /** \mainpage \section _intro Introduction JSON (JavaScript Object Notation) is a lightweight data-interchange format. It can represents integer, real number, string, an ordered sequence of value, and a collection of name/value pairs. QJson is a qt-based library that maps JSON data to QVariant objects. JSON arrays will be mapped to QVariantList instances, while JSON's objects will be mapped to QVariantMap. \section _usage Usage Converting JSON's data to QVariant instance is really simple: \code // create a JSonDriver instance QJson::Parser parser; bool ok; // json is a QString containing the data to convert QVariant result = parser.parse (json, &ok); \endcode Suppose you're going to convert this JSON data: \verbatim { "encoding" : "UTF-8", "plug-ins" : [ "python", "c++", "ruby" ], "indent" : { "length" : 3, "use_space" : true } } \endverbatim The following code would convert the JSON data and parse it: \code QJson::Parser parser; bool ok; QVariantMap result = parser.parse (json, &ok).toMap(); if (!ok) { qFatal("An error occured during parsing"); exit (1); } qDebug() << "encoding:" << result["encoding"].toString(); qDebug() << "plugins:"; foreach (QVariant plugin, result["plug-ins"].toList()) { qDebug() << "\t-" << plugin.toString(); } QVariantMap nestedMap = result["indent"].toMap(); qDebug() << "length:" << nestedMap["length"].toInt(); qDebug() << "use_space:" << nestedMap["use_space"].toBool(); \endcode The output would be: \verbatim encoding: "UTF-8" plugins: - "python" - "c++" - "ruby" length: 3 use_space: true \endverbatim The QJson::QObjectHelper class permits to serialize QObject instances into JSON. QJson::QObjectHelper also allows to initialize a QObject using the values stored inside of a JSON object. \section _build Build instructions QJson build system is based on cmake. Download QJson sources, extract them, move inside the sources directory and then: \code mkdir build cd build cmake .. make sudo make install \endcode \section _download Get the code Actually QJson code is hosted on KDE subversion repository. You can download it using a svn client: \code svn co svn://anonsvn.kde.org/home/kde/trunk/playground/libs/qjson \endcode Otherwise you can download source tarballs here. \author Flavio Castelli */ ================================================ FILE: liteidex/src/3rdparty/qjson/include/QJson/Parser ================================================ #include "../../src/parser.h" ================================================ FILE: liteidex/src/3rdparty/qjson/include/QJson/QObjectHelper ================================================ #include "../../src/qobjecthelper.h" ================================================ FILE: liteidex/src/3rdparty/qjson/include/QJson/Serializer ================================================ #include "../../src/serializer.h" ================================================ FILE: liteidex/src/3rdparty/qjson/qjson.pri ================================================ LIBS *= -l$$qtLibraryName(json) ================================================ FILE: liteidex/src/3rdparty/qjson/qjson.pro ================================================ TEMPLATE = subdirs SUBDIRS = sub_src #sub_unittest sub_src.subdir = src sub_unittest.subdir = tests sub_unittest.depends = sub_src ================================================ FILE: liteidex/src/3rdparty/qjson/src/.gitignore ================================================ moc_* *.o Makefile ================================================ FILE: liteidex/src/3rdparty/qjson/src/CMakeLists.txt ================================================ # add_custom_command (OUTPUT ${qjson_SOURCE_DIR}/lib/json_parser.cc # PRE_BUILD # COMMAND bison -t -o json_parser.cc -d json_parser.yy # DEPENDS json_parser.yy # WORKING_DIRECTORY ${qjson_SOURCE_DIR}/lib/ # ) set(qjson_MOC_HDRS parserrunnable.h serializerrunnable.h ) qt4_wrap_cpp(qjson_MOC_SRCS ${qjson_MOC_HDRS}) set (qjson_SRCS parser.cpp qobjecthelper.cpp json_scanner.cpp json_parser.cc parserrunnable.cpp serializer.cpp serializerrunnable.cpp) set (qjson_HEADERS parser.h parserrunnable.h qobjecthelper.h serializer.h serializerrunnable.h qjson_export.h) add_library (qjson SHARED ${qjson_SRCS} ${qjson_MOC_SRCS} ${qjson_HEADERS}) target_link_libraries( qjson ${QT_LIBRARIES}) if(NOT android) set_target_properties(qjson PROPERTIES VERSION ${QJSON_LIB_MAJOR_VERSION}.${QJSON_LIB_MINOR_VERSION}.${QJSON_LIB_PATCH_VERSION} SOVERSION ${QJSON_LIB_MAJOR_VERSION} ) endif() set_target_properties(qjson PROPERTIES DEFINE_SYMBOL QJSON_MAKEDLL PUBLIC_HEADER "${qjson_HEADERS}" FRAMEWORK ${OSX_FRAMEWORK} ) INSTALL(TARGETS qjson EXPORT qjson-export LIBRARY DESTINATION ${LIB_INSTALL_DIR} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin ARCHIVE DESTINATION ${LIB_INSTALL_DIR} FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR} PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}/qjson ) ================================================ FILE: liteidex/src/3rdparty/qjson/src/json_parser.cc ================================================ /* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison LALR(1) parsers in C++ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #include "json_parser.hh" /* User implementation prologue. */ /* Line 317 of lalr1.cc. */ #line 43 "json_parser.cc" #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* FIXME: INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #define YYUSE(e) ((void) (e)) /* A pseudo ostream that takes yydebug_ into account. */ # define YYCDEBUG \ for (bool yydebugcond_ = yydebug_; yydebugcond_; yydebugcond_ = false) \ (*yycdebug_) /* Enable debugging if requested. */ #if YYDEBUG # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug_) \ { \ *yycdebug_ << Title << ' '; \ yy_symbol_print_ ((Type), (Value), (Location)); \ *yycdebug_ << std::endl; \ } \ } while (false) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug_) \ yy_reduce_print_ (Rule); \ } while (false) # define YY_STACK_PRINT() \ do { \ if (yydebug_) \ yystack_print_ (); \ } while (false) #else /* !YYDEBUG */ # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_REDUCE_PRINT(Rule) # define YY_STACK_PRINT() #endif /* !YYDEBUG */ #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab namespace yy { #if YYERROR_VERBOSE /* Return YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. */ std::string json_parser::yytnamerr_ (const char *yystr) { if (*yystr == '"') { std::string yyr = ""; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: yyr += *yyp; break; case '"': return yyr; } do_not_strip_quotes: ; } return yystr; } #endif /// Build a parser object. json_parser::json_parser (QJson::ParserPrivate* driver_yyarg) : yydebug_ (false), yycdebug_ (&std::cerr), driver (driver_yyarg) { } json_parser::~json_parser () { } #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ inline void json_parser::yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yyvaluep); switch (yytype) { default: break; } } void json_parser::yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp) { *yycdebug_ << (yytype < yyntokens_ ? "token" : "nterm") << ' ' << yytname_[yytype] << " (" << *yylocationp << ": "; yy_symbol_value_print_ (yytype, yyvaluep, yylocationp); *yycdebug_ << ')'; } #endif /* ! YYDEBUG */ void json_parser::yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp) { YYUSE (yylocationp); YYUSE (yymsg); YYUSE (yyvaluep); YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } void json_parser::yypop_ (unsigned int n) { yystate_stack_.pop (n); yysemantic_stack_.pop (n); yylocation_stack_.pop (n); } std::ostream& json_parser::debug_stream () const { return *yycdebug_; } void json_parser::set_debug_stream (std::ostream& o) { yycdebug_ = &o; } json_parser::debug_level_type json_parser::debug_level () const { return yydebug_; } void json_parser::set_debug_level (debug_level_type l) { yydebug_ = l; } int json_parser::parse () { /// Look-ahead and look-ahead in internal form. int yychar = yyempty_; int yytoken = 0; /* State. */ int yyn; int yylen = 0; int yystate = 0; /* Error handling. */ int yynerrs_ = 0; int yyerrstatus_ = 0; /// Semantic value of the look-ahead. semantic_type yylval; /// Location of the look-ahead. location_type yylloc; /// The locations where the error started and ended. location yyerror_range[2]; /// $$. semantic_type yyval; /// @$. location_type yyloc; int yyresult; YYCDEBUG << "Starting parse" << std::endl; /* Initialize the stacks. The initial state will be pushed in yynewstate, since the latter expects the semantical and the location values to have been already stored, initialize these stacks with a primary value. */ yystate_stack_ = state_stack_type (0); yysemantic_stack_ = semantic_stack_type (0); yylocation_stack_ = location_stack_type (0); yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* New state. */ yynewstate: yystate_stack_.push (yystate); YYCDEBUG << "Entering state " << yystate << std::endl; goto yybackup; /* Backup. */ yybackup: /* Try to take a decision without look-ahead. */ yyn = yypact_[yystate]; if (yyn == yypact_ninf_) goto yydefault; /* Read a look-ahead token. */ if (yychar == yyempty_) { YYCDEBUG << "Reading a token: "; yychar = yylex (&yylval, &yylloc, driver); } /* Convert token to internal form. */ if (yychar <= yyeof_) { yychar = yytoken = yyeof_; YYCDEBUG << "Now at end of input." << std::endl; } else { yytoken = yytranslate_ (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yytoken) goto yydefault; /* Reduce or error. */ yyn = yytable_[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == yytable_ninf_) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Accept? */ if (yyn == yyfinal_) goto yyacceptlab; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the token being shifted unless it is eof. */ if (yychar != yyeof_) yychar = yyempty_; yysemantic_stack_.push (yylval); yylocation_stack_.push (yylloc); /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus_) --yyerrstatus_; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact_[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: yylen = yyr2_[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, use the top of the stack. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. */ if (yylen) yyval = yysemantic_stack_[yylen - 1]; else yyval = yysemantic_stack_[0]; { slice slice (yylocation_stack_, yylen); YYLLOC_DEFAULT (yyloc, slice, yylen); } YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 84 "json_parser.yy" { driver->m_result = (yysemantic_stack_[(1) - (1)]); qjsonDebug() << "json_parser - parsing finished"; ;} break; case 3: #line 89 "json_parser.yy" { (yyval) = (yysemantic_stack_[(1) - (1)]); ;} break; case 4: #line 91 "json_parser.yy" { qCritical()<< "json_parser - syntax error found, " << "forcing abort, Line" << (yyloc).begin.line << "Column" << (yyloc).begin.column; YYABORT; ;} break; case 6: #line 98 "json_parser.yy" { (yyval) = (yysemantic_stack_[(3) - (2)]); ;} break; case 7: #line 100 "json_parser.yy" { (yyval) = QVariant (QVariantMap()); ;} break; case 8: #line 101 "json_parser.yy" { QVariantMap members = (yysemantic_stack_[(2) - (2)]).toMap(); (yysemantic_stack_[(2) - (2)]) = QVariant(); // Allow reuse of map (yyval) = QVariant(members.unite ((yysemantic_stack_[(2) - (1)]).toMap())); ;} break; case 9: #line 107 "json_parser.yy" { (yyval) = QVariant (QVariantMap()); ;} break; case 10: #line 108 "json_parser.yy" { QVariantMap members = (yysemantic_stack_[(3) - (3)]).toMap(); (yysemantic_stack_[(3) - (3)]) = QVariant(); // Allow reuse of map (yyval) = QVariant(members.unite ((yysemantic_stack_[(3) - (2)]).toMap())); ;} break; case 11: #line 114 "json_parser.yy" { QVariantMap pair; pair.insert ((yysemantic_stack_[(3) - (1)]).toString(), QVariant((yysemantic_stack_[(3) - (3)]))); (yyval) = QVariant (pair); ;} break; case 12: #line 120 "json_parser.yy" { (yyval) = (yysemantic_stack_[(3) - (2)]); ;} break; case 13: #line 122 "json_parser.yy" { (yyval) = QVariant (QVariantList()); ;} break; case 14: #line 123 "json_parser.yy" { QVariantList members = (yysemantic_stack_[(2) - (2)]).toList(); (yysemantic_stack_[(2) - (2)]) = QVariant(); // Allow reuse of list members.prepend ((yysemantic_stack_[(2) - (1)])); (yyval) = QVariant(members); ;} break; case 15: #line 130 "json_parser.yy" { (yyval) = QVariant (QVariantList()); ;} break; case 16: #line 131 "json_parser.yy" { QVariantList members = (yysemantic_stack_[(3) - (3)]).toList(); (yysemantic_stack_[(3) - (3)]) = QVariant(); // Allow reuse of list members.prepend ((yysemantic_stack_[(3) - (2)])); (yyval) = QVariant(members); ;} break; case 17: #line 138 "json_parser.yy" { (yyval) = (yysemantic_stack_[(1) - (1)]); ;} break; case 18: #line 139 "json_parser.yy" { (yyval) = (yysemantic_stack_[(1) - (1)]); ;} break; case 19: #line 140 "json_parser.yy" { (yyval) = (yysemantic_stack_[(1) - (1)]); ;} break; case 20: #line 141 "json_parser.yy" { (yyval) = (yysemantic_stack_[(1) - (1)]); ;} break; case 21: #line 142 "json_parser.yy" { (yyval) = QVariant (true); ;} break; case 22: #line 143 "json_parser.yy" { (yyval) = QVariant (false); ;} break; case 23: #line 144 "json_parser.yy" { QVariant null_variant; (yyval) = null_variant; ;} break; case 24: #line 149 "json_parser.yy" { (yyval) = QVariant(QVariant::Double); (yyval).setValue( -std::numeric_limits::infinity() ); ;} break; case 25: #line 150 "json_parser.yy" { (yyval) = QVariant(QVariant::Double); (yyval).setValue( std::numeric_limits::infinity() ); ;} break; case 26: #line 151 "json_parser.yy" { (yyval) = QVariant(QVariant::Double); (yyval).setValue( std::numeric_limits::quiet_NaN() ); ;} break; case 28: #line 154 "json_parser.yy" { if ((yysemantic_stack_[(1) - (1)]).toByteArray().startsWith('-')) { (yyval) = QVariant (QVariant::LongLong); (yyval).setValue((yysemantic_stack_[(1) - (1)]).toLongLong()); } else { (yyval) = QVariant (QVariant::ULongLong); (yyval).setValue((yysemantic_stack_[(1) - (1)]).toULongLong()); } ;} break; case 29: #line 164 "json_parser.yy" { const QByteArray value = (yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray(); (yyval) = QVariant(QVariant::Double); (yyval).setValue(value.toDouble()); ;} break; case 30: #line 169 "json_parser.yy" { (yyval) = QVariant ((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;} break; case 31: #line 170 "json_parser.yy" { const QByteArray value = (yysemantic_stack_[(3) - (1)]).toByteArray() + (yysemantic_stack_[(3) - (2)]).toByteArray() + (yysemantic_stack_[(3) - (3)]).toByteArray(); (yyval) = QVariant (value); ;} break; case 32: #line 175 "json_parser.yy" { (yyval) = QVariant ((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;} break; case 33: #line 176 "json_parser.yy" { (yyval) = QVariant (QByteArray("-") + (yysemantic_stack_[(3) - (2)]).toByteArray() + (yysemantic_stack_[(3) - (3)]).toByteArray()); ;} break; case 34: #line 178 "json_parser.yy" { (yyval) = QVariant (QByteArray("")); ;} break; case 35: #line 179 "json_parser.yy" { (yyval) = QVariant((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;} break; case 36: #line 183 "json_parser.yy" { (yyval) = QVariant(QByteArray(".") + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;} break; case 37: #line 187 "json_parser.yy" { (yyval) = QVariant((yysemantic_stack_[(2) - (1)]).toByteArray() + (yysemantic_stack_[(2) - (2)]).toByteArray()); ;} break; case 38: #line 189 "json_parser.yy" { (yyval) = (yysemantic_stack_[(3) - (2)]); ;} break; case 39: #line 191 "json_parser.yy" { (yyval) = QVariant (QString(QLatin1String(""))); ;} break; case 40: #line 192 "json_parser.yy" { (yyval) = (yysemantic_stack_[(1) - (1)]); ;} break; /* Line 675 of lalr1.cc. */ #line 628 "json_parser.cc" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1_[yyn], &yyval, &yyloc); yypop_ (yylen); yylen = 0; YY_STACK_PRINT (); yysemantic_stack_.push (yyval); yylocation_stack_.push (yyloc); /* Shift the result of the reduction. */ yyn = yyr1_[yyn]; yystate = yypgoto_[yyn - yyntokens_] + yystate_stack_[0]; if (0 <= yystate && yystate <= yylast_ && yycheck_[yystate] == yystate_stack_[0]) yystate = yytable_[yystate]; else yystate = yydefgoto_[yyn - yyntokens_]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus_) { ++yynerrs_; error (yylloc, yysyntax_error_ (yystate, yytoken)); } yyerror_range[0] = yylloc; if (yyerrstatus_ == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= yyeof_) { /* Return failure if at end of input. */ if (yychar == yyeof_) YYABORT; } else { yydestruct_ ("Error: discarding", yytoken, &yylval, &yylloc); yychar = yyempty_; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (false) goto yyerrorlab; yyerror_range[0] = yylocation_stack_[yylen - 1]; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ yypop_ (yylen); yylen = 0; yystate = yystate_stack_[0]; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus_ = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact_[yystate]; if (yyn != yypact_ninf_) { yyn += yyterror_; if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_) { yyn = yytable_[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yystate_stack_.height () == 1) YYABORT; yyerror_range[0] = yylocation_stack_[0]; yydestruct_ ("Error: popping", yystos_[yystate], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); yystate = yystate_stack_[0]; YY_STACK_PRINT (); } if (yyn == yyfinal_) goto yyacceptlab; yyerror_range[1] = yylloc; // Using YYLLOC is tempting, but would change the location of // the look-ahead. YYLOC is available though. YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); yysemantic_stack_.push (yylval); yylocation_stack_.push (yyloc); /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos_[yyn], &yysemantic_stack_[0], &yylocation_stack_[0]); yystate = yyn; goto yynewstate; /* Accept. */ yyacceptlab: yyresult = 0; goto yyreturn; /* Abort. */ yyabortlab: yyresult = 1; goto yyreturn; yyreturn: if (yychar != yyeof_ && yychar != yyempty_) yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ yypop_ (yylen); while (yystate_stack_.height () != 1) { yydestruct_ ("Cleanup: popping", yystos_[yystate_stack_[0]], &yysemantic_stack_[0], &yylocation_stack_[0]); yypop_ (); } return yyresult; } // Generate an error message. std::string json_parser::yysyntax_error_ (int yystate, int tok) { std::string res; YYUSE (yystate); #if YYERROR_VERBOSE int yyn = yypact_[yystate]; if (yypact_ninf_ < yyn && yyn <= yylast_) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = yylast_ - yyn + 1; int yyxend = yychecklim < yyntokens_ ? yychecklim : yyntokens_; int count = 0; for (int x = yyxbegin; x < yyxend; ++x) if (yycheck_[x + yyn] == x && x != yyterror_) ++count; // FIXME: This method of building the message is not compatible // with internationalization. It should work like yacc.c does it. // That is, first build a string that looks like this: // "syntax error, unexpected %s or %s or %s" // Then, invoke YY_ on this string. // Finally, use the string as a format to output // yytname_[tok], etc. // Until this gets fixed, this message appears in English only. res = "syntax error, unexpected "; res += yytnamerr_ (yytname_[tok]); if (count < 5) { count = 0; for (int x = yyxbegin; x < yyxend; ++x) if (yycheck_[x + yyn] == x && x != yyterror_) { res += (!count++) ? ", expecting " : " or "; res += yytnamerr_ (yytname_[x]); } } } else #endif res = YY_("syntax error"); return res; } /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ const signed char json_parser::yypact_ninf_ = -21; const signed char json_parser::yypact_[] = { 3, -21, -21, -6, 31, -10, 0, -21, -21, -21, 6, -21, -21, 25, -21, -21, -21, -21, -21, -21, -5, -21, 22, 19, 21, 23, 24, 0, -21, 0, -21, -21, 13, -21, 0, 0, 29, -21, -21, -6, -21, 31, -21, 31, -21, -21, -21, -21, -21, -21, -21, 19, -21, 24, -21, -21 }; /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ const unsigned char json_parser::yydefact_[] = { 0, 5, 4, 7, 13, 0, 34, 21, 22, 23, 39, 25, 26, 0, 2, 19, 20, 3, 18, 27, 28, 17, 0, 9, 0, 0, 15, 34, 24, 34, 32, 40, 0, 1, 34, 34, 29, 30, 6, 0, 8, 0, 12, 0, 14, 33, 35, 38, 36, 37, 31, 9, 11, 15, 10, 16 }; /* YYPGOTO[NTERM-NUM]. */ const signed char json_parser::yypgoto_[] = { -21, -21, -21, -21, -21, -20, 4, -21, -21, -18, -4, -21, -21, -21, -14, -21, -3, -1, -21 }; /* YYDEFGOTO[NTERM-NUM]. */ const signed char json_parser::yydefgoto_[] = { -1, 13, 14, 15, 22, 40, 23, 16, 25, 44, 17, 18, 19, 20, 30, 36, 37, 21, 32 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. */ const signed char json_parser::yytable_ninf_ = -1; const unsigned char json_parser::yytable_[] = { 26, 27, 24, 1, 2, 34, 3, 35, 4, 28, 10, 29, 5, 45, 6, 46, 7, 8, 9, 10, 48, 49, 11, 12, 31, 33, 38, 39, 41, 42, 47, 54, 43, 50, 3, 55, 4, 52, 24, 53, 5, 35, 6, 51, 7, 8, 9, 10, 0, 0, 11, 12 }; /* YYCHECK. */ const signed char json_parser::yycheck_[] = { 4, 11, 3, 0, 1, 10, 3, 12, 5, 19, 16, 11, 9, 27, 11, 29, 13, 14, 15, 16, 34, 35, 19, 20, 18, 0, 4, 8, 7, 6, 17, 51, 8, 36, 3, 53, 5, 41, 39, 43, 9, 12, 11, 39, 13, 14, 15, 16, -1, -1, 19, 20 }; /* STOS_[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ const unsigned char json_parser::yystos_[] = { 0, 0, 1, 3, 5, 9, 11, 13, 14, 15, 16, 19, 20, 22, 23, 24, 28, 31, 32, 33, 34, 38, 25, 27, 38, 29, 31, 11, 19, 11, 35, 18, 39, 0, 10, 12, 36, 37, 4, 8, 26, 7, 6, 8, 30, 35, 35, 17, 35, 35, 37, 27, 31, 31, 26, 30 }; #if YYDEBUG /* TOKEN_NUMBER_[YYLEX-NUM] -- Internal symbol number corresponding to YYLEX-NUM. */ const unsigned short int json_parser::yytoken_number_[] = { 0, 256, 257, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }; #endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ const unsigned char json_parser::yyr1_[] = { 0, 21, 22, 23, 23, 23, 24, 25, 25, 26, 26, 27, 28, 29, 29, 30, 30, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 35, 35, 36, 37, 38, 39, 39 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ const unsigned char json_parser::yyr2_[] = { 0, 2, 1, 1, 1, 1, 3, 0, 2, 0, 3, 3, 3, 0, 2, 0, 3, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 3, 2, 3, 0, 2, 2, 2, 3, 0, 1 }; #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at \a yyntokens_, nonterminals. */ const char* const json_parser::yytname_[] = { "\"end of file\"", "error", "$undefined", "\"{\"", "\"}\"", "\"[\"", "\"]\"", "\":\"", "\",\"", "\"-\"", "\".\"", "\"digit\"", "\"exponential\"", "\"true\"", "\"false\"", "\"null\"", "\"open quotation mark\"", "\"close quotation mark\"", "\"string\"", "\"Infinity\"", "\"NaN\"", "$accept", "start", "data", "object", "members", "r_members", "pair", "array", "values", "r_values", "value", "special_or_number", "number", "int", "digits", "fract", "exp", "string", "string_arg", 0 }; #endif #if YYDEBUG /* YYRHS -- A `-1'-separated list of the rules' RHS. */ const json_parser::rhs_number_type json_parser::yyrhs_[] = { 22, 0, -1, 23, -1, 31, -1, 1, -1, 0, -1, 3, 25, 4, -1, -1, 27, 26, -1, -1, 8, 27, 26, -1, 38, 7, 31, -1, 5, 29, 6, -1, -1, 31, 30, -1, -1, 8, 31, 30, -1, 38, -1, 32, -1, 24, -1, 28, -1, 13, -1, 14, -1, 15, -1, 9, 19, -1, 19, -1, 20, -1, 33, -1, 34, -1, 34, 36, -1, 34, 37, -1, 34, 36, 37, -1, 11, 35, -1, 9, 11, 35, -1, -1, 11, 35, -1, 10, 35, -1, 12, 35, -1, 16, 39, 17, -1, -1, 18, -1 }; /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ const unsigned char json_parser::yyprhs_[] = { 0, 0, 3, 5, 7, 9, 11, 15, 16, 19, 20, 24, 28, 32, 33, 36, 37, 41, 43, 45, 47, 49, 51, 53, 55, 58, 60, 62, 64, 66, 69, 72, 76, 79, 83, 84, 87, 90, 93, 97, 98 }; /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ const unsigned char json_parser::yyrline_[] = { 0, 84, 84, 89, 90, 96, 98, 100, 101, 107, 108, 114, 120, 122, 123, 130, 131, 138, 139, 140, 141, 142, 143, 144, 149, 150, 151, 152, 154, 164, 169, 170, 175, 176, 178, 179, 183, 187, 189, 191, 192 }; // Print the state stack on the debug stream. void json_parser::yystack_print_ () { *yycdebug_ << "Stack now"; for (state_stack_type::const_iterator i = yystate_stack_.begin (); i != yystate_stack_.end (); ++i) *yycdebug_ << ' ' << *i; *yycdebug_ << std::endl; } // Report on the debug stream that the rule \a yyrule is going to be reduced. void json_parser::yy_reduce_print_ (int yyrule) { unsigned int yylno = yyrline_[yyrule]; int yynrhs = yyr2_[yyrule]; /* Print the symbols being reduced, and their result. */ *yycdebug_ << "Reducing stack by rule " << yyrule - 1 << " (line " << yylno << "), "; /* The symbols being reduced. */ for (int yyi = 0; yyi < yynrhs; yyi++) YY_SYMBOL_PRINT (" $" << yyi + 1 << " =", yyrhs_[yyprhs_[yyrule] + yyi], &(yysemantic_stack_[(yynrhs) - (yyi + 1)]), &(yylocation_stack_[(yynrhs) - (yyi + 1)])); } #endif // YYDEBUG /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ json_parser::token_number_type json_parser::yytranslate_ (int t) { static const token_number_type translate_table[] = { 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2 }; if ((unsigned int) t <= yyuser_token_number_max_) return translate_table[t]; else return yyundef_token_; } const int json_parser::yyeof_ = 0; const int json_parser::yylast_ = 51; const int json_parser::yynnts_ = 19; const int json_parser::yyempty_ = -2; const int json_parser::yyfinal_ = 33; const int json_parser::yyterror_ = 1; const int json_parser::yyerrcode_ = 256; const int json_parser::yyntokens_ = 21; const unsigned int json_parser::yyuser_token_number_max_ = 257; const json_parser::token_number_type json_parser::yyundef_token_ = 2; } // namespace yy #line 196 "json_parser.yy" int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver) { JSonScanner* scanner = driver->m_scanner; yylval->clear(); int ret = scanner->yylex(yylval, yylloc); qjsonDebug() << "json_parser::yylex - calling scanner yylval==|" << yylval->toByteArray() << "|, ret==|" << QString::number(ret) << "|"; return ret; } void yy::json_parser::error (const yy::location& yyloc, const std::string& error) { /*qjsonDebug() << yyloc.begin.line; qjsonDebug() << yyloc.begin.column; qjsonDebug() << yyloc.end.line; qjsonDebug() << yyloc.end.column;*/ qjsonDebug() << "json_parser::error [line" << yyloc.end.line << "] -" << error.c_str() ; driver->setError(QString::fromLatin1(error.c_str()), yyloc.end.line); } ================================================ FILE: liteidex/src/3rdparty/qjson/src/json_parser.hh ================================================ /* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton interface for Bison LALR(1) parsers in C++ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C++ LALR(1) parser skeleton written by Akim Demaille. */ #ifndef PARSER_HEADER_H # define PARSER_HEADER_H #include #include #include "stack.hh" namespace yy { class position; class location; } /* First part of user declarations. */ #line 25 "json_parser.yy" #include "parser_p.h" #include "json_scanner.h" #include "qjson_debug.h" #include #include #include #include #include class JSonScanner; namespace QJson { class Parser; } #define YYERROR_VERBOSE 1 /* Line 35 of lalr1.cc. */ #line 75 "json_parser.hh" #include "location.hh" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 1 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 1 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ if (N) \ { \ (Current).begin = (Rhs)[1].begin; \ (Current).end = (Rhs)[N].end; \ } \ else \ { \ (Current).begin = (Current).end = (Rhs)[0].end; \ } \ } while (false) #endif namespace yy { /// A Bison parser. class json_parser { public: /// Symbol semantic values. #ifndef YYSTYPE typedef int semantic_type; #else typedef YYSTYPE semantic_type; #endif /// Symbol locations. typedef location location_type; /// Tokens. struct token { /* Tokens. */ enum yytokentype { END = 0, CURLY_BRACKET_OPEN = 1, CURLY_BRACKET_CLOSE = 2, SQUARE_BRACKET_OPEN = 3, SQUARE_BRACKET_CLOSE = 4, COLON = 5, COMMA = 6, MINUS = 7, DOT = 8, DIGIT = 9, E = 10, TRUE_VAL = 11, FALSE_VAL = 12, NULL_VAL = 13, QUOTMARKOPEN = 14, QUOTMARKCLOSE = 15, STRING = 16, INFINITY_VAL = 17, NAN_VAL = 18 }; }; /// Token type. typedef token::yytokentype token_type; /// Build a parser object. json_parser (QJson::ParserPrivate* driver_yyarg); virtual ~json_parser (); /// Parse. /// \returns 0 iff parsing succeeded. virtual int parse (); /// The current debugging stream. std::ostream& debug_stream () const; /// Set the current debugging stream. void set_debug_stream (std::ostream &); /// Type for debugging levels. typedef int debug_level_type; /// The current debugging level. debug_level_type debug_level () const; /// Set the current debugging level. void set_debug_level (debug_level_type l); private: /// Report a syntax error. /// \param loc where the syntax error is found. /// \param msg a description of the syntax error. virtual void error (const location_type& loc, const std::string& msg); /// Generate an error message. /// \param state the state where the error occurred. /// \param tok the look-ahead token. virtual std::string yysyntax_error_ (int yystate, int tok); #if YYDEBUG /// \brief Report a symbol value on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_value_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); /// \brief Report a symbol on the debug stream. /// \param yytype The token type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. virtual void yy_symbol_print_ (int yytype, const semantic_type* yyvaluep, const location_type* yylocationp); #endif /* ! YYDEBUG */ /// State numbers. typedef int state_type; /// State stack type. typedef stack state_stack_type; /// Semantic value stack type. typedef stack semantic_stack_type; /// location stack type. typedef stack location_stack_type; /// The state stack. state_stack_type yystate_stack_; /// The semantic value stack. semantic_stack_type yysemantic_stack_; /// The location stack. location_stack_type yylocation_stack_; /// Internal symbol numbers. typedef unsigned char token_number_type; /* Tables. */ /// For a state, the index in \a yytable_ of its portion. static const signed char yypact_[]; static const signed char yypact_ninf_; /// For a state, default rule to reduce. /// Unless\a yytable_ specifies something else to do. /// Zero means the default is an error. static const unsigned char yydefact_[]; static const signed char yypgoto_[]; static const signed char yydefgoto_[]; /// What to do in a state. /// \a yytable_[yypact_[s]]: what to do in state \a s. /// - if positive, shift that token. /// - if negative, reduce the rule which number is the opposite. /// - if zero, do what YYDEFACT says. static const unsigned char yytable_[]; static const signed char yytable_ninf_; static const signed char yycheck_[]; /// For a state, its accessing symbol. static const unsigned char yystos_[]; /// For a rule, its LHS. static const unsigned char yyr1_[]; /// For a rule, its RHS length. static const unsigned char yyr2_[]; #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /// For a symbol, its name in clear. static const char* const yytname_[]; #endif #if YYERROR_VERBOSE /// Convert the symbol name \a n to a form suitable for a diagnostic. virtual std::string yytnamerr_ (const char *n); #endif #if YYDEBUG /// A type to store symbol numbers and -1. typedef signed char rhs_number_type; /// A `-1'-separated list of the rules' RHS. static const rhs_number_type yyrhs_[]; /// For each rule, the index of the first RHS symbol in \a yyrhs_. static const unsigned char yyprhs_[]; /// For each rule, its source line number. static const unsigned char yyrline_[]; /// For each scanner token number, its symbol number. static const unsigned short int yytoken_number_[]; /// Report on the debug stream that the rule \a r is going to be reduced. virtual void yy_reduce_print_ (int r); /// Print the state stack on the debug stream. virtual void yystack_print_ (); #endif /// Convert a scanner token number \a t to a symbol number. token_number_type yytranslate_ (int t); /// \brief Reclaim the memory associated to a symbol. /// \param yymsg Why this token is reclaimed. /// \param yytype The symbol type. /// \param yyvaluep Its semantic value. /// \param yylocationp Its location. inline void yydestruct_ (const char* yymsg, int yytype, semantic_type* yyvaluep, location_type* yylocationp); /// Pop \a n symbols the three stacks. inline void yypop_ (unsigned int n = 1); /* Constants. */ static const int yyeof_; /* LAST_ -- Last index in TABLE_. */ static const int yylast_; static const int yynnts_; static const int yyempty_; static const int yyfinal_; static const int yyterror_; static const int yyerrcode_; static const int yyntokens_; static const unsigned int yyuser_token_number_max_; static const token_number_type yyundef_token_; /* Debugging. */ int yydebug_; std::ostream* yycdebug_; /* User arguments. */ QJson::ParserPrivate* driver; }; } #endif /* ! defined PARSER_HEADER_H */ ================================================ FILE: liteidex/src/3rdparty/qjson/src/json_parser.yy ================================================ /* This file is part of QJSon * * Copyright (C) 2008 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ %skeleton "lalr1.cc" %defines %define "parser_class_name" "json_parser" %{ #include "parser_p.h" #include "json_scanner.h" #include "qjson_debug.h" #include #include #include #include #include class JSonScanner; namespace QJson { class Parser; } #define YYERROR_VERBOSE 1 %} %parse-param { QJson::ParserPrivate* driver } %lex-param { QJson::ParserPrivate* driver } %locations %debug %error-verbose %token END 0 "end of file" %token CURLY_BRACKET_OPEN 1 "{" %token CURLY_BRACKET_CLOSE 2 "}" %token SQUARE_BRACKET_OPEN 3 "[" %token SQUARE_BRACKET_CLOSE 4 "]" %token COLON 5 ":" %token COMMA 6 "," %token MINUS 7 "-" %token DOT 8 "." %token DIGIT 9 "digit" %token E 10 "exponential" %token TRUE_VAL 11 "true" %token FALSE_VAL 12 "false" %token NULL_VAL 13 "null" %token QUOTMARKOPEN 14 "open quotation mark" %token QUOTMARKCLOSE 15 "close quotation mark" %token STRING 16 "string" %token INFINITY_VAL 17 "Infinity" %token NAN_VAL 18 "NaN" // define the initial token %start start %% // grammar rules start: data { driver->m_result = $1; qjsonDebug() << "json_parser - parsing finished"; }; data: value { $$ = $1; } | error { qCritical()<< "json_parser - syntax error found, " << "forcing abort, Line" << @$.begin.line << "Column" << @$.begin.column; YYABORT; } | END; object: CURLY_BRACKET_OPEN members CURLY_BRACKET_CLOSE { $$ = $2; }; members: /* empty */ { $$ = QVariant (QVariantMap()); } | pair r_members { QVariantMap members = $2.toMap(); $2 = QVariant(); // Allow reuse of map $$ = QVariant(members.unite ($1.toMap())); }; r_members: /* empty */ { $$ = QVariant (QVariantMap()); } | COMMA pair r_members { QVariantMap members = $3.toMap(); $3 = QVariant(); // Allow reuse of map $$ = QVariant(members.unite ($2.toMap())); }; pair: string COLON value { QVariantMap pair; pair.insert ($1.toString(), QVariant($3)); $$ = QVariant (pair); }; array: SQUARE_BRACKET_OPEN values SQUARE_BRACKET_CLOSE { $$ = $2; }; values: /* empty */ { $$ = QVariant (QVariantList()); } | value r_values { QVariantList members = $2.toList(); $2 = QVariant(); // Allow reuse of list members.prepend ($1); $$ = QVariant(members); }; r_values: /* empty */ { $$ = QVariant (QVariantList()); } | COMMA value r_values { QVariantList members = $3.toList(); $3 = QVariant(); // Allow reuse of list members.prepend ($2); $$ = QVariant(members); }; value: string { $$ = $1; } | special_or_number { $$ = $1; } | object { $$ = $1; } | array { $$ = $1; } | TRUE_VAL { $$ = QVariant (true); } | FALSE_VAL { $$ = QVariant (false); } | NULL_VAL { QVariant null_variant; $$ = null_variant; }; special_or_number: MINUS INFINITY_VAL { $$ = QVariant(QVariant::Double); $$.setValue( -std::numeric_limits::infinity() ); } | INFINITY_VAL { $$ = QVariant(QVariant::Double); $$.setValue( std::numeric_limits::infinity() ); } | NAN_VAL { $$ = QVariant(QVariant::Double); $$.setValue( std::numeric_limits::quiet_NaN() ); } | number; number: int { if ($1.toByteArray().startsWith('-')) { $$ = QVariant (QVariant::LongLong); $$.setValue($1.toLongLong()); } else { $$ = QVariant (QVariant::ULongLong); $$.setValue($1.toULongLong()); } } | int fract { const QByteArray value = $1.toByteArray() + $2.toByteArray(); $$ = QVariant(QVariant::Double); $$.setValue(value.toDouble()); } | int exp { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); } | int fract exp { const QByteArray value = $1.toByteArray() + $2.toByteArray() + $3.toByteArray(); $$ = QVariant (value); }; int: DIGIT digits { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); } | MINUS DIGIT digits { $$ = QVariant (QByteArray("-") + $2.toByteArray() + $3.toByteArray()); }; digits: /* empty */ { $$ = QVariant (QByteArray("")); } | DIGIT digits { $$ = QVariant($1.toByteArray() + $2.toByteArray()); }; fract: DOT digits { $$ = QVariant(QByteArray(".") + $2.toByteArray()); }; exp: E digits { $$ = QVariant($1.toByteArray() + $2.toByteArray()); }; string: QUOTMARKOPEN string_arg QUOTMARKCLOSE { $$ = $2; }; string_arg: /*empty */ { $$ = QVariant (QString(QLatin1String(""))); } | STRING { $$ = $1; }; %% int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver) { JSonScanner* scanner = driver->m_scanner; yylval->clear(); int ret = scanner->yylex(yylval, yylloc); qjsonDebug() << "json_parser::yylex - calling scanner yylval==|" << yylval->toByteArray() << "|, ret==|" << QString::number(ret) << "|"; return ret; } void yy::json_parser::error (const yy::location& yyloc, const std::string& error) { /*qjsonDebug() << yyloc.begin.line; qjsonDebug() << yyloc.begin.column; qjsonDebug() << yyloc.end.line; qjsonDebug() << yyloc.end.column;*/ qjsonDebug() << "json_parser::error [line" << yyloc.end.line << "] -" << error.c_str() ; driver->setError(QString::fromLatin1(error.c_str()), yyloc.end.line); } ================================================ FILE: liteidex/src/3rdparty/qjson/src/json_scanner.cpp ================================================ /* This file is part of QJson * * Copyright (C) 2008 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "qjson_debug.h" #include "json_scanner.h" #include "json_parser.hh" #include #include #include #include bool ishexnstring(const QString& string) { for (int i = 0; i < string.length(); i++) { if (isxdigit(string[i] == 0)) return false; } return true; } JSonScanner::JSonScanner(QIODevice* io) : m_allowSpecialNumbers(false), m_io (io) { m_quotmarkClosed = true; m_quotmarkCount = 0; } void JSonScanner::allowSpecialNumbers(bool allow) { m_allowSpecialNumbers = allow; } static QString unescape( const QByteArray& ba, bool* ok ) { assert( ok ); *ok = false; QString res; QByteArray seg; bool bs = false; for ( int i = 0, size = ba.size(); i < size; ++i ) { const char ch = ba[i]; if ( !bs ) { if ( ch == '\\' ) bs = true; else seg += ch; } else { bs = false; switch ( ch ) { case 'b': seg += '\b'; break; case 'f': seg += '\f'; break; case 'n': seg += '\n'; break; case 'r': seg += '\r'; break; case 't': seg += '\t'; break; case 'u': { res += QString::fromUtf8( seg ); seg.clear(); if ( i > size - 5 ) { //error return QString(); } const QString hex_digit1 = QString::fromUtf8( ba.mid( i + 1, 2 ) ); const QString hex_digit2 = QString::fromUtf8( ba.mid( i + 3, 2 ) ); i += 4; if ( !ishexnstring( hex_digit1 ) || !ishexnstring( hex_digit2 ) ) { qCritical() << "Not an hex string:" << hex_digit1 << hex_digit2; return QString(); } bool hexOk; const ushort hex_code1 = hex_digit1.toShort( &hexOk, 16 ); if (!hexOk) { qCritical() << "error converting hex value to short:" << hex_digit1; return QString(); } const ushort hex_code2 = hex_digit2.toShort( &hexOk, 16 ); if (!hexOk) { qCritical() << "error converting hex value to short:" << hex_digit2; return QString(); } res += QChar(hex_code2, hex_code1); break; } case '\\': seg += '\\'; break; default: seg += ch; break; } } } res += QString::fromUtf8( seg ); *ok = true; return res; } int JSonScanner::yylex(YYSTYPE* yylval, yy::location *yylloc) { char ch; if (!m_io->isOpen()) { qCritical() << "JSonScanner::yylex - io device is not open"; return -1; } yylloc->step(); do { bool ret; if (m_io->atEnd()) { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::END"; return yy::json_parser::token::END; } else ret = m_io->getChar(&ch); if (!ret) { qCritical() << "JSonScanner::yylex - error reading from io device"; return -1; } qjsonDebug() << "JSonScanner::yylex - got |" << ch << "|"; yylloc->columns(); if (ch == '\n' || ch == '\r') yylloc->lines(); } while (m_quotmarkClosed && (isspace(ch) != 0)); if (m_quotmarkClosed && ((ch == 't') || (ch == 'T'))) { const QByteArray buf = m_io->peek(3).toLower(); if (buf == "rue") { m_io->read (3); yylloc->columns(3); qjsonDebug() << "JSonScanner::yylex - TRUE_VAL"; return yy::json_parser::token::TRUE_VAL; } } else if (m_quotmarkClosed && ((ch == 'n') || (ch == 'N'))) { const QByteArray buf = m_io->peek(3).toLower(); if (buf == "ull") { m_io->read (3); yylloc->columns(3); qjsonDebug() << "JSonScanner::yylex - NULL_VAL"; return yy::json_parser::token::NULL_VAL; } else if (buf.startsWith("an") && m_allowSpecialNumbers) { m_io->read(2); yylloc->columns(2); qjsonDebug() << "JSonScanner::yylex - NAN_VAL"; return yy::json_parser::token::NAN_VAL; } } else if (m_quotmarkClosed && ((ch == 'f') || (ch == 'F'))) { // check false value const QByteArray buf = m_io->peek(4).toLower(); if (buf.length() == 4) { if (buf == "alse") { m_io->read (4); yylloc->columns(4); qjsonDebug() << "JSonScanner::yylex - FALSE_VAL"; return yy::json_parser::token::FALSE_VAL; } } } else if (m_quotmarkClosed && ((ch == 'e') || (ch == 'E'))) { QByteArray ret(1, ch); const QByteArray buf = m_io->peek(1); if (!buf.isEmpty()) { if ((buf[0] == '+' ) || (buf[0] == '-' )) { ret += m_io->read (1); yylloc->columns(); } } *yylval = QVariant(QString::fromUtf8(ret)); return yy::json_parser::token::E; } else if (m_allowSpecialNumbers && m_quotmarkClosed && ((ch == 'I') || (ch == 'i'))) { QByteArray ret(1, ch); const QByteArray buf = m_io->peek(7); if (buf == "nfinity") { m_io->read(7); yylloc->columns(7); qjsonDebug() << "JSonScanner::yylex - INFINITY_VAL"; return yy::json_parser::token::INFINITY_VAL; } } if (ch != '"' && !m_quotmarkClosed) { // we're inside a " " block QByteArray raw; raw += ch; char prevCh = ch; bool escape_on = (ch == '\\') ? true : false; while ( true ) { char nextCh; qint64 ret = m_io->peek(&nextCh, 1); if (ret != 1) { if (m_io->atEnd()) return yy::json_parser::token::END; else return -1; } else if ( !escape_on && nextCh == '\"' ) { bool ok; const QString str = unescape( raw, &ok ); *yylval = ok ? str : QString(); return ok ? yy::json_parser::token::STRING : -1; } #if 0 if ( prevCh == '\\' && nextCh != '"' && nextCh != '\\' && nextCh != '/' && nextCh != 'b' && nextCh != 'f' && nextCh != 'n' && nextCh != 'r' && nextCh != 't' && nextCh != 'u') { qjsonDebug() << "Just read" << nextCh; qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence"; return -1; } #endif m_io->read(1); // consume raw += nextCh; prevCh = nextCh; if (escape_on) escape_on = false; else escape_on = (prevCh == '\\') ? true : false; #if 0 if (nextCh == '\\') { char buf; if (m_io->getChar (&buf)) { yylloc->columns(); if (((buf != '"') && (buf != '\\') && (buf != '/') && (buf != 'b') && (buf != 'f') && (buf != 'n') && (buf != 'r') && (buf != 't') && (buf != 'u'))) { qjsonDebug() << "Just read" << buf; qjsonDebug() << "JSonScanner::yylex - error decoding escaped sequence"; return -1; } } else { qCritical() << "JSonScanner::yylex - error decoding escaped sequence : io error"; return -1; } } #endif } } else if (isdigit(ch) != 0 && m_quotmarkClosed) { bool ok; QByteArray numArray = QByteArray::fromRawData( &ch, 1 * sizeof(char) ); qulonglong number = numArray.toULongLong(&ok); if (!ok) { //This shouldn't happen qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1"; return -1; } if (number == 0) { // we have to return immediately otherwise numbers like // 2.04 will be converted to 2.4 *yylval = QVariant(number); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT"; return yy::json_parser::token::DIGIT; } char nextCh; qint64 ret = m_io->peek(&nextCh, 1); while (ret == 1 && isdigit(nextCh)) { m_io->read(1); //consume yylloc->columns(1); numArray = QByteArray::fromRawData( &nextCh, 1 * sizeof(char) ); number = number * 10 + numArray.toULongLong(&ok); if (!ok) { //This shouldn't happen qCritical() << "JSonScanner::yylex - error while converting char to ulonglong, returning -1"; return -1; } ret = m_io->peek(&nextCh, 1); } *yylval = QVariant(number); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DIGIT"; return yy::json_parser::token::DIGIT; } else if (isalnum(ch) != 0) { *yylval = QVariant(QString(QChar::fromLatin1(ch))); qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::WORD (" << ch << ")"; return yy::json_parser::token::STRING; } else if (ch == ':') { // set yylval qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COLON"; return yy::json_parser::token::COLON; } else if (ch == '"') { // yy::json_parser::token::QUOTMARK (") // set yylval m_quotmarkCount++; if (m_quotmarkCount %2 == 0) { m_quotmarkClosed = true; m_quotmarkCount = 0; qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKCLOSE"; return yy::json_parser::token::QUOTMARKCLOSE; } else { m_quotmarkClosed = false; qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::QUOTMARKOPEN"; return yy::json_parser::token::QUOTMARKOPEN; } } else if (ch == ',') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::COMMA"; return yy::json_parser::token::COMMA; } else if (ch == '.') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::DOT"; return yy::json_parser::token::DOT; } else if (ch == '-') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::MINUS"; return yy::json_parser::token::MINUS; } else if (ch == '[') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_OPEN"; return yy::json_parser::token::SQUARE_BRACKET_OPEN; } else if (ch == ']') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::SQUARE_BRACKET_CLOSE"; return yy::json_parser::token::SQUARE_BRACKET_CLOSE; } else if (ch == '{') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_OPEN"; return yy::json_parser::token::CURLY_BRACKET_OPEN; } else if (ch == '}') { qjsonDebug() << "JSonScanner::yylex - yy::json_parser::token::CURLY_BRACKET_CLOSE"; return yy::json_parser::token::CURLY_BRACKET_CLOSE; } //unknown char! //TODO yyerror? qCritical() << "JSonScanner::yylex - unknown char, returning -1"; return -1; } ================================================ FILE: liteidex/src/3rdparty/qjson/src/json_scanner.h ================================================ /* This file is part of QJson * * Copyright (C) 2008 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _JSON_SCANNER #define _JSON_SCANNER #include #include #include #include #define YYSTYPE QVariant #include "parser_p.h" namespace yy { class location; int yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver); } class JSonScanner { public: explicit JSonScanner(QIODevice* io); int yylex(YYSTYPE* yylval, yy::location *yylloc); void allowSpecialNumbers(bool allow); protected: bool m_quotmarkClosed; bool m_allowSpecialNumbers; unsigned int m_quotmarkCount; QIODevice* m_io; }; #endif ================================================ FILE: liteidex/src/3rdparty/qjson/src/location.hh ================================================ /* A Bison parser, made by GNU Bison 2.3. */ /* Locations for Bison parsers in C++ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file location.hh ** Define the yy::location class. */ #ifndef BISON_LOCATION_HH # define BISON_LOCATION_HH # include # include # include "position.hh" namespace yy { /// Abstract a location. class location { public: /// Construct a location. location () : begin (), end () { } /// Initialization. inline void initialize (std::string* fn) { begin.initialize (fn); end = begin; } /** \name Line and Column related manipulators ** \{ */ public: /// Reset initial location to final location. inline void step () { begin = end; } /// Extend the current location to the COUNT next columns. inline void columns (unsigned int count = 1) { end += count; } /// Extend the current location to the COUNT next lines. inline void lines (unsigned int count = 1) { end.lines (count); } /** \} */ public: /// Beginning of the located region. position begin; /// End of the located region. position end; }; /// Join two location objects to create a location. inline const location operator+ (const location& begin, const location& end) { location res = begin; res.end = end.end; return res; } /// Add two location objects. inline const location operator+ (const location& begin, unsigned int width) { location res = begin; res.columns (width); return res; } /// Add and assign a location. inline location& operator+= (location& res, unsigned int width) { res.columns (width); return res; } /** \brief Intercept output stream redirection. ** \param ostr the destination output stream ** \param loc a reference to the location to redirect ** ** Avoid duplicate information. */ inline std::ostream& operator<< (std::ostream& ostr, const location& loc) { position last = loc.end - 1; ostr << loc.begin; if (last.filename && (!loc.begin.filename || *loc.begin.filename != *last.filename)) ostr << '-' << last; else if (loc.begin.line != last.line) ostr << '-' << last.line << '.' << last.column; else if (loc.begin.column != last.column) ostr << '-' << last.column; return ostr; } } #endif // not BISON_LOCATION_HH ================================================ FILE: liteidex/src/3rdparty/qjson/src/parser.cpp ================================================ /* This file is part of QJson * * Copyright (C) 2008 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "parser.h" #include "parser_p.h" #include "json_parser.hh" #include "json_scanner.h" #include #include #include #include using namespace QJson; ParserPrivate::ParserPrivate() : m_scanner(0) , m_negate(false) , m_error(false) , m_errorLine(0) , m_specialNumbersAllowed(false) { } ParserPrivate::~ParserPrivate() { delete m_scanner; } void ParserPrivate::setError(QString errorMsg, int errorLine) { m_error = true; m_errorMsg = errorMsg; m_errorLine = errorLine; } Parser::Parser() : d(new ParserPrivate) { } Parser::~Parser() { delete d; } QVariant Parser::parse (QIODevice* io, bool* ok) { d->m_errorMsg.clear(); delete d->m_scanner; d->m_scanner = 0; if (!io->isOpen()) { if (!io->open(QIODevice::ReadOnly)) { if (ok != 0) *ok = false; qCritical ("Error opening device"); return QVariant(); } } if (!io->isReadable()) { if (ok != 0) *ok = false; qCritical ("Device is not readable"); io->close(); return QVariant(); } d->m_scanner = new JSonScanner (io); d->m_scanner->allowSpecialNumbers(d->m_specialNumbersAllowed); yy::json_parser parser(d); parser.parse(); delete d->m_scanner; d->m_scanner = 0; if (ok != 0) *ok = !d->m_error; io->close(); return d->m_result; } QVariant Parser::parse(const QByteArray& jsonString, bool* ok) { QBuffer buffer; buffer.open(QBuffer::ReadWrite); buffer.write(jsonString); buffer.seek(0); return parse (&buffer, ok); } QString Parser::errorString() const { return d->m_errorMsg; } int Parser::errorLine() const { return d->m_errorLine; } void QJson::Parser::allowSpecialNumbers(bool allowSpecialNumbers) { d->m_specialNumbersAllowed = allowSpecialNumbers; } bool Parser::specialNumbersAllowed() const { return d->m_specialNumbersAllowed; } ================================================ FILE: liteidex/src/3rdparty/qjson/src/parser.h ================================================ /* This file is part of QJson * * Copyright (C) 2008 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef QJSON_PARSER_H #define QJSON_PARSER_H #include "qjson_export.h" class QIODevice; class QVariant; namespace QJson { class ParserPrivate; /** * @brief Main class used to convert JSON data to QVariant objects */ class QJSON_EXPORT Parser { public: Parser(); ~Parser(); /** * Read JSON string from the I/O Device and converts it to a QVariant object * @param io Input output device * @param ok if a conversion error occurs, *ok is set to false; otherwise *ok is set to true. * @returns a QVariant object generated from the JSON string */ QVariant parse(QIODevice* io, bool* ok = 0); /** * This is a method provided for convenience. * @param jsonData data containing the JSON object representation * @param ok if a conversion error occurs, *ok is set to false; otherwise *ok is set to true. * @returns a QVariant object generated from the JSON string * @sa errorString * @sa errorLine */ QVariant parse(const QByteArray& jsonData, bool* ok = 0); /** * This method returns the error message * @returns a QString object containing the error message of the last parse operation * @sa errorLine */ QString errorString() const; /** * This method returns line number where the error occurred * @returns the line number where the error occurred * @sa errorString */ int errorLine() const; /** * Sets whether special numbers (Infinity, -Infinity, NaN) are allowed as an extension to * the standard * @param allowSpecialNumbers new value of whether special numbers are allowed * @sa specialNumbersAllowed */ void allowSpecialNumbers(bool allowSpecialNumbers); /** * @returns whether special numbers (Infinity, -Infinity, NaN) are allowed * @sa allowSpecialNumbers */ bool specialNumbersAllowed() const; private: Q_DISABLE_COPY(Parser) ParserPrivate* const d; }; } #endif // QJSON_PARSER_H ================================================ FILE: liteidex/src/3rdparty/qjson/src/parser_p.h ================================================ /* This file is part of QJson * * Copyright (C) 2008 Flavio Castelli * Copyright (C) 2009 Michael Leupold * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef QJSON_PARSER_P_H #define QJSON_PARSER_P_H #include "parser.h" #include #include class JSonScanner; namespace yy { class json_parser; } namespace QJson { class ParserPrivate { public: ParserPrivate(); ~ParserPrivate(); void setError(QString errorMsg, int line); JSonScanner* m_scanner; bool m_negate; bool m_error; int m_errorLine; QString m_errorMsg; QVariant m_result; bool m_specialNumbersAllowed; }; } #endif // QJSON_PARSER_H ================================================ FILE: liteidex/src/3rdparty/qjson/src/parserrunnable.cpp ================================================ /* This file is part of qjson * * Copyright (C) 2009 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "parserrunnable.h" #include "parser.h" #include #include using namespace QJson; class QJson::ParserRunnable::Private { public: QByteArray m_data; }; ParserRunnable::ParserRunnable(QObject* parent) : QObject(parent), QRunnable(), d(new Private) { qRegisterMetaType("QVariant"); } ParserRunnable::~ParserRunnable() { delete d; } void ParserRunnable::setData( const QByteArray& data ) { d->m_data = data; } void ParserRunnable::run() { //qDebug() << Q_FUNC_INFO; bool ok; Parser parser; QVariant result = parser.parse (d->m_data, &ok); if (ok) { //qDebug() << "successfully converted json item to QVariant object"; emit parsingFinished(result, true, QString()); } else { const QString errorText = tr("An error occurred while parsing json: %1").arg(parser.errorString()); //qCritical() << errorText; emit parsingFinished(QVariant(), false, errorText); } } ================================================ FILE: liteidex/src/3rdparty/qjson/src/parserrunnable.h ================================================ /* This file is part of qjson * * Copyright (C) 2009 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef PARSERRUNNABLE_H #define PARSERRUNNABLE_H #include "qjson_export.h" #include #include class QVariant; namespace QJson { /** * @brief Convenience class for converting JSON data to QVariant objects using a dedicated thread */ class QJSON_EXPORT ParserRunnable : public QObject, public QRunnable { Q_OBJECT public: /** * This signal is emitted when the conversion process has been completed * @param data contains the JSON data that has to be converted * @param parent parent of the object **/ explicit ParserRunnable(QObject* parent = 0); ~ParserRunnable(); void setData( const QByteArray& data ); void run(); Q_SIGNALS: /** * This signal is emitted when the parsing process has been completed * @param json contains the result of the parsing * @param ok if a parsing error occurs ok is set to false, otherwise it's set to true. * @param error_msg contains a string explaining the failure reason **/ void parsingFinished(const QVariant& json, bool ok, const QString& error_msg); private: Q_DISABLE_COPY(ParserRunnable) class Private; Private* const d; }; } #endif // PARSERRUNNABLE_H ================================================ FILE: liteidex/src/3rdparty/qjson/src/position.hh ================================================ /* A Bison parser, made by GNU Bison 2.3. */ /* Positions for Bison parsers in C++ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /** ** \file position.hh ** Define the yy::position class. */ #ifndef BISON_POSITION_HH # define BISON_POSITION_HH # include # include namespace yy { /// Abstract a position. class position { public: /// Construct a position. position () : filename (0), line (1), column (0) { } /// Initialization. inline void initialize (std::string* fn) { filename = fn; line = 1; column = 0; } /** \name Line and Column related manipulators ** \{ */ public: /// (line related) Advance to the COUNT next lines. inline void lines (int count = 1) { column = 0; line += count; } /// (column related) Advance to the COUNT next columns. inline void columns (int count = 1) { int leftmost = 0; int current = column; if (leftmost <= current + count) column += count; else column = 0; } /** \} */ public: /// File name to which this position refers. std::string* filename; /// Current line number. unsigned int line; /// Current column number. unsigned int column; }; /// Add and assign a position. inline const position& operator+= (position& res, const int width) { res.columns (width); return res; } /// Add two position objects. inline const position operator+ (const position& begin, const int width) { position res = begin; return res += width; } /// Add and assign a position. inline const position& operator-= (position& res, const int width) { return res += -width; } /// Add two position objects. inline const position operator- (const position& begin, const int width) { return begin + -width; } /** \brief Intercept output stream redirection. ** \param ostr the destination output stream ** \param pos a reference to the position to redirect */ inline std::ostream& operator<< (std::ostream& ostr, const position& pos) { if (pos.filename) { ostr << (*pos.filename).c_str(); ostr << ':'; } return ostr << pos.line << '.' << pos.column; } } #endif // not BISON_POSITION_HH ================================================ FILE: liteidex/src/3rdparty/qjson/src/qjson_debug.h ================================================ /* This file is part of qjson * * Copyright (C) 2009 Michael Leupold * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef QJSON_DEBUG_H #define QJSON_DEBUG_H #include // define qjsonDebug() #ifdef QJSON_VERBOSE_DEBUG_OUTPUT inline QDebug qjsonDebug() { return QDebug(QtDebugMsg); } #else inline QNoDebug qjsonDebug() { return QNoDebug(); } #endif #endif ================================================ FILE: liteidex/src/3rdparty/qjson/src/qjson_export.h ================================================ /* This file is part of the KDE project Copyright (C) 2009 Pino Toscano This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1, as published by the Free Software Foundation. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef QJSON_EXPORT_H #define QJSON_EXPORT_H #include #define QJSON_EXPORT #ifndef QJSON_EXPORT # if defined(QJSON_MAKEDLL) /* We are building this library */ # define QJSON_EXPORT Q_DECL_EXPORT # else /* We are using this library */ # define QJSON_EXPORT Q_DECL_IMPORT # endif #endif #endif ================================================ FILE: liteidex/src/3rdparty/qjson/src/qobjecthelper.cpp ================================================ /* This file is part of qjson * * Copyright (C) 2009 Till Adam * Copyright (C) 2009 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "qobjecthelper.h" #include #include #include using namespace QJson; class QObjectHelper::QObjectHelperPrivate { }; QObjectHelper::QObjectHelper() : d (new QObjectHelperPrivate) { } QObjectHelper::~QObjectHelper() { delete d; } QVariantMap QObjectHelper::qobject2qvariant( const QObject* object, const QStringList& ignoredProperties) { QVariantMap result; const QMetaObject *metaobject = object->metaObject(); int count = metaobject->propertyCount(); for (int i=0; iproperty(i); const char *name = metaproperty.name(); if (ignoredProperties.contains(QLatin1String(name)) || (!metaproperty.isReadable())) continue; QVariant value = object->property(name); result[QLatin1String(name)] = value; } return result; } void QObjectHelper::qvariant2qobject(const QVariantMap& variant, QObject* object) { const QMetaObject *metaobject = object->metaObject(); QVariantMap::const_iterator iter; for (iter = variant.constBegin(); iter != variant.constEnd(); ++iter) { int pIdx = metaobject->indexOfProperty( iter.key().toLatin1() ); if ( pIdx < 0 ) { continue; } QMetaProperty metaproperty = metaobject->property( pIdx ); QVariant::Type type = metaproperty.type(); QVariant v( iter.value() ); if ( v.canConvert( type ) ) { v.convert( type ); metaproperty.write( object, v ); } else if (QString(QLatin1String("QVariant")).compare(QLatin1String(metaproperty.typeName())) == 0) { metaproperty.write( object, v ); } } } ================================================ FILE: liteidex/src/3rdparty/qjson/src/qobjecthelper.h ================================================ /* This file is part of qjson * * Copyright (C) 2009 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef QOBJECTHELPER_H #define QOBJECTHELPER_H #include "qjson_export.h" #include #include #include class QObject; namespace QJson { /** * @brief Class used to convert QObject into QVariant and vivce-versa. * During these operations only the class attributes defined as properties will * be considered. * Properties marked as 'non-stored' will be ignored. * * Suppose the declaration of the Person class looks like this: * \code * class Person : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName) Q_PROPERTY(int phoneNumber READ phoneNumber WRITE setPhoneNumber) Q_PROPERTY(Gender gender READ gender WRITE setGender) Q_PROPERTY(QDate dob READ dob WRITE setDob) Q_ENUMS(Gender) public: Person(QObject* parent = 0); ~Person(); QString name() const; void setName(const QString& name); int phoneNumber() const; void setPhoneNumber(const int phoneNumber); enum Gender {Male, Female}; void setGender(Gender gender); Gender gender() const; QDate dob() const; void setDob(const QDate& dob); private: QString m_name; int m_phoneNumber; Gender m_gender; QDate m_dob; }; \endcode The following code will serialize an instance of Person to JSON : \code Person person; person.setName("Flavio"); person.setPhoneNumber(123456); person.setGender(Person::Male); person.setDob(QDate(1982, 7, 12)); QVariantMap variant = QObjectHelper::qobject2qvariant(&person); Serializer serializer; qDebug() << serializer.serialize( variant); \endcode The generated output will be: \code { "dob" : "1982-07-12", "gender" : 0, "name" : "Flavio", "phoneNumber" : 123456 } \endcode It's also possible to initialize a QObject using the values stored inside of a QVariantMap. Suppose you have the following JSON data stored into a QString: \code { "dob" : "1982-07-12", "gender" : 0, "name" : "Flavio", "phoneNumber" : 123456 } \endcode The following code will initialize an already allocated instance of Person using the JSON values: \code Parser parser; QVariant variant = parser.parse(json); Person person; QObjectHelper::qvariant2qobject(variant.toMap(), &person); \endcode \sa Parser \sa Serializer */ class QJSON_EXPORT QObjectHelper { public: QObjectHelper(); ~QObjectHelper(); /** * This method converts a QObject instance into a QVariantMap. * * @param object The QObject instance to be converted. * @param ignoredProperties Properties that won't be converted. */ static QVariantMap qobject2qvariant( const QObject* object, const QStringList& ignoredProperties = QStringList(QString(QLatin1String("objectName")))); /** * This method converts a QVariantMap instance into a QObject * * @param object The QObject instance to be converted. */ static void qvariant2qobject(const QVariantMap& variant, QObject* object); private: Q_DISABLE_COPY(QObjectHelper) class QObjectHelperPrivate; QObjectHelperPrivate* const d; }; } #endif // QOBJECTHELPER_H ================================================ FILE: liteidex/src/3rdparty/qjson/src/serializer.cpp ================================================ /* This file is part of qjson * * Copyright (C) 2009 Till Adam * Copyright (C) 2009 Flavio Castelli * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "serializer.h" #include #include #include #include #ifdef _MSC_VER // using MSVC compiler #include #endif using namespace QJson; class Serializer::SerializerPrivate { public: SerializerPrivate() : specialNumbersAllowed(false), indentMode(QJson::IndentNone), doublePrecision(6) { } bool specialNumbersAllowed; IndentMode indentMode; int doublePrecision; QByteArray buildIndent(int spaces); QByteArray serialize( const QVariant &v, int reserved = 0); QString sanitizeString( QString str ); QByteArray join( const QList& list, const QByteArray& sep ); }; QByteArray Serializer::SerializerPrivate::join( const QList& list, const QByteArray& sep ) { QByteArray res; Q_FOREACH( const QByteArray& i, list ) { if ( !res.isEmpty() ) res += sep; res += i; } return res; } QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, int reserved ) { QByteArray str; bool error = false; QByteArray indent; if ( ! v.isValid() ) { // invalid or null? str = "null"; } else if (( v.type() == QVariant::List ) || ( v.type() == QVariant::StringList )){ // an array or a stringlist? const QVariantList list = v.toList(); QList values; Q_FOREACH( const QVariant& var, list ) { reserved++; QByteArray serializedValue = serialize( var,reserved ); reserved--; if ( serializedValue.isNull() ) { error = true; break; } values << serializedValue; } if (indentMode == QJson::IndentMinimum) { QByteArray indent = buildIndent(reserved - 1); str = "[\n" + join( values, ",\n" ) + "\n" + indent + "]"; } else if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) { QByteArray indent = buildIndent(reserved); str = "[\n" + join( values, ",\n" ) + "\n" + indent + "]"; } else if (indentMode == QJson::IndentCompact) { str = "[" + join( values, "," ) + "]"; } else { str = "[ " + join( values, ", " ) + " ]"; } } else if ( v.type() == QVariant::Map ) { // variant is a map? const QVariantMap vmap = v.toMap(); QMapIterator it( vmap ); if (indentMode == QJson::IndentMinimum) { QByteArray indent = buildIndent(reserved); str = indent + "{ "; } else if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) { QByteArray indent = buildIndent(reserved); QByteArray nextindent = buildIndent(reserved + 1); str = indent + "{\n" + nextindent; } else if (indentMode == QJson::IndentCompact) { str = "{"; } else { str = "{ "; } QList pairs; while ( it.hasNext() ) { it.next(); reserved++; QByteArray serializedValue = serialize( it.value() , reserved); reserved--; if ( serializedValue.isNull() ) { error = true; break; } QByteArray key = sanitizeString( it.key() ).toUtf8(); QByteArray value = serializedValue; if (indentMode == QJson::IndentCompact) { pairs << key + ":" + value; } else { pairs << key + " : " + value; } } if (indentMode == QJson::IndentFull) { QByteArray indent = buildIndent(reserved + 1); str += join( pairs, ",\n" + indent); } else if (indentMode == QJson::IndentCompact) { str += join( pairs, "," ); } else { str += join( pairs, ", " ); } if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) { QByteArray indent = buildIndent(reserved); str += "\n" + indent + "}"; } else if (indentMode == QJson::IndentCompact) { str += "}"; } else { str += " }"; } } else if (( v.type() == QVariant::String ) || ( v.type() == QVariant::ByteArray )) { // a string or a byte array? str = sanitizeString( v.toString() ).toUtf8(); } else if (( v.type() == QVariant::Double) || ((QMetaType::Type)v.type() == QMetaType::Float)) { // a double or a float? const double value = v.toDouble(); #if defined _WIN32 && !defined(Q_OS_SYMBIAN) const bool special = _isnan(value) || !_finite(value); #elif defined(Q_OS_SYMBIAN) || defined(Q_OS_ANDROID) const bool special = isnan(value) || isinf(value); #else const bool special = std::isnan(value) || std::isinf(value); #endif if (special) { if (specialNumbersAllowed) { #if defined _WIN32 && !defined(Q_OS_SYMBIAN) if (_isnan(value)) { #elif defined(Q_OS_SYMBIAN) || defined(Q_OS_ANDROID) if (isnan(value)) { #else if (std::isnan(value)) { #endif str += "NaN"; } else { if (value<0) { str += '-'; } str += "Infinity"; } } else { qCritical("Attempt to write NaN or infinity, which is not supported by json"); error = true; } } else { str = QByteArray::number( value , 'g', doublePrecision); if( ! str.contains( "." ) && ! str.contains( "e" ) ) { str += ".0"; } } } else if ( v.type() == QVariant::Bool ) { // boolean value? str = ( v.toBool() ? "true" : "false" ); } else if ( v.type() == QVariant::ULongLong ) { // large unsigned number? str = QByteArray::number( v.value() ); } else if ( v.canConvert() ) { // any signed number? str = QByteArray::number( v.value() ); } else if ( v.canConvert() ){ // can value be converted to string? // this will catch QDate, QDateTime, QUrl, ... str = sanitizeString( v.toString() ).toUtf8(); //TODO: catch other values like QImage, QRect, ... } else { error = true; } if ( !error ) { return str; } else return QByteArray(); } QByteArray Serializer::SerializerPrivate::buildIndent(int spaces) { QByteArray indent; if (spaces < 0) { spaces = 0; } for (int i = 0; i < spaces; i++ ) { indent += " "; } return indent; } QString Serializer::SerializerPrivate::sanitizeString( QString str ) { str.replace( QLatin1String( "\\" ), QLatin1String( "\\\\" ) ); // escape unicode chars QString result; const ushort* unicode = str.utf16(); unsigned int i = 0; while ( unicode[ i ] ) { if ( unicode[ i ] < 128 ) { result.append( QChar( unicode[ i ] ) ); } else { QString hexCode = QString::number( unicode[ i ], 16 ).rightJustified( 4, QLatin1Char('0') ); result.append( QLatin1String ("\\u") ).append( hexCode ); } ++i; } str = result; str.replace( QLatin1String( "\"" ), QLatin1String( "\\\"" ) ); str.replace( QLatin1String( "\b" ), QLatin1String( "\\b" ) ); str.replace( QLatin1String( "\f" ), QLatin1String( "\\f" ) ); str.replace( QLatin1String( "\n" ), QLatin1String( "\\n" ) ); str.replace( QLatin1String( "\r" ), QLatin1String( "\\r" ) ); str.replace( QLatin1String( "\t" ), QLatin1String( "\\t" ) ); return QString( QLatin1String( "\"%1\"" ) ).arg( str ); } Serializer::Serializer() : d( new SerializerPrivate ) { } Serializer::~Serializer() { delete d; } void Serializer::serialize( const QVariant& v, QIODevice* io, bool* ok) { Q_ASSERT( io ); if (ok) *ok = false; if (!io->isOpen()) { if (!io->open(QIODevice::WriteOnly)) { qCritical ("Error opening device"); return; } } if (!io->isWritable()) { qCritical ("Device is not readable"); io->close(); return; } const QByteArray str = serialize( v ); if (io->write(str) == str.count()) { if (ok) *ok = true; } } QByteArray Serializer::serialize( const QVariant &v) { return d->serialize(v); } void QJson::Serializer::allowSpecialNumbers(bool allow) { d->specialNumbersAllowed = allow; } bool QJson::Serializer::specialNumbersAllowed() const { return d->specialNumbersAllowed; } void QJson::Serializer::setIndentMode(IndentMode mode) { d->indentMode = mode; } void QJson::Serializer::setDoublePrecision(int precision) { d->doublePrecision = precision; } IndentMode QJson::Serializer::indentMode() const { return d->indentMode; } ================================================ FILE: liteidex/src/3rdparty/qjson/src/serializer.h ================================================ /* This file is part of qjson * * Copyright (C) 2009 Till Adam * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef QJSON_SERIALIZER_H #define QJSON_SERIALIZER_H #include "qjson_export.h" class QIODevice; class QString; class QVariant; namespace QJson { /** * @brief How the indentation should work. * * none (default) : { "foo" : 0, "foo1" : 1, "foo2" : [ { "foo3" : 3, "foo4" : 4 } ] } * * compact : {"foo":0,"foo1":1,"foo2":[{"foo3":3,"foo4":4}]} * * minimum : { "foo" : 0, "foo1" : 1, "foo2" : [ * { "foo3" : 3, "foo4" : 4 } * ] } * * medium : { * "foo" : 0, "foo1" : 1, "foo2" : [ * { * "foo3" : 3, "foo4" : 4 * } * ] * } * full : { * "foo" : 0, * "foo1" : 1, * "foo2" : [ * { * "foo3" : 3, * "foo4" : 4 * } * ] * } */ enum IndentMode { IndentNone, IndentCompact, IndentMinimum, IndentMedium, IndentFull }; /** * @brief Main class used to convert QVariant objects to JSON data. * * QVariant objects are converted to a string containing the JSON data. * If QVariant object is empty or not valid a null json object is returned. */ class QJSON_EXPORT Serializer { public: Serializer(); ~Serializer(); /** * This method generates a textual JSON representation and outputs it to the * passed in I/O Device. * @param variant The JSON document in its in-memory representation as generated by the * parser. * @param out Input output device * @param ok if a conversion error occurs, *ok is set to false; otherwise *ok is set to true */ void serialize( const QVariant& variant, QIODevice* out, bool* ok = 0); /** * This is a method provided for convenience. It turns the passed in in-memory * representation of the JSON document into a textual one, which is returned. * If the returned string is empty, the document was empty. If it was null, there * was a parsing error. * * @param variant The JSON document in its in-memory representation as generated by the * parser. */ QByteArray serialize( const QVariant& variant); /** * Allow or disallow writing of NaN and/or Infinity (as an extension to QJson) */ void allowSpecialNumbers(bool allow); /** * Is Nan and/or Infinity allowed? */ bool specialNumbersAllowed() const; /** * set output indentation mode as defined in QJson::IndentMode */ void setIndentMode(IndentMode mode = QJson::IndentNone); /** * set double precision used while converting Double * \sa QByteArray::number */ void setDoublePrecision(int precision); /** * Returns one of the indentation modes defined in QJson::IndentMode */ IndentMode indentMode() const; private: Q_DISABLE_COPY(Serializer) class SerializerPrivate; SerializerPrivate* const d; }; } #endif // QJSON_SERIALIZER_H ================================================ FILE: liteidex/src/3rdparty/qjson/src/serializerrunnable.cpp ================================================ #include "serializerrunnable.h" /* This file is part of qjson * * Copyright (C) 2009 Flavio Castelli * 2009 Frank Osterfeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "parserrunnable.h" #include "serializer.h" #include #include using namespace QJson; class SerializerRunnable::Private { public: QVariant json; }; SerializerRunnable::SerializerRunnable(QObject* parent) : QObject(parent), QRunnable(), d(new Private) { qRegisterMetaType("QVariant"); } SerializerRunnable::~SerializerRunnable() { delete d; } void SerializerRunnable::setJsonObject( const QVariant& json ) { d->json = json; } void SerializerRunnable::run() { Serializer serializer; emit parsingFinished( Serializer().serialize( d->json ), true, QString() ); } ================================================ FILE: liteidex/src/3rdparty/qjson/src/serializerrunnable.h ================================================ /* This file is part of qjson * * Copyright (C) 2009 Frank Osterfeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef SERIALIZERRUNNABLE_H #define SERIALIZERRUNNABLE_H #include "qjson_export.h" #include #include class QByteArray; class QString; class QVariant; namespace QJson { /** * @brief Convenience class for converting JSON data to QVariant objects using a dedicated thread */ class QJSON_EXPORT SerializerRunnable : public QObject, public QRunnable { Q_OBJECT public: /** * This signal is emitted when the conversion process has been completed * @param data contains the JSON data that has to be converted * @param parent parent of the object **/ explicit SerializerRunnable(QObject* parent = 0); ~SerializerRunnable(); /** * Sets the json object to serialize. * * @param json QVariant containing the json representation to be serialized */ void setJsonObject( const QVariant& json ); /* reimp */ void run(); Q_SIGNALS: /** * This signal is emitted when the serialization process has been completed * @param serialized contains the result of the serialization * @param ok if a serialization error occurs ok is set to false, otherwise it's set to true. * @param error_msg contains a string explaining the failure reason **/ void parsingFinished(const QByteArray& serialized, bool ok, const QString& error_msg); private: Q_DISABLE_COPY(SerializerRunnable) class Private; Private* const d; }; } #endif // SERIALIZERRUNNABLE_H ================================================ FILE: liteidex/src/3rdparty/qjson/src/src.pro ================================================ TARGET = json TEMPLATE = lib CONFIG += staticlib include(../../../liteideutils.pri) VERSION = 0.7.1 PRIVATE_HEADERS += \ json_parser.hh \ json_scanner.h \ location.hh \ parser_p.h \ position.hh \ qjson_debug.h \ stack.hh PUBLIC_HEADERS += \ parser.h \ parserrunnable.h \ qobjecthelper.h \ serializer.h \ serializerrunnable.h \ qjson_export.h HEADERS += $$PRIVATE_HEADERS $$PUBLIC_HEADERS SOURCES += \ json_parser.cc \ json_scanner.cpp \ parser.cpp \ parserrunnable.cpp \ qobjecthelper.cpp \ serializer.cpp \ serializerrunnable.cpp ================================================ FILE: liteidex/src/3rdparty/qjson/src/stack.hh ================================================ /* A Bison parser, made by GNU Bison 2.3. */ /* Stack handling for Bison parsers in C++ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #ifndef BISON_STACK_HH # define BISON_STACK_HH #include namespace yy { template > class stack { public: // Hide our reversed order. typedef typename S::reverse_iterator iterator; typedef typename S::const_reverse_iterator const_iterator; stack () : seq_ () { } stack (unsigned int n) : seq_ (n) { } inline T& operator [] (unsigned int i) { return seq_[i]; } inline const T& operator [] (unsigned int i) const { return seq_[i]; } inline void push (const T& t) { seq_.push_front (t); } inline void pop (unsigned int n = 1) { for (; n; --n) seq_.pop_front (); } inline unsigned int height () const { return seq_.size (); } inline const_iterator begin () const { return seq_.rbegin (); } inline const_iterator end () const { return seq_.rend (); } private: S seq_; }; /// Present a slice of the top of a stack. template > class slice { public: slice (const S& stack, unsigned int range) : stack_ (stack), range_ (range) { } inline const T& operator [] (unsigned int i) const { return stack_[range_ - i]; } private: const S& stack_; unsigned int range_; }; } #endif // not BISON_STACK_HH ================================================ FILE: liteidex/src/3rdparty/qjson/tests/.gitignore ================================================ Makefile ================================================ FILE: liteidex/src/3rdparty/qjson/tests/CMakeLists.txt ================================================ ADD_SUBDIRECTORY(cmdline_tester) ADD_SUBDIRECTORY(parser) ADD_SUBDIRECTORY(qobjecthelper) ADD_SUBDIRECTORY(serializer) ================================================ FILE: liteidex/src/3rdparty/qjson/tests/tests.pro ================================================ TEMPLATE = subdirs SUBDIRS = cmdline_tester \ parser \ qobjecthelper \ serializer ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/AUTHORS ================================================ Matt Broadstone (mbroadstone (at) devonit.com) Matt Godshall (mgodshall (at) devonit.com) Algirdas Mockus (algirdas.mockus (at) gmail.com) Etienne Savard (esavard (at) symbiosoft.net) Alex Skorodumov Fargier Sylvain (fargier.sylvain (at) free.fr) ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/CHANGES ================================================ qjsonrpc 1.0 (10-29-2013) * added support for Compact wire format * various fixes for stability/performance improvements * eliminate use of QMetaObject::invokeMethod leading to unexpected timeouts * improve unit tests to use QBuffer-backed jsonrpc sockets qjsonrpc 1.1 (UNRELEASED) * allow calling of Q_SIGNALS on service objects * allow for removal of services from QJsonRpcServiceProvider * qt5 cleanups * split most classes out into their own headers/source files * added ObjectCreator for handling object cleanup in dispatch through RAII (Alex Skorodumov) * added QJsonRpcHttpClient for easy access to web services using jsonrpc * removed QVariant-based API for QJsonRpcMessage in favor of QJsonValue/QJsonArray * added support for named parameters (Alexandros Dermenakis) * remove QtGui dependency in manual tests ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/LICENSE ================================================ QJsonRpc is Copyright (C) 2012-2013 Matt Broadstone You may use, distribute and copy QJsonRpc under the terms of GNU Library General Public License version 2, which is displayed below. ------------------------------------------------------------------------- GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU Lesser General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU Lesser General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU Lesser General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU Lesser General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/README.md ================================================ [![Build Status](https://drone.io/bitbucket.org/devonit/qjsonrpc/status.png)](https://drone.io/bitbucket.org/devonit/qjsonrpc/latest) Overview ======= QJsonRpc is a Qt implementation of the JSON-RPC protocol. It integrates nicely with Qt, leveraging Qt's meta object system in order to provide services over the JSON-RPC protocol. QJsonRpc is licensed under the LGPLv2.1. - [JSON](http://www.json.org/) is a lightweight data interchange format. - [JSON-RPC](http://jsonrpc.org/) is lightweight remote procedure call protocol similar to XML-RPC. Help / Questions / Suggestions ============ [qjsonrpc-development](http://groups.google.com/group/qjsonrpc-development) Requirements ============ - Qt 4.7 or greater Features ======== - Support for JSON-RPC 2.0 - Easily create services using the Qt meta object system - QtScript integration Building ======== mkdir build cd build qmake .. && make install You can pass the following arguments to qmake: PREFIX= to change the install prefix default: unix: /usr other: $$[QT_INSTALL_PREFIX] QJSONRPC_LIBRARY_TYPE=staticlib to build a static version of the library -config private-headers build with qt private headers (to reduce allocations) ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/TODO ================================================ - handle default parameters properly - reenable bulk message transfer ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/changelog ================================================ qjsonrpc (1.0) precise; urgency=low * initial packaging of qjsonrpc -- Devon IT Support Thu, 17 Jan 2013 15:49:50 -0500 ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/compat ================================================ 5 ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/control ================================================ Source: qjsonrpc Section: libs Priority: extra Maintainer: Devon IT Developers Build-Depends: libqt4-dev (>= 4.8), cdbs (>= 0.4.41), debhelper (>= 5.0.37.2) Standards-Version: 3.7.2 Homepage: http://symbiosoft.net/projects/qjsonrpc Vcs-Git: git://gitorious.org/qjsonrpc/qjsonrpc.git Vcs-Browser: https://gitorious.org/qjsonrpc/ Package: libqjsonrpc Section: libs Architecture: any Depends: libqtcore4 (>= 4.8), libqt4-network (>= 4.8), ${shlibs:Depends}, ${misc:Depends} Description: The qjsonrpc library is a Qt implementation of the JSON-RPC ( http://jsonrpc.org/ ) protocol Package: libqjsonrpc-dev Section: libdevel Architecture: any Depends: libqjsonrpc (= ${binary:Version}) Description: Development files for the qjsonrpc library ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/copyright ================================================ Format: http://dep.debian.net/deps/dep5 Upstream-Name: qjsonrpc Source: https://gitorious.org/qjsonrpc/ Files: * Copyright: 2012-2013 Etienne Savard 2012-2013 Matt Broadstone 2012-2013 Matt Godshall License: LGPL-3.0+ Files: debian/* Copyright: 2013 Devon IT Support License: LGPL-3.0+ License: LGPL-3.0+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. . This package 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 Lesser 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 . . On Debian systems, the complete text of the GNU Lesser General Public License can be found in "/usr/share/common-licenses/LGPL-3". ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/libqjsonrpc-dev.install ================================================ debian/tmp/usr/include ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/libqjsonrpc.install ================================================ debian/tmp/usr/lib ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/rules ================================================ #!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/qmake.mk DEB_QMAKE_ARGS = "PREFIX=/usr" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/debian/source/format ================================================ 3.0 (native) ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/qjsonrpc.pri ================================================ QJSONRPC_VERSION = 1.1.0 QJSONRPC_LIBRARY_TYPE = staticlib isEmpty(QJSONRPC_LIBRARY_TYPE) { QJSONRPC_LIBRARY_TYPE = shared } private-headers { DEFINES += USE_QT_PRIVATE_HEADERS QT += core-private } QT += network QJSONRPC_INCLUDEPATH = $${PWD}/src contains(QJSONRPC_LIBRARY_TYPE, staticlib) { DEFINES += QJSONRPC_STATIC } else { DEFINES += QJSONRPC_SHARED } isEmpty(PREFIX) { unix { PREFIX = /usr } else { PREFIX = $$[QT_INSTALL_PREFIX] } } isEmpty(LIBDIR) { LIBDIR = lib } LIBS *= -l$$qtLibraryName(qjsonrpc) ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/qjsonrpc.pro ================================================ TEMPLATE = subdirs SUBDIRS += src CONFIG += ordered ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/.gitignore ================================================ /out/ core tags *.o test test_g test_fast url_parser parsertrace parsertrace_g *.mk *.Makefile *.so *.a ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/.mailmap ================================================ # update AUTHORS with: # git log --all --reverse --format='%aN <%aE>' | perl -ne 'BEGIN{print "# Authors ordered by first contribution.\n"} print unless $h{$_}; $h{$_} = 1' > AUTHORS Ryan Dahl Salman Haq Simon Zimmermann Thomas LE ROUX LE ROUX Thomas Thomas LE ROUX Thomas LE ROUX ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/.travis.yml ================================================ language: c compiler: - clang - gcc script: - "make" notifications: email: false irc: - "irc.freenode.net#libuv" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/AUTHORS ================================================ # Authors ordered by first contribution. Ryan Dahl Jeremy Hinegardner Sergey Shepelev Joe Damato tomika Phoenix Sol Cliff Frey Ewen Cheslack-Postava Santiago Gala Tim Becker Jeff Terrace Ben Noordhuis Nathan Rajlich Mark Nottingham Aman Gupta Tim Becker Sean Cunningham Peter Griess Salman Haq Cliff Frey Jon Kolb Fouad Mardini Paul Querna Felix Geisendörfer koichik Andre Caron Ivo Raisr James McLaughlin David Gwynne Thomas LE ROUX Randy Rizun Andre Louis Caron Simon Zimmermann Erik Dubbelboer Martell Malone Bertrand Paquet BogDan Vatra Peter Faiman Corey Richardson Tóth Tamás ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/CONTRIBUTIONS ================================================ Contributors must agree to the Contributor License Agreement before patches can be accepted. http://spreadsheets2.google.com/viewform?hl=en&formkey=dDJXOGUwbzlYaWM4cHN1MERwQS1CSnc6MQ ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/LICENSE-MIT ================================================ http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev. Additional changes are licensed under the same terms as NGINX and copyright Joyent, Inc. and other Node contributors. All rights reserved. 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. ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/README.md ================================================ HTTP Parser =========== [![Build Status](https://travis-ci.org/joyent/http-parser.png?branch=master)](https://travis-ci.org/joyent/http-parser) This is a parser for HTTP messages written in C. It parses both requests and responses. The parser is designed to be used in performance HTTP applications. It does not make any syscalls nor allocations, it does not buffer data, it can be interrupted at anytime. Depending on your architecture, it only requires about 40 bytes of data per message stream (in a web server that is per connection). Features: * No dependencies * Handles persistent streams (keep-alive). * Decodes chunked encoding. * Upgrade support * Defends against buffer overflow attacks. The parser extracts the following information from HTTP messages: * Header fields and values * Content-Length * Request method * Response status code * Transfer-Encoding * HTTP version * Request URL * Message body Usage ----- One `http_parser` object is used per TCP connection. Initialize the struct using `http_parser_init()` and set the callbacks. That might look something like this for a request parser: http_parser_settings settings; settings.on_url = my_url_callback; settings.on_header_field = my_header_field_callback; /* ... */ http_parser *parser = malloc(sizeof(http_parser)); http_parser_init(parser, HTTP_REQUEST); parser->data = my_socket; When data is received on the socket execute the parser and check for errors. size_t len = 80*1024, nparsed; char buf[len]; ssize_t recved; recved = recv(fd, buf, len, 0); if (recved < 0) { /* Handle error. */ } /* Start up / continue the parser. * Note we pass recved==0 to signal that EOF has been recieved. */ nparsed = http_parser_execute(parser, &settings, buf, recved); if (parser->upgrade) { /* handle new protocol */ } else if (nparsed != recved) { /* Handle error. Usually just close the connection. */ } HTTP needs to know where the end of the stream is. For example, sometimes servers send responses without Content-Length and expect the client to consume input (for the body) until EOF. To tell http_parser about EOF, give `0` as the forth parameter to `http_parser_execute()`. Callbacks and errors can still be encountered during an EOF, so one must still be prepared to receive them. Scalar valued message information such as `status_code`, `method`, and the HTTP version are stored in the parser structure. This data is only temporally stored in `http_parser` and gets reset on each new message. If this information is needed later, copy it out of the structure during the `headers_complete` callback. The parser decodes the transfer-encoding for both requests and responses transparently. That is, a chunked encoding is decoded before being sent to the on_body callback. The Special Problem of Upgrade ------------------------------ HTTP supports upgrading the connection to a different protocol. An increasingly common example of this is the Web Socket protocol which sends a request like GET /demo HTTP/1.1 Upgrade: WebSocket Connection: Upgrade Host: example.com Origin: http://example.com WebSocket-Protocol: sample followed by non-HTTP data. (See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more information the Web Socket protocol.) To support this, the parser will treat this as a normal HTTP message without a body. Issuing both on_headers_complete and on_message_complete callbacks. However http_parser_execute() will stop parsing at the end of the headers and return. The user is expected to check if `parser->upgrade` has been set to 1 after `http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied offset by the return value of `http_parser_execute()`. Callbacks --------- During the `http_parser_execute()` call, the callbacks set in `http_parser_settings` will be executed. The parser maintains state and never looks behind, so buffering the data is not necessary. If you need to save certain data for later usage, you can do that from the callbacks. There are two types of callbacks: * notification `typedef int (*http_cb) (http_parser*);` Callbacks: on_message_begin, on_headers_complete, on_message_complete. * data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);` Callbacks: (requests only) on_uri, (common) on_header_field, on_header_value, on_body; Callbacks must return 0 on success. Returning a non-zero value indicates error to the parser, making it exit immediately. In case you parse HTTP message in chunks (i.e. `read()` request line from socket, parse, read half headers, parse, etc) your data callbacks may be called more than once. Http-parser guarantees that data pointer is only valid for the lifetime of callback. You can also `read()` into a heap allocated buffer to avoid copying memory around if this fits your application. Reading headers may be a tricky task if you read/parse headers partially. Basically, you need to remember whether last header callback was field or value and apply following logic: (on_header_field and on_header_value shortened to on_h_*) ------------------------ ------------ -------------------------------------------- | State (prev. callback) | Callback | Description/action | ------------------------ ------------ -------------------------------------------- | nothing (first call) | on_h_field | Allocate new buffer and copy callback data | | | | into it | ------------------------ ------------ -------------------------------------------- | value | on_h_field | New header started. | | | | Copy current name,value buffers to headers | | | | list and allocate new buffer for new name | ------------------------ ------------ -------------------------------------------- | field | on_h_field | Previous name continues. Reallocate name | | | | buffer and append callback data to it | ------------------------ ------------ -------------------------------------------- | field | on_h_value | Value for current header started. Allocate | | | | new buffer and copy callback data to it | ------------------------ ------------ -------------------------------------------- | value | on_h_value | Value continues. Reallocate value buffer | | | | and append callback data to it | ------------------------ ------------ -------------------------------------------- Parsing URLs ------------ A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`. Users of this library may wish to use it to parse URLs constructed from consecutive `on_url` callbacks. See examples of reading in headers: * [partial example](http://gist.github.com/155877) in C * [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C * [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/contrib/parsertrace.c ================================================ /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev * * Additional changes are licensed under the same terms as NGINX and * copyright Joyent, Inc. and other Node contributors. All rights reserved. * * 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. */ /* Dump what the parser finds to stdout as it happen */ #include "http_parser.h" #include #include #include int on_message_begin(http_parser* _) { (void)_; printf("\n***MESSAGE BEGIN***\n\n"); return 0; } int on_headers_complete(http_parser* _) { (void)_; printf("\n***HEADERS COMPLETE***\n\n"); return 0; } int on_message_complete(http_parser* _) { (void)_; printf("\n***MESSAGE COMPLETE***\n\n"); return 0; } int on_url(http_parser* _, const char* at, size_t length) { (void)_; printf("Url: %.*s\n", (int)length, at); return 0; } int on_header_field(http_parser* _, const char* at, size_t length) { (void)_; printf("Header field: %.*s\n", (int)length, at); return 0; } int on_header_value(http_parser* _, const char* at, size_t length) { (void)_; printf("Header value: %.*s\n", (int)length, at); return 0; } int on_body(http_parser* _, const char* at, size_t length) { (void)_; printf("Body: %.*s\n", (int)length, at); return 0; } void usage(const char* name) { fprintf(stderr, "Usage: %s $type $filename\n" " type: -x, where x is one of {r,b,q}\n" " parses file as a Response, reQuest, or Both\n", name); exit(EXIT_FAILURE); } int main(int argc, char* argv[]) { enum http_parser_type file_type; if (argc != 3) { usage(argv[0]); } char* type = argv[1]; if (type[0] != '-') { usage(argv[0]); } switch (type[1]) { /* in the case of "-", type[1] will be NUL */ case 'r': file_type = HTTP_RESPONSE; break; case 'q': file_type = HTTP_REQUEST; break; case 'b': file_type = HTTP_BOTH; break; default: usage(argv[0]); } char* filename = argv[2]; FILE* file = fopen(filename, "r"); if (file == NULL) { perror("fopen"); return EXIT_FAILURE; } fseek(file, 0, SEEK_END); long file_length = ftell(file); if (file_length == -1) { perror("ftell"); return EXIT_FAILURE; } fseek(file, 0, SEEK_SET); char* data = malloc(file_length); if (fread(data, 1, file_length, file) != (size_t)file_length) { fprintf(stderr, "couldn't read entire file\n"); free(data); return EXIT_FAILURE; } http_parser_settings settings; memset(&settings, 0, sizeof(settings)); settings.on_message_begin = on_message_begin; settings.on_url = on_url; settings.on_header_field = on_header_field; settings.on_header_value = on_header_value; settings.on_headers_complete = on_headers_complete; settings.on_body = on_body; settings.on_message_complete = on_message_complete; http_parser parser; http_parser_init(&parser, file_type); size_t nparsed = http_parser_execute(&parser, &settings, data, file_length); free(data); if (nparsed != (size_t)file_length) { fprintf(stderr, "Error: %s (%s)\n", http_errno_description(HTTP_PARSER_ERRNO(&parser)), http_errno_name(HTTP_PARSER_ERRNO(&parser))); return EXIT_FAILURE; } return EXIT_SUCCESS; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/contrib/url_parser.c ================================================ #include "http_parser.h" #include #include void dump_url (const char *url, const struct http_parser_url *u) { unsigned int i; printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port); for (i = 0; i < UF_MAX; i++) { if ((u->field_set & (1 << i)) == 0) { printf("\tfield_data[%u]: unset\n", i); continue; } printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n", i, u->field_data[i].off, u->field_data[i].len, u->field_data[i].len, url + u->field_data[i].off); } } int main(int argc, char ** argv) { if (argc != 3) { printf("Syntax : %s connect|get url\n", argv[0]); return 1; } struct http_parser_url u; int len = strlen(argv[2]); int connect = strcmp("connect", argv[1]) == 0 ? 1 : 0; printf("Parsing %s, connect %d\n", argv[2], connect); int result = http_parser_parse_url(argv[2], len, connect, &u); if (result != 0) { printf("Parse error : %d\n", result); return result; } printf("Parse ok, result : \n"); dump_url(argv[2], &u); return 0; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/http-parser.pri ================================================ INCLUDEPATH += $${PWD} PRIVATE_HEADERS += $${PWD}/http_parser.h SOURCES += $${PWD}/http_parser.c ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/http_parser.c ================================================ /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev * * Additional changes are licensed under the same terms as NGINX and * copyright Joyent, Inc. and other Node contributors. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include "http_parser.h" #include #include #include #include #include #include #ifndef ULLONG_MAX # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ #endif #ifndef MIN # define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef ARRAY_SIZE # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #endif #ifndef BIT_AT # define BIT_AT(a, i) \ (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ (1 << ((unsigned int) (i) & 7)))) #endif #ifndef ELEM_AT # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) #endif #define SET_ERRNO(e) \ do { \ parser->http_errno = (e); \ } while(0) /* Run the notify callback FOR, returning ER if it fails */ #define CALLBACK_NOTIFY_(FOR, ER) \ do { \ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ if (settings->on_##FOR) { \ if (0 != settings->on_##FOR(parser)) { \ SET_ERRNO(HPE_CB_##FOR); \ } \ \ /* We either errored above or got paused; get out */ \ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ return (ER); \ } \ } \ } while (0) /* Run the notify callback FOR and consume the current byte */ #define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) /* Run the notify callback FOR and don't consume the current byte */ #define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) /* Run data callback FOR with LEN bytes, returning ER if it fails */ #define CALLBACK_DATA_(FOR, LEN, ER) \ do { \ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ if (FOR##_mark) { \ if (settings->on_##FOR) { \ if (0 != settings->on_##FOR(parser, FOR##_mark, (LEN))) { \ SET_ERRNO(HPE_CB_##FOR); \ } \ \ /* We either errored above or got paused; get out */ \ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ return (ER); \ } \ } \ FOR##_mark = NULL; \ } \ } while (0) /* Run the data callback FOR and consume the current byte */ #define CALLBACK_DATA(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) /* Run the data callback FOR and don't consume the current byte */ #define CALLBACK_DATA_NOADVANCE(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) /* Set the mark FOR; non-destructive if mark is already set */ #define MARK(FOR) \ do { \ if (!FOR##_mark) { \ FOR##_mark = p; \ } \ } while (0) #define PROXY_CONNECTION "proxy-connection" #define CONNECTION "connection" #define CONTENT_LENGTH "content-length" #define TRANSFER_ENCODING "transfer-encoding" #define UPGRADE "upgrade" #define CHUNKED "chunked" #define KEEP_ALIVE "keep-alive" #define CLOSE "close" static const char *method_strings[] = { #define XX(num, name, string) #string, HTTP_METHOD_MAP(XX) #undef XX }; /* Tokens as defined by rfc 2616. Also lowercases them. * token = 1* * separators = "(" | ")" | "<" | ">" | "@" * | "," | ";" | ":" | "\" | <"> * | "/" | "[" | "]" | "?" | "=" * | "{" | "}" | SP | HT */ static const char tokens[256] = { /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ 0, 0, 0, 0, 0, 0, 0, 0, /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ 0, 0, 0, 0, 0, 0, 0, 0, /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ 0, 0, 0, 0, 0, 0, 0, 0, /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ 0, 0, 0, 0, 0, 0, 0, 0, /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ 0, '!', 0, '#', '$', '%', '&', '\'', /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ 0, 0, '*', '+', 0, '-', '.', 0, /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ '0', '1', '2', '3', '4', '5', '6', '7', /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ '8', '9', 0, 0, 0, 0, 0, 0, /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ 'x', 'y', 'z', 0, 0, 0, '^', '_', /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ 'x', 'y', 'z', 0, '|', 0, '~', 0 }; static const int8_t unhex[256] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; #if HTTP_PARSER_STRICT # define T(v) 0 #else # define T(v) v #endif static const uint8_t normal_url_char[32] = { /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; #undef T enum state { s_dead = 1 /* important that this is > 0 */ , s_start_req_or_res , s_res_or_resp_H , s_start_res , s_res_H , s_res_HT , s_res_HTT , s_res_HTTP , s_res_first_http_major , s_res_http_major , s_res_first_http_minor , s_res_http_minor , s_res_first_status_code , s_res_status_code , s_res_status , s_res_line_almost_done , s_start_req , s_req_method , s_req_spaces_before_url , s_req_schema , s_req_schema_slash , s_req_schema_slash_slash , s_req_server_start , s_req_server , s_req_server_with_at , s_req_path , s_req_query_string_start , s_req_query_string , s_req_fragment_start , s_req_fragment , s_req_http_start , s_req_http_H , s_req_http_HT , s_req_http_HTT , s_req_http_HTTP , s_req_first_http_major , s_req_http_major , s_req_first_http_minor , s_req_http_minor , s_req_line_almost_done , s_header_field_start , s_header_field , s_header_value_start , s_header_value , s_header_value_lws , s_header_almost_done , s_chunk_size_start , s_chunk_size , s_chunk_parameters , s_chunk_size_almost_done , s_headers_almost_done , s_headers_done /* Important: 's_headers_done' must be the last 'header' state. All * states beyond this must be 'body' states. It is used for overflow * checking. See the PARSING_HEADER() macro. */ , s_chunk_data , s_chunk_data_almost_done , s_chunk_data_done , s_body_identity , s_body_identity_eof , s_message_done }; #define PARSING_HEADER(state) (state <= s_headers_done) enum header_states { h_general = 0 , h_C , h_CO , h_CON , h_matching_connection , h_matching_proxy_connection , h_matching_content_length , h_matching_transfer_encoding , h_matching_upgrade , h_connection , h_content_length , h_transfer_encoding , h_upgrade , h_matching_transfer_encoding_chunked , h_matching_connection_keep_alive , h_matching_connection_close , h_transfer_encoding_chunked , h_connection_keep_alive , h_connection_close }; enum http_host_state { s_http_host_dead = 1 , s_http_userinfo_start , s_http_userinfo , s_http_host_start , s_http_host_v6_start , s_http_host , s_http_host_v6 , s_http_host_v6_end , s_http_host_port_start , s_http_host_port }; /* Macros for character classes; depends on strict-mode */ #define CR '\r' #define LF '\n' #define LOWER(c) (unsigned char)(c | 0x20) #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') #define IS_NUM(c) ((c) >= '0' && (c) <= '9') #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ (c) == ')') #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ (c) == '$' || (c) == ',') #if HTTP_PARSER_STRICT #define TOKEN(c) (tokens[(unsigned char)c]) #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') #else #define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) #define IS_URL_CHAR(c) \ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) #define IS_HOST_CHAR(c) \ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') #endif #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) #if HTTP_PARSER_STRICT # define STRICT_CHECK(cond) \ do { \ if (cond) { \ SET_ERRNO(HPE_STRICT); \ goto error; \ } \ } while (0) # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) #else # define STRICT_CHECK(cond) # define NEW_MESSAGE() start_state #endif /* Map errno values to strings for human-readable output */ #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, static struct { const char *name; const char *description; } http_strerror_tab[] = { HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) }; #undef HTTP_STRERROR_GEN int http_message_needs_eof(const http_parser *parser); /* Our URL parser. * * This is designed to be shared by http_parser_execute() for URL validation, * hence it has a state transition + byte-for-byte interface. In addition, it * is meant to be embedded in http_parser_parse_url(), which does the dirty * work of turning state transitions URL components for its API. * * This function should only be invoked with non-space characters. It is * assumed that the caller cares about (and can detect) the transition between * URL and non-URL states by looking for these. */ static enum state parse_url_char(enum state s, const char ch) { if (ch == ' ' || ch == '\r' || ch == '\n') { return s_dead; } #if HTTP_PARSER_STRICT if (ch == '\t' || ch == '\f') { return s_dead; } #endif switch (s) { case s_req_spaces_before_url: /* Proxied requests are followed by scheme of an absolute URI (alpha). * All methods except CONNECT are followed by '/' or '*'. */ if (ch == '/' || ch == '*') { return s_req_path; } if (IS_ALPHA(ch)) { return s_req_schema; } break; case s_req_schema: if (IS_ALPHA(ch)) { return s; } if (ch == ':') { return s_req_schema_slash; } break; case s_req_schema_slash: if (ch == '/') { return s_req_schema_slash_slash; } break; case s_req_schema_slash_slash: if (ch == '/') { return s_req_server_start; } break; case s_req_server_with_at: if (ch == '@') { return s_dead; } /* FALLTHROUGH */ case s_req_server_start: case s_req_server: if (ch == '/') { return s_req_path; } if (ch == '?') { return s_req_query_string_start; } if (ch == '@') { return s_req_server_with_at; } if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { return s_req_server; } break; case s_req_path: if (IS_URL_CHAR(ch)) { return s; } switch (ch) { case '?': return s_req_query_string_start; case '#': return s_req_fragment_start; } break; case s_req_query_string_start: case s_req_query_string: if (IS_URL_CHAR(ch)) { return s_req_query_string; } switch (ch) { case '?': /* allow extra '?' in query string */ return s_req_query_string; case '#': return s_req_fragment_start; } break; case s_req_fragment_start: if (IS_URL_CHAR(ch)) { return s_req_fragment; } switch (ch) { case '?': return s_req_fragment; case '#': return s; } break; case s_req_fragment: if (IS_URL_CHAR(ch)) { return s; } switch (ch) { case '?': case '#': return s; } break; default: break; } /* We should never fall out of the switch above unless there's an error */ return s_dead; } size_t http_parser_execute (http_parser *parser, const http_parser_settings *settings, const char *data, size_t len) { char c, ch; int8_t unhex_val; const char *p = data; const char *header_field_mark = 0; const char *header_value_mark = 0; const char *url_mark = 0; const char *body_mark = 0; /* We're in an error state. Don't bother doing anything. */ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { return 0; } if (len == 0) { switch (parser->state) { case s_body_identity_eof: /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if * we got paused. */ CALLBACK_NOTIFY_NOADVANCE(message_complete); return 0; case s_dead: case s_start_req_or_res: case s_start_res: case s_start_req: return 0; default: SET_ERRNO(HPE_INVALID_EOF_STATE); return 1; } } if (parser->state == s_header_field) header_field_mark = data; if (parser->state == s_header_value) header_value_mark = data; switch (parser->state) { case s_req_path: case s_req_schema: case s_req_schema_slash: case s_req_schema_slash_slash: case s_req_server_start: case s_req_server: case s_req_server_with_at: case s_req_query_string_start: case s_req_query_string: case s_req_fragment_start: case s_req_fragment: url_mark = data; break; } for (p=data; p != data + len; p++) { ch = *p; if (PARSING_HEADER(parser->state)) { ++parser->nread; /* Buffer overflow attack */ if (parser->nread > HTTP_MAX_HEADER_SIZE) { SET_ERRNO(HPE_HEADER_OVERFLOW); goto error; } } reexecute_byte: switch (parser->state) { case s_dead: /* this state is used after a 'Connection: close' message * the parser will error out if it reads another message */ if (ch == CR || ch == LF) break; SET_ERRNO(HPE_CLOSED_CONNECTION); goto error; case s_start_req_or_res: { if (ch == CR || ch == LF) break; parser->flags = 0; parser->content_length = ULLONG_MAX; if (ch == 'H') { parser->state = s_res_or_resp_H; CALLBACK_NOTIFY(message_begin); } else { parser->type = HTTP_REQUEST; parser->state = s_start_req; goto reexecute_byte; } break; } case s_res_or_resp_H: if (ch == 'T') { parser->type = HTTP_RESPONSE; parser->state = s_res_HT; } else { if (ch != 'E') { SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } parser->type = HTTP_REQUEST; parser->method = HTTP_HEAD; parser->index = 2; parser->state = s_req_method; } break; case s_start_res: { parser->flags = 0; parser->content_length = ULLONG_MAX; switch (ch) { case 'H': parser->state = s_res_H; break; case CR: case LF: break; default: SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } CALLBACK_NOTIFY(message_begin); break; } case s_res_H: STRICT_CHECK(ch != 'T'); parser->state = s_res_HT; break; case s_res_HT: STRICT_CHECK(ch != 'T'); parser->state = s_res_HTT; break; case s_res_HTT: STRICT_CHECK(ch != 'P'); parser->state = s_res_HTTP; break; case s_res_HTTP: STRICT_CHECK(ch != '/'); parser->state = s_res_first_http_major; break; case s_res_first_http_major: if (ch < '0' || ch > '9') { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major = ch - '0'; parser->state = s_res_http_major; break; /* major HTTP version or dot */ case s_res_http_major: { if (ch == '.') { parser->state = s_res_first_http_minor; break; } if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major *= 10; parser->http_major += ch - '0'; if (parser->http_major > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } /* first digit of minor HTTP version */ case s_res_first_http_minor: if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor = ch - '0'; parser->state = s_res_http_minor; break; /* minor HTTP version or end of request line */ case s_res_http_minor: { if (ch == ' ') { parser->state = s_res_first_status_code; break; } if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor *= 10; parser->http_minor += ch - '0'; if (parser->http_minor > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } case s_res_first_status_code: { if (!IS_NUM(ch)) { if (ch == ' ') { break; } SET_ERRNO(HPE_INVALID_STATUS); goto error; } parser->status_code = ch - '0'; parser->state = s_res_status_code; break; } case s_res_status_code: { if (!IS_NUM(ch)) { switch (ch) { case ' ': parser->state = s_res_status; break; case CR: parser->state = s_res_line_almost_done; break; case LF: parser->state = s_header_field_start; break; default: SET_ERRNO(HPE_INVALID_STATUS); goto error; } break; } parser->status_code *= 10; parser->status_code += ch - '0'; if (parser->status_code > 999) { SET_ERRNO(HPE_INVALID_STATUS); goto error; } break; } case s_res_status: /* the human readable status. e.g. "NOT FOUND" * we are not humans so just ignore this */ if (ch == CR) { parser->state = s_res_line_almost_done; break; } if (ch == LF) { parser->state = s_header_field_start; break; } break; case s_res_line_almost_done: STRICT_CHECK(ch != LF); parser->state = s_header_field_start; CALLBACK_NOTIFY(status_complete); break; case s_start_req: { if (ch == CR || ch == LF) break; parser->flags = 0; parser->content_length = ULLONG_MAX; if (!IS_ALPHA(ch)) { SET_ERRNO(HPE_INVALID_METHOD); goto error; } parser->method = (enum http_method) 0; parser->index = 1; switch (ch) { case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; case 'D': parser->method = HTTP_DELETE; break; case 'G': parser->method = HTTP_GET; break; case 'H': parser->method = HTTP_HEAD; break; case 'L': parser->method = HTTP_LOCK; break; case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */ break; case 'N': parser->method = HTTP_NOTIFY; break; case 'O': parser->method = HTTP_OPTIONS; break; case 'P': parser->method = HTTP_POST; /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ break; case 'R': parser->method = HTTP_REPORT; break; case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; case 'T': parser->method = HTTP_TRACE; break; case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break; default: SET_ERRNO(HPE_INVALID_METHOD); goto error; } parser->state = s_req_method; CALLBACK_NOTIFY(message_begin); break; } case s_req_method: { const char *matcher; if (ch == '\0') { SET_ERRNO(HPE_INVALID_METHOD); goto error; } matcher = method_strings[parser->method]; if (ch == ' ' && matcher[parser->index] == '\0') { parser->state = s_req_spaces_before_url; } else if (ch == matcher[parser->index]) { ; /* nada */ } else if (parser->method == HTTP_CONNECT) { if (parser->index == 1 && ch == 'H') { parser->method = HTTP_CHECKOUT; } else if (parser->index == 2 && ch == 'P') { parser->method = HTTP_COPY; } else { goto error; } } else if (parser->method == HTTP_MKCOL) { if (parser->index == 1 && ch == 'O') { parser->method = HTTP_MOVE; } else if (parser->index == 1 && ch == 'E') { parser->method = HTTP_MERGE; } else if (parser->index == 1 && ch == '-') { parser->method = HTTP_MSEARCH; } else if (parser->index == 2 && ch == 'A') { parser->method = HTTP_MKACTIVITY; } else { goto error; } } else if (parser->method == HTTP_SUBSCRIBE) { if (parser->index == 1 && ch == 'E') { parser->method = HTTP_SEARCH; } else { goto error; } } else if (parser->index == 1 && parser->method == HTTP_POST) { if (ch == 'R') { parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */ } else if (ch == 'U') { parser->method = HTTP_PUT; /* or HTTP_PURGE */ } else if (ch == 'A') { parser->method = HTTP_PATCH; } else { goto error; } } else if (parser->index == 2) { if (parser->method == HTTP_PUT) { if (ch == 'R') parser->method = HTTP_PURGE; } else if (parser->method == HTTP_UNLOCK) { if (ch == 'S') parser->method = HTTP_UNSUBSCRIBE; } } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') { parser->method = HTTP_PROPPATCH; } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; } ++parser->index; break; } case s_req_spaces_before_url: { if (ch == ' ') break; MARK(url); if (parser->method == HTTP_CONNECT) { parser->state = s_req_server_start; } parser->state = parse_url_char((enum state)parser->state, ch); if (parser->state == s_dead) { SET_ERRNO(HPE_INVALID_URL); goto error; } break; } case s_req_schema: case s_req_schema_slash: case s_req_schema_slash_slash: case s_req_server_start: { switch (ch) { /* No whitespace allowed here */ case ' ': case CR: case LF: SET_ERRNO(HPE_INVALID_URL); goto error; default: parser->state = parse_url_char((enum state)parser->state, ch); if (parser->state == s_dead) { SET_ERRNO(HPE_INVALID_URL); goto error; } } break; } case s_req_server: case s_req_server_with_at: case s_req_path: case s_req_query_string_start: case s_req_query_string: case s_req_fragment_start: case s_req_fragment: { switch (ch) { case ' ': parser->state = s_req_http_start; CALLBACK_DATA(url); break; case CR: case LF: parser->http_major = 0; parser->http_minor = 9; parser->state = (ch == CR) ? s_req_line_almost_done : s_header_field_start; CALLBACK_DATA(url); break; default: parser->state = parse_url_char((enum state)parser->state, ch); if (parser->state == s_dead) { SET_ERRNO(HPE_INVALID_URL); goto error; } } break; } case s_req_http_start: switch (ch) { case 'H': parser->state = s_req_http_H; break; case ' ': break; default: SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } break; case s_req_http_H: STRICT_CHECK(ch != 'T'); parser->state = s_req_http_HT; break; case s_req_http_HT: STRICT_CHECK(ch != 'T'); parser->state = s_req_http_HTT; break; case s_req_http_HTT: STRICT_CHECK(ch != 'P'); parser->state = s_req_http_HTTP; break; case s_req_http_HTTP: STRICT_CHECK(ch != '/'); parser->state = s_req_first_http_major; break; /* first digit of major HTTP version */ case s_req_first_http_major: if (ch < '1' || ch > '9') { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major = ch - '0'; parser->state = s_req_http_major; break; /* major HTTP version or dot */ case s_req_http_major: { if (ch == '.') { parser->state = s_req_first_http_minor; break; } if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major *= 10; parser->http_major += ch - '0'; if (parser->http_major > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } /* first digit of minor HTTP version */ case s_req_first_http_minor: if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor = ch - '0'; parser->state = s_req_http_minor; break; /* minor HTTP version or end of request line */ case s_req_http_minor: { if (ch == CR) { parser->state = s_req_line_almost_done; break; } if (ch == LF) { parser->state = s_header_field_start; break; } /* XXX allow spaces after digit? */ if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor *= 10; parser->http_minor += ch - '0'; if (parser->http_minor > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } break; } /* end of request line */ case s_req_line_almost_done: { if (ch != LF) { SET_ERRNO(HPE_LF_EXPECTED); goto error; } parser->state = s_header_field_start; break; } case s_header_field_start: { if (ch == CR) { parser->state = s_headers_almost_done; break; } if (ch == LF) { /* they might be just sending \n instead of \r\n so this would be * the second \n to denote the end of headers*/ parser->state = s_headers_almost_done; goto reexecute_byte; } c = TOKEN(ch); if (!c) { SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } MARK(header_field); parser->index = 0; parser->state = s_header_field; switch (c) { case 'c': parser->header_state = h_C; break; case 'p': parser->header_state = h_matching_proxy_connection; break; case 't': parser->header_state = h_matching_transfer_encoding; break; case 'u': parser->header_state = h_matching_upgrade; break; default: parser->header_state = h_general; break; } break; } case s_header_field: { c = TOKEN(ch); if (c) { switch (parser->header_state) { case h_general: break; case h_C: parser->index++; parser->header_state = (c == 'o' ? h_CO : h_general); break; case h_CO: parser->index++; parser->header_state = (c == 'n' ? h_CON : h_general); break; case h_CON: parser->index++; switch (c) { case 'n': parser->header_state = h_matching_connection; break; case 't': parser->header_state = h_matching_content_length; break; default: parser->header_state = h_general; break; } break; /* connection */ case h_matching_connection: parser->index++; if (parser->index > sizeof(CONNECTION)-1 || c != CONNECTION[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CONNECTION)-2) { parser->header_state = h_connection; } break; /* proxy-connection */ case h_matching_proxy_connection: parser->index++; if (parser->index > sizeof(PROXY_CONNECTION)-1 || c != PROXY_CONNECTION[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { parser->header_state = h_connection; } break; /* content-length */ case h_matching_content_length: parser->index++; if (parser->index > sizeof(CONTENT_LENGTH)-1 || c != CONTENT_LENGTH[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { parser->header_state = h_content_length; } break; /* transfer-encoding */ case h_matching_transfer_encoding: parser->index++; if (parser->index > sizeof(TRANSFER_ENCODING)-1 || c != TRANSFER_ENCODING[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { parser->header_state = h_transfer_encoding; /* Multiple `Transfer-Encoding` headers should be treated as * one, but with values separate by a comma. * * See: https://tools.ietf.org/html/rfc7230#section-3.2.2 */ parser->flags &= ~F_CHUNKED; } break; /* upgrade */ case h_matching_upgrade: parser->index++; if (parser->index > sizeof(UPGRADE)-1 || c != UPGRADE[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(UPGRADE)-2) { parser->header_state = h_upgrade; } break; case h_connection: case h_content_length: case h_transfer_encoding: case h_upgrade: if (ch != ' ') parser->header_state = h_general; break; default: assert(0 && "Unknown header_state"); break; } break; } if (ch == ':') { parser->state = s_header_value_start; CALLBACK_DATA(header_field); break; } if (ch == CR) { parser->state = s_header_almost_done; CALLBACK_DATA(header_field); break; } if (ch == LF) { parser->state = s_header_field_start; CALLBACK_DATA(header_field); break; } SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } case s_header_value_start: { if (ch == ' ' || ch == '\t') break; MARK(header_value); parser->state = s_header_value; parser->index = 0; if (ch == CR) { parser->header_state = h_general; parser->state = s_header_almost_done; CALLBACK_DATA(header_value); break; } if (ch == LF) { parser->state = s_header_field_start; CALLBACK_DATA(header_value); break; } c = LOWER(ch); switch (parser->header_state) { case h_upgrade: parser->flags |= F_UPGRADE; parser->header_state = h_general; break; case h_transfer_encoding: /* looking for 'Transfer-Encoding: chunked' */ if ('c' == c) { parser->header_state = h_matching_transfer_encoding_chunked; } else { parser->header_state = h_general; } break; case h_content_length: if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } parser->content_length = ch - '0'; break; case h_connection: /* looking for 'Connection: keep-alive' */ if (c == 'k') { parser->header_state = h_matching_connection_keep_alive; /* looking for 'Connection: close' */ } else if (c == 'c') { parser->header_state = h_matching_connection_close; } else { parser->header_state = h_general; } break; default: parser->header_state = h_general; break; } break; } case s_header_value: { if (ch == CR) { parser->state = s_header_almost_done; CALLBACK_DATA(header_value); break; } if (ch == LF) { parser->state = s_header_almost_done; CALLBACK_DATA_NOADVANCE(header_value); goto reexecute_byte; } c = LOWER(ch); switch (parser->header_state) { case h_general: break; case h_connection: case h_transfer_encoding: assert(0 && "Shouldn't get here."); break; case h_content_length: { uint64_t t; if (ch == ' ') break; if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } t = parser->content_length; t *= 10; t += ch - '0'; /* Overflow? */ if (t < parser->content_length || t == ULLONG_MAX) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } parser->content_length = t; break; } /* Transfer-Encoding: chunked */ case h_matching_transfer_encoding_chunked: parser->index++; if (parser->index > sizeof(CHUNKED)-1 || c != CHUNKED[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CHUNKED)-2) { parser->header_state = h_transfer_encoding_chunked; } break; /* looking for 'Connection: keep-alive' */ case h_matching_connection_keep_alive: parser->index++; if (parser->index > sizeof(KEEP_ALIVE)-1 || c != KEEP_ALIVE[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(KEEP_ALIVE)-2) { parser->header_state = h_connection_keep_alive; } break; /* looking for 'Connection: close' */ case h_matching_connection_close: parser->index++; if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CLOSE)-2) { parser->header_state = h_connection_close; } break; case h_transfer_encoding_chunked: case h_connection_keep_alive: case h_connection_close: if (ch != ' ') parser->header_state = h_general; break; default: parser->state = s_header_value; parser->header_state = h_general; break; } break; } case s_header_almost_done: { STRICT_CHECK(ch != LF); parser->state = s_header_value_lws; switch (parser->header_state) { case h_connection_keep_alive: parser->flags |= F_CONNECTION_KEEP_ALIVE; break; case h_connection_close: parser->flags |= F_CONNECTION_CLOSE; break; case h_transfer_encoding_chunked: parser->flags |= F_CHUNKED; break; default: break; } break; } case s_header_value_lws: { if (ch == ' ' || ch == '\t') parser->state = s_header_value_start; else { parser->state = s_header_field_start; goto reexecute_byte; } break; } case s_headers_almost_done: { STRICT_CHECK(ch != LF); if (parser->flags & F_TRAILING) { /* End of a chunked request */ parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); break; } parser->state = s_headers_done; /* Set this here so that on_headers_complete() callbacks can see it */ parser->upgrade = (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT); /* Here we call the headers_complete callback. This is somewhat * different than other callbacks because if the user returns 1, we * will interpret that as saying that this message has no body. This * is needed for the annoying case of recieving a response to a HEAD * request. * * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so * we have to simulate it by handling a change in errno below. */ if (settings->on_headers_complete) { switch (settings->on_headers_complete(parser)) { case 0: break; case 1: parser->flags |= F_SKIPBODY; break; default: SET_ERRNO(HPE_CB_headers_complete); return p - data; /* Error */ } } if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { return p - data; } goto reexecute_byte; } case s_headers_done: { STRICT_CHECK(ch != LF); parser->nread = 0; /* Exit, the rest of the connect is in a different protocol. */ if (parser->upgrade) { parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); return (p - data) + 1; } if (parser->flags & F_SKIPBODY) { parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); } else if (parser->flags & F_CHUNKED) { /* chunked encoding - ignore Content-Length header */ parser->state = s_chunk_size_start; } else { if (parser->content_length == 0) { /* Content-Length header given but zero: Content-Length: 0\r\n */ parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); } else if (parser->content_length != ULLONG_MAX) { /* Content-Length header given and non-zero */ parser->state = s_body_identity; } else { if (parser->type == HTTP_REQUEST || !http_message_needs_eof(parser)) { /* Assume content-length 0 - read the next */ parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); } else { /* Read body until EOF */ parser->state = s_body_identity_eof; } } } break; } case s_body_identity: { uint64_t to_read = MIN(parser->content_length, (uint64_t) ((data + len) - p)); assert(parser->content_length != 0 && parser->content_length != ULLONG_MAX); /* The difference between advancing content_length and p is because * the latter will automaticaly advance on the next loop iteration. * Further, if content_length ends up at 0, we want to see the last * byte again for our message complete callback. */ MARK(body); parser->content_length -= to_read; p += to_read - 1; if (parser->content_length == 0) { parser->state = s_message_done; /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. * * The alternative to doing this is to wait for the next byte to * trigger the data callback, just as in every other case. The * problem with this is that this makes it difficult for the test * harness to distinguish between complete-on-EOF and * complete-on-length. It's not clear that this distinction is * important for applications, but let's keep it for now. */ CALLBACK_DATA_(body, p - body_mark + 1, p - data); goto reexecute_byte; } break; } /* read until EOF */ case s_body_identity_eof: MARK(body); p = data + len - 1; break; case s_message_done: parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); break; case s_chunk_size_start: { assert(parser->nread == 1); assert(parser->flags & F_CHUNKED); unhex_val = unhex[(unsigned char)ch]; if (unhex_val == -1) { SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; } parser->content_length = unhex_val; parser->state = s_chunk_size; break; } case s_chunk_size: { uint64_t t; assert(parser->flags & F_CHUNKED); if (ch == CR) { parser->state = s_chunk_size_almost_done; break; } unhex_val = unhex[(unsigned char)ch]; if (unhex_val == -1) { if (ch == ';' || ch == ' ') { parser->state = s_chunk_parameters; break; } SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; } t = parser->content_length; t *= 16; t += unhex_val; /* Overflow? */ if (t < parser->content_length || t == ULLONG_MAX) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } parser->content_length = t; break; } case s_chunk_parameters: { assert(parser->flags & F_CHUNKED); /* just ignore this shit. TODO check for overflow */ if (ch == CR) { parser->state = s_chunk_size_almost_done; break; } break; } case s_chunk_size_almost_done: { assert(parser->flags & F_CHUNKED); STRICT_CHECK(ch != LF); parser->nread = 0; if (parser->content_length == 0) { parser->flags |= F_TRAILING; parser->state = s_header_field_start; } else { parser->state = s_chunk_data; } break; } case s_chunk_data: { uint64_t to_read = MIN(parser->content_length, (uint64_t) ((data + len) - p)); assert(parser->flags & F_CHUNKED); assert(parser->content_length != 0 && parser->content_length != ULLONG_MAX); /* See the explanation in s_body_identity for why the content * length and data pointers are managed this way. */ MARK(body); parser->content_length -= to_read; p += to_read - 1; if (parser->content_length == 0) { parser->state = s_chunk_data_almost_done; } break; } case s_chunk_data_almost_done: assert(parser->flags & F_CHUNKED); assert(parser->content_length == 0); STRICT_CHECK(ch != CR); parser->state = s_chunk_data_done; CALLBACK_DATA(body); break; case s_chunk_data_done: assert(parser->flags & F_CHUNKED); STRICT_CHECK(ch != LF); parser->nread = 0; parser->state = s_chunk_size_start; break; default: assert(0 && "unhandled state"); SET_ERRNO(HPE_INVALID_INTERNAL_STATE); goto error; } } /* Run callbacks for any marks that we have leftover after we ran our of * bytes. There should be at most one of these set, so it's OK to invoke * them in series (unset marks will not result in callbacks). * * We use the NOADVANCE() variety of callbacks here because 'p' has already * overflowed 'data' and this allows us to correct for the off-by-one that * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' * value that's in-bounds). */ assert(((header_field_mark ? 1 : 0) + (header_value_mark ? 1 : 0) + (url_mark ? 1 : 0) + (body_mark ? 1 : 0)) <= 1); CALLBACK_DATA_NOADVANCE(header_field); CALLBACK_DATA_NOADVANCE(header_value); CALLBACK_DATA_NOADVANCE(url); CALLBACK_DATA_NOADVANCE(body); return len; error: if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { SET_ERRNO(HPE_UNKNOWN); } return (p - data); } /* Does the parser need to see an EOF to find the end of the message? */ int http_message_needs_eof (const http_parser *parser) { if (parser->type == HTTP_REQUEST) { return 0; } /* See RFC 2616 section 4.4 */ if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ parser->status_code == 204 || /* No Content */ parser->status_code == 304 || /* Not Modified */ parser->flags & F_SKIPBODY) { /* response to a HEAD request */ return 0; } if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { return 0; } return 1; } int http_should_keep_alive (const http_parser *parser) { if (parser->http_major > 0 && parser->http_minor > 0) { /* HTTP/1.1 */ if (parser->flags & F_CONNECTION_CLOSE) { return 0; } } else { /* HTTP/1.0 or earlier */ if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { return 0; } } return !http_message_needs_eof(parser); } const char * http_method_str (enum http_method m) { return ELEM_AT(method_strings, m, ""); } void http_parser_init (http_parser *parser, enum http_parser_type t) { void *data = parser->data; /* preserve application data */ memset(parser, 0, sizeof(*parser)); parser->data = data; parser->type = t; parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); parser->http_errno = HPE_OK; } const char * http_errno_name(enum http_errno err) { assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].name; } const char * http_errno_description(enum http_errno err) { assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].description; } static enum http_host_state http_parse_host_char(enum http_host_state s, const char ch) { switch(s) { case s_http_userinfo: case s_http_userinfo_start: if (ch == '@') { return s_http_host_start; } if (IS_USERINFO_CHAR(ch)) { return s_http_userinfo; } break; case s_http_host_start: if (ch == '[') { return s_http_host_v6_start; } if (IS_HOST_CHAR(ch)) { return s_http_host; } break; case s_http_host: if (IS_HOST_CHAR(ch)) { return s_http_host; } /* FALLTHROUGH */ case s_http_host_v6_end: if (ch == ':') { return s_http_host_port_start; } break; case s_http_host_v6: if (ch == ']') { return s_http_host_v6_end; } /* FALLTHROUGH */ case s_http_host_v6_start: if (IS_HEX(ch) || ch == ':' || ch == '.') { return s_http_host_v6; } break; case s_http_host_port: case s_http_host_port_start: if (IS_NUM(ch)) { return s_http_host_port; } break; default: break; } return s_http_host_dead; } static int http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { enum http_host_state s; const char *p; size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; u->field_data[UF_HOST].len = 0; s = found_at ? s_http_userinfo_start : s_http_host_start; for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { enum http_host_state new_s = http_parse_host_char(s, *p); if (new_s == s_http_host_dead) { return 1; } switch(new_s) { case s_http_host: if (s != s_http_host) { u->field_data[UF_HOST].off = p - buf; } u->field_data[UF_HOST].len++; break; case s_http_host_v6: if (s != s_http_host_v6) { u->field_data[UF_HOST].off = p - buf; } u->field_data[UF_HOST].len++; break; case s_http_host_port: if (s != s_http_host_port) { u->field_data[UF_PORT].off = p - buf; u->field_data[UF_PORT].len = 0; u->field_set |= (1 << UF_PORT); } u->field_data[UF_PORT].len++; break; case s_http_userinfo: if (s != s_http_userinfo) { u->field_data[UF_USERINFO].off = p - buf ; u->field_data[UF_USERINFO].len = 0; u->field_set |= (1 << UF_USERINFO); } u->field_data[UF_USERINFO].len++; break; default: break; } s = new_s; } /* Make sure we don't end somewhere unexpected */ switch (s) { case s_http_host_start: case s_http_host_v6_start: case s_http_host_v6: case s_http_host_port_start: case s_http_userinfo: case s_http_userinfo_start: return 1; default: break; } return 0; } int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u) { enum state s; const char *p; enum http_parser_url_fields uf, old_uf; int found_at = 0; u->port = u->field_set = 0; s = is_connect ? s_req_server_start : s_req_spaces_before_url; uf = old_uf = UF_MAX; for (p = buf; p < buf + buflen; p++) { s = parse_url_char(s, *p); /* Figure out the next field that we're operating on */ switch (s) { case s_dead: return 1; /* Skip delimeters */ case s_req_schema_slash: case s_req_schema_slash_slash: case s_req_server_start: case s_req_query_string_start: case s_req_fragment_start: continue; case s_req_schema: uf = UF_SCHEMA; break; case s_req_server_with_at: found_at = 1; /* FALLTROUGH */ case s_req_server: uf = UF_HOST; break; case s_req_path: uf = UF_PATH; break; case s_req_query_string: uf = UF_QUERY; break; case s_req_fragment: uf = UF_FRAGMENT; break; default: assert(!"Unexpected state"); return 1; } /* Nothing's changed; soldier on */ if (uf == old_uf) { u->field_data[uf].len++; continue; } u->field_data[uf].off = p - buf; u->field_data[uf].len = 1; u->field_set |= (1 << uf); old_uf = uf; } /* host must be present if there is a schema */ /* parsing http:///toto will fail */ if ((u->field_set & ((1 << UF_SCHEMA) | (1 << UF_HOST))) != 0) { if (http_parse_host(buf, u, found_at) != 0) { return 1; } } /* CONNECT requests can only contain "hostname:port" */ if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { return 1; } if (u->field_set & (1 << UF_PORT)) { /* Don't bother with endp; we've already validated the string */ unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); /* Ports have a max value of 2^16 */ if (v > 0xffff) { return 1; } u->port = (uint16_t) v; } return 0; } void http_parser_pause(http_parser *parser, int paused) { /* Users should only be pausing/unpausing a parser that is not in an error * state. In non-debug builds, there's not much that we can do about this * other than ignore it. */ if (HTTP_PARSER_ERRNO(parser) == HPE_OK || HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); } else { assert(0 && "Attempting to pause parser in error state"); } } int http_body_is_final(const struct http_parser *parser) { return parser->state == s_message_done; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/http_parser.gyp ================================================ # This file is used with the GYP meta build system. # http://code.google.com/p/gyp/ # To build try this: # svn co http://gyp.googlecode.com/svn/trunk gyp # ./gyp/gyp -f make --depth=`pwd` http_parser.gyp # ./out/Debug/test { 'target_defaults': { 'default_configuration': 'Debug', 'configurations': { # TODO: hoist these out and put them somewhere common, because # RuntimeLibrary MUST MATCH across the entire project 'Debug': { 'defines': [ 'DEBUG', '_DEBUG' ], 'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ], 'msvs_settings': { 'VCCLCompilerTool': { 'RuntimeLibrary': 1, # static debug }, }, }, 'Release': { 'defines': [ 'NDEBUG' ], 'cflags': [ '-Wall', '-Wextra', '-O3' ], 'msvs_settings': { 'VCCLCompilerTool': { 'RuntimeLibrary': 0, # static release }, }, } }, 'msvs_settings': { 'VCCLCompilerTool': { }, 'VCLibrarianTool': { }, 'VCLinkerTool': { 'GenerateDebugInformation': 'true', }, }, 'conditions': [ ['OS == "win"', { 'defines': [ 'WIN32' ], }] ], }, 'targets': [ { 'target_name': 'http_parser', 'type': 'static_library', 'include_dirs': [ '.' ], 'direct_dependent_settings': { 'defines': [ 'HTTP_PARSER_STRICT=0' ], 'include_dirs': [ '.' ], }, 'defines': [ 'HTTP_PARSER_STRICT=0' ], 'sources': [ './http_parser.c', ], 'conditions': [ ['OS=="win"', { 'msvs_settings': { 'VCCLCompilerTool': { # Compile as C++. http_parser.c is actually C99, but C++ is # close enough in this case. 'CompileAs': 2, }, }, }] ], }, { 'target_name': 'http_parser_strict', 'type': 'static_library', 'include_dirs': [ '.' ], 'direct_dependent_settings': { 'defines': [ 'HTTP_PARSER_STRICT=1' ], 'include_dirs': [ '.' ], }, 'defines': [ 'HTTP_PARSER_STRICT=1' ], 'sources': [ './http_parser.c', ], 'conditions': [ ['OS=="win"', { 'msvs_settings': { 'VCCLCompilerTool': { # Compile as C++. http_parser.c is actually C99, but C++ is # close enough in this case. 'CompileAs': 2, }, }, }] ], }, { 'target_name': 'test-nonstrict', 'type': 'executable', 'dependencies': [ 'http_parser' ], 'sources': [ 'test.c' ] }, { 'target_name': 'test-strict', 'type': 'executable', 'dependencies': [ 'http_parser_strict' ], 'sources': [ 'test.c' ] } ] } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/http_parser.h ================================================ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef http_parser_h #define http_parser_h #ifdef __cplusplus extern "C" { #endif #define HTTP_PARSER_VERSION_MAJOR 2 #define HTTP_PARSER_VERSION_MINOR 0 #include #if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600) #include #include typedef __int8 int8_t; typedef unsigned __int8 uint8_t; typedef __int16 int16_t; typedef unsigned __int16 uint16_t; typedef __int32 int32_t; typedef unsigned __int32 uint32_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #else #include #endif /* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run * faster */ #ifndef HTTP_PARSER_STRICT # define HTTP_PARSER_STRICT 1 #endif /* Maximium header size allowed */ #define HTTP_MAX_HEADER_SIZE (80*1024) typedef struct http_parser http_parser; typedef struct http_parser_settings http_parser_settings; /* Callbacks should return non-zero to indicate an error. The parser will * then halt execution. * * The one exception is on_headers_complete. In a HTTP_RESPONSE parser * returning '1' from on_headers_complete will tell the parser that it * should not expect a body. This is used when receiving a response to a * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: * chunked' headers that indicate the presence of a body. * * http_data_cb does not return data chunks. It will be call arbitrarally * many times for each string. E.G. you might get 10 callbacks for "on_url" * each providing just a few characters more data. */ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); typedef int (*http_cb) (http_parser*); /* Request Methods */ #define HTTP_METHOD_MAP(XX) \ XX(0, DELETE, DELETE) \ XX(1, GET, GET) \ XX(2, HEAD, HEAD) \ XX(3, POST, POST) \ XX(4, PUT, PUT) \ /* pathological */ \ XX(5, CONNECT, CONNECT) \ XX(6, OPTIONS, OPTIONS) \ XX(7, TRACE, TRACE) \ /* webdav */ \ XX(8, COPY, COPY) \ XX(9, LOCK, LOCK) \ XX(10, MKCOL, MKCOL) \ XX(11, MOVE, MOVE) \ XX(12, PROPFIND, PROPFIND) \ XX(13, PROPPATCH, PROPPATCH) \ XX(14, SEARCH, SEARCH) \ XX(15, UNLOCK, UNLOCK) \ /* subversion */ \ XX(16, REPORT, REPORT) \ XX(17, MKACTIVITY, MKACTIVITY) \ XX(18, CHECKOUT, CHECKOUT) \ XX(19, MERGE, MERGE) \ /* upnp */ \ XX(20, MSEARCH, M-SEARCH) \ XX(21, NOTIFY, NOTIFY) \ XX(22, SUBSCRIBE, SUBSCRIBE) \ XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \ /* RFC-5789 */ \ XX(24, PATCH, PATCH) \ XX(25, PURGE, PURGE) \ enum http_method { #define XX(num, name, string) HTTP_##name = num, HTTP_METHOD_MAP(XX) #undef XX }; enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; /* Flag values for http_parser.flags field */ enum flags { F_CHUNKED = 1 << 0 , F_CONNECTION_KEEP_ALIVE = 1 << 1 , F_CONNECTION_CLOSE = 1 << 2 , F_TRAILING = 1 << 3 , F_UPGRADE = 1 << 4 , F_SKIPBODY = 1 << 5 }; /* Map for errno-related constants * * The provided argument should be a macro that takes 2 arguments. */ #define HTTP_ERRNO_MAP(XX) \ /* No error */ \ XX(OK, "success") \ \ /* Callback-related errors */ \ XX(CB_message_begin, "the on_message_begin callback failed") \ XX(CB_status_complete, "the on_status_complete callback failed") \ XX(CB_url, "the on_url callback failed") \ XX(CB_header_field, "the on_header_field callback failed") \ XX(CB_header_value, "the on_header_value callback failed") \ XX(CB_headers_complete, "the on_headers_complete callback failed") \ XX(CB_body, "the on_body callback failed") \ XX(CB_message_complete, "the on_message_complete callback failed") \ \ /* Parsing-related errors */ \ XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ XX(HEADER_OVERFLOW, \ "too many header bytes seen; overflow detected") \ XX(CLOSED_CONNECTION, \ "data received after completed connection: close message") \ XX(INVALID_VERSION, "invalid HTTP version") \ XX(INVALID_STATUS, "invalid HTTP status code") \ XX(INVALID_METHOD, "invalid HTTP method") \ XX(INVALID_URL, "invalid URL") \ XX(INVALID_HOST, "invalid host") \ XX(INVALID_PORT, "invalid port") \ XX(INVALID_PATH, "invalid path") \ XX(INVALID_QUERY_STRING, "invalid query string") \ XX(INVALID_FRAGMENT, "invalid fragment") \ XX(LF_EXPECTED, "LF character expected") \ XX(INVALID_HEADER_TOKEN, "invalid character in header") \ XX(INVALID_CONTENT_LENGTH, \ "invalid character in content-length header") \ XX(INVALID_CHUNK_SIZE, \ "invalid character in chunk size header") \ XX(INVALID_CONSTANT, "invalid constant string") \ XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ XX(STRICT, "strict mode assertion failed") \ XX(PAUSED, "parser is paused") \ XX(UNKNOWN, "an unknown error occurred") /* Define HPE_* values for each errno value above */ #define HTTP_ERRNO_GEN(n, s) HPE_##n, enum http_errno { HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) }; #undef HTTP_ERRNO_GEN /* Get an http_errno value from an http_parser */ #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) struct http_parser { /** PRIVATE **/ unsigned char type : 2; /* enum http_parser_type */ unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */ unsigned char state; /* enum state from http_parser.c */ unsigned char header_state; /* enum header_state from http_parser.c */ unsigned char index; /* index into current matcher */ uint32_t nread; /* # bytes read in various scenarios */ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ /** READ-ONLY **/ unsigned short http_major; unsigned short http_minor; unsigned short status_code; /* responses only */ unsigned char method; /* requests only */ unsigned char http_errno : 7; /* 1 = Upgrade header was present and the parser has exited because of that. * 0 = No upgrade header present. * Should be checked when http_parser_execute() returns in addition to * error checking. */ unsigned char upgrade : 1; /** PUBLIC **/ void *data; /* A pointer to get hook to the "connection" or "socket" object */ }; struct http_parser_settings { http_cb on_message_begin; http_data_cb on_url; http_cb on_status_complete; http_data_cb on_header_field; http_data_cb on_header_value; http_cb on_headers_complete; http_data_cb on_body; http_cb on_message_complete; }; enum http_parser_url_fields { UF_SCHEMA = 0 , UF_HOST = 1 , UF_PORT = 2 , UF_PATH = 3 , UF_QUERY = 4 , UF_FRAGMENT = 5 , UF_USERINFO = 6 , UF_MAX = 7 }; /* Result structure for http_parser_parse_url(). * * Callers should index into field_data[] with UF_* values iff field_set * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and * because we probably have padding left over), we convert any port to * a uint16_t. */ struct http_parser_url { uint16_t field_set; /* Bitmask of (1 << UF_*) values */ uint16_t port; /* Converted UF_PORT string */ struct { uint16_t off; /* Offset into buffer in which field starts */ uint16_t len; /* Length of run in buffer */ } field_data[UF_MAX]; }; void http_parser_init(http_parser *parser, enum http_parser_type type); size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, const char *data, size_t len); /* If http_should_keep_alive() in the on_headers_complete or * on_message_complete callback returns 0, then this should be * the last message on the connection. * If you are the server, respond with the "Connection: close" header. * If you are the client, close the connection. */ int http_should_keep_alive(const http_parser *parser); /* Returns a string version of the HTTP method. */ const char *http_method_str(enum http_method m); /* Return a string name of the given error */ const char *http_errno_name(enum http_errno err); /* Return a string description of the given error */ const char *http_errno_description(enum http_errno err); /* Parse a URL; return nonzero on failure */ int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u); /* Pause or un-pause the parser; a nonzero value pauses */ void http_parser_pause(http_parser *parser, int paused); /* Checks if this is the final chunk of the body. */ int http_body_is_final(const http_parser *parser); #ifdef __cplusplus } #endif #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/http-parser/test.c ================================================ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include "http_parser.h" #include #include #include #include /* rand */ #include #include #undef TRUE #define TRUE 1 #undef FALSE #define FALSE 0 #define MAX_HEADERS 13 #define MAX_ELEMENT_SIZE 2048 #define MIN(a,b) ((a) < (b) ? (a) : (b)) static http_parser *parser; struct message { const char *name; // for debugging purposes const char *raw; enum http_parser_type type; enum http_method method; int status_code; char request_path[MAX_ELEMENT_SIZE]; char request_url[MAX_ELEMENT_SIZE]; char fragment[MAX_ELEMENT_SIZE]; char query_string[MAX_ELEMENT_SIZE]; char body[MAX_ELEMENT_SIZE]; size_t body_size; const char *host; const char *userinfo; uint16_t port; int num_headers; enum { NONE=0, FIELD, VALUE } last_header_element; char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE]; int should_keep_alive; const char *upgrade; // upgraded body unsigned short http_major; unsigned short http_minor; int message_begin_cb_called; int headers_complete_cb_called; int message_complete_cb_called; int message_complete_on_eof; int body_is_final; }; static int currently_parsing_eof; static struct message messages[5]; static int num_messages; static http_parser_settings *current_pause_parser; /* * R E Q U E S T S * */ const struct message requests[] = #define CURL_GET 0 { {.name= "curl get" ,.type= HTTP_REQUEST ,.raw= "GET /test HTTP/1.1\r\n" "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n" "Host: 0.0.0.0=5000\r\n" "Accept: */*\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 3 ,.headers= { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" } , { "Host", "0.0.0.0=5000" } , { "Accept", "*/*" } } ,.body= "" } #define FIREFOX_GET 1 , {.name= "firefox get" ,.type= HTTP_REQUEST ,.raw= "GET /favicon.ico HTTP/1.1\r\n" "Host: 0.0.0.0=5000\r\n" "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n" "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" "Accept-Language: en-us,en;q=0.5\r\n" "Accept-Encoding: gzip,deflate\r\n" "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" "Keep-Alive: 300\r\n" "Connection: keep-alive\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/favicon.ico" ,.request_url= "/favicon.ico" ,.num_headers= 8 ,.headers= { { "Host", "0.0.0.0=5000" } , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" } , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" } , { "Accept-Language", "en-us,en;q=0.5" } , { "Accept-Encoding", "gzip,deflate" } , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" } , { "Keep-Alive", "300" } , { "Connection", "keep-alive" } } ,.body= "" } #define DUMBFUCK 2 , {.name= "dumbfuck" ,.type= HTTP_REQUEST ,.raw= "GET /dumbfuck HTTP/1.1\r\n" "aaaaaaaaaaaaa:++++++++++\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/dumbfuck" ,.request_url= "/dumbfuck" ,.num_headers= 1 ,.headers= { { "aaaaaaaaaaaaa", "++++++++++" } } ,.body= "" } #define FRAGMENT_IN_URI 3 , {.name= "fragment in url" ,.type= HTTP_REQUEST ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "page=1" ,.fragment= "posts-17408" ,.request_path= "/forums/1/topics/2375" /* XXX request url does include fragment? */ ,.request_url= "/forums/1/topics/2375?page=1#posts-17408" ,.num_headers= 0 ,.body= "" } #define GET_NO_HEADERS_NO_BODY 4 , {.name= "get no headers no body" ,.type= HTTP_REQUEST ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE /* would need Connection: close */ ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/get_no_headers_no_body/world" ,.request_url= "/get_no_headers_no_body/world" ,.num_headers= 0 ,.body= "" } #define GET_ONE_HEADER_NO_BODY 5 , {.name= "get one header no body" ,.type= HTTP_REQUEST ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n" "Accept: */*\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE /* would need Connection: close */ ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/get_one_header_no_body" ,.request_url= "/get_one_header_no_body" ,.num_headers= 1 ,.headers= { { "Accept" , "*/*" } } ,.body= "" } #define GET_FUNKY_CONTENT_LENGTH 6 , {.name= "get funky content length body hello" ,.type= HTTP_REQUEST ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n" "conTENT-Length: 5\r\n" "\r\n" "HELLO" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/get_funky_content_length_body_hello" ,.request_url= "/get_funky_content_length_body_hello" ,.num_headers= 1 ,.headers= { { "conTENT-Length" , "5" } } ,.body= "HELLO" } #define POST_IDENTITY_BODY_WORLD 7 , {.name= "post identity body world" ,.type= HTTP_REQUEST ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n" "Accept: */*\r\n" "Transfer-Encoding: identity\r\n" "Content-Length: 5\r\n" "\r\n" "World" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST ,.query_string= "q=search" ,.fragment= "hey" ,.request_path= "/post_identity_body_world" ,.request_url= "/post_identity_body_world?q=search#hey" ,.num_headers= 3 ,.headers= { { "Accept", "*/*" } , { "Transfer-Encoding", "identity" } , { "Content-Length", "5" } } ,.body= "World" } #define POST_CHUNKED_ALL_YOUR_BASE 8 , {.name= "post - chunked body: all your base are belong to us" ,.type= HTTP_REQUEST ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" "1e\r\nall your base are belong to us\r\n" "0\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST ,.query_string= "" ,.fragment= "" ,.request_path= "/post_chunked_all_your_base" ,.request_url= "/post_chunked_all_your_base" ,.num_headers= 1 ,.headers= { { "Transfer-Encoding" , "chunked" } } ,.body= "all your base are belong to us" } #define TWO_CHUNKS_MULT_ZERO_END 9 , {.name= "two chunks ; triple zero ending" ,.type= HTTP_REQUEST ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" "5\r\nhello\r\n" "6\r\n world\r\n" "000\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST ,.query_string= "" ,.fragment= "" ,.request_path= "/two_chunks_mult_zero_end" ,.request_url= "/two_chunks_mult_zero_end" ,.num_headers= 1 ,.headers= { { "Transfer-Encoding", "chunked" } } ,.body= "hello world" } #define CHUNKED_W_TRAILING_HEADERS 10 , {.name= "chunked with trailing headers. blech." ,.type= HTTP_REQUEST ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" "5\r\nhello\r\n" "6\r\n world\r\n" "0\r\n" "Vary: *\r\n" "Content-Type: text/plain\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST ,.query_string= "" ,.fragment= "" ,.request_path= "/chunked_w_trailing_headers" ,.request_url= "/chunked_w_trailing_headers" ,.num_headers= 3 ,.headers= { { "Transfer-Encoding", "chunked" } , { "Vary", "*" } , { "Content-Type", "text/plain" } } ,.body= "hello world" } #define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11 , {.name= "with bullshit after the length" ,.type= HTTP_REQUEST ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n" "6; blahblah; blah\r\n world\r\n" "0\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST ,.query_string= "" ,.fragment= "" ,.request_path= "/chunked_w_bullshit_after_length" ,.request_url= "/chunked_w_bullshit_after_length" ,.num_headers= 1 ,.headers= { { "Transfer-Encoding", "chunked" } } ,.body= "hello world" } #define WITH_QUOTES 12 , {.name= "with quotes" ,.type= HTTP_REQUEST ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "foo=\"bar\"" ,.fragment= "" ,.request_path= "/with_\"stupid\"_quotes" ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\"" ,.num_headers= 0 ,.headers= { } ,.body= "" } #define APACHEBENCH_GET 13 /* The server receiving this request SHOULD NOT wait for EOF * to know that content-length == 0. * How to represent this in a unit test? message_complete_on_eof * Compare with NO_CONTENT_LENGTH_RESPONSE. */ , {.name = "apachebench get" ,.type= HTTP_REQUEST ,.raw= "GET /test HTTP/1.0\r\n" "Host: 0.0.0.0:5000\r\n" "User-Agent: ApacheBench/2.3\r\n" "Accept: */*\r\n\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 3 ,.headers= { { "Host", "0.0.0.0:5000" } , { "User-Agent", "ApacheBench/2.3" } , { "Accept", "*/*" } } ,.body= "" } #define QUERY_URL_WITH_QUESTION_MARK_GET 14 /* Some clients include '?' characters in query strings. */ , {.name = "query url with question mark" ,.type= HTTP_REQUEST ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "foo=bar?baz" ,.fragment= "" ,.request_path= "/test.cgi" ,.request_url= "/test.cgi?foo=bar?baz" ,.num_headers= 0 ,.headers= {} ,.body= "" } #define PREFIX_NEWLINE_GET 15 /* Some clients, especially after a POST in a keep-alive connection, * will send an extra CRLF before the next request */ , {.name = "newline prefix get" ,.type= HTTP_REQUEST ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 0 ,.headers= { } ,.body= "" } #define UPGRADE_REQUEST 16 , {.name = "upgrade request" ,.type= HTTP_REQUEST ,.raw= "GET /demo HTTP/1.1\r\n" "Host: example.com\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" "Sec-WebSocket-Protocol: sample\r\n" "Upgrade: WebSocket\r\n" "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" "Origin: http://example.com\r\n" "\r\n" "Hot diggity dogg" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/demo" ,.request_url= "/demo" ,.num_headers= 7 ,.upgrade="Hot diggity dogg" ,.headers= { { "Host", "example.com" } , { "Connection", "Upgrade" } , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" } , { "Sec-WebSocket-Protocol", "sample" } , { "Upgrade", "WebSocket" } , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" } , { "Origin", "http://example.com" } } ,.body= "" } #define CONNECT_REQUEST 17 , {.name = "connect request" ,.type= HTTP_REQUEST ,.raw= "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\n" "User-agent: Mozilla/1.1N\r\n" "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" "\r\n" "some data\r\n" "and yet even more data" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_CONNECT ,.query_string= "" ,.fragment= "" ,.request_path= "" ,.request_url= "0-home0.netscape.com:443" ,.num_headers= 2 ,.upgrade="some data\r\nand yet even more data" ,.headers= { { "User-agent", "Mozilla/1.1N" } , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } } ,.body= "" } #define REPORT_REQ 18 , {.name= "report request" ,.type= HTTP_REQUEST ,.raw= "REPORT /test HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_REPORT ,.query_string= "" ,.fragment= "" ,.request_path= "/test" ,.request_url= "/test" ,.num_headers= 0 ,.headers= {} ,.body= "" } #define NO_HTTP_VERSION 19 , {.name= "request with no http version" ,.type= HTTP_REQUEST ,.raw= "GET /\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 0 ,.http_minor= 9 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/" ,.request_url= "/" ,.num_headers= 0 ,.headers= {} ,.body= "" } #define MSEARCH_REQ 20 , {.name= "m-search request" ,.type= HTTP_REQUEST ,.raw= "M-SEARCH * HTTP/1.1\r\n" "HOST: 239.255.255.250:1900\r\n" "MAN: \"ssdp:discover\"\r\n" "ST: \"ssdp:all\"\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_MSEARCH ,.query_string= "" ,.fragment= "" ,.request_path= "*" ,.request_url= "*" ,.num_headers= 3 ,.headers= { { "HOST", "239.255.255.250:1900" } , { "MAN", "\"ssdp:discover\"" } , { "ST", "\"ssdp:all\"" } } ,.body= "" } #define LINE_FOLDING_IN_HEADER 21 , {.name= "line folding in header value" ,.type= HTTP_REQUEST ,.raw= "GET / HTTP/1.1\r\n" "Line1: abc\r\n" "\tdef\r\n" " ghi\r\n" "\t\tjkl\r\n" " mno \r\n" "\t \tqrs\r\n" "Line2: \t line2\t\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "/" ,.request_url= "/" ,.num_headers= 2 ,.headers= { { "Line1", "abcdefghijklmno qrs" } , { "Line2", "line2\t" } } ,.body= "" } #define QUERY_TERMINATED_HOST 22 , {.name= "host terminated by a query string" ,.type= HTTP_REQUEST ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "hail=all" ,.fragment= "" ,.request_path= "" ,.request_url= "http://hypnotoad.org?hail=all" ,.host= "hypnotoad.org" ,.num_headers= 0 ,.headers= { } ,.body= "" } #define QUERY_TERMINATED_HOSTPORT 23 , {.name= "host:port terminated by a query string" ,.type= HTTP_REQUEST ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "hail=all" ,.fragment= "" ,.request_path= "" ,.request_url= "http://hypnotoad.org:1234?hail=all" ,.host= "hypnotoad.org" ,.port= 1234 ,.num_headers= 0 ,.headers= { } ,.body= "" } #define SPACE_TERMINATED_HOSTPORT 24 , {.name= "host:port terminated by a space" ,.type= HTTP_REQUEST ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "" ,.fragment= "" ,.request_path= "" ,.request_url= "http://hypnotoad.org:1234" ,.host= "hypnotoad.org" ,.port= 1234 ,.num_headers= 0 ,.headers= { } ,.body= "" } #define PATCH_REQ 25 , {.name = "PATCH request" ,.type= HTTP_REQUEST ,.raw= "PATCH /file.txt HTTP/1.1\r\n" "Host: www.example.com\r\n" "Content-Type: application/example\r\n" "If-Match: \"e0023aa4e\"\r\n" "Content-Length: 10\r\n" "\r\n" "cccccccccc" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_PATCH ,.query_string= "" ,.fragment= "" ,.request_path= "/file.txt" ,.request_url= "/file.txt" ,.num_headers= 4 ,.headers= { { "Host", "www.example.com" } , { "Content-Type", "application/example" } , { "If-Match", "\"e0023aa4e\"" } , { "Content-Length", "10" } } ,.body= "cccccccccc" } #define CONNECT_CAPS_REQUEST 26 , {.name = "connect caps request" ,.type= HTTP_REQUEST ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" "User-agent: Mozilla/1.1N\r\n" "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_CONNECT ,.query_string= "" ,.fragment= "" ,.request_path= "" ,.request_url= "HOME0.NETSCAPE.COM:443" ,.num_headers= 2 ,.upgrade="" ,.headers= { { "User-agent", "Mozilla/1.1N" } , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } } ,.body= "" } #if !HTTP_PARSER_STRICT #define UTF8_PATH_REQ 27 , {.name= "utf-8 path request" ,.type= HTTP_REQUEST ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n" "Host: github.com\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.query_string= "q=1" ,.fragment= "narf" ,.request_path= "/δ¶/δt/pope" ,.request_url= "/δ¶/δt/pope?q=1#narf" ,.num_headers= 1 ,.headers= { {"Host", "github.com" } } ,.body= "" } #define HOSTNAME_UNDERSCORE 28 , {.name = "hostname underscore" ,.type= HTTP_REQUEST ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n" "User-agent: Mozilla/1.1N\r\n" "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_CONNECT ,.query_string= "" ,.fragment= "" ,.request_path= "" ,.request_url= "home_0.netscape.com:443" ,.num_headers= 2 ,.upgrade="" ,.headers= { { "User-agent", "Mozilla/1.1N" } , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" } } ,.body= "" } #endif /* !HTTP_PARSER_STRICT */ /* see https://github.com/ry/http-parser/issues/47 */ #define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29 , {.name = "eat CRLF between requests, no \"Connection: close\" header" ,.raw= "POST / HTTP/1.1\r\n" "Host: www.example.com\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: 4\r\n" "\r\n" "q=42\r\n" /* note the trailing CRLF */ ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST ,.query_string= "" ,.fragment= "" ,.request_path= "/" ,.request_url= "/" ,.num_headers= 3 ,.upgrade= 0 ,.headers= { { "Host", "www.example.com" } , { "Content-Type", "application/x-www-form-urlencoded" } , { "Content-Length", "4" } } ,.body= "q=42" } /* see https://github.com/ry/http-parser/issues/47 */ #define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30 , {.name = "eat CRLF between requests even if \"Connection: close\" is set" ,.raw= "POST / HTTP/1.1\r\n" "Host: www.example.com\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: 4\r\n" "Connection: close\r\n" "\r\n" "q=42\r\n" /* note the trailing CRLF */ ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE /* input buffer isn't empty when on_message_complete is called */ ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST ,.query_string= "" ,.fragment= "" ,.request_path= "/" ,.request_url= "/" ,.num_headers= 4 ,.upgrade= 0 ,.headers= { { "Host", "www.example.com" } , { "Content-Type", "application/x-www-form-urlencoded" } , { "Content-Length", "4" } , { "Connection", "close" } } ,.body= "q=42" } #define PURGE_REQ 31 , {.name = "PURGE request" ,.type= HTTP_REQUEST ,.raw= "PURGE /file.txt HTTP/1.1\r\n" "Host: www.example.com\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_PURGE ,.query_string= "" ,.fragment= "" ,.request_path= "/file.txt" ,.request_url= "/file.txt" ,.num_headers= 1 ,.headers= { { "Host", "www.example.com" } } ,.body= "" } #define SEARCH_REQ 32 , {.name = "SEARCH request" ,.type= HTTP_REQUEST ,.raw= "SEARCH / HTTP/1.1\r\n" "Host: www.example.com\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_SEARCH ,.query_string= "" ,.fragment= "" ,.request_path= "/" ,.request_url= "/" ,.num_headers= 1 ,.headers= { { "Host", "www.example.com" } } ,.body= "" } #define PROXY_WITH_BASIC_AUTH 33 , {.name= "host:port and basic_auth" ,.type= HTTP_REQUEST ,.raw= "GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET ,.fragment= "" ,.request_path= "/toto" ,.request_url= "http://a%12:b!&*$@hypnotoad.org:1234/toto" ,.host= "hypnotoad.org" ,.userinfo= "a%12:b!&*$" ,.port= 1234 ,.num_headers= 0 ,.headers= { } ,.body= "" } , {.name= NULL } /* sentinel */ }; /* * R E S P O N S E S * */ const struct message responses[] = #define GOOGLE_301 0 { {.name= "google 301" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 301 Moved Permanently\r\n" "Location: http://www.google.com/\r\n" "Content-Type: text/html; charset=UTF-8\r\n" "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n" "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n" "X-$PrototypeBI-Version: 1.6.0.3\r\n" /* $ char in header field */ "Cache-Control: public, max-age=2592000\r\n" "Server: gws\r\n" "Content-Length: 219 \r\n" "\r\n" "\n" "301 Moved\n" "

301 Moved

\n" "The document has moved\n" "here.\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 301 ,.num_headers= 8 ,.headers= { { "Location", "http://www.google.com/" } , { "Content-Type", "text/html; charset=UTF-8" } , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" } , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" } , { "X-$PrototypeBI-Version", "1.6.0.3" } , { "Cache-Control", "public, max-age=2592000" } , { "Server", "gws" } , { "Content-Length", "219 " } } ,.body= "\n" "301 Moved\n" "

301 Moved

\n" "The document has moved\n" "here.\r\n" "\r\n" } #define NO_CONTENT_LENGTH_RESPONSE 1 /* The client should wait for the server's EOF. That is, when content-length * is not specified, and "Connection: close", the end of body is specified * by the EOF. * Compare with APACHEBENCH_GET */ , {.name= "no content-length response" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n" "Server: Apache\r\n" "X-Powered-By: Servlet/2.5 JSP/2.1\r\n" "Content-Type: text/xml; charset=utf-8\r\n" "Connection: close\r\n" "\r\n" "\n" "\n" " \n" " \n" " SOAP-ENV:Client\n" " Client Error\n" " \n" " \n" "" ,.should_keep_alive= FALSE ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 5 ,.headers= { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" } , { "Server", "Apache" } , { "X-Powered-By", "Servlet/2.5 JSP/2.1" } , { "Content-Type", "text/xml; charset=utf-8" } , { "Connection", "close" } } ,.body= "\n" "\n" " \n" " \n" " SOAP-ENV:Client\n" " Client Error\n" " \n" " \n" "" } #define NO_HEADERS_NO_BODY_404 2 , {.name= "404 no headers no body" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 404 ,.num_headers= 0 ,.headers= {} ,.body_size= 0 ,.body= "" } #define NO_REASON_PHRASE 3 , {.name= "301 no response phrase" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 301\r\n\r\n" ,.should_keep_alive = FALSE ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 301 ,.num_headers= 0 ,.headers= {} ,.body= "" } #define TRAILING_SPACE_ON_CHUNKED_BODY 4 , {.name="200 trailing space on chunked body" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" "25 \r\n" "This is the data in the first chunk\r\n" "\r\n" "1C\r\n" "and this is the second one\r\n" "\r\n" "0 \r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 2 ,.headers= { {"Content-Type", "text/plain" } , {"Transfer-Encoding", "chunked" } } ,.body_size = 37+28 ,.body = "This is the data in the first chunk\r\n" "and this is the second one\r\n" } #define NO_CARRIAGE_RET 5 , {.name="no carriage ret" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\n" "Content-Type: text/html; charset=utf-8\n" "Connection: close\n" "\n" "these headers are from http://news.ycombinator.com/" ,.should_keep_alive= FALSE ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 2 ,.headers= { {"Content-Type", "text/html; charset=utf-8" } , {"Connection", "close" } } ,.body= "these headers are from http://news.ycombinator.com/" } #define PROXY_CONNECTION 6 , {.name="proxy connection" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Content-Type: text/html; charset=UTF-8\r\n" "Content-Length: 11\r\n" "Proxy-Connection: close\r\n" "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n" "\r\n" "hello world" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 4 ,.headers= { {"Content-Type", "text/html; charset=UTF-8" } , {"Content-Length", "11" } , {"Proxy-Connection", "close" } , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"} } ,.body= "hello world" } #define UNDERSTORE_HEADER_KEY 7 // shown by // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;" , {.name="underscore header key" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Server: DCLK-AdSvr\r\n" "Content-Type: text/xml\r\n" "Content-Length: 0\r\n" "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 4 ,.headers= { {"Server", "DCLK-AdSvr" } , {"Content-Type", "text/xml" } , {"Content-Length", "0" } , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" } } ,.body= "" } #define BONJOUR_MADAME_FR 8 /* The client should not merge two headers fields when the first one doesn't * have a value. */ , {.name= "bonjourmadame.fr" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.0 301 Moved Permanently\r\n" "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n" "Server: Apache/2.2.3 (Red Hat)\r\n" "Cache-Control: public\r\n" "Pragma: \r\n" "Location: http://www.bonjourmadame.fr/\r\n" "Vary: Accept-Encoding\r\n" "Content-Length: 0\r\n" "Content-Type: text/html; charset=UTF-8\r\n" "Connection: keep-alive\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.status_code= 301 ,.num_headers= 9 ,.headers= { { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" } , { "Server", "Apache/2.2.3 (Red Hat)" } , { "Cache-Control", "public" } , { "Pragma", "" } , { "Location", "http://www.bonjourmadame.fr/" } , { "Vary", "Accept-Encoding" } , { "Content-Length", "0" } , { "Content-Type", "text/html; charset=UTF-8" } , { "Connection", "keep-alive" } } ,.body= "" } #define RES_FIELD_UNDERSCORE 9 /* Should handle spaces in header fields */ , {.name= "field underscore" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n" "Server: Apache\r\n" "Cache-Control: no-cache, must-revalidate\r\n" "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n" "Vary: Accept-Encoding\r\n" "_eep-Alive: timeout=45\r\n" /* semantic value ignored */ "_onnection: Keep-Alive\r\n" /* semantic value ignored */ "Transfer-Encoding: chunked\r\n" "Content-Type: text/html\r\n" "Connection: close\r\n" "\r\n" "0\r\n\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 11 ,.headers= { { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" } , { "Server", "Apache" } , { "Cache-Control", "no-cache, must-revalidate" } , { "Expires", "Mon, 26 Jul 1997 05:00:00 GMT" } , { ".et-Cookie", "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" } , { "Vary", "Accept-Encoding" } , { "_eep-Alive", "timeout=45" } , { "_onnection", "Keep-Alive" } , { "Transfer-Encoding", "chunked" } , { "Content-Type", "text/html" } , { "Connection", "close" } } ,.body= "" } #define NON_ASCII_IN_STATUS_LINE 10 /* Should handle non-ASCII in status line */ , {.name= "non-ASCII in status line" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n" "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n" "Content-Length: 0\r\n" "Connection: close\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 500 ,.num_headers= 3 ,.headers= { { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" } , { "Content-Length", "0" } , { "Connection", "close" } } ,.body= "" } #define HTTP_VERSION_0_9 11 /* Should handle HTTP/0.9 */ , {.name= "http version 0.9" ,.type= HTTP_RESPONSE ,.raw= "HTTP/0.9 200 OK\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= TRUE ,.http_major= 0 ,.http_minor= 9 ,.status_code= 200 ,.num_headers= 0 ,.headers= {} ,.body= "" } #define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12 /* The client should wait for the server's EOF. That is, when neither * content-length nor transfer-encoding is specified, the end of body * is specified by the EOF. */ , {.name= "neither content-length nor transfer-encoding response" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "\r\n" "hello world" ,.should_keep_alive= FALSE ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 1 ,.headers= { { "Content-Type", "text/plain" } } ,.body= "hello world" } #define NO_BODY_HTTP10_KA_200 13 , {.name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.0 200 OK\r\n" "Connection: keep-alive\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 0 ,.status_code= 200 ,.num_headers= 1 ,.headers= { { "Connection", "keep-alive" } } ,.body_size= 0 ,.body= "" } #define NO_BODY_HTTP10_KA_204 14 , {.name= "HTTP/1.0 with keep-alive and a 204 status" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.0 204 No content\r\n" "Connection: keep-alive\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.status_code= 204 ,.num_headers= 1 ,.headers= { { "Connection", "keep-alive" } } ,.body_size= 0 ,.body= "" } #define NO_BODY_HTTP11_KA_200 15 , {.name= "HTTP/1.1 with an EOF-terminated 200 status" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 0 ,.headers={} ,.body_size= 0 ,.body= "" } #define NO_BODY_HTTP11_KA_204 16 , {.name= "HTTP/1.1 with a 204 status" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 204 No content\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 204 ,.num_headers= 0 ,.headers={} ,.body_size= 0 ,.body= "" } #define NO_BODY_HTTP11_NOKA_204 17 , {.name= "HTTP/1.1 with a 204 status and keep-alive disabled" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 204 No content\r\n" "Connection: close\r\n" "\r\n" ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 204 ,.num_headers= 1 ,.headers= { { "Connection", "close" } } ,.body_size= 0 ,.body= "" } #define NO_BODY_HTTP11_KA_CHUNKED_200 18 , {.name= "HTTP/1.1 with chunked endocing and a 200 response" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Transfer-Encoding: chunked\r\n" "\r\n" "0\r\n" "\r\n" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 1 ,.headers= { { "Transfer-Encoding", "chunked" } } ,.body_size= 0 ,.body= "" } #if !HTTP_PARSER_STRICT #define SPACE_IN_FIELD_RES 19 /* Should handle spaces in header fields */ , {.name= "field space" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 200 OK\r\n" "Server: Microsoft-IIS/6.0\r\n" "X-Powered-By: ASP.NET\r\n" "en-US Content-Type: text/xml\r\n" /* this is the problem */ "Content-Type: text/xml\r\n" "Content-Length: 16\r\n" "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" "Connection: keep-alive\r\n" "\r\n" "hello" /* fake body */ ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 ,.num_headers= 7 ,.headers= { { "Server", "Microsoft-IIS/6.0" } , { "X-Powered-By", "ASP.NET" } , { "en-US Content-Type", "text/xml" } , { "Content-Type", "text/xml" } , { "Content-Length", "16" } , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" } , { "Connection", "keep-alive" } } ,.body= "hello" } #endif /* !HTTP_PARSER_STRICT */ , {.name= NULL } /* sentinel */ }; /* strnlen() is a POSIX.2008 addition. Can't rely on it being available so * define it ourselves. */ size_t strnlen(const char *s, size_t maxlen) { const char *p; p = memchr(s, '\0', maxlen); if (p == NULL) return maxlen; return p - s; } size_t strlncat(char *dst, size_t len, const char *src, size_t n) { size_t slen; size_t dlen; size_t rlen; size_t ncpy; slen = strnlen(src, n); dlen = strnlen(dst, len); if (dlen < len) { rlen = len - dlen; ncpy = slen < rlen ? slen : (rlen - 1); memcpy(dst + dlen, src, ncpy); dst[dlen + ncpy] = '\0'; } assert(len > slen + dlen); return slen + dlen; } size_t strlcat(char *dst, const char *src, size_t len) { return strlncat(dst, len, src, (size_t) -1); } size_t strlncpy(char *dst, size_t len, const char *src, size_t n) { size_t slen; size_t ncpy; slen = strnlen(src, n); if (len > 0) { ncpy = slen < len ? slen : (len - 1); memcpy(dst, src, ncpy); dst[ncpy] = '\0'; } assert(len > slen); return slen; } size_t strlcpy(char *dst, const char *src, size_t len) { return strlncpy(dst, len, src, (size_t) -1); } int request_url_cb (http_parser *p, const char *buf, size_t len) { assert(p == parser); strlncat(messages[num_messages].request_url, sizeof(messages[num_messages].request_url), buf, len); return 0; } int status_complete_cb (http_parser *p) { assert(p == parser); p->data++; return 0; } int header_field_cb (http_parser *p, const char *buf, size_t len) { assert(p == parser); struct message *m = &messages[num_messages]; if (m->last_header_element != FIELD) m->num_headers++; strlncat(m->headers[m->num_headers-1][0], sizeof(m->headers[m->num_headers-1][0]), buf, len); m->last_header_element = FIELD; return 0; } int header_value_cb (http_parser *p, const char *buf, size_t len) { assert(p == parser); struct message *m = &messages[num_messages]; strlncat(m->headers[m->num_headers-1][1], sizeof(m->headers[m->num_headers-1][1]), buf, len); m->last_header_element = VALUE; return 0; } void check_body_is_final (const http_parser *p) { if (messages[num_messages].body_is_final) { fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 " "on last on_body callback call " "but it doesn't! ***\n\n"); assert(0); abort(); } messages[num_messages].body_is_final = http_body_is_final(p); } int body_cb (http_parser *p, const char *buf, size_t len) { assert(p == parser); strlncat(messages[num_messages].body, sizeof(messages[num_messages].body), buf, len); messages[num_messages].body_size += len; check_body_is_final(p); // printf("body_cb: '%s'\n", requests[num_messages].body); return 0; } int count_body_cb (http_parser *p, const char *buf, size_t len) { assert(p == parser); assert(buf); messages[num_messages].body_size += len; check_body_is_final(p); return 0; } int message_begin_cb (http_parser *p) { assert(p == parser); messages[num_messages].message_begin_cb_called = TRUE; return 0; } int headers_complete_cb (http_parser *p) { assert(p == parser); messages[num_messages].method = parser->method; messages[num_messages].status_code = parser->status_code; messages[num_messages].http_major = parser->http_major; messages[num_messages].http_minor = parser->http_minor; messages[num_messages].headers_complete_cb_called = TRUE; messages[num_messages].should_keep_alive = http_should_keep_alive(parser); return 0; } int message_complete_cb (http_parser *p) { assert(p == parser); if (messages[num_messages].should_keep_alive != http_should_keep_alive(parser)) { fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same " "value in both on_message_complete and on_headers_complete " "but it doesn't! ***\n\n"); assert(0); abort(); } if (messages[num_messages].body_size && http_body_is_final(p) && !messages[num_messages].body_is_final) { fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 " "on last on_body callback call " "but it doesn't! ***\n\n"); assert(0); abort(); } messages[num_messages].message_complete_cb_called = TRUE; messages[num_messages].message_complete_on_eof = currently_parsing_eof; num_messages++; return 0; } /* These dontcall_* callbacks exist so that we can verify that when we're * paused, no additional callbacks are invoked */ int dontcall_message_begin_cb (http_parser *p) { if (p) { } // gcc fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n"); abort(); } int dontcall_header_field_cb (http_parser *p, const char *buf, size_t len) { if (p || buf || len) { } // gcc fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n"); abort(); } int dontcall_header_value_cb (http_parser *p, const char *buf, size_t len) { if (p || buf || len) { } // gcc fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n"); abort(); } int dontcall_request_url_cb (http_parser *p, const char *buf, size_t len) { if (p || buf || len) { } // gcc fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n"); abort(); } int dontcall_body_cb (http_parser *p, const char *buf, size_t len) { if (p || buf || len) { } // gcc fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n"); abort(); } int dontcall_headers_complete_cb (http_parser *p) { if (p) { } // gcc fprintf(stderr, "\n\n*** on_headers_complete() called on paused " "parser ***\n\n"); abort(); } int dontcall_message_complete_cb (http_parser *p) { if (p) { } // gcc fprintf(stderr, "\n\n*** on_message_complete() called on paused " "parser ***\n\n"); abort(); } static http_parser_settings settings_dontcall = {.on_message_begin = dontcall_message_begin_cb ,.on_header_field = dontcall_header_field_cb ,.on_header_value = dontcall_header_value_cb ,.on_url = dontcall_request_url_cb ,.on_body = dontcall_body_cb ,.on_headers_complete = dontcall_headers_complete_cb ,.on_message_complete = dontcall_message_complete_cb }; /* These pause_* callbacks always pause the parser and just invoke the regular * callback that tracks content. Before returning, we overwrite the parser * settings to point to the _dontcall variety so that we can verify that * the pause actually did, you know, pause. */ int pause_message_begin_cb (http_parser *p) { http_parser_pause(p, 1); *current_pause_parser = settings_dontcall; return message_begin_cb(p); } int pause_header_field_cb (http_parser *p, const char *buf, size_t len) { http_parser_pause(p, 1); *current_pause_parser = settings_dontcall; return header_field_cb(p, buf, len); } int pause_header_value_cb (http_parser *p, const char *buf, size_t len) { http_parser_pause(p, 1); *current_pause_parser = settings_dontcall; return header_value_cb(p, buf, len); } int pause_request_url_cb (http_parser *p, const char *buf, size_t len) { http_parser_pause(p, 1); *current_pause_parser = settings_dontcall; return request_url_cb(p, buf, len); } int pause_body_cb (http_parser *p, const char *buf, size_t len) { http_parser_pause(p, 1); *current_pause_parser = settings_dontcall; return body_cb(p, buf, len); } int pause_headers_complete_cb (http_parser *p) { http_parser_pause(p, 1); *current_pause_parser = settings_dontcall; return headers_complete_cb(p); } int pause_message_complete_cb (http_parser *p) { http_parser_pause(p, 1); *current_pause_parser = settings_dontcall; return message_complete_cb(p); } static http_parser_settings settings_pause = {.on_message_begin = pause_message_begin_cb ,.on_header_field = pause_header_field_cb ,.on_header_value = pause_header_value_cb ,.on_url = pause_request_url_cb ,.on_body = pause_body_cb ,.on_headers_complete = pause_headers_complete_cb ,.on_message_complete = pause_message_complete_cb }; static http_parser_settings settings = {.on_message_begin = message_begin_cb ,.on_header_field = header_field_cb ,.on_header_value = header_value_cb ,.on_url = request_url_cb ,.on_body = body_cb ,.on_headers_complete = headers_complete_cb ,.on_message_complete = message_complete_cb }; static http_parser_settings settings_count_body = {.on_message_begin = message_begin_cb ,.on_header_field = header_field_cb ,.on_header_value = header_value_cb ,.on_url = request_url_cb ,.on_body = count_body_cb ,.on_headers_complete = headers_complete_cb ,.on_message_complete = message_complete_cb }; static http_parser_settings settings_null = {.on_message_begin = 0 ,.on_header_field = 0 ,.on_header_value = 0 ,.on_url = 0 ,.on_body = 0 ,.on_headers_complete = 0 ,.on_message_complete = 0 }; void parser_init (enum http_parser_type type) { num_messages = 0; assert(parser == NULL); parser = malloc(sizeof(http_parser)); http_parser_init(parser, type); memset(&messages, 0, sizeof messages); } void parser_free () { assert(parser); free(parser); parser = NULL; } size_t parse (const char *buf, size_t len) { size_t nparsed; currently_parsing_eof = (len == 0); nparsed = http_parser_execute(parser, &settings, buf, len); return nparsed; } size_t parse_count_body (const char *buf, size_t len) { size_t nparsed; currently_parsing_eof = (len == 0); nparsed = http_parser_execute(parser, &settings_count_body, buf, len); return nparsed; } size_t parse_pause (const char *buf, size_t len) { size_t nparsed; http_parser_settings s = settings_pause; currently_parsing_eof = (len == 0); current_pause_parser = &s; nparsed = http_parser_execute(parser, current_pause_parser, buf, len); return nparsed; } static inline int check_str_eq (const struct message *m, const char *prop, const char *expected, const char *found) { if ((expected == NULL) != (found == NULL)) { printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); printf("expected %s\n", (expected == NULL) ? "NULL" : expected); printf(" found %s\n", (found == NULL) ? "NULL" : found); return 0; } if (expected != NULL && 0 != strcmp(expected, found)) { printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); printf("expected '%s'\n", expected); printf(" found '%s'\n", found); return 0; } return 1; } static inline int check_num_eq (const struct message *m, const char *prop, int expected, int found) { if (expected != found) { printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name); printf("expected %d\n", expected); printf(" found %d\n", found); return 0; } return 1; } #define MESSAGE_CHECK_STR_EQ(expected, found, prop) \ if (!check_str_eq(expected, #prop, expected->prop, found->prop)) return 0 #define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \ if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0 #define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \ do { \ char ubuf[256]; \ \ if ((u)->field_set & (1 << (fn))) { \ memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \ (u)->field_data[(fn)].len); \ ubuf[(u)->field_data[(fn)].len] = '\0'; \ } else { \ ubuf[0] = '\0'; \ } \ \ check_str_eq(expected, #prop, expected->prop, ubuf); \ } while(0) int message_eq (int index, const struct message *expected) { int i; struct message *m = &messages[index]; MESSAGE_CHECK_NUM_EQ(expected, m, http_major); MESSAGE_CHECK_NUM_EQ(expected, m, http_minor); if (expected->type == HTTP_REQUEST) { MESSAGE_CHECK_NUM_EQ(expected, m, method); } else { MESSAGE_CHECK_NUM_EQ(expected, m, status_code); } MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive); MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof); assert(m->message_begin_cb_called); assert(m->headers_complete_cb_called); assert(m->message_complete_cb_called); MESSAGE_CHECK_STR_EQ(expected, m, request_url); /* Check URL components; we can't do this w/ CONNECT since it doesn't * send us a well-formed URL. */ if (*m->request_url && m->method != HTTP_CONNECT) { struct http_parser_url u; if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) { fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n", m->request_url); abort(); } if (expected->host) { MESSAGE_CHECK_URL_EQ(&u, expected, m, host, UF_HOST); } if (expected->userinfo) { MESSAGE_CHECK_URL_EQ(&u, expected, m, userinfo, UF_USERINFO); } m->port = (u.field_set & (1 << UF_PORT)) ? u.port : 0; MESSAGE_CHECK_URL_EQ(&u, expected, m, query_string, UF_QUERY); MESSAGE_CHECK_URL_EQ(&u, expected, m, fragment, UF_FRAGMENT); MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH); MESSAGE_CHECK_NUM_EQ(expected, m, port); } if (expected->body_size) { MESSAGE_CHECK_NUM_EQ(expected, m, body_size); } else { MESSAGE_CHECK_STR_EQ(expected, m, body); } MESSAGE_CHECK_NUM_EQ(expected, m, num_headers); int r; for (i = 0; i < m->num_headers; i++) { r = check_str_eq(expected, "header field", expected->headers[i][0], m->headers[i][0]); if (!r) return 0; r = check_str_eq(expected, "header value", expected->headers[i][1], m->headers[i][1]); if (!r) return 0; } MESSAGE_CHECK_STR_EQ(expected, m, upgrade); return 1; } /* Given a sequence of varargs messages, return the number of them that the * parser should successfully parse, taking into account that upgraded * messages prevent all subsequent messages from being parsed. */ size_t count_parsed_messages(const size_t nmsgs, ...) { size_t i; va_list ap; va_start(ap, nmsgs); for (i = 0; i < nmsgs; i++) { struct message *m = va_arg(ap, struct message *); if (m->upgrade) { va_end(ap); return i + 1; } } va_end(ap); return nmsgs; } /* Given a sequence of bytes and the number of these that we were able to * parse, verify that upgrade bodies are correct. */ void upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) { va_list ap; size_t i; size_t off = 0; va_start(ap, nmsgs); for (i = 0; i < nmsgs; i++) { struct message *m = va_arg(ap, struct message *); off += strlen(m->raw); if (m->upgrade) { off -= strlen(m->upgrade); /* Check the portion of the response after its specified upgrade */ if (!check_str_eq(m, "upgrade", body + off, body + nread)) { abort(); } /* Fix up the response so that message_eq() will verify the beginning * of the upgrade */ *(body + nread + strlen(m->upgrade)) = '\0'; messages[num_messages -1 ].upgrade = body + nread; va_end(ap); return; } } va_end(ap); printf("\n\n*** Error: expected a message with upgrade ***\n"); abort(); } static void print_error (const char *raw, size_t error_location) { fprintf(stderr, "\n*** %s ***\n\n", http_errno_description(HTTP_PARSER_ERRNO(parser))); int this_line = 0, char_len = 0; size_t i, j, len = strlen(raw), error_location_line = 0; for (i = 0; i < len; i++) { if (i == error_location) this_line = 1; switch (raw[i]) { case '\r': char_len = 2; fprintf(stderr, "\\r"); break; case '\n': char_len = 2; fprintf(stderr, "\\n\n"); if (this_line) goto print; error_location_line = 0; continue; default: char_len = 1; fputc(raw[i], stderr); break; } if (!this_line) error_location_line += char_len; } fprintf(stderr, "[eof]\n"); print: for (j = 0; j < error_location_line; j++) { fputc(' ', stderr); } fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location); } void test_preserve_data (void) { char my_data[] = "application-specific data"; http_parser parser; parser.data = my_data; http_parser_init(&parser, HTTP_REQUEST); if (parser.data != my_data) { printf("\n*** parser.data not preserved accross http_parser_init ***\n\n"); abort(); } } struct url_test { const char *name; const char *url; int is_connect; struct http_parser_url u; int rv; }; const struct url_test url_tests[] = { {.name="proxy request" ,.url="http://hostname/" ,.is_connect=0 ,.u= {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) ,.port=0 ,.field_data= {{ 0, 4 } /* UF_SCHEMA */ ,{ 7, 8 } /* UF_HOST */ ,{ 0, 0 } /* UF_PORT */ ,{ 15, 1 } /* UF_PATH */ ,{ 0, 0 } /* UF_QUERY */ ,{ 0, 0 } /* UF_FRAGMENT */ ,{ 0, 0 } /* UF_USERINFO */ } } ,.rv=0 } , {.name="proxy request with port" ,.url="http://hostname:444/" ,.is_connect=0 ,.u= {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH) ,.port=444 ,.field_data= {{ 0, 4 } /* UF_SCHEMA */ ,{ 7, 8 } /* UF_HOST */ ,{ 16, 3 } /* UF_PORT */ ,{ 19, 1 } /* UF_PATH */ ,{ 0, 0 } /* UF_QUERY */ ,{ 0, 0 } /* UF_FRAGMENT */ ,{ 0, 0 } /* UF_USERINFO */ } } ,.rv=0 } , {.name="CONNECT request" ,.url="hostname:443" ,.is_connect=1 ,.u= {.field_set=(1 << UF_HOST) | (1 << UF_PORT) ,.port=443 ,.field_data= {{ 0, 0 } /* UF_SCHEMA */ ,{ 0, 8 } /* UF_HOST */ ,{ 9, 3 } /* UF_PORT */ ,{ 0, 0 } /* UF_PATH */ ,{ 0, 0 } /* UF_QUERY */ ,{ 0, 0 } /* UF_FRAGMENT */ ,{ 0, 0 } /* UF_USERINFO */ } } ,.rv=0 } , {.name="CONNECT request but not connect" ,.url="hostname:443" ,.is_connect=0 ,.rv=1 } , {.name="proxy ipv6 request" ,.url="http://[1:2::3:4]/" ,.is_connect=0 ,.u= {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) ,.port=0 ,.field_data= {{ 0, 4 } /* UF_SCHEMA */ ,{ 8, 8 } /* UF_HOST */ ,{ 0, 0 } /* UF_PORT */ ,{ 17, 1 } /* UF_PATH */ ,{ 0, 0 } /* UF_QUERY */ ,{ 0, 0 } /* UF_FRAGMENT */ ,{ 0, 0 } /* UF_USERINFO */ } } ,.rv=0 } , {.name="proxy ipv6 request with port" ,.url="http://[1:2::3:4]:67/" ,.is_connect=0 ,.u= {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH) ,.port=67 ,.field_data= {{ 0, 4 } /* UF_SCHEMA */ ,{ 8, 8 } /* UF_HOST */ ,{ 18, 2 } /* UF_PORT */ ,{ 20, 1 } /* UF_PATH */ ,{ 0, 0 } /* UF_QUERY */ ,{ 0, 0 } /* UF_FRAGMENT */ ,{ 0, 0 } /* UF_USERINFO */ } } ,.rv=0 } , {.name="CONNECT ipv6 address" ,.url="[1:2::3:4]:443" ,.is_connect=1 ,.u= {.field_set=(1 << UF_HOST) | (1 << UF_PORT) ,.port=443 ,.field_data= {{ 0, 0 } /* UF_SCHEMA */ ,{ 1, 8 } /* UF_HOST */ ,{ 11, 3 } /* UF_PORT */ ,{ 0, 0 } /* UF_PATH */ ,{ 0, 0 } /* UF_QUERY */ ,{ 0, 0 } /* UF_FRAGMENT */ ,{ 0, 0 } /* UF_USERINFO */ } } ,.rv=0 } , {.name="ipv4 in ipv6 address" ,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/" ,.is_connect=0 ,.u= {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH) ,.port=0 ,.field_data= {{ 0, 4 } /* UF_SCHEMA */ ,{ 8, 37 } /* UF_HOST */ ,{ 0, 0 } /* UF_PORT */ ,{ 46, 1 } /* UF_PATH */ ,{ 0, 0 } /* UF_QUERY */ ,{ 0, 0 } /* UF_FRAGMENT */ ,{ 0, 0 } /* UF_USERINFO */ } } ,.rv=0 } , {.name="extra ? in query string" ,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css," "fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css," "fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css" ,.is_connect=0 ,.u= {.field_set=(1<field_set, u->port); for (i = 0; i < UF_MAX; i++) { if ((u->field_set & (1 << i)) == 0) { printf("\tfield_data[%u]: unset\n", i); continue; } printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"", i, u->field_data[i].off, u->field_data[i].len, u->field_data[i].len, url + u->field_data[i].off); } } void test_parse_url (void) { struct http_parser_url u; const struct url_test *test; unsigned int i; int rv; for (i = 0; i < (sizeof(url_tests) / sizeof(url_tests[0])); i++) { test = &url_tests[i]; memset(&u, 0, sizeof(u)); rv = http_parser_parse_url(test->url, strlen(test->url), test->is_connect, &u); if (test->rv == 0) { if (rv != 0) { printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " "unexpected rv %d ***\n\n", test->url, test->name, rv); abort(); } if (memcmp(&u, &test->u, sizeof(u)) != 0) { printf("\n*** http_parser_parse_url(\"%s\") \"%s\" failed ***\n", test->url, test->name); printf("target http_parser_url:\n"); dump_url(test->url, &test->u); printf("result http_parser_url:\n"); dump_url(test->url, &u); abort(); } } else { /* test->rv != 0 */ if (rv == 0) { printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, " "unexpected rv %d ***\n\n", test->url, test->name, rv); abort(); } } } } void test_method_str (void) { assert(0 == strcmp("GET", http_method_str(HTTP_GET))); assert(0 == strcmp("", http_method_str(1337))); } void test_message (const struct message *message) { size_t raw_len = strlen(message->raw); size_t msg1len; for (msg1len = 0; msg1len < raw_len; msg1len++) { parser_init(message->type); size_t read; const char *msg1 = message->raw; const char *msg2 = msg1 + msg1len; size_t msg2len = raw_len - msg1len; if (msg1len) { read = parse(msg1, msg1len); if (message->upgrade && parser->upgrade) { messages[num_messages - 1].upgrade = msg1 + read; goto test; } if (read != msg1len) { print_error(msg1, read); abort(); } } read = parse(msg2, msg2len); if (message->upgrade && parser->upgrade) { messages[num_messages - 1].upgrade = msg2 + read; goto test; } if (read != msg2len) { print_error(msg2, read); abort(); } read = parse(NULL, 0); if (read != 0) { print_error(message->raw, read); abort(); } test: if (num_messages != 1) { printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); abort(); } if(!message_eq(0, message)) abort(); parser_free(); } } void test_message_count_body (const struct message *message) { parser_init(message->type); size_t read; size_t l = strlen(message->raw); size_t i, toread; size_t chunk = 4024; for (i = 0; i < l; i+= chunk) { toread = MIN(l-i, chunk); read = parse_count_body(message->raw + i, toread); if (read != toread) { print_error(message->raw, read); abort(); } } read = parse_count_body(NULL, 0); if (read != 0) { print_error(message->raw, read); abort(); } if (num_messages != 1) { printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name); abort(); } if(!message_eq(0, message)) abort(); parser_free(); } void test_simple (const char *buf, enum http_errno err_expected) { parser_init(HTTP_REQUEST); size_t parsed; int pass; enum http_errno err; parsed = parse(buf, strlen(buf)); pass = (parsed == strlen(buf)); err = HTTP_PARSER_ERRNO(parser); parsed = parse(NULL, 0); pass &= (parsed == 0); parser_free(); /* In strict mode, allow us to pass with an unexpected HPE_STRICT as * long as the caller isn't expecting success. */ #if HTTP_PARSER_STRICT if (err_expected != err && err_expected != HPE_OK && err != HPE_STRICT) { #else if (err_expected != err) { #endif fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n", http_errno_name(err_expected), http_errno_name(err), buf); abort(); } } void test_header_overflow_error (int req) { http_parser parser; http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); size_t parsed; const char *buf; buf = req ? "GET / HTTP/1.1\r\n" : "HTTP/1.0 200 OK\r\n"; parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf)); assert(parsed == strlen(buf)); buf = "header-key: header-value\r\n"; size_t buflen = strlen(buf); int i; for (i = 0; i < 10000; i++) { parsed = http_parser_execute(&parser, &settings_null, buf, buflen); if (parsed != buflen) { //fprintf(stderr, "error found on iter %d\n", i); assert(HTTP_PARSER_ERRNO(&parser) == HPE_HEADER_OVERFLOW); return; } } fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n"); abort(); } static void test_content_length_overflow (const char *buf, size_t buflen, int expect_ok) { http_parser parser; http_parser_init(&parser, HTTP_RESPONSE); http_parser_execute(&parser, &settings_null, buf, buflen); if (expect_ok) assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK); else assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CONTENT_LENGTH); } void test_header_content_length_overflow_error (void) { #define X(size) \ "HTTP/1.1 200 OK\r\n" \ "Content-Length: " #size "\r\n" \ "\r\n" const char a[] = X(18446744073709551614); /* 2^64-2 */ const char b[] = X(18446744073709551615); /* 2^64-1 */ const char c[] = X(18446744073709551616); /* 2^64 */ #undef X test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ } void test_chunk_content_length_overflow_error (void) { #define X(size) \ "HTTP/1.1 200 OK\r\n" \ "Transfer-Encoding: chunked\r\n" \ "\r\n" \ #size "\r\n" \ "..." const char a[] = X(FFFFFFFFFFFFFFFE); /* 2^64-2 */ const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */ const char c[] = X(10000000000000000); /* 2^64 */ #undef X test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */ test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */ test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */ } void test_no_overflow_long_body (int req, size_t length) { http_parser parser; http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE); size_t parsed; size_t i; char buf1[3000]; size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %lu\r\n\r\n", req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", (unsigned long)length); parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len); if (parsed != buf1len) goto err; for (i = 0; i < length; i++) { char foo = 'a'; parsed = http_parser_execute(&parser, &settings_null, &foo, 1); if (parsed != 1) goto err; } parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len); if (parsed != buf1len) goto err; return; err: fprintf(stderr, "\n*** error in test_no_overflow_long_body %s of length %lu ***\n", req ? "REQUEST" : "RESPONSE", (unsigned long)length); abort(); } void test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3) { int message_count = count_parsed_messages(3, r1, r2, r3); char total[ strlen(r1->raw) + strlen(r2->raw) + strlen(r3->raw) + 1 ]; total[0] = '\0'; strcat(total, r1->raw); strcat(total, r2->raw); strcat(total, r3->raw); parser_init(r1->type); size_t read; read = parse(total, strlen(total)); if (parser->upgrade) { upgrade_message_fix(total, read, 3, r1, r2, r3); goto test; } if (read != strlen(total)) { print_error(total, read); abort(); } read = parse(NULL, 0); if (read != 0) { print_error(total, read); abort(); } test: if (message_count != num_messages) { fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages); abort(); } if (!message_eq(0, r1)) abort(); if (message_count > 1 && !message_eq(1, r2)) abort(); if (message_count > 2 && !message_eq(2, r3)) abort(); parser_free(); } /* SCAN through every possible breaking to make sure the * parser can handle getting the content in any chunks that * might come from the socket */ void test_scan (const struct message *r1, const struct message *r2, const struct message *r3) { char total[80*1024] = "\0"; char buf1[80*1024] = "\0"; char buf2[80*1024] = "\0"; char buf3[80*1024] = "\0"; strcat(total, r1->raw); strcat(total, r2->raw); strcat(total, r3->raw); size_t read; int total_len = strlen(total); int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2; int ops = 0 ; size_t buf1_len, buf2_len, buf3_len; int message_count = count_parsed_messages(3, r1, r2, r3); int i,j,type_both; for (type_both = 0; type_both < 2; type_both ++ ) { for (j = 2; j < total_len; j ++ ) { for (i = 1; i < j; i ++ ) { if (ops % 1000 == 0) { printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops); fflush(stdout); } ops += 1; parser_init(type_both ? HTTP_BOTH : r1->type); buf1_len = i; strlncpy(buf1, sizeof(buf1), total, buf1_len); buf1[buf1_len] = 0; buf2_len = j - i; strlncpy(buf2, sizeof(buf1), total+i, buf2_len); buf2[buf2_len] = 0; buf3_len = total_len - j; strlncpy(buf3, sizeof(buf1), total+j, buf3_len); buf3[buf3_len] = 0; read = parse(buf1, buf1_len); if (parser->upgrade) goto test; if (read != buf1_len) { print_error(buf1, read); goto error; } read += parse(buf2, buf2_len); if (parser->upgrade) goto test; if (read != buf1_len + buf2_len) { print_error(buf2, read); goto error; } read += parse(buf3, buf3_len); if (parser->upgrade) goto test; if (read != buf1_len + buf2_len + buf3_len) { print_error(buf3, read); goto error; } parse(NULL, 0); test: if (parser->upgrade) { upgrade_message_fix(total, read, 3, r1, r2, r3); } if (message_count != num_messages) { fprintf(stderr, "\n\nParser didn't see %d messages only %d\n", message_count, num_messages); goto error; } if (!message_eq(0, r1)) { fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n"); goto error; } if (message_count > 1 && !message_eq(1, r2)) { fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n"); goto error; } if (message_count > 2 && !message_eq(2, r3)) { fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n"); goto error; } parser_free(); } } } puts("\b\b\b\b100%"); return; error: fprintf(stderr, "i=%d j=%d\n", i, j); fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1); fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2); fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3); abort(); } // user required to free the result // string terminated by \0 char * create_large_chunked_message (int body_size_in_kb, const char* headers) { int i; size_t wrote = 0; size_t headers_len = strlen(headers); size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6; char * buf = malloc(bufsize); memcpy(buf, headers, headers_len); wrote += headers_len; for (i = 0; i < body_size_in_kb; i++) { // write 1kb chunk into the body. memcpy(buf + wrote, "400\r\n", 5); wrote += 5; memset(buf + wrote, 'C', 1024); wrote += 1024; strcpy(buf + wrote, "\r\n"); wrote += 2; } memcpy(buf + wrote, "0\r\n\r\n", 6); wrote += 6; assert(wrote == bufsize); return buf; } void test_status_complete (void) { parser_init(HTTP_RESPONSE); parser->data = 0; http_parser_settings settings = settings_null; settings.on_status_complete = status_complete_cb; char *response = "don't mind me, just a simple response"; http_parser_execute(parser, &settings, response, strlen(response)); assert(parser->data == (void*)0); // the status_complete callback was never called assert(parser->http_errno == HPE_INVALID_CONSTANT); // the errno for an invalid status line } /* Verify that we can pause parsing at any of the bytes in the * message and still get the result that we're expecting. */ void test_message_pause (const struct message *msg) { char *buf = (char*) msg->raw; size_t buflen = strlen(msg->raw); size_t nread; parser_init(msg->type); do { nread = parse_pause(buf, buflen); // We can only set the upgrade buffer once we've gotten our message // completion callback. if (messages[0].message_complete_cb_called && msg->upgrade && parser->upgrade) { messages[0].upgrade = buf + nread; goto test; } if (nread < buflen) { // Not much do to if we failed a strict-mode check if (HTTP_PARSER_ERRNO(parser) == HPE_STRICT) { parser_free(); return; } assert (HTTP_PARSER_ERRNO(parser) == HPE_PAUSED); } buf += nread; buflen -= nread; http_parser_pause(parser, 0); } while (buflen > 0); nread = parse_pause(NULL, 0); assert (nread == 0); test: if (num_messages != 1) { printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name); abort(); } if(!message_eq(0, msg)) abort(); parser_free(); } int main (void) { parser = NULL; int i, j, k; int request_count; int response_count; printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser)); for (request_count = 0; requests[request_count].name; request_count++); for (response_count = 0; responses[response_count].name; response_count++); //// API test_preserve_data(); test_parse_url(); test_method_str(); //// OVERFLOW CONDITIONS test_header_overflow_error(HTTP_REQUEST); test_no_overflow_long_body(HTTP_REQUEST, 1000); test_no_overflow_long_body(HTTP_REQUEST, 100000); test_header_overflow_error(HTTP_RESPONSE); test_no_overflow_long_body(HTTP_RESPONSE, 1000); test_no_overflow_long_body(HTTP_RESPONSE, 100000); test_header_content_length_overflow_error(); test_chunk_content_length_overflow_error(); //// RESPONSES for (i = 0; i < response_count; i++) { test_message(&responses[i]); } for (i = 0; i < response_count; i++) { test_message_pause(&responses[i]); } for (i = 0; i < response_count; i++) { if (!responses[i].should_keep_alive) continue; for (j = 0; j < response_count; j++) { if (!responses[j].should_keep_alive) continue; for (k = 0; k < response_count; k++) { test_multiple3(&responses[i], &responses[j], &responses[k]); } } } test_message_count_body(&responses[NO_HEADERS_NO_BODY_404]); test_message_count_body(&responses[TRAILING_SPACE_ON_CHUNKED_BODY]); // test very large chunked response { char * msg = create_large_chunked_message(31337, "HTTP/1.0 200 OK\r\n" "Transfer-Encoding: chunked\r\n" "Content-Type: text/plain\r\n" "\r\n"); struct message large_chunked = {.name= "large chunked" ,.type= HTTP_RESPONSE ,.raw= msg ,.should_keep_alive= FALSE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.status_code= 200 ,.num_headers= 2 ,.headers= { { "Transfer-Encoding", "chunked" } , { "Content-Type", "text/plain" } } ,.body_size= 31337*1024 }; test_message_count_body(&large_chunked); free(msg); } printf("response scan 1/2 "); test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY] , &responses[NO_BODY_HTTP10_KA_204] , &responses[NO_REASON_PHRASE] ); printf("response scan 2/2 "); test_scan( &responses[BONJOUR_MADAME_FR] , &responses[UNDERSTORE_HEADER_KEY] , &responses[NO_CARRIAGE_RET] ); puts("responses okay"); /// REQUESTS test_simple("hello world", HPE_INVALID_METHOD); test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION); test_simple("ASDF / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD); test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD); test_simple("GETA / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD); // Well-formed but incomplete test_simple("GET / HTTP/1.1\r\n" "Content-Type: text/plain\r\n" "Content-Length: 6\r\n" "\r\n" "fooba", HPE_OK); static const char *all_methods[] = { "DELETE", "GET", "HEAD", "POST", "PUT", //"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel "OPTIONS", "TRACE", "COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "REPORT", "MKACTIVITY", "CHECKOUT", "MERGE", "M-SEARCH", "NOTIFY", "SUBSCRIBE", "UNSUBSCRIBE", "PATCH", 0 }; const char **this_method; for (this_method = all_methods; *this_method; this_method++) { char buf[200]; sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method); test_simple(buf, HPE_OK); } static const char *bad_methods[] = { "C******", "M****", 0 }; for (this_method = bad_methods; *this_method; this_method++) { char buf[200]; sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method); test_simple(buf, HPE_UNKNOWN); } const char *dumbfuck2 = "GET / HTTP/1.1\r\n" "X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n" "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n" "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n" "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n" "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n" "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n" "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n" "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n" "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n" "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n" "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n" "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n" "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n" "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n" "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n" "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n" "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n" "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n" "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n" "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n" "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n" "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n" "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n" "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n" "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n" "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n" "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n" "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n" "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n" "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n" "\tRA==\r\n" "\t-----END CERTIFICATE-----\r\n" "\r\n"; test_simple(dumbfuck2, HPE_OK); #if 0 // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body // until EOF. // // no content-length // error if there is a body without content length const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n" "Accept: */*\r\n" "\r\n" "HELLO"; test_simple(bad_get_no_headers_no_body, 0); #endif /* TODO sending junk and large headers gets rejected */ /* check to make sure our predefined requests are okay */ for (i = 0; requests[i].name; i++) { test_message(&requests[i]); } for (i = 0; i < request_count; i++) { test_message_pause(&requests[i]); } for (i = 0; i < request_count; i++) { if (!requests[i].should_keep_alive) continue; for (j = 0; j < request_count; j++) { if (!requests[j].should_keep_alive) continue; for (k = 0; k < request_count; k++) { test_multiple3(&requests[i], &requests[j], &requests[k]); } } } printf("request scan 1/4 "); test_scan( &requests[GET_NO_HEADERS_NO_BODY] , &requests[GET_ONE_HEADER_NO_BODY] , &requests[GET_NO_HEADERS_NO_BODY] ); printf("request scan 2/4 "); test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE] , &requests[POST_IDENTITY_BODY_WORLD] , &requests[GET_FUNKY_CONTENT_LENGTH] ); printf("request scan 3/4 "); test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END] , &requests[CHUNKED_W_TRAILING_HEADERS] , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH] ); printf("request scan 4/4 "); test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET] , &requests[PREFIX_NEWLINE_GET ] , &requests[CONNECT_REQUEST] ); test_status_complete(); puts("requests okay"); return 0; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/json.pri ================================================ INCLUDEPATH += $${PWD} QJSON_INSTALL_HEADERS += \ $${PWD}/qjson_export.h PRIVATE_HEADERS += \ $${PWD}/qjson_p.h \ $${PWD}/qjsonwriter_p.h \ $${PWD}/qjsonparser_p.h \ $${PWD}/qjsondocument.h \ $${PWD}/qjsonobject.h \ $${PWD}/qjsonvalue.h \ $${PWD}/qjsonarray.h SOURCES += \ $${PWD}/qjson.cpp \ $${PWD}/qjsondocument.cpp \ $${PWD}/qjsonobject.cpp \ $${PWD}/qjsonarray.cpp \ $${PWD}/qjsonvalue.cpp \ $${PWD}/qjsonwriter.cpp \ $${PWD}/qjsonparser.cpp json.files = \ $${PWD}/qjsondocument.h \ $${PWD}/qjsonobject.h \ $${PWD}/qjsonvalue.h \ $${PWD}/qjsonarray.h json.path = $${PREFIX}/include/qjsonrpc/json INSTALLS += json ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjson.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qjson_p.h" #include QT_BEGIN_NAMESPACE namespace QJsonPrivate { #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN #define Q_TO_LITTLE_ENDIAN(x) (x) #else #define Q_TO_LITTLE_ENDIAN(x) ( ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24) ) #endif static const Base emptyArray = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } }; static const Base emptyObject = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } }; void Data::compact() { Q_ASSERT(sizeof(Value) == sizeof(offset)); if (!compactionCounter) return; Base *base = header->root(); int reserve = 0; if (base->is_object) { Object *o = static_cast(base); for (int i = 0; i < (int)o->length; ++i) reserve += o->entryAt(i)->usedStorage(o); } else { Array *a = static_cast(base); for (int i = 0; i < (int)a->length; ++i) reserve += (*a)[i].usedStorage(a); } int size = sizeof(Base) + reserve + base->length*sizeof(offset); int alloc = sizeof(Header) + size; Header *h = (Header *) malloc(alloc); h->tag = QJsonDocument::BinaryFormatTag; h->version = 1; Base *b = h->root(); b->size = size; b->is_object = header->root()->is_object; b->length = base->length; b->tableOffset = reserve + sizeof(Array); int offset = sizeof(Base); if (b->is_object) { Object *o = static_cast(base); Object *no = static_cast(b); for (int i = 0; i < (int)o->length; ++i) { no->table()[i] = offset; const Entry *e = o->entryAt(i); Entry *ne = no->entryAt(i); int s = e->size(); memcpy(ne, e, s); offset += s; int dataSize = e->value.usedStorage(o); if (dataSize) { memcpy((char *)no + offset, e->value.data(o), dataSize); ne->value.value = offset; offset += dataSize; } } } else { Array *a = static_cast(base); Array *na = static_cast(b); for (int i = 0; i < (int)a->length; ++i) { const Value &v = (*a)[i]; Value &nv = (*na)[i]; nv = v; int dataSize = v.usedStorage(a); if (dataSize) { memcpy((char *)na + offset, v.data(a), dataSize); nv.value = offset; offset += dataSize; } } } Q_ASSERT(offset == (int)b->tableOffset); free(header); header = h; this->alloc = alloc; compactionCounter = 0; } bool Data::valid() const { if (header->tag != QJsonDocument::BinaryFormatTag || header->version != 1u) return false; bool res = false; if (header->root()->is_object) res = static_cast(header->root())->isValid(); else res = static_cast(header->root())->isValid(); return res; } int Base::reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace) { Q_ASSERT(posInTable >= 0 && posInTable <= (int)length); if (size + dataSize >= Value::MaxSize) { qWarning("QJson: Document too large to store in data structure %d %d %d", (uint)size, dataSize, Value::MaxSize); return 0; } offset off = tableOffset; // move table to new position if (replace) { memmove((char *)(table()) + dataSize, table(), length*sizeof(offset)); } else { memmove((char *)(table() + posInTable + numItems) + dataSize, table() + posInTable, (length - posInTable)*sizeof(offset)); memmove((char *)(table()) + dataSize, table(), posInTable*sizeof(offset)); } tableOffset += dataSize; for (int i = 0; i < (int)numItems; ++i) table()[posInTable + i] = off; size += dataSize; if (!replace) { length += numItems; size += numItems * sizeof(offset); } return off; } void Base::removeItems(int pos, int numItems) { Q_ASSERT(pos >= 0 && pos <= (int)length); if (pos + numItems < (int)length) memmove(table() + pos, table() + pos + numItems, (length - pos - numItems)*sizeof(offset)); length -= numItems; } int Object::indexOf(const QString &key, bool *exists) { int min = 0; int n = length; while (n > 0) { int half = n >> 1; int middle = min + half; if (*entryAt(middle) >= key) { n = half; } else { min = middle + 1; n -= half + 1; } } if (min < (int)length && *entryAt(min) == key) { *exists = true; return min; } *exists = false; return min; } bool Object::isValid() const { if (tableOffset + length*sizeof(offset) > size) return false; for (uint i = 0; i < length; ++i) { offset entryOffset = table()[i]; if (entryOffset + sizeof(Entry) >= tableOffset) return false; Entry *e = entryAt(i); int s = e->size(); if (table()[i] + s > tableOffset) return false; if (!e->value.isValid(this)) return false; } return true; } bool Array::isValid() const { if (tableOffset + length*sizeof(offset) > size) return false; for (uint i = 0; i < length; ++i) { if (!at(i).isValid(this)) return false; } return true; } bool Entry::operator ==(const QString &key) const { if (value.latinKey) return (shallowLatin1Key() == key); else return (shallowKey() == key); } bool Entry::operator ==(const Entry &other) const { if (value.latinKey) { if (other.value.latinKey) return shallowLatin1Key() == other.shallowLatin1Key(); return shallowLatin1Key() == other.shallowKey(); } else if (other.value.latinKey) { return shallowKey() == other.shallowLatin1Key(); } return shallowKey() == other.shallowKey(); } bool Entry::operator >=(const Entry &other) const { if (value.latinKey) { if (other.value.latinKey) return shallowLatin1Key() >= other.shallowLatin1Key(); return shallowLatin1Key() >= other.shallowKey(); } else if (other.value.latinKey) { return shallowKey() >= other.shallowLatin1Key(); } return shallowKey() >= other.shallowKey(); } int Value::usedStorage(const Base *b) const { int s = 0; switch (type) { case QJsonValue::Double: if (latinOrIntValue) break; s = sizeof(double); break; case QJsonValue::String: { char *d = data(b); if (latinOrIntValue) s = sizeof(ushort) + qFromLittleEndian(*(ushort *)d); else s = sizeof(int) + sizeof(ushort) * qFromLittleEndian(*(int *)d); break; } case QJsonValue::Array: case QJsonValue::Object: s = base(b)->size; break; case QJsonValue::Null: case QJsonValue::Bool: default: break; } return alignedSize(s); } bool Value::isValid(const Base *b) const { int offset = 0; switch (type) { case QJsonValue::Double: if (latinOrIntValue) break; // fall through case QJsonValue::String: case QJsonValue::Array: case QJsonValue::Object: offset = value; break; case QJsonValue::Null: case QJsonValue::Bool: default: break; } if (!offset) return true; if (offset + sizeof(uint) > b->tableOffset) return false; int s = usedStorage(b); if (!s) return true; if (s < 0 || offset + s > (int)b->tableOffset) return false; if (type == QJsonValue::Array) return static_cast(base(b))->isValid(); if (type == QJsonValue::Object) return static_cast(base(b))->isValid(); return true; } /*! \internal */ int Value::requiredStorage(QJsonValue &v, bool *compressed) { *compressed = false; switch (v.t) { case QJsonValue::Double: if (QJsonPrivate::compressedNumber(v.dbl) != INT_MAX) { *compressed = true; return 0; } return sizeof(double); case QJsonValue::String: { QString s = v.toString(); *compressed = QJsonPrivate::useCompressed(s); return QJsonPrivate::qStringSize(s, *compressed); } case QJsonValue::Array: case QJsonValue::Object: if (v.d && v.d->compactionCounter) { v.detach(); v.d->compact(); v.base = static_cast(v.d->header->root()); } return v.base ? v.base->size : sizeof(QJsonPrivate::Base); case QJsonValue::Undefined: case QJsonValue::Null: case QJsonValue::Bool: break; } return 0; } /*! \internal */ uint Value::valueToStore(const QJsonValue &v, uint offset) { switch (v.t) { case QJsonValue::Undefined: case QJsonValue::Null: break; case QJsonValue::Bool: return v.b; case QJsonValue::Double: { int c = QJsonPrivate::compressedNumber(v.dbl); if (c != INT_MAX) return c; } // fall through case QJsonValue::String: case QJsonValue::Array: case QJsonValue::Object: return offset; } return 0; } /*! \internal */ void Value::copyData(const QJsonValue &v, char *dest, bool compressed) { switch (v.t) { case QJsonValue::Double: if (!compressed) { qToLittleEndian(v.ui, (uchar *)dest); } break; case QJsonValue::String: { QString str = v.toString(); QJsonPrivate::copyString(dest, str, compressed); break; } case QJsonValue::Array: case QJsonValue::Object: { const QJsonPrivate::Base *b = v.base; if (!b) b = (v.t == QJsonValue::Array ? &emptyArray : &emptyObject); memcpy(dest, b, b->size); break; } default: break; } } } // namespace QJsonPrivate QT_END_NAMESPACE ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjson_export.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSON_EXPORT_H #define QJSON_EXPORT_H #ifdef QJSONRPC_SHARED # ifdef QJSONRPC_BUILD # define QJSON_EXPORT Q_DECL_EXPORT # else # define QJSON_EXPORT Q_DECL_IMPORT # endif #else # define QJSON_EXPORT #endif #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjson_p.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QJSON_P_H #define QJSON_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qjsonobject.h" #include "qjsonvalue.h" #include "qjsondocument.h" #include "qjsonarray.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE /* This defines a binary data structure for Json data. The data structure is optimised for fast reading and minimum allocations. The whole data structure can be mmap'ed and used directly. In most cases the binary structure is not as space efficient as a utf8 encoded text representation, but much faster to access. The size requirements are: String: Latin1 data: 2 bytes header + string.length() Full Unicode: 4 bytes header + 2*(string.length()) Values: 4 bytes + size of data (size can be 0 for some data) bool: 0 bytes double: 8 bytes (0 if integer with less than 27bits) string: see above array: size of array object: size of object Array: 12 bytes + 4*length + size of Value data Object: 12 bytes + 8*length + size of Key Strings + size of Value data For an example such as { // object: 12 + 5*8 = 52 "firstName": "John", // key 12, value 8 = 20 "lastName" : "Smith", // key 12, value 8 = 20 "age" : 25, // key 8, value 0 = 8 "address" : // key 12, object below = 140 { // object: 12 + 4*8 "streetAddress": "21 2nd Street", // key 16, value 16 "city" : "New York", // key 8, value 12 "state" : "NY", // key 8, value 4 "postalCode" : "10021" // key 12, value 8 }, // object total: 128 "phoneNumber": // key: 16, value array below = 172 [ // array: 12 + 2*4 + values below: 156 { // object 12 + 2*8 "type" : "home", // key 8, value 8 "number": "212 555-1234" // key 8, value 16 }, // object total: 68 { // object 12 + 2*8 "type" : "fax", // key 8, value 8 "number": "646 555-4567" // key 8, value 16 } // object total: 68 ] // array total: 156 } // great total: 412 bytes The uncompressed text file used roughly 500 bytes, so in this case we end up using about the same space as the text representation. Other measurements have shown a slightly bigger binary size than a compact text representation where all possible whitespace was stripped out. */ namespace QJsonPrivate { class Array; class Object; class Value; class Entry; template class q_littleendian { public: T val; q_littleendian &operator =(T i) { val = qToLittleEndian(i); return *this; } operator T() const { return qFromLittleEndian(val); } bool operator ==(T i) { return qFromLittleEndian(val) == i; } bool operator !=(T i) { return qFromLittleEndian(val) != i; } bool operator ==(q_littleendian i) { return val == i.val; } bool operator !=(q_littleendian i) { return val != i.val; } bool operator <(T i) { return qFromLittleEndian(val) < i; } bool operator >(T i) { return qFromLittleEndian(val) > i; } bool operator <=(T i) { return qFromLittleEndian(val) <= i; } bool operator >=(T i) { return qFromLittleEndian(val) >= i; } q_littleendian &operator +=(T i) { val = qToLittleEndian(qFromLittleEndian(val) + i); return *this; } }; typedef q_littleendian qle_short; typedef q_littleendian qle_ushort; typedef q_littleendian qle_int; typedef q_littleendian qle_uint; template class qle_bitfield { public: uint val; enum { mask = ((1u << width) - 1) << pos }; void operator =(uint t) { uint i = qFromLittleEndian(val); i &= ~mask; i |= t << pos; val = qToLittleEndian(i); } operator uint() const { uint t = qFromLittleEndian(val); t &= mask; t >>= pos; return t; } bool operator !() const { return !operator uint(); } bool operator ==(uint t) { return uint(*this) == t; } bool operator !=(uint t) { return uint(*this) != t; } bool operator <(uint t) { return uint(*this) < t; } bool operator >(uint t) { return uint(*this) > t; } bool operator <=(uint t) { return uint(*this) <= t; } bool operator >=(uint t) { return uint(*this) >= t; } qle_bitfield &operator +=(uint i) { *this = (uint(*this) + i); return *this; } qle_bitfield &operator -=(uint i) { *this = (uint(*this) - i); return *this; } }; template class qle_signedbitfield { public: uint val; enum { mask = ((1u << width) - 1) << pos }; void operator =(int t) { uint i = qFromLittleEndian(val); i &= ~mask; i |= t << pos; val = qToLittleEndian(i); } operator int() const { uint i = qFromLittleEndian(val); i <<= 32 - width - pos; int t = (int) i; t >>= pos; return t; } bool operator !() const { return !operator int(); } bool operator ==(int t) { return int(*this) == t; } bool operator !=(int t) { return int(*this) != t; } bool operator <(int t) { return int(*this) < t; } bool operator >(int t) { return int(*this) > t; } bool operator <=(int t) { return int(*this) <= t; } bool operator >=(int t) { return int(*this) >= t; } qle_signedbitfield &operator +=(int i) { *this = (int(*this) + i); return *this; } qle_signedbitfield &operator -=(int i) { *this = (int(*this) - i); return *this; } }; typedef qle_uint offset; // round the size up to the next 4 byte boundary inline int alignedSize(int size) { return (size + 3) & ~3; } static inline bool useCompressed(const QString &s) { if (s.length() >= 0x8000) return false; const ushort *uc = (const ushort *)s.constData(); const ushort *e = uc + s.length(); while (uc < e) { if (*uc > 0xff) return false; ++uc; } return true; } static inline int qStringSize(const QString &string, bool compress) { int l = 2 + string.length(); if (!compress) l *= 2; return alignedSize(l); } // returns INT_MAX if it can't compress it into 28 bits static inline int compressedNumber(double d) { // this relies on details of how ieee floats are represented const int exponent_off = 52; const quint64 fraction_mask = 0x000fffffffffffffull; const quint64 exponent_mask = 0x7ff0000000000000ull; quint64 val; memcpy (&val, &d, sizeof(double)); int exp = (int)((val & exponent_mask) >> exponent_off) - 1023; if (exp < 0 || exp > 25) return INT_MAX; quint64 non_int = val & (fraction_mask >> exp); if (non_int) return INT_MAX; bool neg = (val >> 63); val &= fraction_mask; val |= ((quint64)1 << 52); int res = (int)(val >> (52 - exp)); return neg ? -res : res; } class Latin1String; class String { public: String(const char *data) { d = (Data *)data; } struct Data { qle_int length; qle_ushort utf16[1]; }; Data *d; inline String &operator=(const QString &str) { d->length = str.length(); #if Q_BYTE_ORDER == Q_BIG_ENDIAN const qle_ushort *uc = (const qle_ushort *)str.unicode(); for (int i = 0; i < str.length(); ++i) d->utf16[i] = uc[i]; #else memcpy(d->utf16, str.unicode(), str.length()*sizeof(ushort)); #endif if (str.length() & 1) d->utf16[str.length()] = 0; return *this; } inline bool operator ==(const QString &str) const { int slen = str.length(); int l = d->length; if (slen != l) return false; const ushort *s = (const ushort *)str.constData(); const qle_ushort *a = d->utf16; const ushort *b = s; while (l-- && *a == *b) a++,b++; return (l == -1); } inline bool operator !=(const QString &str) const { return !operator ==(str); } inline bool operator >=(const QString &str) const { // ### return toString() >= str; } inline bool operator<(const Latin1String &str) const; inline bool operator>=(const Latin1String &str) const { return !operator <(str); } inline bool operator ==(const Latin1String &str) const; inline bool operator ==(const String &str) const { if (d->length != str.d->length) return false; return !memcmp(d->utf16, str.d->utf16, d->length*sizeof(ushort)); } inline bool operator<(const String &other) const; inline bool operator >=(const String &other) const { return !(*this < other); } inline QString toString() const { #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN return QString((QChar *)d->utf16, d->length); #else int l = d->length; QString str(l, Qt::Uninitialized); QChar *ch = str.data(); for (int i = 0; i < l; ++i) ch[i] = QChar(d->utf16[i]); return str; #endif } }; class Latin1String { public: Latin1String(const char *data) { d = (Data *)data; } struct Data { qle_short length; char latin1[1]; }; Data *d; inline Latin1String &operator=(const QString &str) { d->length = str.length(); uchar *l = (uchar *)d->latin1; const ushort *uc = (const ushort *)str.unicode(); for (int i = 0; i < str.length(); ++i) *l++ = uc[i]; while ((quintptr)l & 0x3) *l++ = 0; return *this; } inline bool operator ==(const QString &str) const { // return QLatin1String(d->latin1, d->length) == str; return QString::fromLatin1(d->latin1, d->length) == str; } inline bool operator !=(const QString &str) const { return !operator ==(str); } inline bool operator >=(const QString &str) const { // return QLatin1String(d->latin1, d->length) >= str; return QString::fromLatin1(d->latin1, d->length) >= str; } inline bool operator ==(const Latin1String &str) const { return d->length == str.d->length && !strcmp(d->latin1, str.d->latin1); } inline bool operator >=(const Latin1String &str) const { int l = qMin(d->length, str.d->length); int val = strncmp(d->latin1, str.d->latin1, l); if (!val) val = d->length - str.d->length; return val >= 0; } inline bool operator<(const String &str) const { const qle_ushort *uc = (qle_ushort *) str.d->utf16; if (!uc || *uc == 0) return false; const uchar *c = (uchar *)d->latin1; const uchar *e = c + qMin((int)d->length, (int)str.d->length); while (c < e) { if (*c != *uc) break; ++c; ++uc; } return (c == e ? (int)d->length < (int)str.d->length : *c < *uc); } inline bool operator ==(const String &str) const { return (str == *this); } inline bool operator >=(const String &str) const { return !(*this < str); } inline QString toString() const { return QString::fromLatin1(d->latin1, d->length); } }; inline bool String::operator ==(const Latin1String &str) const { if ((int)d->length != (int)str.d->length) return false; const qle_ushort *uc = d->utf16; const qle_ushort *e = uc + d->length; const uchar *c = (uchar *)str.d->latin1; while (uc < e) { if (*uc != *c) return false; ++uc; ++c; } return true; } inline bool String::operator <(const String &other) const { int alen = d->length; int blen = other.d->length; int l = qMin(alen, blen); qle_ushort *a = d->utf16; qle_ushort *b = other.d->utf16; while (l-- && *a == *b) a++,b++; if (l==-1) return (alen < blen); return (ushort)*a < (ushort)*b; } inline bool String::operator<(const Latin1String &str) const { const uchar *c = (uchar *) str.d->latin1; if (!c || *c == 0) return false; const qle_ushort *uc = d->utf16; const qle_ushort *e = uc + qMin((int)d->length, (int)str.d->length); while (uc < e) { if (*uc != *c) break; ++uc; ++c; } return (uc == e ? (int)d->length < (int)str.d->length : (ushort)*uc < *c); } static inline void copyString(char *dest, const QString &str, bool compress) { if (compress) { Latin1String string(dest); string = str; } else { String string(dest); string = str; } } /* Base is the base class for both Object and Array. Both classe work more or less the same way. The class starts with a header (defined by the struct below), then followed by data (the data for values in the Array case and Entry's (see below) for objects. After the data a table follows (tableOffset points to it) containing Value objects for Arrays, and offsets from the beginning of the object to Entry's in the case of Object. Entry's in the Object's table are lexicographically sorted by key in the table(). This allows the usage of a binary search over the keys in an Object. */ class Base { public: qle_uint size; union { uint _dummy; qle_bitfield<0, 1> is_object; qle_bitfield<1, 31> length; }; offset tableOffset; // content follows here inline bool isObject() const { return is_object; } inline bool isArray() const { return !isObject(); } inline offset *table() const { return (offset *) (((char *) this) + tableOffset); } int reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace); void removeItems(int pos, int numItems); }; class Object : public Base { public: Entry *entryAt(int i) const { return reinterpret_cast(((char *)this) + table()[i]); } int indexOf(const QString &key, bool *exists); bool isValid() const; }; class Array : public Base { public: inline Value at(int i) const; inline Value &operator [](int i); bool isValid() const; }; class Value { public: enum { MaxSize = (1<<27) - 1 }; union { uint _dummy; qle_bitfield<0, 3> type; qle_bitfield<3, 1> latinOrIntValue; qle_bitfield<4, 1> latinKey; qle_bitfield<5, 27> value; qle_signedbitfield<5, 27> int_value; }; inline char *data(const Base *b) const { return ((char *)b) + value; } int usedStorage(const Base *b) const; bool toBoolean() const; double toDouble(const Base *b) const; QString toString(const Base *b) const; String asString(const Base *b) const; Latin1String asLatin1String(const Base *b) const; Base *base(const Base *b) const; bool isValid(const Base *b) const; static int requiredStorage(QJsonValue &v, bool *compressed); static uint valueToStore(const QJsonValue &v, uint offset); static void copyData(const QJsonValue &v, char *dest, bool compressed); }; inline Value Array::at(int i) const { return *(Value *) (table() + i); } inline Value &Array::operator [](int i) { return *(Value *) (table() + i); } class Entry { public: Value value; // key // value data follows key int size() const { int s = sizeof(Entry); if (value.latinKey) s += sizeof(ushort) + qFromLittleEndian(*(ushort *) ((const char *)this + sizeof(Entry))); else s += sizeof(uint) + qFromLittleEndian(*(int *) ((const char *)this + sizeof(Entry))); return alignedSize(s); } int usedStorage(Base *b) const { return size() + value.usedStorage(b); } String shallowKey() const { Q_ASSERT(!value.latinKey); return String((const char *)this + sizeof(Entry)); } Latin1String shallowLatin1Key() const { Q_ASSERT(value.latinKey); return Latin1String((const char *)this + sizeof(Entry)); } QString key() const { if (value.latinKey) { return shallowLatin1Key().toString(); } return shallowKey().toString(); } bool operator ==(const QString &key) const; inline bool operator !=(const QString &key) const { return !operator ==(key); } inline bool operator >=(const QString &key) const; bool operator ==(const Entry &other) const; bool operator >=(const Entry &other) const; }; inline bool Entry::operator >=(const QString &key) const { if (value.latinKey) return (shallowLatin1Key() >= key); else return (shallowKey() >= key); } inline bool operator <(const QString &key, const Entry &e) { return e >= key; } class Header { public: qle_uint tag; // 'qbjs' qle_uint version; // 1 Base *root() { return (Base *)(this + 1); } }; inline bool Value::toBoolean() const { Q_ASSERT(type == QJsonValue::Bool); return value != 0; } inline double Value::toDouble(const Base *b) const { Q_ASSERT(type == QJsonValue::Double); if (latinOrIntValue) return int_value; quint64 i = qFromLittleEndian((const uchar *)b + value); double d; memcpy(&d, &i, sizeof(double)); return d; } inline String Value::asString(const Base *b) const { Q_ASSERT(type == QJsonValue::String && !latinOrIntValue); return String(data(b)); } inline Latin1String Value::asLatin1String(const Base *b) const { Q_ASSERT(type == QJsonValue::String && latinOrIntValue); return Latin1String(data(b)); } inline QString Value::toString(const Base *b) const { if (latinOrIntValue) return asLatin1String(b).toString(); else return asString(b).toString(); } inline Base *Value::base(const Base *b) const { Q_ASSERT(type == QJsonValue::Array || type == QJsonValue::Object); return reinterpret_cast(data(b)); } class Data { public: enum Validation { Unchecked, Validated, Invalid }; QAtomicInt ref; int alloc; union { char *rawData; Header *header; }; uint compactionCounter : 31; uint ownsData : 1; inline Data(char *raw, int a) : alloc(a), rawData(raw), compactionCounter(0), ownsData(true) { } inline Data(int reserved, QJsonValue::Type valueType) : rawData(0), compactionCounter(0), ownsData(true) { Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object); alloc = sizeof(Header) + sizeof(Base) + reserved + sizeof(offset); header = (Header *)malloc(alloc); Q_CHECK_PTR(header); header->tag = QJsonDocument::BinaryFormatTag; header->version = 1; Base *b = header->root(); b->size = sizeof(Base); b->is_object = (valueType == QJsonValue::Object); b->tableOffset = sizeof(Base); b->length = 0; } inline ~Data() { if (ownsData) free(rawData); } uint offsetOf(const void *ptr) const { return (uint)(((char *)ptr - rawData)); } QJsonObject toObject(Object *o) const { return QJsonObject(const_cast(this), o); } QJsonArray toArray(Array *a) const { return QJsonArray(const_cast(this), a); } Data *clone(Base *b, int reserve = 0) { int size = sizeof(Header) + b->size; if (b == header->root() && int(ref) == 1 && alloc >= size + reserve) return this; if (reserve) { if (reserve < 128) reserve = 128; size = qMax(size + reserve, size *2); } char *raw = (char *)malloc(size); Q_CHECK_PTR(raw); memcpy(raw + sizeof(Header), b, b->size); Header *h = (Header *)raw; h->tag = QJsonDocument::BinaryFormatTag; h->version = 1; Data *d = new Data(raw, size); d->compactionCounter = (b == header->root()) ? compactionCounter : 0; return d; } void compact(); bool valid() const; private: Q_DISABLE_COPY(Data) }; } QT_END_NAMESPACE #endif // QJSON_P_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonarray.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include "qjsonwriter_p.h" #include "qjson_p.h" QT_BEGIN_NAMESPACE /*! \class QJsonArray \inmodule QtCore \ingroup json \reentrant \since 5.0 \brief The QJsonArray class encapsulates a JSON array. A JSON array is a list of values. The list can be manipulated by inserting and removing QJsonValue's from the array. A QJsonArray can be converted to and from a QVariantList. You can query the number of entries with size(), insert(), and removeAt() entries from it and iterate over its content using the standard C++ iterator pattern. QJsonArray is an implicitly shared class and shares the data with the document it has been created from as long as it is not being modified. You can convert the array to and from text based JSON through QJsonDocument. \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef QJsonArray::Iterator Qt-style synonym for QJsonArray::iterator. */ /*! \typedef QJsonArray::ConstIterator Qt-style synonym for QJsonArray::const_iterator. */ /*! \typedef QJsonArray::size_type Typedef for int. Provided for STL compatibility. */ /*! \typedef QJsonArray::value_type Typedef for QJsonValue. Provided for STL compatibility. */ /*! \typedef QJsonArray::difference_type Typedef for int. Provided for STL compatibility. */ /*! \typedef QJsonArray::pointer Typedef for QJsonValue *. Provided for STL compatibility. */ /*! \typedef QJsonArray::const_pointer Typedef for const QJsonValue *. Provided for STL compatibility. */ /*! \typedef QJsonArray::reference Typedef for QJsonValue &. Provided for STL compatibility. */ /*! \typedef QJsonArray::const_reference Typedef for const QJsonValue &. Provided for STL compatibility. */ /*! Creates an empty array. */ QJsonArray::QJsonArray() : d(0), a(0) { } /*! \fn QJsonArray::QJsonArray(std::initializer_list args) \since 5.4 Creates an array initialized from \a args initialization list. QJsonArray can be constructed in a way similar to JSON notation, for example: \code QJsonArray array = { 1, 2.2, QString() }; \endcode */ /*! \internal */ QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array) : d(data), a(array) { Q_ASSERT(data); Q_ASSERT(array); d->ref.ref(); } /*! This method replaces part of QJsonArray(std::initializer_list args) . The constructor needs to be inline, but we do not want to leak implementation details of this class. \note this method is called for an uninitialized object \internal */ void QJsonArray::initialize() { d = 0; a = 0; } /*! Deletes the array. */ QJsonArray::~QJsonArray() { if (d && !d->ref.deref()) delete d; } /*! Creates a copy of \a other. Since QJsonArray is implicitly shared, the copy is shallow as long as the object doesn't get modified. */ QJsonArray::QJsonArray(const QJsonArray &other) { d = other.d; a = other.a; if (d) d->ref.ref(); } /*! Assigns \a other to this array. */ QJsonArray &QJsonArray::operator =(const QJsonArray &other) { if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } a = other.a; return *this; } /*! \fn QJsonArray &QJsonArray::operator+=(const QJsonValue &value) Appends \a value to the array, and returns a reference to the array itself. \since 5.3 \sa append(), operator<<() */ /*! \fn QJsonArray QJsonArray::operator+(const QJsonValue &value) const Returns an array that contains all the items in this array followed by the provided \a value. \since 5.3 \sa operator+=() */ /*! \fn QJsonArray &QJsonArray::operator<<(const QJsonValue &value) Appends \a value to the array, and returns a reference to the array itself. \since 5.3 \sa operator+=(), append() */ /*! Converts the string list \a list to a QJsonArray. The values in \a list will be converted to JSON values. \sa toVariantList(), QJsonValue::fromVariant() */ QJsonArray QJsonArray::fromStringList(const QStringList &list) { QJsonArray array; for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it) array.append(QJsonValue(*it)); return array; } /*! Converts the variant list \a list to a QJsonArray. The QVariant values in \a list will be converted to JSON values. \sa toVariantList(), QJsonValue::fromVariant() */ QJsonArray QJsonArray::fromVariantList(const QVariantList &list) { QJsonArray array; for (QVariantList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it) array.append(QJsonValue::fromVariant(*it)); return array; } /*! Converts this object to a QVariantList. Returns the created map. */ QVariantList QJsonArray::toVariantList() const { QVariantList list; if (a) { for (int i = 0; i < (int)a->length; ++i) list.append(QJsonValue(d, a, a->at(i)).toVariant()); } return list; } /*! Returns the number of values stored in the array. */ int QJsonArray::size() const { if (!d) return 0; return (int)a->length; } /*! \fn QJsonArray::count() const Same as size(). \sa size() */ /*! Returns \c true if the object is empty. This is the same as size() == 0. \sa size() */ bool QJsonArray::isEmpty() const { if (!d) return true; return !a->length; } /*! Returns a QJsonValue representing the value for index \a i. The returned QJsonValue is \c Undefined, if \a i is out of bounds. */ QJsonValue QJsonArray::at(int i) const { if (!a || i < 0 || i >= (int)a->length) return QJsonValue(QJsonValue::Undefined); return QJsonValue(d, a, a->at(i)); } /*! Returns the first value stored in the array. Same as \c at(0). \sa at() */ QJsonValue QJsonArray::first() const { return at(0); } /*! Returns the last value stored in the array. Same as \c{at(size() - 1)}. \sa at() */ QJsonValue QJsonArray::last() const { return at(a ? (a->length - 1) : 0); } /*! Inserts \a value at the beginning of the array. This is the same as \c{insert(0, value)} and will prepend \a value to the array. \sa append(), insert() */ void QJsonArray::prepend(const QJsonValue &value) { insert(0, value); } /*! Inserts \a value at the end of the array. \sa prepend(), insert() */ void QJsonArray::append(const QJsonValue &value) { insert(a ? (int)a->length : 0, value); } /*! Removes the value at index position \a i. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). \sa insert(), replace() */ void QJsonArray::removeAt(int i) { if (!a || i < 0 || i >= (int)a->length) return; detach(); a->removeItems(i, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) compact(); } /*! \fn void QJsonArray::removeFirst() Removes the first item in the array. Calling this function is equivalent to calling \c{removeAt(0)}. The array must not be empty. If the array can be empty, call isEmpty() before calling this function. \sa removeAt(), removeLast() */ /*! \fn void QJsonArray::removeLast() Removes the last item in the array. Calling this function is equivalent to calling \c{removeAt(size() - 1)}. The array must not be empty. If the array can be empty, call isEmpty() before calling this function. \sa removeAt(), removeFirst() */ /*! Removes the item at index position \a i and returns it. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). If you don't use the return value, removeAt() is more efficient. \sa removeAt() */ QJsonValue QJsonArray::takeAt(int i) { if (!a || i < 0 || i >= (int)a->length) return QJsonValue(QJsonValue::Undefined); QJsonValue v(d, a, a->at(i)); removeAt(i); // detaches return v; } /*! Inserts \a value at index position \a i in the array. If \a i is \c 0, the value is prepended to the array. If \a i is size(), the value is appended to the array. \sa append(), prepend(), replace(), removeAt() */ void QJsonArray::insert(int i, const QJsonValue &value) { Q_ASSERT (i >= 0 && i <= (a ? (int)a->length : 0)); QJsonValue val = value; bool compressed; int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); detach(valueSize + sizeof(QJsonPrivate::Value)); if (!a->length) a->tableOffset = sizeof(QJsonPrivate::Array); int valueOffset = a->reserveSpace(valueSize, i, 1, false); if (!valueOffset) return; QJsonPrivate::Value &v = (*a)[i]; v.type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); v.latinOrIntValue = compressed; v.latinKey = false; v.value = QJsonPrivate::Value::valueToStore(val, valueOffset); if (valueSize) QJsonPrivate::Value::copyData(val, (char *)a + valueOffset, compressed); } /*! \fn QJsonArray::iterator QJsonArray::insert(iterator before, const QJsonValue &value) Inserts \a value before the position pointed to by \a before, and returns an iterator pointing to the newly inserted item. \sa erase(), insert() */ /*! \fn QJsonArray::iterator QJsonArray::erase(iterator it) Removes the item pointed to by \a it, and returns an iterator pointing to the next item. \sa removeAt() */ /*! Replaces the item at index position \a i with \a value. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). \sa operator[](), removeAt() */ void QJsonArray::replace(int i, const QJsonValue &value) { Q_ASSERT (a && i >= 0 && i < (int)(a->length)); QJsonValue val = value; bool compressed; int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); detach(valueSize); if (!a->length) a->tableOffset = sizeof(QJsonPrivate::Array); int valueOffset = a->reserveSpace(valueSize, i, 1, true); if (!valueOffset) return; QJsonPrivate::Value &v = (*a)[i]; v.type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); v.latinOrIntValue = compressed; v.latinKey = false; v.value = QJsonPrivate::Value::valueToStore(val, valueOffset); if (valueSize) QJsonPrivate::Value::copyData(val, (char *)a + valueOffset, compressed); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) compact(); } /*! Returns \c true if the array contains an occurrence of \a value, otherwise \c false. \sa count() */ bool QJsonArray::contains(const QJsonValue &value) const { for (int i = 0; i < size(); i++) { if (at(i) == value) return true; } return false; } /*! Returns the value at index position \a i as a modifiable reference. \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the character in the QJsonArray of QJsonObject from which you got the reference. \sa at() */ QJsonValueRef QJsonArray::operator [](int i) { Q_ASSERT(a && i >= 0 && i < (int)a->length); return QJsonValueRef(this, i); } /*! \overload Same as at(). */ QJsonValue QJsonArray::operator[](int i) const { return at(i); } /*! Returns \c true if this array is equal to \a other. */ bool QJsonArray::operator==(const QJsonArray &other) const { if (a == other.a) return true; if (!a) return !other.a->length; if (!other.a) return !a->length; if (a->length != other.a->length) return false; for (int i = 0; i < (int)a->length; ++i) { if (QJsonValue(d, a, a->at(i)) != QJsonValue(other.d, other.a, other.a->at(i))) return false; } return true; } /*! Returns \c true if this array is not equal to \a other. */ bool QJsonArray::operator!=(const QJsonArray &other) const { return !(*this == other); } /*! \fn QJsonArray::iterator QJsonArray::begin() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the array. \sa constBegin(), end() */ /*! \fn QJsonArray::const_iterator QJsonArray::begin() const \overload */ /*! \fn QJsonArray::const_iterator QJsonArray::constBegin() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the array. \sa begin(), constEnd() */ /*! \fn QJsonArray::iterator QJsonArray::end() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the array. \sa begin(), constEnd() */ /*! \fn const_iterator QJsonArray::end() const \overload */ /*! \fn QJsonArray::const_iterator QJsonArray::constEnd() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the array. \sa constBegin(), end() */ /*! \fn void QJsonArray::push_back(const QJsonValue &value) This function is provided for STL compatibility. It is equivalent to \l{QJsonArray::append()}{append(value)} and will append \a value to the array. */ /*! \fn void QJsonArray::push_front(const QJsonValue &value) This function is provided for STL compatibility. It is equivalent to \l{QJsonArray::prepend()}{prepend(value)} and will prepend \a value to the array. */ /*! \fn void QJsonArray::pop_front() This function is provided for STL compatibility. It is equivalent to removeFirst(). The array must not be empty. If the array can be empty, call isEmpty() before calling this function. */ /*! \fn void QJsonArray::pop_back() This function is provided for STL compatibility. It is equivalent to removeLast(). The array must not be empty. If the array can be empty, call isEmpty() before calling this function. */ /*! \fn bool QJsonArray::empty() const This function is provided for STL compatibility. It is equivalent to isEmpty() and returns \c true if the array is empty. */ /*! \class QJsonArray::iterator \inmodule QtCore \brief The QJsonArray::iterator class provides an STL-style non-const iterator for QJsonArray. QJsonArray::iterator allows you to iterate over a QJsonArray and to modify the array item associated with the iterator. If you want to iterate over a const QJsonArray, use QJsonArray::const_iterator instead. It is generally a good practice to use QJsonArray::const_iterator on a non-const QJsonArray as well, unless you need to change the QJsonArray through the iterator. Const iterators are slightly faster and improves code readability. The default QJsonArray::iterator constructor creates an uninitialized iterator. You must initialize it using a QJsonArray function like QJsonArray::begin(), QJsonArray::end(), or QJsonArray::insert() before you can start iterating. Most QJsonArray functions accept an integer index rather than an iterator. For that reason, iterators are rarely useful in connection with QJsonArray. One place where STL-style iterators do make sense is as arguments to \l{generic algorithms}. Multiple iterators can be used on the same array. However, be aware that any non-const function call performed on the QJsonArray will render all existing iterators undefined. \sa QJsonArray::const_iterator */ /*! \typedef QJsonArray::iterator::iterator_category A synonym for \e {std::random_access_iterator_tag} indicating this iterator is a random access iterator. */ /*! \typedef QJsonArray::iterator::difference_type \internal */ /*! \typedef QJsonArray::iterator::value_type \internal */ /*! \typedef QJsonArray::iterator::reference \internal */ /*! \typedef QJsonArray::iterator::pointer \internal */ /*! \fn QJsonArray::iterator::iterator() Constructs an uninitialized iterator. Functions like operator*() and operator++() should not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa QJsonArray::begin(), QJsonArray::end() */ /*! \fn QJsonArray::iterator::iterator(QJsonArray *array, int index) \internal */ /*! \fn QJsonValueRef QJsonArray::iterator::operator*() const Returns a modifiable reference to the current item. You can change the value of an item by using operator*() on the left side of an assignment. The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the character in the QJsonArray of QJsonObject from which you got the reference. */ /*! \fn QJsonValueRef *QJsonArray::iterator::operator->() const Returns a pointer to a modifiable reference to the current item. */ /*! \fn QJsonValueRef QJsonArray::iterator::operator[](int j) const Returns a modifiable reference to the item at offset \a j from the item pointed to by this iterator (the item at position \c{*this + j}). This function is provided to make QJsonArray iterators behave like C++ pointers. The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the character in the QJsonArray of QJsonObject from which you got the reference. \sa operator+() */ /*! \fn bool QJsonArray::iterator::operator==(const iterator &other) const \fn bool QJsonArray::iterator::operator==(const const_iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool QJsonArray::iterator::operator!=(const iterator &other) const \fn bool QJsonArray::iterator::operator!=(const const_iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn bool QJsonArray::iterator::operator<(const iterator& other) const \fn bool QJsonArray::iterator::operator<(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than the item pointed to by the \a other iterator. */ /*! \fn bool QJsonArray::iterator::operator<=(const iterator& other) const \fn bool QJsonArray::iterator::operator<=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than or equal to the item pointed to by the \a other iterator. */ /*! \fn bool QJsonArray::iterator::operator>(const iterator& other) const \fn bool QJsonArray::iterator::operator>(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than the item pointed to by the \a other iterator. */ /*! \fn bool QJsonArray::iterator::operator>=(const iterator& other) const \fn bool QJsonArray::iterator::operator>=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than or equal to the item pointed to by the \a other iterator. */ /*! \fn QJsonArray::iterator &QJsonArray::iterator::operator++() The prefix ++ operator, \c{++it}, advances the iterator to the next item in the array and returns an iterator to the new current item. Calling this function on QJsonArray::end() leads to undefined results. \sa operator--() */ /*! \fn QJsonArray::iterator QJsonArray::iterator::operator++(int) \overload The postfix ++ operator, \c{it++}, advances the iterator to the next item in the array and returns an iterator to the previously current item. */ /*! \fn QJsonArray::iterator &QJsonArray::iterator::operator--() The prefix -- operator, \c{--it}, makes the preceding item current and returns an iterator to the new current item. Calling this function on QJsonArray::begin() leads to undefined results. \sa operator++() */ /*! \fn QJsonArray::iterator QJsonArray::iterator::operator--(int) \overload The postfix -- operator, \c{it--}, makes the preceding item current and returns an iterator to the previously current item. */ /*! \fn QJsonArray::iterator &QJsonArray::iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. \sa operator-=(), operator+() */ /*! \fn QJsonArray::iterator &QJsonArray::iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. \sa operator+=(), operator-() */ /*! \fn QJsonArray::iterator QJsonArray::iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. \sa operator-(), operator+=() */ /*! \fn QJsonArray::iterator QJsonArray::iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. \sa operator+(), operator-=() */ /*! \fn int QJsonArray::iterator::operator-(iterator other) const Returns the number of items between the item pointed to by \a other and the item pointed to by this iterator. */ /*! \class QJsonArray::const_iterator \inmodule QtCore \brief The QJsonArray::const_iterator class provides an STL-style const iterator for QJsonArray. QJsonArray::const_iterator allows you to iterate over a QJsonArray. If you want to modify the QJsonArray as you iterate over it, use QJsonArray::iterator instead. It is generally a good practice to use QJsonArray::const_iterator on a non-const QJsonArray as well, unless you need to change the QJsonArray through the iterator. Const iterators are slightly faster and improves code readability. The default QJsonArray::const_iterator constructor creates an uninitialized iterator. You must initialize it using a QJsonArray function like QJsonArray::constBegin(), QJsonArray::constEnd(), or QJsonArray::insert() before you can start iterating. Most QJsonArray functions accept an integer index rather than an iterator. For that reason, iterators are rarely useful in connection with QJsonArray. One place where STL-style iterators do make sense is as arguments to \l{generic algorithms}. Multiple iterators can be used on the same array. However, be aware that any non-const function call performed on the QJsonArray will render all existing iterators undefined. \sa QJsonArray::iterator */ /*! \fn QJsonArray::const_iterator::const_iterator() Constructs an uninitialized iterator. Functions like operator*() and operator++() should not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa QJsonArray::constBegin(), QJsonArray::constEnd() */ /*! \fn QJsonArray::const_iterator::const_iterator(const QJsonArray *array, int index) \internal */ /*! \typedef QJsonArray::const_iterator::iterator_category A synonym for \e {std::random_access_iterator_tag} indicating this iterator is a random access iterator. */ /*! \typedef QJsonArray::const_iterator::difference_type \internal */ /*! \typedef QJsonArray::const_iterator::value_type \internal */ /*! \typedef QJsonArray::const_iterator::reference \internal */ /*! \typedef QJsonArray::const_iterator::pointer \internal */ /*! \fn QJsonArray::const_iterator::const_iterator(const const_iterator &other) Constructs a copy of \a other. */ /*! \fn QJsonArray::const_iterator::const_iterator(const iterator &other) Constructs a copy of \a other. */ /*! \fn QJsonValue QJsonArray::const_iterator::operator*() const Returns the current item. */ /*! \fn QJsonValue *QJsonArray::const_iterator::operator->() const Returns a pointer to the current item. */ /*! \fn QJsonValue QJsonArray::const_iterator::operator[](int j) const Returns the item at offset \a j from the item pointed to by this iterator (the item at position \c{*this + j}). This function is provided to make QJsonArray iterators behave like C++ pointers. \sa operator+() */ /*! \fn bool QJsonArray::const_iterator::operator==(const const_iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool QJsonArray::const_iterator::operator!=(const const_iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn bool QJsonArray::const_iterator::operator<(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than the item pointed to by the \a other iterator. */ /*! \fn bool QJsonArray::const_iterator::operator<=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is less than or equal to the item pointed to by the \a other iterator. */ /*! \fn bool QJsonArray::const_iterator::operator>(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than the item pointed to by the \a other iterator. */ /*! \fn bool QJsonArray::const_iterator::operator>=(const const_iterator& other) const Returns \c true if the item pointed to by this iterator is greater than or equal to the item pointed to by the \a other iterator. */ /*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator++() The prefix ++ operator, \c{++it}, advances the iterator to the next item in the array and returns an iterator to the new current item. Calling this function on QJsonArray::end() leads to undefined results. \sa operator--() */ /*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator++(int) \overload The postfix ++ operator, \c{it++}, advances the iterator to the next item in the array and returns an iterator to the previously current item. */ /*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator--() The prefix -- operator, \c{--it}, makes the preceding item current and returns an iterator to the new current item. Calling this function on QJsonArray::begin() leads to undefined results. \sa operator++() */ /*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator--(int) \overload The postfix -- operator, \c{it--}, makes the preceding item current and returns an iterator to the previously current item. */ /*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. \sa operator-=(), operator+() */ /*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. \sa operator+=(), operator-() */ /*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. \sa operator-(), operator+=() */ /*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. \sa operator+(), operator-=() */ /*! \fn int QJsonArray::const_iterator::operator-(const_iterator other) const Returns the number of items between the item pointed to by \a other and the item pointed to by this iterator. */ /*! \internal */ void QJsonArray::detach(uint reserve) { if (!d) { d = new QJsonPrivate::Data(reserve, QJsonValue::Array); a = static_cast(d->header->root()); d->ref.ref(); return; } /* if (reserve == 0 && d->ref.load() == 1) return; */ if (reserve == 0 && int(d->ref) == 1) return; QJsonPrivate::Data *x = d->clone(a, reserve); x->ref.ref(); if (!d->ref.deref()) delete d; d = x; a = static_cast(d->header->root()); } /*! \internal */ void QJsonArray::compact() { if (!d || !d->compactionCounter) return; detach(); d->compact(); a = static_cast(d->header->root()); } #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonArray &a) { if (!a.a) { dbg << "QJsonArray()"; return dbg; } QByteArray json; QJsonPrivate::Writer::arrayToJson(a.a, json, 0, true); dbg.nospace() << "QJsonArray(" << json.constData() // print as utf-8 string without extra quotation marks << ")"; return dbg.space(); } #endif QT_END_NAMESPACE ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonarray.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QJSONARRAY_H #define QJSONARRAY_H #include "qjsonvalue.h" #include #include #if defined(Q_COMPILER_INITIALIZER_LISTS) #include #endif QT_BEGIN_NAMESPACE class QDebug; class QStringList; template class QList; typedef QList QVariantList; class QJSON_EXPORT QJsonArray { public: QJsonArray(); #if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) QJsonArray(std::initializer_list args) { initialize(); for (std::initializer_list::const_iterator i = args.begin(); i != args.end(); ++i) append(*i); } #endif ~QJsonArray(); QJsonArray(const QJsonArray &other); QJsonArray &operator =(const QJsonArray &other); static QJsonArray fromStringList(const QStringList &list); static QJsonArray fromVariantList(const QVariantList &list); QVariantList toVariantList() const; int size() const; inline int count() const { return size(); } bool isEmpty() const; QJsonValue at(int i) const; QJsonValue first() const; QJsonValue last() const; void prepend(const QJsonValue &value); void append(const QJsonValue &value); void removeAt(int i); QJsonValue takeAt(int i); inline void removeFirst() { removeAt(0); } inline void removeLast() { removeAt(size() - 1); } void insert(int i, const QJsonValue &value); void replace(int i, const QJsonValue &value); bool contains(const QJsonValue &element) const; QJsonValueRef operator[](int i); QJsonValue operator[](int i) const; bool operator==(const QJsonArray &other) const; bool operator!=(const QJsonArray &other) const; class const_iterator; class iterator { public: QJsonArray *a; int i; typedef std::random_access_iterator_tag iterator_category; typedef int difference_type; typedef QJsonValue value_type; typedef QJsonValueRef reference; typedef QJsonValueRefPtr pointer; inline iterator() : a(0), i(0) { } explicit inline iterator(QJsonArray *array, int index) : a(array), i(index) { } inline QJsonValueRef operator*() const { return QJsonValueRef(a, i); } #ifdef Q_QDOC inline QJsonValueRef* operator->() const; #else inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(a, i); } #endif inline QJsonValueRef operator[](int j) const { return QJsonValueRef(a, i + j); } inline bool operator==(const iterator &o) const { return i == o.i; } inline bool operator!=(const iterator &o) const { return i != o.i; } inline bool operator<(const iterator& other) const { return i < other.i; } inline bool operator<=(const iterator& other) const { return i <= other.i; } inline bool operator>(const iterator& other) const { return i > other.i; } inline bool operator>=(const iterator& other) const { return i >= other.i; } inline bool operator==(const const_iterator &o) const { return i == o.i; } inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline bool operator<(const const_iterator& other) const { return i < other.i; } inline bool operator<=(const const_iterator& other) const { return i <= other.i; } inline bool operator>(const const_iterator& other) const { return i > other.i; } inline bool operator>=(const const_iterator& other) const { return i >= other.i; } inline iterator &operator++() { ++i; return *this; } inline iterator operator++(int) { iterator n = *this; ++i; return n; } inline iterator &operator--() { i--; return *this; } inline iterator operator--(int) { iterator n = *this; i--; return n; } inline iterator &operator+=(int j) { i+=j; return *this; } inline iterator &operator-=(int j) { i-=j; return *this; } inline iterator operator+(int j) const { return iterator(a, i+j); } inline iterator operator-(int j) const { return iterator(a, i-j); } inline int operator-(iterator j) const { return i - j.i; } }; friend class iterator; class const_iterator { public: const QJsonArray *a; int i; typedef std::random_access_iterator_tag iterator_category; typedef qptrdiff difference_type; typedef QJsonValue value_type; typedef QJsonValue reference; typedef QJsonValuePtr pointer; inline const_iterator() : a(0), i(0) { } explicit inline const_iterator(const QJsonArray *array, int index) : a(array), i(index) { } inline const_iterator(const const_iterator &o) : a(o.a), i(o.i) {} inline const_iterator(const iterator &o) : a(o.a), i(o.i) {} inline QJsonValue operator*() const { return a->at(i); } #ifdef Q_QDOC inline QJsonValue* operator->() const; #else inline QJsonValuePtr operator->() const { return QJsonValuePtr(a->at(i)); } #endif inline QJsonValue operator[](int j) const { return a->at(i+j); } inline bool operator==(const const_iterator &o) const { return i == o.i; } inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline bool operator<(const const_iterator& other) const { return i < other.i; } inline bool operator<=(const const_iterator& other) const { return i <= other.i; } inline bool operator>(const const_iterator& other) const { return i > other.i; } inline bool operator>=(const const_iterator& other) const { return i >= other.i; } inline const_iterator &operator++() { ++i; return *this; } inline const_iterator operator++(int) { const_iterator n = *this; ++i; return n; } inline const_iterator &operator--() { i--; return *this; } inline const_iterator operator--(int) { const_iterator n = *this; i--; return n; } inline const_iterator &operator+=(int j) { i+=j; return *this; } inline const_iterator &operator-=(int j) { i-=j; return *this; } inline const_iterator operator+(int j) const { return const_iterator(a, i+j); } inline const_iterator operator-(int j) const { return const_iterator(a, i-j); } inline int operator-(const_iterator j) const { return i - j.i; } }; friend class const_iterator; // stl style inline iterator begin() { detach(); return iterator(this, 0); } inline const_iterator begin() const { return const_iterator(this, 0); } inline const_iterator constBegin() const { return const_iterator(this, 0); } inline iterator end() { detach(); return iterator(this, size()); } inline const_iterator end() const { return const_iterator(this, size()); } inline const_iterator constEnd() const { return const_iterator(this, size()); } iterator insert(iterator before, const QJsonValue &value) { insert(before.i, value); return before; } iterator erase(iterator it) { removeAt(it.i); return it; } // more Qt typedef iterator Iterator; typedef const_iterator ConstIterator; // convenience inline QJsonArray operator+(const QJsonValue &v) const { QJsonArray n = *this; n += v; return n; } inline QJsonArray &operator+=(const QJsonValue &v) { append(v); return *this; } inline QJsonArray &operator<< (const QJsonValue &v) { append(v); return *this; } // stl compatibility inline void push_back(const QJsonValue &t) { append(t); } inline void push_front(const QJsonValue &t) { prepend(t); } inline void pop_front() { removeFirst(); } inline void pop_back() { removeLast(); } inline bool empty() const { return isEmpty(); } typedef int size_type; typedef QJsonValue value_type; typedef value_type *pointer; typedef const value_type *const_pointer; typedef QJsonValueRef reference; typedef QJsonValue const_reference; typedef int difference_type; private: friend class QJsonPrivate::Data; friend class QJsonValue; friend class QJsonDocument; friend QJSON_EXPORT QDebug operator<<(QDebug, const QJsonArray &); QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array); void initialize(); void compact(); void detach(uint reserve = 0); QJsonPrivate::Data *d; QJsonPrivate::Array *a; }; Q_DECLARE_METATYPE(QJsonArray) #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QJSON_EXPORT QDebug operator<<(QDebug, const QJsonArray &); #endif QT_END_NAMESPACE #endif // QJSONARRAY_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsondocument.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qjsondocument.h" #include "qjsonobject.h" #include "qjsonvalue.h" #include "qjsonarray.h" #include #include #include #include "qjsonwriter_p.h" #include "qjsonparser_p.h" #include "qjson_p.h" QT_BEGIN_NAMESPACE /*! \class QJsonDocument \inmodule QtCore \ingroup json \reentrant \since 5.0 \brief The QJsonDocument class provides a way to read and write JSON documents. QJsonDocument is a class that wraps a complete JSON document and can read and write this document both from a UTF-8 encoded text based representation as well as Qt's own binary format. A JSON document can be converted from its text-based representation to a QJsonDocument using QJsonDocument::fromJson(). toJson() converts it back to text. The parser is very fast and efficient and converts the JSON to the binary representation used by Qt. Validity of the parsed document can be queried with !isNull() A document can be queried as to whether it contains an array or an object using isArray() and isObject(). The array or object contained in the document can be retrieved using array() or object() and then read or manipulated. A document can also be created from a stored binary representation using fromBinaryData() or fromRawData(). \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! * Constructs an empty and invalid document. */ QJsonDocument::QJsonDocument() : d(0) { } /*! * Creates a QJsonDocument from \a object. */ QJsonDocument::QJsonDocument(const QJsonObject &object) : d(0) { setObject(object); } /*! * Constructs a QJsonDocument from \a array. */ QJsonDocument::QJsonDocument(const QJsonArray &array) : d(0) { setArray(array); } /*! \internal */ QJsonDocument::QJsonDocument(QJsonPrivate::Data *data) : d(data) { Q_ASSERT(d); d->ref.ref(); } /*! Deletes the document. Binary data set with fromRawData is not freed. */ QJsonDocument::~QJsonDocument() { if (d && !d->ref.deref()) delete d; } /*! * Creates a copy of the \a other document. */ QJsonDocument::QJsonDocument(const QJsonDocument &other) { d = other.d; if (d) d->ref.ref(); } /*! * Assigns the \a other document to this QJsonDocument. * Returns a reference to this object. */ QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other) { if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } return *this; } /*! \enum QJsonDocument::DataValidation This value is used to tell QJsonDocument whether to validate the binary data when converting to a QJsonDocument using fromBinaryData() or fromRawData(). \value Validate Validate the data before using it. This is the default. \value BypassValidation Bypasses data validation. Only use if you received the data from a trusted place and know it's valid, as using of invalid data can crash the application. */ /*! Creates a QJsonDocument that uses the first \a size bytes from \a data. It assumes \a data contains a binary encoded JSON document. The created document does not take ownership of \a data and the caller has to guarantee that \a data will not be deleted or modified as long as any QJsonDocument, QJsonObject or QJsonArray still references the data. \a data has to be aligned to a 4 byte boundary. \a validation decides whether the data is checked for validity before being used. By default the data is validated. If the \a data is not valid, the method returns a null document. Returns a QJsonDocument representing the data. \sa rawData(), fromBinaryData(), isNull(), DataValidation */ QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation) { if (quintptr(data) & 3) { qWarning() <<"QJsonDocument::fromRawData: data has to have 4 byte alignment"; return QJsonDocument(); } QJsonPrivate::Data *d = new QJsonPrivate::Data((char *)data, size); d->ownsData = false; if (validation != BypassValidation && !d->valid()) { delete d; return QJsonDocument(); } return QJsonDocument(d); } /*! Returns the raw binary representation of the data \a size will contain the size of the returned data. This method is useful to e.g. stream the JSON document in it's binary form to a file. */ const char *QJsonDocument::rawData(int *size) const { if (!d) { *size = 0; return 0; } *size = d->alloc; return d->rawData; } /*! Creates a QJsonDocument from \a data. \a validation decides whether the data is checked for validity before being used. By default the data is validated. If the \a data is not valid, the method returns a null document. \sa toBinaryData(), fromRawData(), isNull(), DataValidation */ QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation) { if (data.size() < (int)(sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base))) return QJsonDocument(); QJsonPrivate::Header h; memcpy(&h, data.constData(), sizeof(QJsonPrivate::Header)); QJsonPrivate::Base root; memcpy(&root, data.constData() + sizeof(QJsonPrivate::Header), sizeof(QJsonPrivate::Base)); // do basic checks here, so we don't try to allocate more memory than we can. if (h.tag != QJsonDocument::BinaryFormatTag || h.version != 1u || sizeof(QJsonPrivate::Header) + root.size > (uint)data.size()) return QJsonDocument(); const uint size = sizeof(QJsonPrivate::Header) + root.size; char *raw = (char *)malloc(size); if (!raw) return QJsonDocument(); memcpy(raw, data.constData(), size); QJsonPrivate::Data *d = new QJsonPrivate::Data(raw, size); if (validation != BypassValidation && !d->valid()) { delete d; return QJsonDocument(); } return QJsonDocument(d); } /*! Creates a QJsonDocument from the QVariant \a variant. If the \a variant contains any other type than a QVariantMap, QVariantList or QStringList, the returned document document is invalid. \sa toVariant() */ QJsonDocument QJsonDocument::fromVariant(const QVariant &variant) { QJsonDocument doc; if (variant.type() == QVariant::Map) { doc.setObject(QJsonObject::fromVariantMap(variant.toMap())); } else if (variant.type() == QVariant::List) { doc.setArray(QJsonArray::fromVariantList(variant.toList())); } else if (variant.type() == QVariant::StringList) { doc.setArray(QJsonArray::fromStringList(variant.toStringList())); } return doc; } /*! Returns a QVariant representing the Json document. The returned variant will be a QVariantList if the document is a QJsonArray and a QVariantMap if the document is a QJsonObject. \sa fromVariant(), QJsonValue::toVariant() */ QVariant QJsonDocument::toVariant() const { if (!d) return QVariant(); if (d->header->root()->isArray()) return QJsonArray(d, static_cast(d->header->root())).toVariantList(); else return QJsonObject(d, static_cast(d->header->root())).toVariantMap(); } /*! Converts the QJsonDocument to a UTF-8 encoded JSON document. \sa fromJson() */ #ifndef QT_JSON_READONLY QByteArray QJsonDocument::toJson() const { return toJson(Indented); } #endif /*! \enum QJsonDocument::JsonFormat This value defines the format of the JSON byte array produced when converting to a QJsonDocument using toJson(). \value Indented Defines human readable output as follows: \code { "Array": [ true, 999, "string" ], "Key": "Value", "null": null } \endcode \value Compact Defines a compact output as follows: \code {"Array":[true,999,"string"],"Key":"Value","null":null} \endcode */ /*! Converts the QJsonDocument to a UTF-8 encoded JSON document in the provided \a format. \sa fromJson(), JsonFormat */ #ifndef QT_JSON_READONLY QByteArray QJsonDocument::toJson(JsonFormat format) const { if (!d) return QByteArray(); QByteArray json; if (d->header->root()->isArray()) QJsonPrivate::Writer::arrayToJson(static_cast(d->header->root()), json, 0, (format == Compact)); else QJsonPrivate::Writer::objectToJson(static_cast(d->header->root()), json, 0, (format == Compact)); return json; } #endif /*! Parses a UTF-8 encoded JSON document and creates a QJsonDocument from it. \a json contains the json document to be parsed. The optional \a error variable can be used to pass in a QJsonParseError data structure that will contain information about possible errors encountered during parsing. \sa toJson(), QJsonParseError */ QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error) { QJsonPrivate::Parser parser(json.constData(), json.length()); return parser.parse(error); } /*! Returns \c true if the document doesn't contain any data. */ bool QJsonDocument::isEmpty() const { if (!d) return true; return false; } /*! Returns a binary representation of the document. The binary representation is also the native format used internally in Qt, and is very efficient and fast to convert to and from. The binary format can be stored on disk and interchanged with other applications or computers. fromBinaryData() can be used to convert it back into a JSON document. \sa fromBinaryData() */ QByteArray QJsonDocument::toBinaryData() const { if (!d || !d->rawData) return QByteArray(); return QByteArray(d->rawData, d->header->root()->size + sizeof(QJsonPrivate::Header)); } /*! Returns \c true if the document contains an array. \sa array(), isObject() */ bool QJsonDocument::isArray() const { if (!d) return false; QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData; return h->root()->isArray(); } /*! Returns \c true if the document contains an object. \sa object(), isArray() */ bool QJsonDocument::isObject() const { if (!d) return false; QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData; return h->root()->isObject(); } /*! Returns the QJsonObject contained in the document. Returns an empty object if the document contains an array. \sa isObject(), array(), setObject() */ QJsonObject QJsonDocument::object() const { if (d) { QJsonPrivate::Base *b = d->header->root(); if (b->isObject()) return QJsonObject(d, static_cast(b)); } return QJsonObject(); } /*! Returns the QJsonArray contained in the document. Returns an empty array if the document contains an object. \sa isArray(), object(), setArray() */ QJsonArray QJsonDocument::array() const { if (d) { QJsonPrivate::Base *b = d->header->root(); if (b->isArray()) return QJsonArray(d, static_cast(b)); } return QJsonArray(); } /*! Sets \a object as the main object of this document. \sa setArray(), object() */ void QJsonDocument::setObject(const QJsonObject &object) { if (d && !d->ref.deref()) delete d; d = object.d; if (!d) { d = new QJsonPrivate::Data(0, QJsonValue::Object); } else if (d->compactionCounter || object.o != d->header->root()) { QJsonObject o(object); if (d->compactionCounter) o.compact(); else o.detach(); d = o.d; d->ref.ref(); return; } d->ref.ref(); } /*! Sets \a array as the main object of this document. \sa setObject(), array() */ void QJsonDocument::setArray(const QJsonArray &array) { if (d && !d->ref.deref()) delete d; d = array.d; if (!d) { d = new QJsonPrivate::Data(0, QJsonValue::Array); } else if (d->compactionCounter || array.a != d->header->root()) { QJsonArray a(array); if (d->compactionCounter) a.compact(); else a.detach(); d = a.d; d->ref.ref(); return; } d->ref.ref(); } /*! Returns \c true if the \a other document is equal to this document. */ bool QJsonDocument::operator==(const QJsonDocument &other) const { if (d == other.d) return true; if (!d || !other.d) return false; if (d->header->root()->isArray() != other.d->header->root()->isArray()) return false; if (d->header->root()->isObject()) return QJsonObject(d, static_cast(d->header->root())) == QJsonObject(other.d, static_cast(other.d->header->root())); else return QJsonArray(d, static_cast(d->header->root())) == QJsonArray(other.d, static_cast(other.d->header->root())); } /*! \fn bool QJsonDocument::operator!=(const QJsonDocument &other) const returns \c true if \a other is not equal to this document */ /*! returns \c true if this document is null. Null documents are documents created through the default constructor. Documents created from UTF-8 encoded text or the binary format are validated during parsing. If validation fails, the returned document will also be null. */ bool QJsonDocument::isNull() const { return (d == 0); } #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonDocument &o) { if (!o.d) { dbg << "QJsonDocument()"; return dbg; } QByteArray json; if (o.d->header->root()->isArray()) QJsonPrivate::Writer::arrayToJson(static_cast(o.d->header->root()), json, 0, true); else QJsonPrivate::Writer::objectToJson(static_cast(o.d->header->root()), json, 0, true); dbg.nospace() << "QJsonDocument(" << json.constData() // print as utf-8 string without extra quotation marks << ")"; return dbg.space(); } #endif QT_END_NAMESPACE ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsondocument.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QJSONDOCUMENT_H #define QJSONDOCUMENT_H #include "qjsonvalue.h" QT_BEGIN_NAMESPACE class QDebug; namespace QJsonPrivate { class Parser; } struct QJSON_EXPORT QJsonParseError { enum ParseError { NoError = 0, UnterminatedObject, MissingNameSeparator, UnterminatedArray, MissingValueSeparator, IllegalValue, TerminationByNumber, IllegalNumber, IllegalEscapeSequence, IllegalUTF8String, UnterminatedString, MissingObject, DeepNesting, DocumentTooLarge, GarbageAtEnd }; QString errorString() const; int offset; ParseError error; }; class QJSON_EXPORT QJsonDocument { public: #ifdef Q_LITTLE_ENDIAN static const uint BinaryFormatTag = ('q') | ('b' << 8) | ('j' << 16) | ('s' << 24); #else static const uint BinaryFormatTag = ('q' << 24) | ('b' << 16) | ('j' << 8) | ('s'); #endif QJsonDocument(); explicit QJsonDocument(const QJsonObject &object); explicit QJsonDocument(const QJsonArray &array); ~QJsonDocument(); QJsonDocument(const QJsonDocument &other); QJsonDocument &operator =(const QJsonDocument &other); enum DataValidation { Validate, BypassValidation }; static QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate); const char *rawData(int *size) const; static QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate); QByteArray toBinaryData() const; static QJsonDocument fromVariant(const QVariant &variant); QVariant toVariant() const; enum JsonFormat { Indented, Compact }; static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = 0); #ifdef Q_QDOC QByteArray toJson(JsonFormat format = Indented) const; #elif !defined(QT_JSON_READONLY) QByteArray toJson() const; //### Merge in Qt6 QByteArray toJson(JsonFormat format) const; #endif bool isEmpty() const; bool isArray() const; bool isObject() const; QJsonObject object() const; QJsonArray array() const; void setObject(const QJsonObject &object); void setArray(const QJsonArray &array); bool operator==(const QJsonDocument &other) const; bool operator!=(const QJsonDocument &other) const { return !(*this == other); } bool isNull() const; private: friend class QJsonValue; friend class QJsonPrivate::Data; friend class QJsonPrivate::Parser; friend QJSON_EXPORT QDebug operator<<(QDebug, const QJsonDocument &); QJsonDocument(QJsonPrivate::Data *data); QJsonPrivate::Data *d; }; #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QJSON_EXPORT QDebug operator<<(QDebug, const QJsonDocument &); #endif QT_END_NAMESPACE #endif // QJSONDOCUMENT_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonobject.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include "qjson_p.h" #include "qjsonwriter_p.h" QT_BEGIN_NAMESPACE /*! \class QJsonObject \inmodule QtCore \ingroup json \reentrant \since 5.0 \brief The QJsonObject class encapsulates a JSON object. A JSON object is a list of key value pairs, where the keys are unique strings and the values are represented by a QJsonValue. A QJsonObject can be converted to and from a QVariantMap. You can query the number of (key, value) pairs with size(), insert(), and remove() entries from it and iterate over its content using the standard C++ iterator pattern. QJsonObject is an implicitly shared class, and shares the data with the document it has been created from as long as it is not being modified. You can convert the object to and from text based JSON through QJsonDocument. \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef QJsonObject::Iterator Qt-style synonym for QJsonObject::iterator. */ /*! \typedef QJsonObject::ConstIterator Qt-style synonym for QJsonObject::const_iterator. */ /*! \typedef QJsonObject::key_type Typedef for QString. Provided for STL compatibility. */ /*! \typedef QJsonObject::mapped_type Typedef for QJsonValue. Provided for STL compatibility. */ /*! \typedef QJsonObject::size_type Typedef for int. Provided for STL compatibility. */ /*! Constructs an empty JSON object. \sa isEmpty() */ QJsonObject::QJsonObject() : d(0), o(0) { } /*! \fn QJsonObject::QJsonObject(std::initializer_list > args) \since 5.4 Constructs a QJsonObject instance initialized from \a args initialization list. For example: \code QJsonObject object { {"property1", 1}, {"property2", 2} }; \endcode */ /*! \internal */ QJsonObject::QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object) : d(data), o(object) { Q_ASSERT(d); Q_ASSERT(o); d->ref.ref(); } /*! This method replaces part of the QJsonObject(std::initializer_list> args) body. The constructor needs to be inline, but we do not want to leak implementation details of this class. \note this method is called for an uninitialized object \internal */ void QJsonObject::initialize() { d = 0; o = 0; } /*! Destroys the object. */ QJsonObject::~QJsonObject() { if (d && !d->ref.deref()) delete d; } /*! Creates a copy of \a other. Since QJsonObject is implicitly shared, the copy is shallow as long as the object does not get modified. */ QJsonObject::QJsonObject(const QJsonObject &other) { d = other.d; o = other.o; if (d) d->ref.ref(); } /*! Assigns \a other to this object. */ QJsonObject &QJsonObject::operator =(const QJsonObject &other) { if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } o = other.o; return *this; } /*! Converts the variant map \a map to a QJsonObject. The keys in \a map will be used as the keys in the JSON object, and the QVariant values will be converted to JSON values. \sa toVariantMap(), QJsonValue::fromVariant() */ QJsonObject QJsonObject::fromVariantMap(const QVariantMap &map) { // ### this is implemented the trivial way, not the most efficient way QJsonObject object; for (QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) object.insert(it.key(), QJsonValue::fromVariant(it.value())); return object; } /*! Converts this object to a QVariantMap. Returns the created map. */ QVariantMap QJsonObject::toVariantMap() const { QVariantMap map; if (o) { for (uint i = 0; i < o->length; ++i) { QJsonPrivate::Entry *e = o->entryAt(i); map.insert(e->key(), QJsonValue(d, o, e->value).toVariant()); } } return map; } /*! Returns a list of all keys in this object. */ QStringList QJsonObject::keys() const { if (!d) return QStringList(); QStringList keys; for (uint i = 0; i < o->length; ++i) { QJsonPrivate::Entry *e = o->entryAt(i); keys.append(e->key()); } return keys; } /*! Returns the number of (key, value) pairs stored in the object. */ int QJsonObject::size() const { if (!d) return 0; return o->length; } /*! Returns \c true if the object is empty. This is the same as size() == 0. \sa size() */ bool QJsonObject::isEmpty() const { if (!d) return true; return !o->length; } /*! Returns a QJsonValue representing the value for the key \a key. The returned QJsonValue is QJsonValue::Undefined if the key does not exist. \sa QJsonValue, QJsonValue::isUndefined() */ QJsonValue QJsonObject::value(const QString &key) const { if (!d) return QJsonValue(QJsonValue::Undefined); bool keyExists; int i = o->indexOf(key, &keyExists); if (!keyExists) return QJsonValue(QJsonValue::Undefined); return QJsonValue(d, o, o->entryAt(i)->value); } /*! Returns a QJsonValue representing the value for the key \a key. This does the same as value(). The returned QJsonValue is QJsonValue::Undefined if the key does not exist. \sa value(), QJsonValue, QJsonValue::isUndefined() */ QJsonValue QJsonObject::operator [](const QString &key) const { return value(key); } /*! Returns a reference to the value for \a key. The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the element in the QJsonArray or QJsonObject from which you got the reference. \sa value() */ QJsonValueRef QJsonObject::operator [](const QString &key) { // ### somewhat inefficient, as we lookup the key twice if it doesn't yet exist bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : -1; if (!keyExists) { iterator i = insert(key, QJsonValue()); index = i.i; } return QJsonValueRef(this, index); } /*! Inserts a new item with the key \a key and a value of \a value. If there is already an item with the key \a key, then that item's value is replaced with \a value. Returns an iterator pointing to the inserted item. If the value is QJsonValue::Undefined, it will cause the key to get removed from the object. The returned iterator will then point to end(). \sa remove(), take(), QJsonObject::iterator, end() */ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &value) { if (value.t == QJsonValue::Undefined) { remove(key); return end(); } QJsonValue val = value; bool latinOrIntValue; int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); bool latinKey = QJsonPrivate::useCompressed(key); int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey); int requiredSize = valueOffset + valueSize; detach(requiredSize + sizeof(QJsonPrivate::offset)); // offset for the new index entry if (!o->length) o->tableOffset = sizeof(QJsonPrivate::Object); bool keyExists = false; int pos = o->indexOf(key, &keyExists); if (keyExists) ++d->compactionCounter; uint off = o->reserveSpace(requiredSize, pos, 1, keyExists); if (!off) return end(); QJsonPrivate::Entry *e = o->entryAt(pos); e->value.type = val.t; e->value.latinKey = latinKey; e->value.latinOrIntValue = latinOrIntValue; e->value.value = QJsonPrivate::Value::valueToStore(val, (char *)e - (char *)o + valueOffset); QJsonPrivate::copyString((char *)(e + 1), key, latinKey); if (valueSize) QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue); if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); return iterator(this, pos); } /*! Removes \a key from the object. \sa insert(), take() */ void QJsonObject::remove(const QString &key) { if (!d) return; bool keyExists; int index = o->indexOf(key, &keyExists); if (!keyExists) return; detach(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); } /*! Removes \a key from the object. Returns a QJsonValue containing the value referenced by \a key. If \a key was not contained in the object, the returned QJsonValue is QJsonValue::Undefined. \sa insert(), remove(), QJsonValue */ QJsonValue QJsonObject::take(const QString &key) { if (!o) return QJsonValue(QJsonValue::Undefined); bool keyExists; int index = o->indexOf(key, &keyExists); if (!keyExists) return QJsonValue(QJsonValue::Undefined); QJsonValue v(d, o, o->entryAt(index)->value); detach(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); return v; } /*! Returns \c true if the object contains key \a key. \sa insert(), remove(), take() */ bool QJsonObject::contains(const QString &key) const { if (!o) return false; bool keyExists; o->indexOf(key, &keyExists); return keyExists; } /*! Returns \c true if \a other is equal to this object. */ bool QJsonObject::operator==(const QJsonObject &other) const { if (o == other.o) return true; if (!o) return !other.o->length; if (!other.o) return !o->length; if (o->length != other.o->length) return false; for (uint i = 0; i < o->length; ++i) { QJsonPrivate::Entry *e = o->entryAt(i); QJsonValue v(d, o, e->value); if (other.value(e->key()) != v) return false; } return true; } /*! Returns \c true if \a other is not equal to this object. */ bool QJsonObject::operator!=(const QJsonObject &other) const { return !(*this == other); } /*! Removes the (key, value) pair pointed to by the iterator \a it from the map, and returns an iterator to the next item in the map. \sa remove() */ QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it) { Q_ASSERT(d && int(d->ref) == 1); if (it.o != this || it.i < 0 || it.i >= (int)o->length) return iterator(this, o->length); int index = it.i; o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) compact(); // iterator hasn't changed return it; } /*! Returns an iterator pointing to the item with key \a key in the map. If the map contains no item with key \a key, the function returns end(). */ QJsonObject::iterator QJsonObject::find(const QString &key) { bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : 0; if (!keyExists) return end(); detach(); return iterator(this, index); } /*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const \overload */ /*! Returns a const iterator pointing to the item with key \a key in the map. If the map contains no item with key \a key, the function returns constEnd(). */ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const { bool keyExists = false; int index = o ? o->indexOf(key, &keyExists) : 0; if (!keyExists) return end(); return const_iterator(this, index); } /*! \fn int QJsonObject::count() const \overload Same as size(). */ /*! \fn int QJsonObject::length() const \overload Same as size(). */ /*! \fn QJsonObject::iterator QJsonObject::begin() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the object. \sa constBegin(), end() */ /*! \fn QJsonObject::const_iterator QJsonObject::begin() const \overload */ /*! \fn QJsonObject::const_iterator QJsonObject::constBegin() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the object. \sa begin(), constEnd() */ /*! \fn QJsonObject::iterator QJsonObject::end() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the object. \sa begin(), constEnd() */ /*! \fn QJsonObject::const_iterator QJsonObject::end() const \overload */ /*! \fn QJsonObject::const_iterator QJsonObject::constEnd() const Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last item in the object. \sa constBegin(), end() */ /*! \fn bool QJsonObject::empty() const This function is provided for STL compatibility. It is equivalent to isEmpty(), returning \c true if the object is empty; otherwise returning \c false. */ /*! \class QJsonObject::iterator \inmodule QtCore \ingroup json \reentrant \since 5.0 \brief The QJsonObject::iterator class provides an STL-style non-const iterator for QJsonObject. QJsonObject::iterator allows you to iterate over a QJsonObject and to modify the value (but not the key) stored under a particular key. If you want to iterate over a const QJsonObject, you should use QJsonObject::const_iterator. It is generally good practice to use QJsonObject::const_iterator on a non-const QJsonObject as well, unless you need to change the QJsonObject through the iterator. Const iterators are slightly faster, and improve code readability. The default QJsonObject::iterator constructor creates an uninitialized iterator. You must initialize it using a QJsonObject function like QJsonObject::begin(), QJsonObject::end(), or QJsonObject::find() before you can start iterating. Multiple iterators can be used on the same object. Existing iterators will however become dangling once the object gets modified. \sa QJsonObject::const_iterator, {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef QJsonObject::iterator::difference_type \internal */ /*! \typedef QJsonObject::iterator::iterator_category A synonym for \e {std::bidirectional_iterator_tag} indicating this iterator is a bidirectional iterator. */ /*! \typedef QJsonObject::iterator::reference \internal */ /*! \typedef QJsonObject::iterator::value_type \internal */ /*! \fn QJsonObject::iterator::iterator() Constructs an uninitialized iterator. Functions like key(), value(), and operator++() must not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa QJsonObject::begin(), QJsonObject::end() */ /*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, int index) \internal */ /*! \fn QString QJsonObject::iterator::key() const Returns the current item's key. There is no direct way of changing an item's key through an iterator, although it can be done by calling QJsonObject::erase() followed by QJsonObject::insert(). \sa value() */ /*! \fn QJsonValueRef QJsonObject::iterator::value() const Returns a modifiable reference to the current item's value. You can change the value of an item by using value() on the left side of an assignment. The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the element in the QJsonArray or QJsonObject from which you got the reference. \sa key(), operator*() */ /*! \fn QJsonValueRef QJsonObject::iterator::operator*() const Returns a modifiable reference to the current item's value. Same as value(). The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the element in the QJsonArray or QJsonObject from which you got the reference. \sa key() */ /*! \fn QJsonValueRef *QJsonObject::iterator::operator->() const Returns a pointer to a modifiable reference to the current item. */ /*! \fn bool QJsonObject::iterator::operator==(const iterator &other) const \fn bool QJsonObject::iterator::operator==(const const_iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool QJsonObject::iterator::operator!=(const iterator &other) const \fn bool QJsonObject::iterator::operator!=(const const_iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn QJsonObject::iterator QJsonObject::iterator::operator++() The prefix ++ operator, \c{++i}, advances the iterator to the next item in the object and returns an iterator to the new current item. Calling this function on QJsonObject::end() leads to undefined results. \sa operator--() */ /*! \fn QJsonObject::iterator QJsonObject::iterator::operator++(int) \overload The postfix ++ operator, \c{i++}, advances the iterator to the next item in the object and returns an iterator to the previously current item. */ /*! \fn QJsonObject::iterator QJsonObject::iterator::operator--() The prefix -- operator, \c{--i}, makes the preceding item current and returns an iterator pointing to the new current item. Calling this function on QJsonObject::begin() leads to undefined results. \sa operator++() */ /*! \fn QJsonObject::iterator QJsonObject::iterator::operator--(int) \overload The postfix -- operator, \c{i--}, makes the preceding item current and returns an iterator pointing to the previously current item. */ /*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. \sa operator-() */ /*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. \sa operator+() */ /*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. \sa operator-=(), operator+() */ /*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. \sa operator+=(), operator-() */ /*! \class QJsonObject::const_iterator \inmodule QtCore \ingroup json \since 5.0 \brief The QJsonObject::const_iterator class provides an STL-style const iterator for QJsonObject. QJsonObject::const_iterator allows you to iterate over a QJsonObject. If you want to modify the QJsonObject as you iterate over it, you must use QJsonObject::iterator instead. It is generally good practice to use QJsonObject::const_iterator on a non-const QJsonObject as well, unless you need to change the QJsonObject through the iterator. Const iterators are slightly faster and improve code readability. The default QJsonObject::const_iterator constructor creates an uninitialized iterator. You must initialize it using a QJsonObject function like QJsonObject::constBegin(), QJsonObject::constEnd(), or QJsonObject::find() before you can start iterating. Multiple iterators can be used on the same object. Existing iterators will however become dangling if the object gets modified. \sa QJsonObject::iterator, {JSON Support in Qt}, {JSON Save Game Example} */ /*! \typedef QJsonObject::const_iterator::difference_type \internal */ /*! \typedef QJsonObject::const_iterator::iterator_category A synonym for \e {std::bidirectional_iterator_tag} indicating this iterator is a bidirectional iterator. */ /*! \typedef QJsonObject::const_iterator::reference \internal */ /*! \typedef QJsonObject::const_iterator::value_type \internal */ /*! \fn QJsonObject::const_iterator::const_iterator() Constructs an uninitialized iterator. Functions like key(), value(), and operator++() must not be called on an uninitialized iterator. Use operator=() to assign a value to it before using it. \sa QJsonObject::constBegin(), QJsonObject::constEnd() */ /*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, int index) \internal */ /*! \fn QJsonObject::const_iterator::const_iterator(const iterator &other) Constructs a copy of \a other. */ /*! \fn QString QJsonObject::const_iterator::key() const Returns the current item's key. \sa value() */ /*! \fn QJsonValue QJsonObject::const_iterator::value() const Returns the current item's value. \sa key(), operator*() */ /*! \fn QJsonValue QJsonObject::const_iterator::operator*() const Returns the current item's value. Same as value(). \sa key() */ /*! \fn QJsonValue *QJsonObject::const_iterator::operator->() const Returns a pointer to the current item. */ /*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &other) const \fn bool QJsonObject::const_iterator::operator==(const iterator &other) const Returns \c true if \a other points to the same item as this iterator; otherwise returns \c false. \sa operator!=() */ /*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &other) const \fn bool QJsonObject::const_iterator::operator!=(const iterator &other) const Returns \c true if \a other points to a different item than this iterator; otherwise returns \c false. \sa operator==() */ /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++() The prefix ++ operator, \c{++i}, advances the iterator to the next item in the object and returns an iterator to the new current item. Calling this function on QJsonObject::end() leads to undefined results. \sa operator--() */ /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++(int) \overload The postfix ++ operator, \c{i++}, advances the iterator to the next item in the object and returns an iterator to the previously current item. */ /*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator--() The prefix -- operator, \c{--i}, makes the preceding item current and returns an iterator pointing to the new current item. Calling this function on QJsonObject::begin() leads to undefined results. \sa operator++() */ /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator--(int) \overload The postfix -- operator, \c{i--}, makes the preceding item current and returns an iterator pointing to the previously current item. */ /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(int j) const Returns an iterator to the item at \a j positions forward from this iterator. If \a j is negative, the iterator goes backward. This operation can be slow for large \a j values. \sa operator-() */ /*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(int j) const Returns an iterator to the item at \a j positions backward from this iterator. If \a j is negative, the iterator goes forward. This operation can be slow for large \a j values. \sa operator+() */ /*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(int j) Advances the iterator by \a j items. If \a j is negative, the iterator goes backward. This operation can be slow for large \a j values. \sa operator-=(), operator+() */ /*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(int j) Makes the iterator go back by \a j items. If \a j is negative, the iterator goes forward. This operation can be slow for large \a j values. \sa operator+=(), operator-() */ /*! \internal */ void QJsonObject::detach(uint reserve) { if (!d) { d = new QJsonPrivate::Data(reserve, QJsonValue::Object); o = static_cast(d->header->root()); d->ref.ref(); return; } /* if (reserve == 0 && d->ref.load() == 1) return; */ if (reserve == 0 && int(d->ref) == 1) return; QJsonPrivate::Data *x = d->clone(o, reserve); x->ref.ref(); if (!d->ref.deref()) delete d; d = x; o = static_cast(d->header->root()); } /*! \internal */ void QJsonObject::compact() { if (!d || !d->compactionCounter) return; detach(); d->compact(); o = static_cast(d->header->root()); } /*! \internal */ QString QJsonObject::keyAt(int i) const { Q_ASSERT(o && i >= 0 && i < (int)o->length); QJsonPrivate::Entry *e = o->entryAt(i); return e->key(); } /*! \internal */ QJsonValue QJsonObject::valueAt(int i) const { if (!o || i < 0 || i >= (int)o->length) return QJsonValue(QJsonValue::Undefined); QJsonPrivate::Entry *e = o->entryAt(i); return QJsonValue(d, o, e->value); } /*! \internal */ void QJsonObject::setValueAt(int i, const QJsonValue &val) { Q_ASSERT(o && i >= 0 && i < (int)o->length); QJsonPrivate::Entry *e = o->entryAt(i); insert(e->key(), val); } #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonObject &o) { if (!o.o) { dbg << "QJsonObject()"; return dbg; } QByteArray json; QJsonPrivate::Writer::objectToJson(o.o, json, 0, true); dbg.nospace() << "QJsonObject(" << json.constData() // print as utf-8 string without extra quotation marks << ")"; return dbg.space(); } #endif QT_END_NAMESPACE ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonobject.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QJSONOBJECT_H #define QJSONOBJECT_H #include "qjsonvalue.h" #include #include #ifdef Q_COMPILER_INITIALIZER_LISTS #include #include #endif QT_BEGIN_NAMESPACE class QDebug; template class QMap; typedef QMap QVariantMap; class QJSON_EXPORT QJsonObject { public: QJsonObject(); #if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) QJsonObject(std::initializer_list > args) { initialize(); for (std::initializer_list >::const_iterator i = args.begin(); i != args.end(); ++i) insert(i->first, i->second); } #endif ~QJsonObject(); QJsonObject(const QJsonObject &other); QJsonObject &operator =(const QJsonObject &other); static QJsonObject fromVariantMap(const QVariantMap &map); QVariantMap toVariantMap() const; QStringList keys() const; int size() const; inline int count() const { return size(); } inline int length() const { return size(); } bool isEmpty() const; QJsonValue value(const QString &key) const; QJsonValue operator[] (const QString &key) const; QJsonValueRef operator[] (const QString &key); void remove(const QString &key); QJsonValue take(const QString &key); bool contains(const QString &key) const; bool operator==(const QJsonObject &other) const; bool operator!=(const QJsonObject &other) const; class const_iterator; class iterator { friend class const_iterator; friend class QJsonObject; QJsonObject *o; int i; public: typedef std::bidirectional_iterator_tag iterator_category; typedef int difference_type; typedef QJsonValue value_type; typedef QJsonValueRef reference; inline iterator() : o(0), i(0) {} inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {} inline QString key() const { return o->keyAt(i); } inline QJsonValueRef value() const { return QJsonValueRef(o, i); } inline QJsonValueRef operator*() const { return QJsonValueRef(o, i); } #ifdef Q_QDOC inline QJsonValueRef* operator->() const; #else inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(o, i); } #endif inline bool operator==(const iterator &other) const { return i == other.i; } inline bool operator!=(const iterator &other) const { return i != other.i; } inline iterator &operator++() { ++i; return *this; } inline iterator operator++(int) { iterator r = *this; ++i; return r; } inline iterator &operator--() { --i; return *this; } inline iterator operator--(int) { iterator r = *this; --i; return r; } inline iterator operator+(int j) const { iterator r = *this; r.i += j; return r; } inline iterator operator-(int j) const { return operator+(-j); } inline iterator &operator+=(int j) { i += j; return *this; } inline iterator &operator-=(int j) { i -= j; return *this; } public: inline bool operator==(const const_iterator &other) const { return i == other.i; } inline bool operator!=(const const_iterator &other) const { return i != other.i; } }; friend class iterator; class const_iterator { friend class iterator; const QJsonObject *o; int i; public: typedef std::bidirectional_iterator_tag iterator_category; typedef int difference_type; typedef QJsonValue value_type; typedef QJsonValue reference; inline const_iterator() : o(0), i(0) {} inline const_iterator(const QJsonObject *obj, int index) : o(obj), i(index) {} inline const_iterator(const iterator &other) : o(other.o), i(other.i) {} inline QString key() const { return o->keyAt(i); } inline QJsonValue value() const { return o->valueAt(i); } inline QJsonValue operator*() const { return o->valueAt(i); } #ifdef Q_QDOC inline QJsonValue* operator->() const; #else inline QJsonValuePtr operator->() const { return QJsonValuePtr(o->valueAt(i)); } #endif inline bool operator==(const const_iterator &other) const { return i == other.i; } inline bool operator!=(const const_iterator &other) const { return i != other.i; } inline const_iterator &operator++() { ++i; return *this; } inline const_iterator operator++(int) { const_iterator r = *this; ++i; return r; } inline const_iterator &operator--() { --i; return *this; } inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; } inline const_iterator operator+(int j) const { const_iterator r = *this; r.i += j; return r; } inline const_iterator operator-(int j) const { return operator+(-j); } inline const_iterator &operator+=(int j) { i += j; return *this; } inline const_iterator &operator-=(int j) { i -= j; return *this; } inline bool operator==(const iterator &other) const { return i == other.i; } inline bool operator!=(const iterator &other) const { return i != other.i; } }; friend class const_iterator; // STL style inline iterator begin() { detach(); return iterator(this, 0); } inline const_iterator begin() const { return const_iterator(this, 0); } inline const_iterator constBegin() const { return const_iterator(this, 0); } inline iterator end() { detach(); return iterator(this, size()); } inline const_iterator end() const { return const_iterator(this, size()); } inline const_iterator constEnd() const { return const_iterator(this, size()); } iterator erase(iterator it); // more Qt typedef iterator Iterator; typedef const_iterator ConstIterator; iterator find(const QString &key); const_iterator find(const QString &key) const { return constFind(key); } const_iterator constFind(const QString &key) const; iterator insert(const QString &key, const QJsonValue &value); // STL compatibility typedef QJsonValue mapped_type; typedef QString key_type; typedef int size_type; inline bool empty() const { return isEmpty(); } private: friend class QJsonPrivate::Data; friend class QJsonValue; friend class QJsonDocument; friend class QJsonValueRef; friend QJSON_EXPORT QDebug operator<<(QDebug, const QJsonObject &); QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object); void initialize(); void detach(uint reserve = 0); void compact(); QString keyAt(int i) const; QJsonValue valueAt(int i) const; void setValueAt(int i, const QJsonValue &val); QJsonPrivate::Data *d; QJsonPrivate::Object *o; }; Q_DECLARE_METATYPE(QJsonObject) #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QJSON_EXPORT QDebug operator<<(QDebug, const QJsonObject &); #endif QT_END_NAMESPACE #endif // QJSONOBJECT_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonparser.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Copyright (C) 2013 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QT_BOOTSTRAPPED #include #endif #include #include "qjsonparser_p.h" #include "qjson_p.h" //#define PARSER_DEBUG #ifdef PARSER_DEBUG static int indent = 0; #define BEGIN qDebug() << QByteArray(4*indent++, ' ').constData() << "pos=" << current #define END --indent #define DEBUG qDebug() << QByteArray(4*indent, ' ').constData() #else #define BEGIN if (1) ; else qDebug() #define END do {} while (0) #define DEBUG if (1) ; else qDebug() #endif static const int nestingLimit = 1024; QT_BEGIN_NAMESPACE // error strings for the JSON parser #define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred") #define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object") #define JSONERR_MISS_NSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing name separator") #define JSONERR_UNTERM_AR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated array") #define JSONERR_MISS_VSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing value separator") #define JSONERR_ILLEGAL_VAL QT_TRANSLATE_NOOP("QJsonParseError", "illegal value") #define JSONERR_END_OF_NUM QT_TRANSLATE_NOOP("QJsonParseError", "invalid termination by number") #define JSONERR_ILLEGAL_NUM QT_TRANSLATE_NOOP("QJsonParseError", "illegal number") #define JSONERR_STR_ESC_SEQ QT_TRANSLATE_NOOP("QJsonParseError", "invalid escape sequence") #define JSONERR_STR_UTF8 QT_TRANSLATE_NOOP("QJsonParseError", "invalid UTF8 string") #define JSONERR_UTERM_STR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated string") #define JSONERR_MISS_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "object is missing after a comma") #define JSONERR_DEEP_NEST QT_TRANSLATE_NOOP("QJsonParseError", "too deeply nested document") #define JSONERR_DOC_LARGE QT_TRANSLATE_NOOP("QJsonParseError", "too large document") #define JSONERR_GARBAGEEND QT_TRANSLATE_NOOP("QJsonParseError", "garbage at the end of the document") /*! \class QJsonParseError \inmodule QtCore \ingroup json \reentrant \since 5.0 \brief The QJsonParseError class is used to report errors during JSON parsing. \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! \enum QJsonParseError::ParseError This enum describes the type of error that occurred during the parsing of a JSON document. \value NoError No error occurred \value UnterminatedObject An object is not correctly terminated with a closing curly bracket \value MissingNameSeparator A comma separating different items is missing \value UnterminatedArray The array is not correctly terminated with a closing square bracket \value MissingValueSeparator A colon separating keys from values inside objects is missing \value IllegalValue The value is illegal \value TerminationByNumber The input stream ended while parsing a number \value IllegalNumber The number is not well formed \value IllegalEscapeSequence An illegal escape sequence occurred in the input \value IllegalUTF8String An illegal UTF8 sequence occurred in the input \value UnterminatedString A string wasn't terminated with a quote \value MissingObject An object was expected but couldn't be found \value DeepNesting The JSON document is too deeply nested for the parser to parse it \value DocumentTooLarge The JSON document is too large for the parser to parse it \value GarbageAtEnd The parsed document contains additional garbage characters at the end */ /*! \variable QJsonParseError::error Contains the type of the parse error. Is equal to QJsonParseError::NoError if the document was parsed correctly. \sa ParseError, errorString() */ /*! \variable QJsonParseError::offset Contains the offset in the input string where the parse error occurred. \sa error, errorString() */ /*! Returns the human-readable message appropriate to the reported JSON parsing error. \sa error */ QString QJsonParseError::errorString() const { const char *sz = ""; switch (error) { case NoError: sz = JSONERR_OK; break; case UnterminatedObject: sz = JSONERR_UNTERM_OBJ; break; case MissingNameSeparator: sz = JSONERR_MISS_NSEP; break; case UnterminatedArray: sz = JSONERR_UNTERM_AR; break; case MissingValueSeparator: sz = JSONERR_MISS_VSEP; break; case IllegalValue: sz = JSONERR_ILLEGAL_VAL; break; case TerminationByNumber: sz = JSONERR_END_OF_NUM; break; case IllegalNumber: sz = JSONERR_ILLEGAL_NUM; break; case IllegalEscapeSequence: sz = JSONERR_STR_ESC_SEQ; break; case IllegalUTF8String: sz = JSONERR_STR_UTF8; break; case UnterminatedString: sz = JSONERR_UTERM_STR; break; case MissingObject: sz = JSONERR_MISS_OBJ; break; case DeepNesting: sz = JSONERR_DEEP_NEST; break; case DocumentTooLarge: sz = JSONERR_DOC_LARGE; break; case GarbageAtEnd: sz = JSONERR_GARBAGEEND; break; } #ifndef QT_BOOTSTRAPPED return QCoreApplication::translate("QJsonParseError", sz); #else return QLatin1String(sz); #endif } using namespace QJsonPrivate; Parser::Parser(const char *json, int length) : head(json), json(json), data(0), dataLength(0), current(0), nestingLevel(0), lastError(QJsonParseError::NoError) { end = json + length; } /* begin-array = ws %x5B ws ; [ left square bracket begin-object = ws %x7B ws ; { left curly bracket end-array = ws %x5D ws ; ] right square bracket end-object = ws %x7D ws ; } right curly bracket name-separator = ws %x3A ws ; : colon value-separator = ws %x2C ws ; , comma Insignificant whitespace is allowed before or after any of the six structural characters. ws = *( %x20 / ; Space %x09 / ; Horizontal tab %x0A / ; Line feed or New line %x0D ; Carriage return ) */ enum { Space = 0x20, Tab = 0x09, LineFeed = 0x0a, Return = 0x0d, BeginArray = 0x5b, BeginObject = 0x7b, EndArray = 0x5d, EndObject = 0x7d, NameSeparator = 0x3a, ValueSeparator = 0x2c, Quote = 0x22 }; void Parser::eatBOM() { // eat UTF-8 byte order mark uchar utf8bom[3] = { 0xef, 0xbb, 0xbf }; if (end - json > 3 && (uchar)json[0] == utf8bom[0] && (uchar)json[1] == utf8bom[1] && (uchar)json[2] == utf8bom[2]) json += 3; } bool Parser::eatSpace() { while (json < end) { if (*json > Space) break; if (*json != Space && *json != Tab && *json != LineFeed && *json != Return) break; ++json; } return (json < end); } char Parser::nextToken() { if (!eatSpace()) return 0; char token = *json++; switch (token) { case BeginArray: case BeginObject: case NameSeparator: case ValueSeparator: case EndArray: case EndObject: eatSpace(); case Quote: break; default: token = 0; break; } return token; } /* JSON-text = object / array */ QJsonDocument Parser::parse(QJsonParseError *error) { #ifdef PARSER_DEBUG indent = 0; qDebug() << ">>>>> parser begin"; #endif // allocate some space dataLength = qMax(end - json, (ptrdiff_t) 256); data = (char *)malloc(dataLength); // fill in Header data QJsonPrivate::Header *h = (QJsonPrivate::Header *)data; h->tag = QJsonDocument::BinaryFormatTag; h->version = 1u; current = sizeof(QJsonPrivate::Header); eatBOM(); char token = nextToken(); DEBUG << hex << (uint)token; if (token == BeginArray) { if (!parseArray()) goto error; } else if (token == BeginObject) { if (!parseObject()) goto error; } else { lastError = QJsonParseError::IllegalValue; goto error; } eatSpace(); if (json < end) { lastError = QJsonParseError::GarbageAtEnd; goto error; } END; { if (error) { error->offset = 0; error->error = QJsonParseError::NoError; } QJsonPrivate::Data *d = new QJsonPrivate::Data(data, current); return QJsonDocument(d); } error: #ifdef PARSER_DEBUG qDebug() << ">>>>> parser error"; #endif if (error) { error->offset = json - head; error->error = lastError; } free(data); return QJsonDocument(); } void Parser::ParsedObject::insert(uint offset) { const QJsonPrivate::Entry *newEntry = reinterpret_cast(parser->data + objectPosition + offset); int min = 0; int n = offsets.size(); while (n > 0) { int half = n >> 1; int middle = min + half; if (*entryAt(middle) >= *newEntry) { n = half; } else { min = middle + 1; n -= half + 1; } } if (min < offsets.size() && *entryAt(min) == *newEntry) { offsets[min] = offset; } else { offsets.insert(min, offset); } } /* object = begin-object [ member *( value-separator member ) ] end-object */ bool Parser::parseObject() { if (++nestingLevel > nestingLimit) { lastError = QJsonParseError::DeepNesting; return false; } int objectOffset = reserveSpace(sizeof(QJsonPrivate::Object)); BEGIN << "parseObject pos=" << objectOffset << current << json; ParsedObject parsedObject(this, objectOffset); char token = nextToken(); while (token == Quote) { int off = current - objectOffset; if (!parseMember(objectOffset)) return false; parsedObject.insert(off); token = nextToken(); if (token != ValueSeparator) break; token = nextToken(); if (token == EndObject) { lastError = QJsonParseError::MissingObject; return false; } } DEBUG << "end token=" << token; if (token != EndObject) { lastError = QJsonParseError::UnterminatedObject; return false; } DEBUG << "numEntries" << parsedObject.offsets.size(); int table = objectOffset; // finalize the object if (parsedObject.offsets.size()) { int tableSize = parsedObject.offsets.size()*sizeof(uint); table = reserveSpace(tableSize); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN memcpy(data + table, parsedObject.offsets.constData(), tableSize); #else offset *o = (offset *)(data + table); for (int i = 0; i < parsedObject.offsets.size(); ++i) o[i] = parsedObject.offsets[i]; #endif } QJsonPrivate::Object *o = (QJsonPrivate::Object *)(data + objectOffset); o->tableOffset = table - objectOffset; o->size = current - objectOffset; o->is_object = true; o->length = parsedObject.offsets.size(); DEBUG << "current=" << current; END; --nestingLevel; return true; } /* member = string name-separator value */ bool Parser::parseMember(int baseOffset) { int entryOffset = reserveSpace(sizeof(QJsonPrivate::Entry)); BEGIN << "parseMember pos=" << entryOffset; bool latin1; if (!parseString(&latin1)) return false; char token = nextToken(); if (token != NameSeparator) { lastError = QJsonParseError::MissingNameSeparator; return false; } QJsonPrivate::Value val; if (!parseValue(&val, baseOffset)) return false; // finalize the entry QJsonPrivate::Entry *e = (QJsonPrivate::Entry *)(data + entryOffset); e->value = val; e->value.latinKey = latin1; END; return true; } /* array = begin-array [ value *( value-separator value ) ] end-array */ bool Parser::parseArray() { BEGIN << "parseArray"; if (++nestingLevel > nestingLimit) { lastError = QJsonParseError::DeepNesting; return false; } int arrayOffset = reserveSpace(sizeof(QJsonPrivate::Array)); QVarLengthArray values; if (!eatSpace()) { lastError = QJsonParseError::UnterminatedArray; return false; } if (*json == EndArray) { nextToken(); } else { while (1) { QJsonPrivate::Value val; if (!parseValue(&val, arrayOffset)) return false; values.append(val); char token = nextToken(); if (token == EndArray) break; else if (token != ValueSeparator) { if (!eatSpace()) lastError = QJsonParseError::UnterminatedArray; else lastError = QJsonParseError::MissingValueSeparator; return false; } } } DEBUG << "size =" << values.size(); int table = arrayOffset; // finalize the object if (values.size()) { int tableSize = values.size()*sizeof(QJsonPrivate::Value); table = reserveSpace(tableSize); memcpy(data + table, values.constData(), tableSize); } QJsonPrivate::Array *a = (QJsonPrivate::Array *)(data + arrayOffset); a->tableOffset = table - arrayOffset; a->size = current - arrayOffset; a->is_object = false; a->length = values.size(); DEBUG << "current=" << current; END; --nestingLevel; return true; } /* value = false / null / true / object / array / number / string */ bool Parser::parseValue(QJsonPrivate::Value *val, int baseOffset) { BEGIN << "parse Value" << json; val->_dummy = 0; switch (*json++) { case 'n': if (end - json < 4) { lastError = QJsonParseError::IllegalValue; return false; } if (*json++ == 'u' && *json++ == 'l' && *json++ == 'l') { val->type = QJsonValue::Null; DEBUG << "value: null"; END; return true; } lastError = QJsonParseError::IllegalValue; return false; case 't': if (end - json < 4) { lastError = QJsonParseError::IllegalValue; return false; } if (*json++ == 'r' && *json++ == 'u' && *json++ == 'e') { val->type = QJsonValue::Bool; val->value = true; DEBUG << "value: true"; END; return true; } lastError = QJsonParseError::IllegalValue; return false; case 'f': if (end - json < 5) { lastError = QJsonParseError::IllegalValue; return false; } if (*json++ == 'a' && *json++ == 'l' && *json++ == 's' && *json++ == 'e') { val->type = QJsonValue::Bool; val->value = false; DEBUG << "value: false"; END; return true; } lastError = QJsonParseError::IllegalValue; return false; case Quote: { val->type = QJsonValue::String; if (current - baseOffset >= Value::MaxSize) { lastError = QJsonParseError::DocumentTooLarge; return false; } val->value = current - baseOffset; bool latin1; if (!parseString(&latin1)) return false; val->latinOrIntValue = latin1; DEBUG << "value: string"; END; return true; } case BeginArray: val->type = QJsonValue::Array; if (current - baseOffset >= Value::MaxSize) { lastError = QJsonParseError::DocumentTooLarge; return false; } val->value = current - baseOffset; if (!parseArray()) return false; DEBUG << "value: array"; END; return true; case BeginObject: val->type = QJsonValue::Object; if (current - baseOffset >= Value::MaxSize) { lastError = QJsonParseError::DocumentTooLarge; return false; } val->value = current - baseOffset; if (!parseObject()) return false; DEBUG << "value: object"; END; return true; case EndArray: lastError = QJsonParseError::MissingObject; return false; default: --json; if (!parseNumber(val, baseOffset)) return false; DEBUG << "value: number"; END; } return true; } /* number = [ minus ] int [ frac ] [ exp ] decimal-point = %x2E ; . digit1-9 = %x31-39 ; 1-9 e = %x65 / %x45 ; e E exp = e [ minus / plus ] 1*DIGIT frac = decimal-point 1*DIGIT int = zero / ( digit1-9 *DIGIT ) minus = %x2D ; - plus = %x2B ; + zero = %x30 ; 0 */ bool Parser::parseNumber(QJsonPrivate::Value *val, int baseOffset) { BEGIN << "parseNumber" << json; val->type = QJsonValue::Double; const char *start = json; bool isInt = true; // minus if (json < end && *json == '-') ++json; // int = zero / ( digit1-9 *DIGIT ) if (json < end && *json == '0') { ++json; } else { while (json < end && *json >= '0' && *json <= '9') ++json; } // frac = decimal-point 1*DIGIT if (json < end && *json == '.') { isInt = false; ++json; while (json < end && *json >= '0' && *json <= '9') ++json; } // exp = e [ minus / plus ] 1*DIGIT if (json < end && (*json == 'e' || *json == 'E')) { isInt = false; ++json; if (json < end && (*json == '-' || *json == '+')) ++json; while (json < end && *json >= '0' && *json <= '9') ++json; } if (json >= end) { lastError = QJsonParseError::TerminationByNumber; return false; } QByteArray number(start, json - start); DEBUG << "numberstring" << number; if (isInt) { bool ok; int n = number.toInt(&ok); if (ok && n < (1<<25) && n > -(1<<25)) { val->int_value = n; val->latinOrIntValue = true; END; return true; } } bool ok; union { quint64 ui; double d; }; d = number.toDouble(&ok); if (!ok) { lastError = QJsonParseError::IllegalNumber; return false; } int pos = reserveSpace(sizeof(double)); *(quint64 *)(data + pos) = qToLittleEndian(ui); if (current - baseOffset >= Value::MaxSize) { lastError = QJsonParseError::DocumentTooLarge; return false; } val->value = pos - baseOffset; val->latinOrIntValue = false; END; return true; } /* string = quotation-mark *char quotation-mark char = unescaped / escape ( %x22 / ; " quotation mark U+0022 %x5C / ; \ reverse solidus U+005C %x2F / ; / solidus U+002F %x62 / ; b backspace U+0008 %x66 / ; f form feed U+000C %x6E / ; n line feed U+000A %x72 / ; r carriage return U+000D %x74 / ; t tab U+0009 %x75 4HEXDIG ) ; uXXXX U+XXXX escape = %x5C ; \ quotation-mark = %x22 ; " unescaped = %x20-21 / %x23-5B / %x5D-10FFFF */ static inline bool addHexDigit(char digit, uint *result) { *result <<= 4; if (digit >= '0' && digit <= '9') *result |= (digit - '0'); else if (digit >= 'a' && digit <= 'f') *result |= (digit - 'a') + 10; else if (digit >= 'A' && digit <= 'F') *result |= (digit - 'A') + 10; else return false; return true; } static inline bool scanEscapeSequence(const char *&json, const char *end, uint *ch) { ++json; if (json >= end) return false; DEBUG << "scan escape" << (char)*json; uint escaped = *json++; switch (escaped) { case '"': *ch = '"'; break; case '\\': *ch = '\\'; break; case '/': *ch = '/'; break; case 'b': *ch = 0x8; break; case 'f': *ch = 0xc; break; case 'n': *ch = 0xa; break; case 'r': *ch = 0xd; break; case 't': *ch = 0x9; break; case 'u': { *ch = 0; if (json > end - 4) return false; for (int i = 0; i < 4; ++i) { if (!addHexDigit(*json, ch)) return false; ++json; } return true; } default: // this is not as strict as one could be, but allows for more Json files // to be parsed correctly. *ch = escaped; return true; } return true; } static inline bool isUnicodeNonCharacter(uint ucs4) { // Unicode has a couple of "non-characters" that one can use internally, // but are not allowed to be used for text interchange. // // Those are the last two entries each Unicode Plane (U+FFFE, U+FFFF, // U+1FFFE, U+1FFFF, etc.) as well as the entries between U+FDD0 and // U+FDEF (inclusive) return (ucs4 & 0xfffe) == 0xfffe || (ucs4 - 0xfdd0U) < 16; } static inline bool scanUtf8Char(const char *&json, const char *end, uint *result) { int need; uint min_uc; uint uc; uchar ch = *json++; if (ch < 128) { *result = ch; return true; } else if ((ch & 0xe0) == 0xc0) { uc = ch & 0x1f; need = 1; min_uc = 0x80; } else if ((ch & 0xf0) == 0xe0) { uc = ch & 0x0f; need = 2; min_uc = 0x800; } else if ((ch&0xf8) == 0xf0) { uc = ch & 0x07; need = 3; min_uc = 0x10000; } else { return false; } if (json >= end - need) return false; for (int i = 0; i < need; ++i) { ch = *json++; if ((ch&0xc0) != 0x80) return false; uc = (uc << 6) | (ch & 0x3f); } if (isUnicodeNonCharacter(uc) || uc >= 0x110000 || (uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff)) return false; *result = uc; return true; } bool Parser::parseString(bool *latin1) { *latin1 = true; const char *start = json; int outStart = current; // try to write out a latin1 string int stringPos = reserveSpace(2); BEGIN << "parse string stringPos=" << stringPos << json; while (json < end) { uint ch = 0; if (*json == '"') break; else if (*json == '\\') { if (!scanEscapeSequence(json, end, &ch)) { lastError = QJsonParseError::IllegalEscapeSequence; return false; } } else { if (!scanUtf8Char(json, end, &ch)) { lastError = QJsonParseError::IllegalUTF8String; return false; } } // bail out if the string is not pure latin1 or too long to hold as a latin1string (which has only 16 bit for the length) if (ch > 0xff || json - start >= 0x8000) { *latin1 = false; break; } int pos = reserveSpace(1); DEBUG << " " << ch << (char)ch; data[pos] = (uchar)ch; } ++json; DEBUG << "end of string"; if (json >= end) { lastError = QJsonParseError::UnterminatedString; return false; } // no unicode string, we are done if (*latin1) { // write string length *(QJsonPrivate::qle_ushort *)(data + stringPos) = ushort(current - outStart - sizeof(ushort)); int pos = reserveSpace((4 - current) & 3); while (pos & 3) data[pos++] = 0; END; return true; } *latin1 = false; DEBUG << "not latin"; json = start; current = outStart + sizeof(int); while (json < end) { uint ch = 0; if (*json == '"') break; else if (*json == '\\') { if (!scanEscapeSequence(json, end, &ch)) { lastError = QJsonParseError::IllegalEscapeSequence; return false; } } else { if (!scanUtf8Char(json, end, &ch)) { lastError = QJsonParseError::IllegalUTF8String; return false; } } if (QChar::requiresSurrogates(ch)) { int pos = reserveSpace(4); *(QJsonPrivate::qle_ushort *)(data + pos) = QChar::highSurrogate(ch); *(QJsonPrivate::qle_ushort *)(data + pos + 2) = QChar::lowSurrogate(ch); } else { int pos = reserveSpace(2); *(QJsonPrivate::qle_ushort *)(data + pos) = (ushort)ch; } } ++json; if (json >= end) { lastError = QJsonParseError::UnterminatedString; return false; } // write string length *(QJsonPrivate::qle_int *)(data + stringPos) = (current - outStart - sizeof(int))/2; int pos = reserveSpace((4 - current) & 3); while (pos & 3) data[pos++] = 0; END; return true; } QT_END_NAMESPACE ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonparser_p.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QJSONPARSER_P_H #define QJSONPARSER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qjsondocument.h" #include QT_BEGIN_NAMESPACE namespace QJsonPrivate { class Parser { public: Parser(const char *json, int length); QJsonDocument parse(QJsonParseError *error); class ParsedObject { public: ParsedObject(Parser *p, int pos) : parser(p), objectPosition(pos) { #if QT_VERSION >= 0x040800 offsets.reserve(64); #endif } void insert(uint offset); Parser *parser; int objectPosition; #if QT_VERSION >= 0x040800 QVarLengthArray offsets; #else QVector offsets; #endif inline QJsonPrivate::Entry *entryAt(int i) const { return reinterpret_cast(parser->data + objectPosition + offsets[i]); } }; private: inline void eatBOM(); inline bool eatSpace(); inline char nextToken(); bool parseObject(); bool parseArray(); bool parseMember(int baseOffset); bool parseString(bool *latin1); bool parseValue(QJsonPrivate::Value *val, int baseOffset); bool parseNumber(QJsonPrivate::Value *val, int baseOffset); const char *head; const char *json; const char *end; char *data; int dataLength; int current; int nestingLevel; QJsonParseError::ParseError lastError; inline int reserveSpace(int space) { if (current + space >= dataLength) { dataLength = 2*dataLength + space; data = (char *)realloc(data, dataLength); } int pos = current; current += space; return pos; } }; } QT_END_NAMESPACE #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonvalue.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qjsonobject.h" #include "qjsonvalue.h" #include "qjsonarray.h" #include #include #include #include "qjson_p.h" QT_BEGIN_NAMESPACE /*! \class QJsonValue \inmodule QtCore \ingroup json \reentrant \since 5.0 \brief The QJsonValue class encapsulates a value in JSON. A value in JSON can be one of 6 basic types: JSON is a format to store structured data. It has 6 basic data types: \list \li bool QJsonValue::Bool \li double QJsonValue::Double \li string QJsonValue::String \li array QJsonValue::Array \li object QJsonValue::Object \li null QJsonValue::Null \endlist A value can represent any of the above data types. In addition, QJsonValue has one special flag to represent undefined values. This can be queried with isUndefined(). The type of the value can be queried with type() or accessors like isBool(), isString(), and so on. Likewise, the value can be converted to the type stored in it using the toBool(), toString() and so on. Values are strictly typed internally and contrary to QVariant will not attempt to do any implicit type conversions. This implies that converting to a type that is not stored in the value will return a default constructed return value. \sa {JSON Support in Qt}, {JSON Save Game Example} */ /*! Creates a QJsonValue of type \a type. The default is to create a Null value. */ QJsonValue::QJsonValue(Type type) : ui(0), d(0), t(type) { } /*! \internal */ QJsonValue::QJsonValue(QJsonPrivate::Data *data, QJsonPrivate::Base *base, const QJsonPrivate::Value &v) : d(0) { t = (Type)(uint)v.type; switch (t) { case Undefined: case Null: dbl = 0; break; case Bool: b = v.toBoolean(); break; case Double: dbl = v.toDouble(base); break; case String: { /* QString s = v.toString(base); stringData = s.data_ptr(); stringData->ref.ref(); */ stringValue = v.toString(base); break; } case Array: case Object: d = data; this->base = v.base(base); break; } if (d) d->ref.ref(); } /*! Creates a value of type Bool, with value \a b. */ QJsonValue::QJsonValue(bool b) : d(0), t(Bool) { this->b = b; } /*! Creates a value of type Double, with value \a n. */ QJsonValue::QJsonValue(double n) : d(0), t(Double) { this->dbl = n; } /*! \overload Creates a value of type Double, with value \a n. */ QJsonValue::QJsonValue(int n) : d(0), t(Double) { this->dbl = n; } /*! \overload Creates a value of type Double, with value \a n. NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992). If you pass in values outside this range expect a loss of precision to occur. */ QJsonValue::QJsonValue(qint64 n) : d(0), t(Double) { this->dbl = n; } /*! Creates a value of type String, with value \a s. */ QJsonValue::QJsonValue(const QString &s) : d(0), t(String) { stringDataFromQStringHelper(s); } /*! \fn QJsonValue::QJsonValue(const char *s) Creates a value of type String with value \a s, assuming UTF-8 encoding of the input. You can disable this constructor by defining \c QT_NO_CAST_FROM_ASCII when you compile your applications. \since 5.3 */ void QJsonValue::stringDataFromQStringHelper(const QString &string) { // stringData = *(QStringData **)(&string); // stringData->ref.ref(); stringValue = string; } /*! Creates a value of type String, with value \a s. */ QJsonValue::QJsonValue(QLatin1String s) : d(0), t(String) { // ### FIXME: Avoid creating the temp QString below QString str(s); stringDataFromQStringHelper(str); } /*! Creates a value of type Array, with value \a a. */ QJsonValue::QJsonValue(const QJsonArray &a) : d(a.d), t(Array) { base = a.a; if (d) d->ref.ref(); } /*! Creates a value of type Object, with value \a o. */ QJsonValue::QJsonValue(const QJsonObject &o) : d(o.d), t(Object) { base = o.o; if (d) d->ref.ref(); } /*! Destroys the value. */ QJsonValue::~QJsonValue() { /* if (t == String && stringData && !stringData->ref.deref()) free(stringData); */ if (d && !d->ref.deref()) delete d; } /*! Creates a copy of \a other. */ QJsonValue::QJsonValue(const QJsonValue &other) { t = other.t; d = other.d; ui = other.ui; stringValue = other.stringValue; if (d) d->ref.ref(); /* if (t == String && stringData) stringData->ref.ref(); */ } /*! Assigns the value stored in \a other to this object. */ QJsonValue &QJsonValue::operator =(const QJsonValue &other) { /* if (t == String && stringData && !stringData->ref.deref()) free(stringData); */ t = other.t; dbl = other.dbl; stringValue = other.stringValue; if (d != other.d) { if (d && !d->ref.deref()) delete d; d = other.d; if (d) d->ref.ref(); } /* if (t == String && stringData) stringData->ref.ref(); */ return *this; } /*! \fn bool QJsonValue::isNull() const Returns \c true if the value is null. */ /*! \fn bool QJsonValue::isBool() const Returns \c true if the value contains a boolean. \sa toBool() */ /*! \fn bool QJsonValue::isDouble() const Returns \c true if the value contains a double. \sa toDouble() */ /*! \fn bool QJsonValue::isString() const Returns \c true if the value contains a string. \sa toString() */ /*! \fn bool QJsonValue::isArray() const Returns \c true if the value contains an array. \sa toArray() */ /*! \fn bool QJsonValue::isObject() const Returns \c true if the value contains an object. \sa toObject() */ /*! \fn bool QJsonValue::isUndefined() const Returns \c true if the value is undefined. This can happen in certain error cases as e.g. accessing a non existing key in a QJsonObject. */ /*! Converts \a variant to a QJsonValue and returns it. The conversion will convert QVariant types as follows: \table \header \li Source type \li Destination type \row \li \list \li QMetaType::Bool \endlist \li QJsonValue::Bool \row \li \list \li QMetaType::Int \li QMetaType::UInt \li QMetaType::LongLong \li QMetaType::ULongLong \li QMetaType::Float \li QMetaType::Double \endlist \li QJsonValue::Double \row \li \list \li QMetaType::QString \endlist \li QJsonValue::String \row \li \list \li QMetaType::QStringList \li QMetaType::QVariantList \endlist \li QJsonValue::Array \row \li \list \li QMetaType::QVariantMap \endlist \li QJsonValue::Object \endtable For all other QVariant types a conversion to a QString will be attempted. If the returned string is empty, a Null QJsonValue will be stored, otherwise a String value using the returned QString. \sa toVariant() */ QJsonValue QJsonValue::fromVariant(const QVariant &variant) { switch (variant.userType()) { case QVariant::Bool: return QJsonValue(variant.toBool()); case QVariant::Int: case QMetaType::Float: case QVariant::Double: case QVariant::LongLong: case QVariant::ULongLong: case QVariant::UInt: return QJsonValue(variant.toDouble()); case QVariant::String: return QJsonValue(variant.toString()); case QVariant::StringList: return QJsonValue(QJsonArray::fromStringList(variant.toStringList())); case QVariant::List: return QJsonValue(QJsonArray::fromVariantList(variant.toList())); case QVariant::Map: return QJsonValue(QJsonObject::fromVariantMap(variant.toMap())); default: break; } QString string = variant.toString(); if (string.isEmpty()) return QJsonValue(); return QJsonValue(string); } /*! Converts the value to a \l {QVariant::}{QVariant()}. The QJsonValue types will be converted as follows: \value Null {QVariant::}{QVariant()} \value Bool QMetaType::Bool \value Double QMetaType::Double \value String QString \value Array QVariantList \value Object QVariantMap \value Undefined {QVariant::}{QVariant()} \sa fromVariant() */ QVariant QJsonValue::toVariant() const { switch (t) { case Bool: return b; case Double: return dbl; case String: return toString(); case Array: return d ? QJsonArray(d, static_cast(base)).toVariantList() : QVariantList(); case Object: return d ? QJsonObject(d, static_cast(base)).toVariantMap() : QVariantMap(); case Null: case Undefined: break; } return QVariant(); } /*! \enum QJsonValue::Type This enum describes the type of the JSON value. \value Null A Null value \value Bool A boolean value. Use toBool() to convert to a bool. \value Double A double. Use toDouble() to convert to a double. \value String A string. Use toString() to convert to a QString. \value Array An array. Use toArray() to convert to a QJsonArray. \value Object An object. Use toObject() to convert to a QJsonObject. \value Undefined The value is undefined. This is usually returned as an error condition, when trying to read an out of bounds value in an array or a non existent key in an object. */ /*! Returns the type of the value. \sa QJsonValue::Type */ QJsonValue::Type QJsonValue::type() const { return t; } /*! Converts the value to a bool and returns it. If type() is not bool, the \a defaultValue will be returned. */ bool QJsonValue::toBool(bool defaultValue) const { if (t != Bool) return defaultValue; return b; } /*! Converts the value to an int and returns it. If type() is not Double or the value is not a whole number, the \a defaultValue will be returned. */ int QJsonValue::toInt(int defaultValue) const { if (t == Double && int(dbl) == dbl) return dbl; return defaultValue; } /*! Converts the value to a double and returns it. If type() is not Double, the \a defaultValue will be returned. */ double QJsonValue::toDouble(double defaultValue) const { if (t != Double) return defaultValue; return dbl; } /*! Converts the value to a QString and returns it. If type() is not String, the \a defaultValue will be returned. */ QString QJsonValue::toString(const QString &defaultValue) const { if (t != String) return defaultValue; /* stringData->ref.ref(); // the constructor below doesn't add a ref. QStringDataPtr holder = { stringData }; return QString(holder); */ return stringValue; } /*! Converts the value to an array and returns it. If type() is not Array, the \a defaultValue will be returned. */ QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const { if (!d || t != Array) return defaultValue; return QJsonArray(d, static_cast(base)); } /*! \overload Converts the value to an array and returns it. If type() is not Array, a \l{QJsonArray::}{QJsonArray()} will be returned. */ QJsonArray QJsonValue::toArray() const { return toArray(QJsonArray()); } /*! Converts the value to an object and returns it. If type() is not Object, the \a defaultValue will be returned. */ QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const { if (!d || t != Object) return defaultValue; return QJsonObject(d, static_cast(base)); } /*! \overload Converts the value to an object and returns it. If type() is not Object, the \l {QJsonObject::}{QJsonObject()} will be returned. */ QJsonObject QJsonValue::toObject() const { return toObject(QJsonObject()); } /*! Returns \c true if the value is equal to \a other. */ bool QJsonValue::operator==(const QJsonValue &other) const { if (t != other.t) return false; switch (t) { case Undefined: case Null: break; case Bool: return b == other.b; case Double: return dbl == other.dbl; case String: return toString() == other.toString(); case Array: if (base == other.base) return true; if (!base) return !other.base->length; if (!other.base) return !base->length; return QJsonArray(d, static_cast(base)) == QJsonArray(other.d, static_cast(other.base)); case Object: if (base == other.base) return true; if (!base) return !other.base->length; if (!other.base) return !base->length; return QJsonObject(d, static_cast(base)) == QJsonObject(other.d, static_cast(other.base)); } return true; } /*! Returns \c true if the value is not equal to \a other. */ bool QJsonValue::operator!=(const QJsonValue &other) const { return !(*this == other); } /*! \internal */ void QJsonValue::detach() { if (!d) return; QJsonPrivate::Data *x = d->clone(base); x->ref.ref(); if (!d->ref.deref()) delete d; d = x; base = static_cast(d->header->root()); } /*! \class QJsonValueRef \inmodule QtCore \reentrant \brief The QJsonValueRef class is a helper class for QJsonValue. \internal \ingroup json When you get an object of type QJsonValueRef, if you can assign to it, the assignment will apply to the character in the string from which you got the reference. That is its whole purpose in life. You can use it exactly in the same way as a reference to a QJsonValue. The QJsonValueRef becomes invalid once modifications are made to the string: if you want to keep the character, copy it into a QJsonValue. Most of the QJsonValue member functions also exist in QJsonValueRef. However, they are not explicitly documented here. */ QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val) { if (is_object) o->setValueAt(index, val); else a->replace(index, val); return *this; } QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref) { if (is_object) o->setValueAt(index, ref); else a->replace(index, ref); return *this; } QJsonArray QJsonValueRef::toArray() const { return toValue().toArray(); } QJsonObject QJsonValueRef::toObject() const { return toValue().toObject(); } QJsonValue QJsonValueRef::toValue() const { if (!is_object) return a->at(index); return o->valueAt(index); } #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonValue &o) { switch (o.t) { case QJsonValue::Undefined: dbg.nospace() << "QJsonValue(undefined)"; break; case QJsonValue::Null: dbg.nospace() << "QJsonValue(null)"; break; case QJsonValue::Bool: dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ")"; break; case QJsonValue::Double: dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ")"; break; case QJsonValue::String: dbg.nospace() << "QJsonValue(string, " << o.toString() << ")"; break; case QJsonValue::Array: dbg.nospace() << "QJsonValue(array, "; dbg.nospace() << o.toArray(); dbg.nospace() << ")"; break; case QJsonValue::Object: dbg.nospace() << "QJsonValue(object, "; dbg.nospace() << o.toObject(); dbg.nospace() << ")"; break; } return dbg.space(); } #endif QT_END_NAMESPACE ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonvalue.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QJSONVALUE_H #define QJSONVALUE_H #include "qjson_export.h" #include #include #include QT_BEGIN_NAMESPACE class QDebug; class QVariant; class QJsonArray; class QJsonObject; namespace QJsonPrivate { class Data; class Base; class Object; class Header; class Array; class Value; class Entry; } class QJSON_EXPORT QJsonValue { public: enum Type { Null = 0x0, Bool = 0x1, Double = 0x2, String = 0x3, Array = 0x4, Object = 0x5, Undefined = 0x80 }; QJsonValue(Type = Null); QJsonValue(bool b); QJsonValue(double n); QJsonValue(int n); QJsonValue(qint64 n); QJsonValue(const QString &s); QJsonValue(QLatin1String s); #ifndef QT_NO_CAST_FROM_ASCII inline QT_ASCII_CAST_WARN QJsonValue(const char *s) : d(0), t(String) { stringDataFromQStringHelper(QString::fromUtf8(s)); } #endif QJsonValue(const QJsonArray &a); QJsonValue(const QJsonObject &o); ~QJsonValue(); QJsonValue(const QJsonValue &other); QJsonValue &operator =(const QJsonValue &other); static QJsonValue fromVariant(const QVariant &variant); QVariant toVariant() const; Type type() const; inline bool isNull() const { return type() == Null; } inline bool isBool() const { return type() == Bool; } inline bool isDouble() const { return type() == Double; } inline bool isString() const { return type() == String; } inline bool isArray() const { return type() == Array; } inline bool isObject() const { return type() == Object; } inline bool isUndefined() const { return type() == Undefined; } bool toBool(bool defaultValue = false) const; int toInt(int defaultValue = 0) const; double toDouble(double defaultValue = 0) const; QString toString(const QString &defaultValue = QString()) const; QJsonArray toArray() const; QJsonArray toArray(const QJsonArray &defaultValue) const; QJsonObject toObject() const; QJsonObject toObject(const QJsonObject &defaultValue) const; bool operator==(const QJsonValue &other) const; bool operator!=(const QJsonValue &other) const; private: // avoid implicit conversions from char * to bool inline QJsonValue(const void *) {} friend class QJsonPrivate::Value; friend class QJsonArray; friend class QJsonObject; friend QJSON_EXPORT QDebug operator<<(QDebug, const QJsonValue &); QJsonValue(QJsonPrivate::Data *d, QJsonPrivate::Base *b, const QJsonPrivate::Value& v); void stringDataFromQStringHelper(const QString &string); void detach(); union { quint64 ui; bool b; double dbl; // QStringData *stringData; QJsonPrivate::Base *base; }; QString stringValue; QJsonPrivate::Data *d; // needed for Objects and Arrays Type t; }; class QJSON_EXPORT QJsonValueRef { public: QJsonValueRef(QJsonArray *array, int idx) : a(array), is_object(false), index(idx) {} QJsonValueRef(QJsonObject *object, int idx) : o(object), is_object(true), index(idx) {} inline operator QJsonValue() const { return toValue(); } QJsonValueRef &operator = (const QJsonValue &val); QJsonValueRef &operator = (const QJsonValueRef &val); inline QJsonValue::Type type() const { return toValue().type(); } inline bool isNull() const { return type() == QJsonValue::Null; } inline bool isBool() const { return type() == QJsonValue::Bool; } inline bool isDouble() const { return type() == QJsonValue::Double; } inline bool isString() const { return type() == QJsonValue::String; } inline bool isArray() const { return type() == QJsonValue::Array; } inline bool isObject() const { return type() == QJsonValue::Object; } inline bool isUndefined() const { return type() == QJsonValue::Undefined; } inline bool toBool() const { return toValue().toBool(); } inline int toInt() const { return toValue().toInt(); } inline double toDouble() const { return toValue().toDouble(); } inline QString toString() const { return toValue().toString(); } QJsonArray toArray() const; QJsonObject toObject() const; // ### Qt 6: Add default values inline bool toBool(bool defaultValue) const { return toValue().toBool(defaultValue); } inline int toInt(int defaultValue) const { return toValue().toInt(defaultValue); } inline double toDouble(double defaultValue) const { return toValue().toDouble(defaultValue); } inline QString toString(const QString &defaultValue) const { return toValue().toString(defaultValue); } inline bool operator==(const QJsonValue &other) const { return toValue() == other; } inline bool operator!=(const QJsonValue &other) const { return toValue() != other; } private: QJsonValue toValue() const; union { QJsonArray *a; QJsonObject *o; }; uint is_object : 1; uint index : 31; }; #ifndef Q_QDOC // ### Qt 6: Get rid of these fake pointer classes class QJsonValuePtr { QJsonValue value; public: explicit QJsonValuePtr(const QJsonValue& val) : value(val) {} QJsonValue& operator*() { return value; } QJsonValue* operator->() { return &value; } }; class QJsonValueRefPtr { QJsonValueRef valueRef; public: QJsonValueRefPtr(QJsonArray *array, int idx) : valueRef(array, idx) {} QJsonValueRefPtr(QJsonObject *object, int idx) : valueRef(object, idx) {} QJsonValueRef& operator*() { return valueRef; } QJsonValueRef* operator->() { return &valueRef; } }; #endif Q_DECLARE_METATYPE(QJsonValue) #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QJSON_EXPORT QDebug operator<<(QDebug, const QJsonValue &); #endif QT_END_NAMESPACE #endif // QJSONVALUE_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonwriter.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Copyright (C) 2013 Intel Corporation ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qjsonwriter_p.h" #include "qjson_p.h" QT_BEGIN_NAMESPACE using namespace QJsonPrivate; static void objectContentToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact); static void arrayContentToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact); // some code from qutfcodec.cpp, inlined here for performance reasons // to allow fast escaping of strings static inline bool isUnicodeNonCharacter(uint ucs4) { // Unicode has a couple of "non-characters" that one can use internally, // but are not allowed to be used for text interchange. // // Those are the last two entries each Unicode Plane (U+FFFE, U+FFFF, // U+1FFFE, U+1FFFF, etc.) as well as the entries between U+FDD0 and // U+FDEF (inclusive) return (ucs4 & 0xfffe) == 0xfffe || (ucs4 - 0xfdd0U) < 16; } static inline uchar hexdig(uint u) { return (u < 0xa ? '0' + u : 'a' + u - 0xa); } static QByteArray escapedString(const QString &s) { const uchar replacement = '?'; QByteArray ba(s.length(), Qt::Uninitialized); uchar *cursor = (uchar *)ba.data(); const uchar *ba_end = cursor + ba.length(); const QChar *ch = (const QChar *)s.constData(); const QChar *end = ch + s.length(); int surrogate_high = -1; while (ch < end) { if (cursor >= ba_end - 6) { // ensure we have enough space int pos = cursor - (const uchar *)ba.constData(); ba.resize(ba.size()*2); cursor = (uchar *)ba.data() + pos; ba_end = (const uchar *)ba.constData() + ba.length(); } uint u = ch->unicode(); if (surrogate_high >= 0) { if (ch->isLowSurrogate()) { u = QChar::surrogateToUcs4(surrogate_high, u); surrogate_high = -1; } else { // high surrogate without low *cursor = replacement; ++ch; surrogate_high = -1; continue; } } else if (ch->isLowSurrogate()) { // low surrogate without high *cursor = replacement; ++ch; continue; } else if (ch->isHighSurrogate()) { surrogate_high = u; ++ch; continue; } if (u < 0x80) { if (u < 0x20 || u == 0x22 || u == 0x5c) { *cursor++ = '\\'; switch (u) { case 0x22: *cursor++ = '"'; break; case 0x5c: *cursor++ = '\\'; break; case 0x8: *cursor++ = 'b'; break; case 0xc: *cursor++ = 'f'; break; case 0xa: *cursor++ = 'n'; break; case 0xd: *cursor++ = 'r'; break; case 0x9: *cursor++ = 't'; break; default: *cursor++ = 'u'; *cursor++ = '0'; *cursor++ = '0'; *cursor++ = hexdig(u>>4); *cursor++ = hexdig(u & 0xf); } } else { *cursor++ = (uchar)u; } } else { if (u < 0x0800) { *cursor++ = 0xc0 | ((uchar) (u >> 6)); } else { // is it one of the Unicode non-characters? if (isUnicodeNonCharacter(u)) { *cursor++ = replacement; ++ch; continue; } if (u > 0xffff) { *cursor++ = 0xf0 | ((uchar) (u >> 18)); *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f); } else { *cursor++ = 0xe0 | (((uchar) (u >> 12)) & 0x3f); } *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f); } *cursor++ = 0x80 | ((uchar) (u&0x3f)); } ++ch; } ba.resize(cursor - (const uchar *)ba.constData()); return ba; } static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value &v, QByteArray &json, int indent, bool compact) { QJsonValue::Type type = (QJsonValue::Type)(uint)v.type; switch (type) { case QJsonValue::Bool: json += v.toBoolean() ? "true" : "false"; break; case QJsonValue::Double: { const double d = v.toDouble(b); if (qIsFinite(d)) // +2 to format to ensure the expected precision json += QByteArray::number(d, 'g', std::numeric_limits::digits10 + 2); // ::digits10 is 15 else json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4) break; } case QJsonValue::String: json += '"'; json += escapedString(v.toString(b)); json += '"'; break; case QJsonValue::Array: json += compact ? "[" : "[\n"; arrayContentToJson(static_cast(v.base(b)), json, indent + (compact ? 0 : 1), compact); json += QByteArray(4*indent, ' '); json += "]"; break; case QJsonValue::Object: json += compact ? "{" : "{\n"; objectContentToJson(static_cast(v.base(b)), json, indent + (compact ? 0 : 1), compact); json += QByteArray(4*indent, ' '); json += "}"; break; case QJsonValue::Null: default: json += "null"; } } static void arrayContentToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact) { if (!a || !a->length) return; QByteArray indentString(4*indent, ' '); uint i = 0; while (1) { json += indentString; valueToJson(a, a->at(i), json, indent, compact); if (++i == a->length) { if (!compact) json += '\n'; break; } json += compact ? "," : ",\n"; } } static void objectContentToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact) { if (!o || !o->length) return; QByteArray indentString(4*indent, ' '); uint i = 0; while (1) { QJsonPrivate::Entry *e = o->entryAt(i); json += indentString; json += '"'; json += escapedString(e->key()); json += compact ? "\":" : "\": "; valueToJson(o, e->value, json, indent, compact); if (++i == o->length) { if (!compact) json += '\n'; break; } json += compact ? "," : ",\n"; } } void Writer::objectToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact) { json.reserve(json.size() + (o ? (int)o->size : 16)); json += compact ? "{" : "{\n"; objectContentToJson(o, json, indent + (compact ? 0 : 1), compact); json += QByteArray(4*indent, ' '); json += compact ? "}" : "}\n"; } void Writer::arrayToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact) { json.reserve(json.size() + (a ? (int)a->size : 16)); json += compact ? "[" : "[\n"; arrayContentToJson(a, json, indent + (compact ? 0 : 1), compact); json += QByteArray(4*indent, ' '); json += compact ? "]" : "]\n"; } QT_END_NAMESPACE ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/json/qjsonwriter_p.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QJSONWRITER_P_H #define QJSONWRITER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qjsonvalue.h" QT_BEGIN_NAMESPACE namespace QJsonPrivate { class Writer { public: static void objectToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact = false); static void arrayToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact = false); }; } QT_END_NAMESPACE #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcabstractserver.cpp ================================================ #include "qjsonrpcsocket.h" #include "qjsonrpcabstractserver_p.h" #include "qjsonrpcabstractserver.h" QJsonRpcAbstractServer::~QJsonRpcAbstractServer() { } void QJsonRpcAbstractServerPrivate::_q_notifyConnectedClients(const QString &method, const QJsonArray ¶ms) { QJsonRpcMessage notification = QJsonRpcMessage::createNotification(method, params); _q_notifyConnectedClients(notification); } void QJsonRpcAbstractServerPrivate::_q_notifyConnectedClients(const QJsonRpcMessage &message) { for (int i = 0; i < clients.size(); ++i) clients[i]->notify(message); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcabstractserver.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCABSTRACTSERVER_H #define QJSONRPCABSTRACTSERVER_H #include "qjsonrpcserviceprovider.h" #include "qjsonrpcglobal.h" class QJsonArray; class QJsonRpcMessage; class QJsonRpcAbstractServerPrivate; class QJSONRPC_EXPORT QJsonRpcAbstractServer : public QJsonRpcServiceProvider { public: virtual ~QJsonRpcAbstractServer(); virtual int connectedClientCount() const = 0; // Q_SIGNALS: virtual void clientConnected() = 0; virtual void clientDisconnected() = 0; // public Q_SLOTS: virtual void notifyConnectedClients(const QJsonRpcMessage &message) = 0; virtual void notifyConnectedClients(const QString &method, const QJsonArray ¶ms) = 0; }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcabstractserver_p.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCABSTRACTSERVER_P_H #define QJSONRPCABSTRACTSERVER_P_H #include "qjsonrpcabstractserver.h" class QJsonRpcSocket; #if defined(USE_QT_PRIVATE_HEADERS) #include class QJsonRpcAbstractServerPrivate : public QObjectPrivate #else class QJsonRpcAbstractServerPrivate #endif { public: #if !defined(USE_QT_PRIVATE_HEADERS) virtual ~QJsonRpcAbstractServerPrivate() {} #endif void _q_notifyConnectedClients(const QJsonRpcMessage &message); void _q_notifyConnectedClients(const QString &method, const QJsonArray ¶ms); QList clients; }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcglobal.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCGLOBAL_H #define QJSONRPCGLOBAL_H #include #include // error codes defined by spec namespace QJsonRpc { enum ErrorCode { NoError = 0, ParseError = -32700, // Invalid JSON was received by the server. // An error occurred on the server while parsing the JSON text. InvalidRequest = -32600, // The JSON sent is not a valid Request object. MethodNotFound = -32601, // The method does not exist / is not available. InvalidParams = -32602, // Invalid method parameter(s). InternalError = -32603, // Internal JSON-RPC error. ServerErrorBase = -32000, // Reserved for implementation-defined server-errors. UserError = -32099, // Anything after this is user defined TimeoutError = -32100 }; } Q_DECLARE_METATYPE(QJsonRpc::ErrorCode) #define qJsonRpcDebug if (qgetenv("QJSONRPC_DEBUG").isEmpty()); else qDebug #ifdef QJSONRPC_SHARED # ifdef QJSONRPC_BUILD # define QJSONRPC_EXPORT Q_DECL_EXPORT # else # define QJSONRPC_EXPORT Q_DECL_IMPORT # endif #else # define QJSONRPC_EXPORT #endif #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpchttpclient.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcsocket_p.h" #include "qjsonrpcservicereply_p.h" #include "qjsonrpchttpclient.h" class QJsonRpcHttpReplyPrivate : public QJsonRpcServiceReplyPrivate { public: QNetworkReply *reply; }; class QJsonRpcHttpReply : public QJsonRpcServiceReply { Q_OBJECT public: QJsonRpcHttpReply(const QJsonRpcMessage &request, QNetworkReply *reply, QObject *parent = 0) : QJsonRpcServiceReply(*new QJsonRpcHttpReplyPrivate, parent) { Q_D(QJsonRpcHttpReply); d->request = request; d->reply = reply; connect(d->reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); connect(d->reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); } virtual ~QJsonRpcHttpReply() {} Q_SIGNALS: void messageReceived(const QJsonRpcMessage &message); private Q_SLOTS: void networkReplyFinished() { Q_D(QJsonRpcHttpReply); QNetworkReply *reply = qobject_cast(sender()); if (!reply) { qJsonRpcDebug() << Q_FUNC_INFO << "invalid reply"; return; } if (reply->error() != QNetworkReply::NoError) { // this should be handled by the networkReplyError slot } else { QByteArray data = reply->readAll(); QJsonDocument doc = QJsonDocument::fromJson(data); if (doc.isEmpty() || doc.isNull() || !doc.isObject()) { d->response = d->request.createErrorResponse(QJsonRpc::ParseError, "unable to process incoming JSON data", QString::fromUtf8(data)); } else { qJsonRpcDebug() << "received: " << doc.toJson(); QJsonRpcMessage response = QJsonRpcMessage::fromObject(doc.object()); Q_EMIT messageReceived(response); if (d->request.type() == QJsonRpcMessage::Request && d->request.id() != response.id()) { d->response = d->request.createErrorResponse(QJsonRpc::InternalError, "invalid response id", QString::fromUtf8(data)); } else { d->response = response; } } } reply->deleteLater(); Q_EMIT finished(); } void networkReplyError(QNetworkReply::NetworkError code) { Q_D(QJsonRpcHttpReply); QNetworkReply *reply = qobject_cast(sender()); if (!reply) { qJsonRpcDebug() << Q_FUNC_INFO << "invalid reply"; return; } if (code == QNetworkReply::NoError) return; QJsonRpcMessage response = QJsonRpcMessage::fromJson(reply->readAll()); if (response.isValid()) { d->response = response; Q_EMIT messageReceived(response); } else { d->response = d->request.createErrorResponse(QJsonRpc::InternalError, QString("error with http request: %1").arg(reply->error()), reply->errorString()); } } private: Q_DISABLE_COPY(QJsonRpcHttpReply) Q_DECLARE_PRIVATE(QJsonRpcHttpReply) }; class QJsonRpcHttpClientPrivate : public QJsonRpcAbstractSocketPrivate { public: void initializeNetworkAccessManager(QJsonRpcHttpClient *client) { QObject::connect(networkAccessManager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), client, SLOT(handleAuthenticationRequired(QNetworkReply*,QAuthenticator*))); QObject::connect(networkAccessManager, SIGNAL(sslErrors(QNetworkReply*,QList)), client, SLOT(handleSslErrors(QNetworkReply*,QList))); } QNetworkReply *writeMessage(const QJsonRpcMessage &message) { QNetworkRequest request(endPoint); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json-rpc"); if (!sslConfiguration.isNull()) request.setSslConfiguration(sslConfiguration); QByteArray data = message.toJson(); qJsonRpcDebug() << "sending: " << data; return networkAccessManager->post(request, data); } QUrl endPoint; QNetworkAccessManager *networkAccessManager; QSslConfiguration sslConfiguration; }; QJsonRpcHttpClient::QJsonRpcHttpClient(QObject *parent) : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent) { Q_D(QJsonRpcHttpClient); d->networkAccessManager = new QNetworkAccessManager(this); d->initializeNetworkAccessManager(this); } QJsonRpcHttpClient::QJsonRpcHttpClient(QNetworkAccessManager *manager, QObject *parent) : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent) { Q_D(QJsonRpcHttpClient); d->networkAccessManager = manager; d->initializeNetworkAccessManager(this); } QJsonRpcHttpClient::QJsonRpcHttpClient(const QString &endPoint, QObject *parent) : QJsonRpcAbstractSocket(*new QJsonRpcHttpClientPrivate, parent) { Q_D(QJsonRpcHttpClient); d->endPoint = QUrl::fromUserInput(endPoint); d->networkAccessManager = new QNetworkAccessManager(this); d->initializeNetworkAccessManager(this); } QJsonRpcHttpClient::~QJsonRpcHttpClient() { } bool QJsonRpcHttpClient::isValid() const { Q_D(const QJsonRpcHttpClient); return d->networkAccessManager && !d->endPoint.isEmpty() && d->endPoint.isValid(); } QUrl QJsonRpcHttpClient::endPoint() const { Q_D(const QJsonRpcHttpClient); return d->endPoint; } void QJsonRpcHttpClient::setEndPoint(const QUrl &endPoint) { Q_D(QJsonRpcHttpClient); d->endPoint = endPoint; } void QJsonRpcHttpClient::setEndPoint(const QString &endPoint) { Q_D(QJsonRpcHttpClient); d->endPoint = QUrl::fromUserInput(endPoint); } QNetworkAccessManager *QJsonRpcHttpClient::networkAccessManager() { Q_D(QJsonRpcHttpClient); return d->networkAccessManager; } QSslConfiguration QJsonRpcHttpClient::sslConfiguration() const { Q_D(const QJsonRpcHttpClient); return d->sslConfiguration; } void QJsonRpcHttpClient::setSslConfiguration(const QSslConfiguration &sslConfiguration) { Q_D(QJsonRpcHttpClient); d->sslConfiguration = sslConfiguration; } void QJsonRpcHttpClient::notify(const QJsonRpcMessage &message) { Q_D(QJsonRpcHttpClient); if (d->endPoint.isEmpty()) { qJsonRpcDebug() << Q_FUNC_INFO << "invalid endpoint specified"; return; } QNetworkReply *reply = d->writeMessage(message); connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater())); // NOTE: we might want to connect this to a local slot to track errors // for debugging later? connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), reply, SLOT(deleteLater())); } QJsonRpcServiceReply *QJsonRpcHttpClient::sendMessage(const QJsonRpcMessage &message) { Q_D(QJsonRpcHttpClient); if (d->endPoint.isEmpty()) { qJsonRpcDebug() << Q_FUNC_INFO << "invalid endpoint specified"; return 0; } QNetworkReply *reply = d->writeMessage(message); QJsonRpcHttpReply *serviceReply = new QJsonRpcHttpReply(message, reply); connect(serviceReply, SIGNAL(messageReceived(QJsonRpcMessage)), this, SIGNAL(messageReceived(QJsonRpcMessage))); return serviceReply; } QJsonRpcMessage QJsonRpcHttpClient::sendMessageBlocking(const QJsonRpcMessage &message, int msecs) { QJsonRpcServiceReply *reply = sendMessage(message); QScopedPointer replyPtr(reply); QEventLoop responseLoop; connect(reply, SIGNAL(finished()), &responseLoop, SLOT(quit())); QTimer::singleShot(msecs, &responseLoop, SLOT(quit())); responseLoop.exec(); if (!reply->response().isValid()) return message.createErrorResponse(QJsonRpc::TimeoutError, "request timed out"); return reply->response(); } QJsonRpcMessage QJsonRpcHttpClient::invokeRemoteMethodBlocking(const QString &method, int msecs, const QVariant ¶m1, const QVariant ¶m2, const QVariant ¶m3, const QVariant ¶m4, const QVariant ¶m5, const QVariant ¶m6, const QVariant ¶m7, const QVariant ¶m8, const QVariant ¶m9, const QVariant ¶m10) { QVariantList params; if (param1.isValid()) params.append(param1); if (param2.isValid()) params.append(param2); if (param3.isValid()) params.append(param3); if (param4.isValid()) params.append(param4); if (param5.isValid()) params.append(param5); if (param6.isValid()) params.append(param6); if (param7.isValid()) params.append(param7); if (param8.isValid()) params.append(param8); if (param9.isValid()) params.append(param9); if (param10.isValid()) params.append(param10); QJsonRpcMessage request = QJsonRpcMessage::createRequest(method, QJsonArray::fromVariantList(params)); return sendMessageBlocking(request, msecs); } QJsonRpcMessage QJsonRpcHttpClient::invokeRemoteMethodBlocking(const QString &method, const QVariant ¶m1, const QVariant ¶m2, const QVariant ¶m3, const QVariant ¶m4, const QVariant ¶m5, const QVariant ¶m6, const QVariant ¶m7, const QVariant ¶m8, const QVariant ¶m9, const QVariant ¶m10) { Q_D(QJsonRpcHttpClient); return invokeRemoteMethodBlocking(method, d->defaultRequestTimeout, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); } QJsonRpcServiceReply *QJsonRpcHttpClient::invokeRemoteMethod(const QString &method, const QVariant ¶m1, const QVariant ¶m2, const QVariant ¶m3, const QVariant ¶m4, const QVariant ¶m5, const QVariant ¶m6, const QVariant ¶m7, const QVariant ¶m8, const QVariant ¶m9, const QVariant ¶m10) { QVariantList params; if (param1.isValid()) params.append(param1); if (param2.isValid()) params.append(param2); if (param3.isValid()) params.append(param3); if (param4.isValid()) params.append(param4); if (param5.isValid()) params.append(param5); if (param6.isValid()) params.append(param6); if (param7.isValid()) params.append(param7); if (param8.isValid()) params.append(param8); if (param9.isValid()) params.append(param9); if (param10.isValid()) params.append(param10); QJsonRpcMessage request = QJsonRpcMessage::createRequest(method, QJsonArray::fromVariantList(params)); return sendMessage(request); } void QJsonRpcHttpClient::handleAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator) { Q_UNUSED(reply) Q_UNUSED(authenticator) } void QJsonRpcHttpClient::handleSslErrors(QNetworkReply *reply, const QList &errors) { Q_UNUSED(errors) reply->ignoreSslErrors(); } #include "qjsonrpchttpclient.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpchttpclient.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCHTTPCLIENT_H #define QJSONRPCHTTPCLIENT_H #include #include #include #include "qjsonrpcglobal.h" #include "qjsonrpcmessage.h" #include "qjsonrpcsocket.h" #include "qjsonrpcservicereply.h" class QNetwokReply; class QAuthenticator; class QSslError; class QNetworkAccessManager; class QJsonRpcHttpClientPrivate; class QJSONRPC_EXPORT QJsonRpcHttpClient : public QJsonRpcAbstractSocket { Q_OBJECT public: QJsonRpcHttpClient(QObject *parent = 0); QJsonRpcHttpClient(const QString &endPoint, QObject *parent = 0); QJsonRpcHttpClient(QNetworkAccessManager *manager, QObject *parent = 0); ~QJsonRpcHttpClient(); virtual bool isValid() const; QUrl endPoint() const; void setEndPoint(const QUrl &endPoint); void setEndPoint(const QString &endPoint); QNetworkAccessManager *networkAccessManager(); QSslConfiguration sslConfiguration() const; void setSslConfiguration(const QSslConfiguration &sslConfiguration); public Q_SLOTS: virtual void notify(const QJsonRpcMessage &message); virtual QJsonRpcMessage sendMessageBlocking(const QJsonRpcMessage &message, int msecs = DEFAULT_MSECS_REQUEST_TIMEOUT); virtual QJsonRpcServiceReply *sendMessage(const QJsonRpcMessage &message); virtual QJsonRpcMessage invokeRemoteMethodBlocking(const QString &method, int msecs, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); virtual QJsonRpcMessage invokeRemoteMethodBlocking(const QString &method, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); virtual QJsonRpcServiceReply *invokeRemoteMethod(const QString &method, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); protected Q_SLOTS: virtual void handleAuthenticationRequired(QNetworkReply *reply, QAuthenticator * authenticator); virtual void handleSslErrors( QNetworkReply * reply, const QList &errors); private: Q_DISABLE_COPY(QJsonRpcHttpClient) Q_DECLARE_PRIVATE(QJsonRpcHttpClient) }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpchttpserver.cpp ================================================ #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcsocket.h" #include "qjsonrpcmessage.h" #include "qjsonrpchttpserver_p.h" #include "qjsonrpchttpserver.h" QJsonRpcHttpServerSocket::QJsonRpcHttpServerSocket(QObject *parent) : QSslSocket(parent), m_requestParser(0) { // initialize request parser m_requestParser = (http_parser*)malloc(sizeof(http_parser)); http_parser_init(m_requestParser, HTTP_REQUEST); m_requestParserSettings.on_message_begin = onMessageBegin; m_requestParserSettings.on_url = onUrl; m_requestParserSettings.on_header_field = onHeaderField; m_requestParserSettings.on_header_value = onHeaderValue; m_requestParserSettings.on_headers_complete = onHeadersComplete; m_requestParserSettings.on_body = onBody; m_requestParserSettings.on_message_complete = onMessageComplete; m_requestParser->data = this; connect(this, SIGNAL(readyRead()), this, SLOT(readIncomingData())); } QJsonRpcHttpServerSocket::~QJsonRpcHttpServerSocket() { free(m_requestParser); } static inline QByteArray statusMessageForCode(int code) { switch (code) { case 200: return "OK"; case 400: return "Bad Request"; case 404: return "Not Found"; case 405: return "Method Not Allowed"; case 500: return "Internal Server Error"; } return QByteArray(); } qint64 QJsonRpcHttpServerSocket::writeData(const char *data, qint64 maxSize) { m_responseBuffer.append(data, (int)maxSize); QJsonDocument document = QJsonDocument::fromJson(m_responseBuffer); if (document.isObject()) { // determine the HTTP code to respond with int statusCode = 200; QJsonRpcMessage message = QJsonRpcMessage::fromObject(document.object()); switch (message.type()) { case QJsonRpcMessage::Error: switch (message.errorCode()) { case QJsonRpc::InvalidRequest: statusCode = 400; break; case QJsonRpc::MethodNotFound: statusCode = 404; break; default: statusCode = 500; break; } break; case QJsonRpcMessage::Invalid: statusCode = 400; break; case QJsonRpcMessage::Notification: case QJsonRpcMessage::Response: case QJsonRpcMessage::Request: statusCode = 200; break; } // header QByteArray responseHeader; responseHeader += "HTTP/1.1 " + QByteArray::number(statusCode) +" " + statusMessageForCode(statusCode) + "\r\n"; if(m_requestHeaders.contains("origin")) { QString origin = m_requestHeaders["origin"]; responseHeader += "Access-Control-Allow-Origin: " + origin.toUtf8() + "\r\n"; } responseHeader += "Content-Type: application/json-rpc\r\n"; responseHeader += "Content-Length: " + QByteArray::number(m_responseBuffer.size()) + "\r\n"; responseHeader += "\r\n"; // body m_responseBuffer.prepend(responseHeader); qint64 bytesWritten = QSslSocket::writeData(m_responseBuffer.constData(), m_responseBuffer.size()); close(); // then clear the buffer m_responseBuffer.clear(); return bytesWritten; } return maxSize; } void QJsonRpcHttpServerSocket::sendOptionsResponse(int statusCode) { QByteArray responseHeader; responseHeader += "HTTP/1.1 " + QByteArray::number(statusCode) +" " + statusMessageForCode(statusCode) + "\r\n"; if(m_requestHeaders.contains("origin")) { QByteArray origin = m_requestHeaders["origin"].toLatin1(); responseHeader += "Access-Control-Allow-Origin: " + origin + "\r\n"; } if(m_requestHeaders.contains("access-control-request-method")) { QByteArray allowed_method = m_requestHeaders["access-control-request-method"].toLatin1(); responseHeader += "Access-Control-Allow-Methods: " + allowed_method + "\r\n"; } if(m_requestHeaders.contains("access-control-request-headers")) { QByteArray allowed_headers = m_requestHeaders["access-control-request-headers"].toLatin1(); responseHeader += "Access-Control-Allow-Headers: " + allowed_headers + "\r\n"; } responseHeader += "Content-Type: text/plain\r\n"; responseHeader += "Connection: keep-alive\r\n"; responseHeader += "\r\n"; QSslSocket::writeData(responseHeader.constData(), responseHeader.size()); close(); } void QJsonRpcHttpServerSocket::sendErrorResponse(int statusCode) { QByteArray responseHeader; responseHeader += "HTTP/1.1 " + QByteArray::number(statusCode) +" " + statusMessageForCode(statusCode) + "\r\n"; responseHeader += "\r\n"; QSslSocket::writeData(responseHeader.constData(), responseHeader.size()); close(); } void QJsonRpcHttpServerSocket::readIncomingData() { QByteArray requestBuffer = readAll(); http_parser_execute(m_requestParser, &m_requestParserSettings, requestBuffer.constData(), requestBuffer.size()); } int QJsonRpcHttpServerSocket::onBody(http_parser *parser, const char *at, size_t length) { QJsonRpcHttpServerSocket *request = (QJsonRpcHttpServerSocket *)parser->data; request->m_requestPayload = QByteArray(at, length); return 0; } int QJsonRpcHttpServerSocket::onMessageComplete(http_parser *parser) { QJsonRpcHttpServerSocket *request = (QJsonRpcHttpServerSocket *)parser->data; QJsonRpcMessage message = QJsonRpcMessage::fromJson(request->m_requestPayload); Q_EMIT request->messageReceived(message); return 0; } int QJsonRpcHttpServerSocket::onHeadersComplete(http_parser *parser) { QJsonRpcHttpServerSocket *request = (QJsonRpcHttpServerSocket *)parser->data; if (parser->method == HTTP_OPTIONS) { qJsonRpcDebug() << Q_FUNC_INFO << "OPTIONS method" << parser->method; request->sendOptionsResponse(200); return 0; } // need to add the final headers received if (!request->m_currentHeaderField.isEmpty() && !request->m_currentHeaderValue.isEmpty()) { request->m_requestHeaders.insert(request->m_currentHeaderField.toLower(), request->m_currentHeaderValue); request->m_currentHeaderField.clear(); request->m_currentHeaderValue.clear(); } if (parser->method != HTTP_GET && parser->method != HTTP_POST) { // NOTE: close the socket, cleanup, delete, etc.. qJsonRpcDebug() << Q_FUNC_INFO << "invalid method: " << parser->method; request->sendErrorResponse(405); return -1; } // check headers // see: http://www.jsonrpc.org/historical/json-rpc-over-http.html#http-header QStringList requiredHeaders = QStringList() << "content-type" << "content-length" << "accept"; foreach (QString requiredHeader, requiredHeaders) { if (!request->m_requestHeaders.contains(requiredHeader)) { qJsonRpcDebug() << Q_FUNC_INFO << "error: " << request->m_requestHeaders; request->sendErrorResponse(400); return -1; } } QStringList supportedContentTypes = QStringList() << "application/json-rpc" << "application/json" << "application/jsonrequest"; QString contentType = request->m_requestHeaders.value("content-type"); bool foundSupportedContentType = false; foreach (QString supportedContentType, supportedContentTypes) { if (contentType.contains(supportedContentType)) { foundSupportedContentType = true; break; } } QString acceptType = request->m_requestHeaders.value("accept"); if (!foundSupportedContentType || !supportedContentTypes.contains(acceptType)) { // NOTE: signal the error qJsonRpcDebug() << Q_FUNC_INFO << "invalid content or accept type"; request->sendErrorResponse(400); return -1; } return 0; } int QJsonRpcHttpServerSocket::onHeaderField(http_parser *parser, const char *at, size_t length) { QJsonRpcHttpServerSocket *request = (QJsonRpcHttpServerSocket *)parser->data; if (!request->m_currentHeaderField.isEmpty() && !request->m_currentHeaderValue.isEmpty()) { request->m_requestHeaders.insert(request->m_currentHeaderField.toLower(), request->m_currentHeaderValue); request->m_currentHeaderField.clear(); request->m_currentHeaderValue.clear(); } request->m_currentHeaderField.append(QString::fromUtf8(at, length)); return 0; } int QJsonRpcHttpServerSocket::onHeaderValue(http_parser *parser, const char *at, size_t length) { QJsonRpcHttpServerSocket *request = (QJsonRpcHttpServerSocket *)parser->data; request->m_currentHeaderValue.append(QString::fromUtf8(at, length)); return 0; } int QJsonRpcHttpServerSocket::onMessageBegin(http_parser *parser) { QJsonRpcHttpServerSocket *request = (QJsonRpcHttpServerSocket *)parser->data; request->m_requestHeaders.clear(); return 0; } int QJsonRpcHttpServerSocket::onUrl(http_parser *parser, const char *at, size_t length) { Q_UNUSED(parser) Q_UNUSED(at) Q_UNUSED(length) // QString url = QString::fromLatin1(at, length); // qDebug() << "requested url: " << url; return 0; } QJsonRpcHttpServerRpcSocket::QJsonRpcHttpServerRpcSocket(QIODevice *device, QObject *parent) : QJsonRpcSocket(device, parent) { disconnect(device, SIGNAL(readyRead()), this, SLOT(_q_processIncomingData())); } QJsonRpcHttpServer::QJsonRpcHttpServer(QObject *parent) : QTcpServer(parent), d_ptr(new QJsonRpcHttpServerPrivate(this)) { } QJsonRpcHttpServer::~QJsonRpcHttpServer() { } QSslConfiguration QJsonRpcHttpServer::sslConfiguration() const { Q_D(const QJsonRpcHttpServer); return d->sslConfiguration; } void QJsonRpcHttpServer::setSslConfiguration(const QSslConfiguration &config) { Q_D(QJsonRpcHttpServer); d->sslConfiguration = config; } #if QT_VERSION >= 0x050000 void QJsonRpcHttpServer::incomingConnection(qintptr socketDescriptor) #else void QJsonRpcHttpServer::incomingConnection(int socketDescriptor) #endif { Q_D(QJsonRpcHttpServer); QJsonRpcHttpServerSocket *socket = new QJsonRpcHttpServerSocket(this); if (!socket->setSocketDescriptor(socketDescriptor)) { qJsonRpcDebug() << Q_FUNC_INFO << "unable to set socket descriptor"; socket->deleteLater(); return; } if (!d->sslConfiguration.isNull()) { socket->setSslConfiguration(d->sslConfiguration); socket->startServerEncryption(); // connect ssl error signals etc // NOTE: unsafe connect(socket, SIGNAL(sslErrors(QList)), socket, SLOT(ignoreSslErrors())); } connect(socket, SIGNAL(disconnected()), this, SLOT(_q_socketDisconnected())); connect(socket, SIGNAL(messageReceived(QJsonRpcMessage)), this, SLOT(processIncomingMessage(QJsonRpcMessage))); QJsonRpcHttpServerRpcSocket *rpcSocket = new QJsonRpcHttpServerRpcSocket(socket, this); d->requestSocketLookup.insert(socket, rpcSocket); } void QJsonRpcHttpServer::processIncomingMessage(const QJsonRpcMessage &message) { Q_D(QJsonRpcHttpServer); QJsonRpcHttpServerSocket *request = qobject_cast(sender()); if (!request) return; QJsonRpcSocket *socket = d->requestSocketLookup.value(request); processMessage(socket, message); } int QJsonRpcHttpServer::connectedClientCount() const { return 0; } void QJsonRpcHttpServer::notifyConnectedClients(const QJsonRpcMessage &message) { Q_UNUSED(message); } void QJsonRpcHttpServer::notifyConnectedClients(const QString &method, const QJsonArray ¶ms) { Q_UNUSED(method); Q_UNUSED(params); } void QJsonRpcHttpServerPrivate::_q_socketDisconnected() { Q_Q(QJsonRpcHttpServer); QJsonRpcHttpServerSocket *socket = qobject_cast(q->sender()); if (!socket) return; QJsonRpcSocket *rpcSocket = requestSocketLookup.take(socket); rpcSocket->deleteLater(); socket->deleteLater(); } #include "moc_qjsonrpchttpserver.cpp" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpchttpserver.h ================================================ #ifndef QJSONRPCHTTPSERVER_H #define QJSONRPCHTTPSERVER_H #include #include #include #include "qjsonrpcabstractserver.h" #include "qjsonrpcglobal.h" class QJsonRpcHttpServerPrivate; class QJSONRPC_EXPORT QJsonRpcHttpServer : public QTcpServer, public QJsonRpcAbstractServer { Q_OBJECT public: QJsonRpcHttpServer(QObject *parent = 0); ~QJsonRpcHttpServer(); QSslConfiguration sslConfiguration() const; void setSslConfiguration(const QSslConfiguration &config); virtual int connectedClientCount() const; Q_SIGNALS: void clientConnected(); void clientDisconnected(); public Q_SLOTS: virtual void notifyConnectedClients(const QJsonRpcMessage &message); virtual void notifyConnectedClients(const QString &method, const QJsonArray ¶ms); protected: #if QT_VERSION >= 0x050000 virtual void incomingConnection(qintptr socketDescriptor); #else virtual void incomingConnection(int socketDescriptor); #endif private Q_SLOTS: void processIncomingMessage(const QJsonRpcMessage &message); private: Q_DECLARE_PRIVATE(QJsonRpcHttpServer) Q_DISABLE_COPY(QJsonRpcHttpServer) QScopedPointer d_ptr; Q_PRIVATE_SLOT(d_func(), void _q_socketDisconnected()) }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpchttpserver_p.h ================================================ #ifndef QJSONRPCHTTPSERVER_P_H #define QJSONRPCHTTPSERVER_P_H #include #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcmessage.h" #include "qjsonrpcabstractserver_p.h" #include "http_parser.h" class QJsonRpcHttpServerRpcSocket : public QJsonRpcSocket { public: explicit QJsonRpcHttpServerRpcSocket(QIODevice *device, QObject *parent = 0); }; class QAbstractSocket; class QJsonRpcHttpServerSocket : public QSslSocket { Q_OBJECT public: explicit QJsonRpcHttpServerSocket(QObject *parent = 0); ~QJsonRpcHttpServerSocket(); void sendErrorResponse(int statusCode); void sendOptionsResponse(int statusCode); Q_SIGNALS: void messageReceived(const QJsonRpcMessage &message); protected: virtual qint64 writeData(const char *data, qint64 maxSize); private Q_SLOTS: void readIncomingData(); private: static int onMessageBegin(http_parser *parser); static int onUrl(http_parser *parser, const char *at, size_t length); static int onHeaderField(http_parser *parser, const char *at, size_t length); static int onHeaderValue(http_parser *parser, const char *at, size_t length); static int onHeadersComplete(http_parser *parser); static int onBody(http_parser *parser, const char *at, size_t length); static int onMessageComplete(http_parser *parser); private: Q_DISABLE_COPY(QJsonRpcHttpServerSocket) // request QByteArray m_requestPayload; http_parser *m_requestParser; http_parser_settings m_requestParserSettings; // for header processing QHash m_requestHeaders; QString m_currentHeaderField; QString m_currentHeaderValue; // response QByteArray m_responseBuffer; }; class QJsonRpcHttpServer; class QJsonRpcHttpServerPrivate : public QJsonRpcAbstractServerPrivate { public: QJsonRpcHttpServerPrivate(QJsonRpcHttpServer *qq) : q_ptr(qq) { } // slots void _q_socketDisconnected(); QHash requestSocketLookup; QSslConfiguration sslConfiguration; QJsonRpcHttpServer * const q_ptr; Q_DECLARE_PUBLIC(QJsonRpcHttpServer) }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpclocalserver.cpp ================================================ #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcabstractserver_p.h" #include "qjsonrpclocalserver.h" class QJsonRpcLocalServerPrivate : public QJsonRpcAbstractServerPrivate { public: QHash socketLookup; }; QJsonRpcLocalServer::QJsonRpcLocalServer(QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QLocalServer(*new QJsonRpcLocalServerPrivate, parent) #else : QLocalServer(parent), d_ptr(new QJsonRpcLocalServerPrivate) #endif { } QJsonRpcLocalServer::~QJsonRpcLocalServer() { Q_D(QJsonRpcLocalServer); foreach (QLocalSocket *socket, d->socketLookup.keys()) { socket->flush(); socket->deleteLater(); } d->socketLookup.clear(); foreach (QJsonRpcSocket *client, d->clients) client->deleteLater(); d->clients.clear(); } int QJsonRpcLocalServer::connectedClientCount() const { Q_D(const QJsonRpcLocalServer); return d->clients.size(); } bool QJsonRpcLocalServer::addService(QJsonRpcService *service) { if (!QJsonRpcServiceProvider::addService(service)) return false; connect(service, SIGNAL(notifyConnectedClients(QJsonRpcMessage)), this, SLOT(notifyConnectedClients(QJsonRpcMessage))); connect(service, SIGNAL(notifyConnectedClients(QString,QJsonArray)), this, SLOT(notifyConnectedClients(QString,QJsonArray))); return true; } bool QJsonRpcLocalServer::removeService(QJsonRpcService *service) { if (!QJsonRpcServiceProvider::removeService(service)) return false; disconnect(service, SIGNAL(notifyConnectedClients(QJsonRpcMessage)), this, SLOT(notifyConnectedClients(QJsonRpcMessage))); disconnect(service, SIGNAL(notifyConnectedClients(QString,QJsonArray)), this, SLOT(notifyConnectedClients(QString,QJsonArray))); return true; } void QJsonRpcLocalServer::incomingConnection(quintptr socketDescriptor) { Q_D(QJsonRpcLocalServer); QLocalSocket *localSocket = new QLocalSocket(this); if (!localSocket->setSocketDescriptor(socketDescriptor)) { qJsonRpcDebug() << Q_FUNC_INFO << "nextPendingConnection is null"; localSocket->deleteLater(); return; } QIODevice *device = qobject_cast(localSocket); QJsonRpcSocket *socket = new QJsonRpcSocket(device, this); connect(socket, SIGNAL(messageReceived(QJsonRpcMessage)), this, SLOT(_q_processMessage(QJsonRpcMessage))); d->clients.append(socket); connect(localSocket, SIGNAL(disconnected()), this, SLOT(_q_clientDisconnected())); d->socketLookup.insert(localSocket, socket); Q_EMIT clientConnected(); } void QJsonRpcLocalServer::_q_clientDisconnected() { Q_D(QJsonRpcLocalServer); QLocalSocket *localSocket = static_cast(sender()); if (!localSocket) { qJsonRpcDebug() << Q_FUNC_INFO << "called with invalid socket"; return; } if (d->socketLookup.contains(localSocket)) { QJsonRpcSocket *socket = d->socketLookup.take(localSocket); d->clients.removeAll(socket); socket->deleteLater(); } localSocket->deleteLater(); Q_EMIT clientDisconnected(); } void QJsonRpcLocalServer::_q_processMessage(const QJsonRpcMessage &message) { QJsonRpcSocket *socket = static_cast(sender()); if (!socket) { qJsonRpcDebug() << Q_FUNC_INFO << "called without service socket"; return; } processMessage(socket, message); } void QJsonRpcLocalServer::notifyConnectedClients(const QJsonRpcMessage &message) { Q_D(QJsonRpcLocalServer); d->_q_notifyConnectedClients(message); } void QJsonRpcLocalServer::notifyConnectedClients(const QString &method, const QJsonArray ¶ms) { Q_D(QJsonRpcLocalServer); d->_q_notifyConnectedClients(method, params); } #include "moc_qjsonrpclocalserver.cpp" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpclocalserver.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCLOCALSERVER_H #define QJSONRPCLOCALSERVER_H #include #include "qjsonrpcabstractserver.h" class QJsonRpcLocalServerPrivate; class QJSONRPC_EXPORT QJsonRpcLocalServer : public QLocalServer, public QJsonRpcAbstractServer { Q_OBJECT public: explicit QJsonRpcLocalServer(QObject *parent = 0); ~QJsonRpcLocalServer(); virtual int connectedClientCount() const; // reimp bool addService(QJsonRpcService *service); bool removeService(QJsonRpcService *service); Q_SIGNALS: void clientConnected(); void clientDisconnected(); public Q_SLOTS: void notifyConnectedClients(const QJsonRpcMessage &message); void notifyConnectedClients(const QString &method, const QJsonArray ¶ms); protected: virtual void incomingConnection(quintptr socketDescriptor); private Q_SLOTS: void _q_clientDisconnected(); void _q_processMessage(const QJsonRpcMessage &message); private: Q_DECLARE_PRIVATE(QJsonRpcLocalServer) Q_DISABLE_COPY(QJsonRpcLocalServer) #if !defined(USE_QT_PRIVATE_HEADERS) QScopedPointer d_ptr; #endif }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcmessage.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #if QT_VERSION >= 0x050000 # include #else # include "json/qjsondocument.h" #endif #include "qjsonrpcmessage.h" class QJsonRpcMessagePrivate : public QSharedData { public: QJsonRpcMessagePrivate(); ~QJsonRpcMessagePrivate(); QJsonRpcMessagePrivate(const QJsonRpcMessagePrivate &other); void initializeWithObject(const QJsonObject &message); static QJsonRpcMessage createBasicRequest(const QString &method, const QJsonArray ¶ms); static QJsonRpcMessage createBasicRequest(const QString &method, const QJsonObject &namedParameters); QJsonRpcMessage::Type type; QScopedPointer object; static int uniqueRequestCounter; }; int QJsonRpcMessagePrivate::uniqueRequestCounter = 0; QJsonRpcMessagePrivate::QJsonRpcMessagePrivate() : type(QJsonRpcMessage::Invalid), object(0) { } QJsonRpcMessagePrivate::QJsonRpcMessagePrivate(const QJsonRpcMessagePrivate &other) : QSharedData(other), type(other.type), object(other.object ? new QJsonObject(*other.object) : 0) { } void QJsonRpcMessagePrivate::initializeWithObject(const QJsonObject &message) { object.reset(new QJsonObject(message)); if (message.contains(QLatin1String("id"))) { if (message.contains(QLatin1String("result")) || message.contains(QLatin1String("error"))) { if (message.contains(QLatin1String("error")) && !message.value(QLatin1String("error")).isNull()) type = QJsonRpcMessage::Error; else type = QJsonRpcMessage::Response; } else if (message.contains(QLatin1String("method"))) { type = QJsonRpcMessage::Request; } } else { if (message.contains(QLatin1String("method"))) type = QJsonRpcMessage::Notification; } } QJsonRpcMessagePrivate::~QJsonRpcMessagePrivate() { } QJsonRpcMessage::QJsonRpcMessage() : d(new QJsonRpcMessagePrivate) { d->object.reset(new QJsonObject); } QJsonRpcMessage::QJsonRpcMessage(const QJsonRpcMessage &other) : d(other.d) { } QJsonRpcMessage::~QJsonRpcMessage() { } QJsonRpcMessage &QJsonRpcMessage::operator=(const QJsonRpcMessage &other) { d = other.d; return *this; } bool QJsonRpcMessage::operator==(const QJsonRpcMessage &message) const { if (message.d == d) return true; if (message.type() == type()) { if (message.type() == QJsonRpcMessage::Error) { return (message.errorCode() == errorCode() && message.errorMessage() == errorMessage() && message.errorData() == errorData()); } else { if (message.type() == QJsonRpcMessage::Notification) { return (message.method() == method() && message.params() == params()); } else { return (message.id() == id() && message.method() == method() && message.params() == params()); } } } return false; } QJsonRpcMessage QJsonRpcMessage::fromJson(const QByteArray &message) { QJsonRpcMessage result; QJsonParseError error; QJsonDocument document = QJsonDocument::fromJson(message, &error); if (error.error != QJsonParseError::NoError) { qJsonRpcDebug() << Q_FUNC_INFO << error.errorString(); return result; } if (!document.isObject()) { qJsonRpcDebug() << Q_FUNC_INFO << "invalid message: " << message; return result; } result.d->initializeWithObject(document.object()); return result; } QJsonRpcMessage QJsonRpcMessage::fromObject(const QJsonObject &message) { QJsonRpcMessage result; result.d->initializeWithObject(message); return result; } QJsonObject QJsonRpcMessage::toObject() const { if (d->object) return QJsonObject(*d->object); return QJsonObject(); } QByteArray QJsonRpcMessage::toJson() const { if (d->object) { QJsonDocument doc(*d->object); return doc.toJson(); } return QByteArray(); } bool QJsonRpcMessage::isValid() const { return d->type != QJsonRpcMessage::Invalid; } QJsonRpcMessage::Type QJsonRpcMessage::type() const { return d->type; } QJsonRpcMessage QJsonRpcMessagePrivate::createBasicRequest(const QString &method, const QJsonArray ¶ms) { QJsonRpcMessage request; request.d->object->insert(QLatin1String("jsonrpc"), QLatin1String("2.0")); request.d->object->insert(QLatin1String("method"), method); //if (!params.isEmpty()) request.d->object->insert(QLatin1String("params"), params); return request; } QJsonRpcMessage QJsonRpcMessagePrivate::createBasicRequest(const QString &method, const QJsonObject &namedParameters) { QJsonRpcMessage request; request.d->object->insert(QLatin1String("jsonrpc"), QLatin1String("2.0")); request.d->object->insert(QLatin1String("method"), method); //if (!namedParameters.isEmpty()) request.d->object->insert(QLatin1String("params"), namedParameters); return request; } QJsonRpcMessage QJsonRpcMessage::createRequest(const QString &method, const QJsonArray ¶ms) { QJsonRpcMessage request = QJsonRpcMessagePrivate::createBasicRequest(method, params); request.d->type = QJsonRpcMessage::Request; QJsonRpcMessagePrivate::uniqueRequestCounter++; request.d->object->insert(QLatin1String("id"), QJsonRpcMessagePrivate::uniqueRequestCounter); return request; } QJsonRpcMessage QJsonRpcMessage::createRequest(const QString &method, const QJsonValue ¶m) { QJsonArray params; params.append(param); return createRequest(method, params); } QJsonRpcMessage QJsonRpcMessage::createRequest(const QString &method, const QJsonObject &namedParameters) { QJsonRpcMessage request = QJsonRpcMessagePrivate::createBasicRequest(method, namedParameters); request.d->type = QJsonRpcMessage::Request; QJsonRpcMessagePrivate::uniqueRequestCounter++; request.d->object->insert(QLatin1String("id"), QJsonRpcMessagePrivate::uniqueRequestCounter); return request; } QJsonRpcMessage QJsonRpcMessage::createNotification(const QString &method, const QJsonArray ¶ms) { QJsonRpcMessage notification = QJsonRpcMessagePrivate::createBasicRequest(method, params); notification.d->type = QJsonRpcMessage::Notification; return notification; } QJsonRpcMessage QJsonRpcMessage::createNotification(const QString &method, const QJsonValue ¶m) { QJsonArray params; params.append(param); return createNotification(method, params); } QJsonRpcMessage QJsonRpcMessage::createNotification(const QString &method, const QJsonObject &namedParameters) { QJsonRpcMessage notification = QJsonRpcMessagePrivate::createBasicRequest(method, namedParameters); notification.d->type = QJsonRpcMessage::Notification; return notification; } QJsonRpcMessage QJsonRpcMessage::createResponse(const QJsonValue &result) const { QJsonRpcMessage response; if (d->object->contains(QLatin1String("id"))) { QJsonObject *object = response.d->object.data(); object->insert(QLatin1String("jsonrpc"), QLatin1String("2.0")); object->insert(QLatin1String("id"), d->object->value(QLatin1String("id"))); object->insert(QLatin1String("result"), result); response.d->type = QJsonRpcMessage::Response; } return response; } QJsonRpcMessage QJsonRpcMessage::createErrorResponse(QJsonRpc::ErrorCode code, const QString &message, const QJsonValue &data) const { QJsonRpcMessage response; QJsonObject error; error.insert(QLatin1String("code"), code); if (!message.isEmpty()) error.insert(QLatin1String("message"), message); if (!data.isUndefined()) error.insert(QLatin1String("data"), data); response.d->type = QJsonRpcMessage::Error; QJsonObject *object = response.d->object.data(); object->insert(QLatin1String("jsonrpc"), QLatin1String("2.0")); if (d->object->contains(QLatin1String("id"))) object->insert(QLatin1String("id"), d->object->value(QLatin1String("id"))); else object->insert(QLatin1String("id"), 0); object->insert(QLatin1String("error"), error); return response; } int QJsonRpcMessage::id() const { if (d->type == QJsonRpcMessage::Notification || !d->object) return -1; const QJsonValue &value = d->object->value(QLatin1String("id")); if (value.isString()) return value.toString().toInt(); #if QT_VERSION >= 0x050200 return value.toInt(); #else return value.toDouble(); #endif } QString QJsonRpcMessage::method() const { if (d->type == QJsonRpcMessage::Response || !d->object) return QString(); return d->object->value(QLatin1String("method")).toString(); } QJsonValue QJsonRpcMessage::params() const { if (d->type == QJsonRpcMessage::Response || d->type == QJsonRpcMessage::Error) return QJsonValue(QJsonValue::Undefined); if (!d->object) return QJsonValue(QJsonValue::Undefined); return d->object->value(QLatin1String("params")); } QJsonValue QJsonRpcMessage::result() const { if (d->type != QJsonRpcMessage::Response || !d->object) return QJsonValue(QJsonValue::Undefined); return d->object->value(QLatin1String("result")); } int QJsonRpcMessage::errorCode() const { if (d->type != QJsonRpcMessage::Error || !d->object) return 0; QJsonObject error = d->object->value(QLatin1String("error")).toObject(); const QJsonValue &value = error.value(QLatin1String("code")); if (value.isString()) return value.toString().toInt(); #if QT_VERSION >= 0x050200 return value.toInt(); #else return value.toDouble(); #endif } QString QJsonRpcMessage::errorMessage() const { if (d->type != QJsonRpcMessage::Error || !d->object) return QString(); QJsonObject error = d->object->value(QLatin1String("error")).toObject(); return error.value(QLatin1String("message")).toString(); } QJsonValue QJsonRpcMessage::errorData() const { if (d->type != QJsonRpcMessage::Error || !d->object) return QJsonValue(QJsonValue::Undefined); QJsonObject error = d->object->value(QLatin1String("error")).toObject(); return error.value(QLatin1String("data")); } #if QT_VERSION < 0x050000 bool QJsonRpcMessage::isDetached() const { return d && d->ref == 1; } #endif static QDebug operator<<(QDebug dbg, QJsonRpcMessage::Type type) { switch (type) { case QJsonRpcMessage::Request: return dbg << "QJsonRpcMessage::Request"; case QJsonRpcMessage::Response: return dbg << "QJsonRpcMessage::Response"; case QJsonRpcMessage::Notification: return dbg << "QJsonRpcMessage::Notification"; case QJsonRpcMessage::Error: return dbg << "QJsonRpcMessage::Error"; default: return dbg << "QJsonRpcMessage::Invalid"; } } QDebug operator<<(QDebug dbg, const QJsonRpcMessage &msg) { dbg.nospace() << "QJsonRpcMessage(type=" << msg.type(); if (msg.type() != QJsonRpcMessage::Notification) { dbg.nospace() << ", id=" << msg.id(); } if (msg.type() == QJsonRpcMessage::Request || msg.type() == QJsonRpcMessage::Notification) { dbg.nospace() << ", method=" << msg.method() << ", params=" << msg.params(); } else if (msg.type() == QJsonRpcMessage::Response) { dbg.nospace() << ", result=" << msg.result(); } else if (msg.type() == QJsonRpcMessage::Error) { dbg.nospace() << ", code=" << msg.errorCode() << ", message=" << msg.errorMessage() << ", data=" << msg.errorData(); } dbg.nospace() << ")"; return dbg.space(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcmessage.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCMESSAGE_H #define QJSONRPCMESSAGE_H #include #include #if QT_VERSION >= 0x050000 #include #include #include #else #include "json/qjsonvalue.h" #include "json/qjsonobject.h" #include "json/qjsonarray.h" #endif #include "qjsonrpcglobal.h" class QJsonRpcMessagePrivate; class QJSONRPC_EXPORT QJsonRpcMessage { public: QJsonRpcMessage(); QJsonRpcMessage(const QJsonRpcMessage &other); QJsonRpcMessage &operator=(const QJsonRpcMessage &other); ~QJsonRpcMessage(); #if QT_VERSION >= 0x050000 inline void swap(QJsonRpcMessage &other) { qSwap(d, other.d); } #endif enum Type { Invalid, Request, Response, Notification, Error }; static QJsonRpcMessage createRequest(const QString &method, const QJsonArray ¶ms = QJsonArray()); static QJsonRpcMessage createRequest(const QString &method, const QJsonValue ¶m); static QJsonRpcMessage createRequest(const QString &method, const QJsonObject &namedParameters); static QJsonRpcMessage createNotification(const QString &method, const QJsonArray ¶ms = QJsonArray()); static QJsonRpcMessage createNotification(const QString &method, const QJsonValue ¶m); static QJsonRpcMessage createNotification(const QString &method, const QJsonObject &namedParameters); QJsonRpcMessage createResponse(const QJsonValue &result) const; QJsonRpcMessage createErrorResponse(QJsonRpc::ErrorCode code, const QString &message = QString(), const QJsonValue &data = QJsonValue()) const; QJsonRpcMessage::Type type() const; bool isValid() const; int id() const; // request QString method() const; QJsonValue params() const; // response QJsonValue result() const; // error int errorCode() const; QString errorMessage() const; QJsonValue errorData() const; QJsonObject toObject() const; static QJsonRpcMessage fromObject(const QJsonObject &object); QByteArray toJson() const; static QJsonRpcMessage fromJson(const QByteArray &data); bool operator==(const QJsonRpcMessage &message) const; inline bool operator!=(const QJsonRpcMessage &message) const { return !(operator==(message)); } private: friend class QJsonRpcMessagePrivate; QSharedDataPointer d; #if QT_VERSION < 0x050000 public: typedef QSharedDataPointer DataPtr; inline DataPtr &data_ptr() { return d; } // internal bool isDetached() const; #endif }; QJSONRPC_EXPORT QDebug operator<<(QDebug, const QJsonRpcMessage &); Q_DECLARE_METATYPE(QJsonRpcMessage) #if QT_VERSION < 0x050000 Q_DECLARE_TYPEINFO(QJsonRpcMessage, Q_MOVABLE_TYPE); #endif Q_DECLARE_SHARED(QJsonRpcMessage) #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcmetatype.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Copyright (C) 2013 Fargier Sylvain * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCMETATYPE_H #define QJSONRPCMETATYPE_H #include template void qRegisterJsonRpcMetaType(const char *typeName, T * = 0) { Q_UNUSED(typeName) QMetaType::registerConverter(&T::toJson); QMetaType::registerConverter(&T::fromJson); } #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcservice.cpp ================================================ /* * Copyright (C) 2012-2014 Matt Broadstone * Copyright (C) 2013 Fargier Sylvain * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcservice_p.h" #include "qjsonrpcservice.h" QJsonRpcServiceRequest::QJsonRpcServiceRequest() : d(new QJsonRpcServiceRequestPrivate) { } QJsonRpcServiceRequest::QJsonRpcServiceRequest(const QJsonRpcServiceRequest &other) : d (other.d) { } QJsonRpcServiceRequest::QJsonRpcServiceRequest(const QJsonRpcMessage &request, QJsonRpcAbstractSocket *socket) : d(new QJsonRpcServiceRequestPrivate) { d->request = request; d->socket = socket; } QJsonRpcServiceRequest &QJsonRpcServiceRequest::operator=(const QJsonRpcServiceRequest &other) { d = other.d; return *this; } QJsonRpcServiceRequest::~QJsonRpcServiceRequest() { } bool QJsonRpcServiceRequest::isValid() const { return (d && d->request.isValid() && !d->socket.isNull()); } QJsonRpcMessage QJsonRpcServiceRequest::request() const { return d->request; } QJsonRpcAbstractSocket *QJsonRpcServiceRequest::socket() const { return d->socket; } bool QJsonRpcServiceRequest::respond(QVariant returnValue) { if (!d->socket) { qJsonRpcDebug() << Q_FUNC_INFO << "socket was closed"; return false; } QJsonRpcMessage response = d->request.createResponse(QJsonRpcServicePrivate::convertReturnValue(returnValue)); return respond(response); } bool QJsonRpcServiceRequest::respond(const QJsonRpcMessage &response) { if (!d->socket) { qJsonRpcDebug() << Q_FUNC_INFO << "socket was closed"; return false; } QMetaObject::invokeMethod(d->socket, "notify", Q_ARG(QJsonRpcMessage, response)); return true; } QJsonRpcServicePrivate::ParameterInfo::ParameterInfo(const QString &n, int t, bool o) : type(t), jsType(convertVariantTypeToJSType(t)), name(n), out(o) { } QJsonRpcServicePrivate::MethodInfo::MethodInfo() : returnType(QMetaType::Void), valid(false), hasOut(false) { } QJsonRpcServicePrivate::MethodInfo::MethodInfo(const QMetaMethod &method) : returnType(QMetaType::Void), valid(true), hasOut(false) { #if QT_VERSION >= 0x050000 returnType = method.returnType(); if (returnType == QMetaType::UnknownType) { qJsonRpcDebug() << "QJsonRpcService: can't bind method's return type" << QString(method.name()); valid = false; return; } parameters.reserve(method.parameterCount()); #else returnType = QMetaType::type(method.typeName()); parameters.reserve(method.parameterNames().count()); #endif const QList &types = method.parameterTypes(); const QList &names = method.parameterNames(); for (int i = 0; i < types.size(); ++i) { QByteArray parameterType = types.at(i); const QByteArray ¶meterName = names.at(i); bool out = parameterType.endsWith('&'); if (out) { hasOut = true; parameterType.resize(parameterType.size() - 1); } int type = QMetaType::type(parameterType); if (type == 0) { qJsonRpcDebug() << "QJsonRpcService: can't bind method's parameter" << QString(parameterType); valid = false; break; } parameters.append(ParameterInfo(parameterName, type, out)); } } QJsonRpcService::QJsonRpcService(QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QObject(*new QJsonRpcServicePrivate(this), parent) #else : QObject(parent), d_ptr(new QJsonRpcServicePrivate(this)) #endif { } QJsonRpcService::~QJsonRpcService() { } QJsonRpcServiceRequest QJsonRpcService::currentRequest() const { Q_D(const QJsonRpcService); return d->currentRequest; } void QJsonRpcService::beginDelayedResponse() { Q_D(QJsonRpcService); d->delayedResponse = true; } int QJsonRpcServicePrivate::convertVariantTypeToJSType(int type) { switch (type) { case QMetaType::Int: case QMetaType::UInt: case QMetaType::Double: case QMetaType::Long: case QMetaType::LongLong: case QMetaType::Short: case QMetaType::Char: case QMetaType::ULong: case QMetaType::ULongLong: case QMetaType::UShort: case QMetaType::UChar: case QMetaType::Float: return QJsonValue::Double; // all numeric types in js are doubles case QMetaType::QVariantList: case QMetaType::QStringList: return QJsonValue::Array; case QMetaType::QVariantMap: return QJsonValue::Object; case QMetaType::QString: return QJsonValue::String; case QMetaType::Bool: return QJsonValue::Bool; default: break; } return QJsonValue::Undefined; } int QJsonRpcServicePrivate::qjsonRpcMessageType = qRegisterMetaType("QJsonRpcMessage"); void QJsonRpcServicePrivate::cacheInvokableInfo() { Q_Q(QJsonRpcService); const QMetaObject *obj = q->metaObject(); int startIdx = q->staticMetaObject.methodCount(); // skip QObject slots for (int idx = startIdx; idx < obj->methodCount(); ++idx) { const QMetaMethod method = obj->method(idx); if ((method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) || method.methodType() == QMetaMethod::Signal) { #if QT_VERSION >= 0x050000 QByteArray signature = method.methodSignature(); QByteArray methodName = method.name(); #else QByteArray signature = method.signature(); QByteArray methodName = signature.left(signature.indexOf('(')); #endif MethodInfo info(method); if (!info.valid) continue; if (signature.contains("QVariant")) invokableMethodHash[methodName].append(idx); else invokableMethodHash[methodName].prepend(idx); methodInfoHash[idx] = info; } } } static bool jsParameterCompare(const QJsonArray ¶meters, const QJsonRpcServicePrivate::MethodInfo &info) { int j = 0; for (int i = 0; i < info.parameters.size() && j < parameters.size(); ++i) { int jsType = info.parameters.at(i).jsType; if (jsType != QJsonValue::Undefined && jsType != parameters.at(j).type()) { if (!info.parameters.at(i).out) return false; } else { ++j; } } return (j == parameters.size()); } static bool jsParameterCompare(const QJsonObject ¶meters, const QJsonRpcServicePrivate::MethodInfo &info) { for (int i = 0; i < info.parameters.size(); ++i) { int jsType = info.parameters.at(i).jsType; QJsonValue value = parameters.value(info.parameters.at(i).name); if (value == QJsonValue::Undefined) { if (!info.parameters.at(i).out) return false; } else if (jsType == QJsonValue::Undefined) { continue; } else if (jsType != value.type()) { return false; } } return true; } static inline QVariant convertArgument(const QJsonValue &argument, const QJsonRpcServicePrivate::ParameterInfo &info) { if (argument.isUndefined()) #if QT_VERSION >= 0x050000 return QVariant(info.type, Q_NULLPTR); #else return QVariant(info.type, (const void *) NULL); #endif #if QT_VERSION >= 0x050200 if (info.type == QMetaType::QJsonValue || info.type == QMetaType::QVariant || info.type >= QMetaType::User) { if (info.type == QMetaType::QVariant) return argument.toVariant(); QVariant result(argument); if (info.type >= QMetaType::User && result.canConvert(info.type)) result.convert(info.type); return result; } QVariant result = argument.toVariant(); if (result.userType() == info.type || info.type == QMetaType::QVariant) { return result; } else if (result.canConvert(info.type)) { result.convert(info.type); return result; } else if (info.type < QMetaType::User) { // already tried for >= user, this is the last resort QVariant result(argument); if (result.canConvert(info.type)) { result.convert(info.type); return result; } } return QVariant(); #else QVariant result = argument.toVariant(); QVariant::Type variantType = static_cast(info.type); if (info.type != QMetaType::QVariant && variantType != result.type() && !result.canConvert(variantType)) return QVariant(); if (!result.canConvert(variantType)) { // toVariant succeeded, no need to convert return result; } result.convert(variantType); return result; #endif } QJsonValue QJsonRpcServicePrivate::convertReturnValue(QVariant &returnValue) { #if QT_VERSION >= 0x050200 if (static_cast(returnValue.type()) == qMetaTypeId()) return QJsonValue(returnValue.toJsonObject()); else if (static_cast(returnValue.type()) == qMetaTypeId()) return QJsonValue(returnValue.toJsonArray()); switch (returnValue.type()) { case QMetaType::Bool: case QMetaType::Int: case QMetaType::Double: case QMetaType::LongLong: case QMetaType::ULongLong: case QMetaType::UInt: case QMetaType::QString: case QMetaType::QStringList: case QMetaType::QVariantList: case QMetaType::QVariantMap: return QJsonValue::fromVariant(returnValue); default: // if a conversion operator was registered it will be used if (returnValue.convert(QMetaType::QJsonValue)) return returnValue.toJsonValue(); else return QJsonValue(); } #else // custom conversions could not be registered before 5.2, so this is only an optimization return QJsonValue::fromVariant(returnValue); #endif } static inline QByteArray methodName(const QJsonRpcMessage &request) { const QString &methodPath(request.method()); return methodPath.midRef(methodPath.lastIndexOf('.') + 1).toLatin1(); } QJsonRpcMessage QJsonRpcService::dispatch(const QJsonRpcMessage &request) { Q_D(QJsonRpcService); if (request.type() != QJsonRpcMessage::Request && request.type() != QJsonRpcMessage::Notification) { return request.createErrorResponse(QJsonRpc::InvalidRequest, "invalid request"); } const QByteArray &method(methodName(request)); if (!d->invokableMethodHash.contains(method)) { return request.createErrorResponse(QJsonRpc::MethodNotFound, "invalid method called"); } int idx = -1; QVariantList arguments; const QList &indexes = d->invokableMethodHash.value(method); const QJsonValue ¶ms = request.params(); QVarLengthArray parameters; QVariant returnValue; QMetaType::Type returnType = QMetaType::Void; bool usingNamedParameters = params.isObject(); foreach (int methodIndex, indexes) { QJsonRpcServicePrivate::MethodInfo &info = d->methodInfoHash[methodIndex]; bool methodMatch = usingNamedParameters ? jsParameterCompare(params.toObject(), info) : jsParameterCompare(params.toArray(), info); if (methodMatch) { idx = methodIndex; arguments.reserve(info.parameters.size()); returnType = static_cast(info.returnType); #if QT_VERSION >= 0x050000 returnValue = (returnType == QMetaType::Void) ? QVariant() : QVariant(returnType, Q_NULLPTR); #else returnValue = (returnType == QMetaType::Void) ? QVariant() : QVariant(returnType, (const void *) NULL); #endif if (returnType == QMetaType::QVariant) parameters.append(&returnValue); else parameters.append(returnValue.data()); for (int i = 0; i < info.parameters.size(); ++i) { const QJsonRpcServicePrivate::ParameterInfo ¶meterInfo = info.parameters.at(i); QJsonValue incomingArgument = usingNamedParameters ? params.toObject().value(parameterInfo.name) : params.toArray().at(i); QVariant argument = convertArgument(incomingArgument, parameterInfo); if (!argument.isValid()) { QString message = incomingArgument.isUndefined() ? QString("failed to construct default object for '%1'").arg(parameterInfo.name) : QString("failed to convert from JSON for '%1'").arg(parameterInfo.name); return request.createErrorResponse(QJsonRpc::InvalidParams, message); } arguments.push_back(argument); if (parameterInfo.type == QMetaType::QVariant) parameters.append(static_cast(&arguments.last())); else parameters.append(const_cast(arguments.last().constData())); } // found a match break; } } if (idx == -1) { return request.createErrorResponse(QJsonRpc::InvalidParams, "invalid parameters"); } QJsonRpcServicePrivate::MethodInfo &info = d->methodInfoHash[idx]; bool success = const_cast(this)->qt_metacall(QMetaObject::InvokeMetaMethod, idx, parameters.data()) < 0; if (!success) { QString message = QString("dispatch for method '%1' failed").arg(method.constData()); return request.createErrorResponse(QJsonRpc::InvalidRequest, message); } if (d->delayedResponse) { d->delayedResponse = false; return QJsonRpcMessage(); } if (info.hasOut) { QJsonArray ret; if (info.returnType != QMetaType::Void) ret.append(QJsonRpcServicePrivate::convertReturnValue(returnValue)); for (int i = 0; i < info.parameters.size(); ++i) if (info.parameters.at(i).out) ret.append(QJsonRpcServicePrivate::convertReturnValue(arguments[i])); if (ret.size() > 1) return request.createResponse(ret); return request.createResponse(ret.first()); } return request.createResponse(QJsonRpcServicePrivate::convertReturnValue(returnValue)); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcservice.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSERVICE_H #define QJSONRPCSERVICE_H #include #include #include "qjsonrpcmessage.h" class QJsonRpcAbstractSocket; class QJsonRpcServiceRequestPrivate; class QJSONRPC_EXPORT QJsonRpcServiceRequest { public: QJsonRpcServiceRequest(); QJsonRpcServiceRequest(const QJsonRpcServiceRequest &other); QJsonRpcServiceRequest(const QJsonRpcMessage &request, QJsonRpcAbstractSocket *socket); QJsonRpcServiceRequest &operator=(const QJsonRpcServiceRequest &other); ~QJsonRpcServiceRequest(); bool isValid() const; QJsonRpcMessage request() const; QJsonRpcAbstractSocket *socket() const; bool respond(const QJsonRpcMessage &response); bool respond(QVariant returnValue); private: QSharedDataPointer d; }; class QJsonRpcServiceProvider; class QJsonRpcServicePrivate; class QJSONRPC_EXPORT QJsonRpcService : public QObject { Q_OBJECT public: explicit QJsonRpcService(QObject *parent = 0); ~QJsonRpcService(); Q_SIGNALS: void result(const QJsonRpcMessage &result); void notifyConnectedClients(const QJsonRpcMessage &message); void notifyConnectedClients(const QString &method, const QJsonArray ¶ms = QJsonArray()); protected: QJsonRpcServiceRequest currentRequest() const; void beginDelayedResponse(); protected Q_SLOTS: QJsonRpcMessage dispatch(const QJsonRpcMessage &request); private: Q_DISABLE_COPY(QJsonRpcService) Q_DECLARE_PRIVATE(QJsonRpcService) friend class QJsonRpcServiceProvider; #if !defined(USE_QT_PRIVATE_HEADERS) QScopedPointer d_ptr; #endif }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcservice_p.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Copyright (C) 2013 Fargier Sylvain * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSERVICE_P_H #define QJSONRPCSERVICE_P_H #include #include #include #include #include "qjsonrpcservice.h" class QJsonRpcAbstractSocket; class QJsonRpcServiceRequestPrivate : public QSharedData { public: QJsonRpcMessage request; QPointer socket; }; class QJsonRpcService; #if defined(USE_QT_PRIVATE_HEADERS) #include class QJsonRpcServicePrivate : public QObjectPrivate #else class QJsonRpcServicePrivate #endif { public: QJsonRpcServicePrivate(QJsonRpcService *parent) : delayedResponse(false), q_ptr(parent) { } void cacheInvokableInfo(); static int qjsonRpcMessageType; static int convertVariantTypeToJSType(int type); static QJsonValue convertReturnValue(QVariant &returnValue); struct ParameterInfo { ParameterInfo(const QString &name = QString(), int type = 0, bool out = false); int type; int jsType; QString name; bool out; }; struct MethodInfo { MethodInfo(); MethodInfo(const QMetaMethod &method); QVarLengthArray parameters; int returnType; bool valid; bool hasOut; }; QHash methodInfoHash; QHash > invokableMethodHash; QJsonRpcServiceRequest currentRequest; bool delayedResponse; QJsonRpcService * const q_ptr; Q_DECLARE_PUBLIC(QJsonRpcService) }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcserviceprovider.cpp ================================================ #include #include #include #include #include "qjsonrpcservice.h" #include "qjsonrpcservice_p.h" #include "qjsonrpcsocket.h" #include "qjsonrpcserviceprovider.h" class QJsonRpcServiceProviderPrivate { public: QByteArray serviceName(QJsonRpcService *service); QHash services; QObjectCleanupHandler cleanupHandler; }; QJsonRpcServiceProvider::QJsonRpcServiceProvider() : d(new QJsonRpcServiceProviderPrivate) { } QJsonRpcServiceProvider::~QJsonRpcServiceProvider() { } QByteArray QJsonRpcServiceProviderPrivate::serviceName(QJsonRpcService *service) { const QMetaObject *mo = service->metaObject(); for (int i = 0; i < mo->classInfoCount(); i++) { const QMetaClassInfo mci = mo->classInfo(i); if (mci.name() == QLatin1String("serviceName")) return mci.value(); } return QByteArray(mo->className()).toLower(); } bool QJsonRpcServiceProvider::addService(QJsonRpcService *service) { QByteArray serviceName = d->serviceName(service); if (serviceName.isEmpty()) { qJsonRpcDebug() << Q_FUNC_INFO << "service added without serviceName classinfo, aborting"; return false; } if (d->services.contains(serviceName)) { qJsonRpcDebug() << Q_FUNC_INFO << "service with name " << serviceName << " already exist"; return false; } service->d_func()->cacheInvokableInfo(); d->services.insert(serviceName, service); if (!service->parent()) d->cleanupHandler.add(service); return true; } bool QJsonRpcServiceProvider::removeService(QJsonRpcService *service) { QByteArray serviceName = d->serviceName(service); if (!d->services.contains(serviceName)) { qJsonRpcDebug() << Q_FUNC_INFO << "can not find service with name " << serviceName; return false; } d->cleanupHandler.remove(d->services.value(serviceName)); d->services.remove(serviceName); return true; } void QJsonRpcServiceProvider::processMessage(QJsonRpcAbstractSocket *socket, const QJsonRpcMessage &message) { switch (message.type()) { case QJsonRpcMessage::Request: case QJsonRpcMessage::Notification: { QByteArray serviceName = message.method().section(".", 0, -2).toLatin1(); if (serviceName.isEmpty() || !d->services.contains(serviceName)) { if (message.type() == QJsonRpcMessage::Request) { QJsonRpcMessage error = message.createErrorResponse(QJsonRpc::MethodNotFound, QString("service '%1' not found").arg(serviceName.constData())); socket->notify(error); } } else { QJsonRpcService *service = d->services.value(serviceName); service->d_func()->currentRequest = QJsonRpcServiceRequest(message, socket); if (message.type() == QJsonRpcMessage::Request) QObject::connect(service, SIGNAL(result(QJsonRpcMessage)), socket, SLOT(notify(QJsonRpcMessage)), Qt::UniqueConnection); QJsonRpcMessage response = service->dispatch(message); if (response.isValid()) socket->notify(response); } } break; case QJsonRpcMessage::Response: // we don't handle responses in the provider break; default: { QJsonRpcMessage error = message.createErrorResponse(QJsonRpc::InvalidRequest, QString("invalid request")); socket->notify(error); break; } }; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcserviceprovider.h ================================================ /* * Copyright (C) 2012-2014 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSERVICEPROVIDER_H #define QJSONRPCSERVICEPROVIDER_H #include "qjsonrpcglobal.h" class QJsonRpcMessage; class QJsonRpcService; class QJsonRpcAbstractSocket; class QJsonRpcServiceProviderPrivate; class QJSONRPC_EXPORT QJsonRpcServiceProvider { public: ~QJsonRpcServiceProvider(); virtual bool addService(QJsonRpcService *service); virtual bool removeService(QJsonRpcService *service); protected: QJsonRpcServiceProvider(); void processMessage(QJsonRpcAbstractSocket *socket, const QJsonRpcMessage &message); private: QScopedPointer d; }; #endif // QJSONRPCSERVICEPROVIDER_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcservicereply.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include "qjsonrpcservicereply_p.h" #include "qjsonrpcservicereply.h" QJsonRpcServiceReply::QJsonRpcServiceReply(QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QObject(*new QJsonRpcServiceReplyPrivate, parent) #else : QObject(parent), d_ptr(new QJsonRpcServiceReplyPrivate) #endif { } QJsonRpcServiceReply::~QJsonRpcServiceReply() { } QJsonRpcServiceReply::QJsonRpcServiceReply(QJsonRpcServiceReplyPrivate &dd, QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QObject(dd, parent) #else : QObject(parent), d_ptr(&dd) #endif { } QJsonRpcMessage QJsonRpcServiceReply::request() const { Q_D(const QJsonRpcServiceReply); return d->request; } QJsonRpcMessage QJsonRpcServiceReply::response() const { Q_D(const QJsonRpcServiceReply); return d->response; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcservicereply.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSERVICEREPLY_H #define QJSONRPCSERVICEREPLY_H #include #include #include "qjsonrpcglobal.h" #include "qjsonrpcmessage.h" class QJsonRpcServiceReplyPrivate; class QJSONRPC_EXPORT QJsonRpcServiceReply : public QObject { Q_OBJECT public: explicit QJsonRpcServiceReply(QObject *parent = 0); virtual ~QJsonRpcServiceReply(); QJsonRpcMessage request() const; QJsonRpcMessage response() const; Q_SIGNALS: void finished(); protected: Q_DECLARE_PRIVATE(QJsonRpcServiceReply) Q_DISABLE_COPY(QJsonRpcServiceReply) QJsonRpcServiceReply(QJsonRpcServiceReplyPrivate &dd, QObject *parent = 0); friend class QJsonRpcSocketPrivate; friend class QJsonRpcSocket; #if !defined(USE_QT_PRIVATE_HEADERS) QScopedPointer d_ptr; #endif }; #endif // QJSONRPCSERVICEREPLY_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcservicereply_p.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSERVICEREPLY_P_H #define QJSONRPCSERVICEREPLY_P_H #include "qjsonrpcmessage.h" #if defined(USE_QT_PRIVATE_HEADERS) #include class QJsonRpcServiceReplyPrivate : public QObjectPrivate #else class QJsonRpcServiceReplyPrivate #endif { public: QJsonRpcMessage request; QJsonRpcMessage response; }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcsocket.cpp ================================================ #include #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcservice.h" #include "qjsonrpcservicereply_p.h" #include "qjsonrpcservicereply.h" #include "qjsonrpcsocket_p.h" #include "qjsonrpcsocket.h" int QJsonRpcSocketPrivate::findJsonDocumentEnd(const QByteArray &jsonData) { const char* pos = jsonData.constData(); const char* end = pos + jsonData.length(); char blockStart = 0; char blockEnd = 0; int index = 0; // Find the beginning of the JSON document and determine if it is an object or an array while (true) { if (pos == end) { return -1; } else if (*pos == '{') { blockStart = '{'; blockEnd = '}'; break; } else if(*pos == '[') { blockStart = '['; blockEnd = ']'; break; } pos++; index++; } // Find the end of the JSON document pos++; index++; int depth = 1; bool inString = false; while (depth > 0 && pos <= end) { if (*pos == '\\') { pos += 2; index += 2; continue; } else if (*pos == '"') { inString = !inString; } else if (!inString) { if (*pos == blockStart) depth++; else if (*pos == blockEnd) depth--; } pos++; index++; } // index-1 because we are one position ahead return depth == 0 ? index-1 : -1; } void QJsonRpcSocketPrivate::writeData(const QJsonRpcMessage &message) { Q_Q(QJsonRpcSocket); QJsonDocument doc = QJsonDocument(message.toObject()); #if QT_VERSION >= 0x050100 || QT_VERSION <= 0x050000 QByteArray data = doc.toJson(QJsonDocument::Compact); #else QByteArray data = doc.toJson(); #endif device.data()->write(data); qJsonRpcDebug() << "sending(" << q << "): " << data; } QJsonRpcAbstractSocket::QJsonRpcAbstractSocket(QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QObject(*new QJsonRpcAbstractSocketPrivate, parent) #else : QObject(parent), d_ptr(new QJsonRpcAbstractSocketPrivate) #endif { } QJsonRpcAbstractSocket::~QJsonRpcAbstractSocket() { } QJsonRpcAbstractSocket::QJsonRpcAbstractSocket(QJsonRpcAbstractSocketPrivate &dd, QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QObject(dd, parent) #else : QObject(parent), d_ptr(&dd) #endif { } bool QJsonRpcAbstractSocket::isValid() const { return false; } void QJsonRpcAbstractSocket::setDefaultRequestTimeout(int msecs) { Q_D(QJsonRpcAbstractSocket); if (msecs < 0) { qJsonRpcDebug() << "Cannot set a negative request timeout msecs value"; return; } d->defaultRequestTimeout = msecs; } int QJsonRpcAbstractSocket::getDefaultRequestTimeout() const { Q_D(const QJsonRpcAbstractSocket); return d->defaultRequestTimeout; } QJsonRpcMessage QJsonRpcAbstractSocket::sendMessageBlocking(const QJsonRpcMessage &message, int msecs) { Q_UNUSED(message) Q_UNUSED(msecs) return QJsonRpcMessage(); } QJsonRpcServiceReply *QJsonRpcAbstractSocket::sendMessage(const QJsonRpcMessage &message) { Q_UNUSED(message) return 0; } QJsonRpcMessage QJsonRpcAbstractSocket::invokeRemoteMethodBlocking(const QString &method, int msecs, const QVariant &arg1, const QVariant &arg2, const QVariant &arg3, const QVariant &arg4, const QVariant &arg5, const QVariant &arg6, const QVariant &arg7, const QVariant &arg8, const QVariant &arg9, const QVariant &arg10) { Q_UNUSED(method) Q_UNUSED(msecs) Q_UNUSED(arg1) Q_UNUSED(arg2) Q_UNUSED(arg3) Q_UNUSED(arg4) Q_UNUSED(arg5) Q_UNUSED(arg6) Q_UNUSED(arg7) Q_UNUSED(arg8) Q_UNUSED(arg9) Q_UNUSED(arg10) return QJsonRpcMessage(); } QJsonRpcMessage QJsonRpcAbstractSocket::invokeRemoteMethodBlocking(const QString &method, const QVariant &arg1, const QVariant &arg2, const QVariant &arg3, const QVariant &arg4, const QVariant &arg5, const QVariant &arg6, const QVariant &arg7, const QVariant &arg8, const QVariant &arg9, const QVariant &arg10) { Q_D(QJsonRpcAbstractSocket); return invokeRemoteMethodBlocking(method, d->defaultRequestTimeout, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } QJsonRpcServiceReply *QJsonRpcAbstractSocket::invokeRemoteMethod(const QString &method, const QVariant &arg1, const QVariant &arg2, const QVariant &arg3, const QVariant &arg4, const QVariant &arg5, const QVariant &arg6, const QVariant &arg7, const QVariant &arg8, const QVariant &arg9, const QVariant &arg10) { Q_UNUSED(method) Q_UNUSED(arg1) Q_UNUSED(arg2) Q_UNUSED(arg3) Q_UNUSED(arg4) Q_UNUSED(arg5) Q_UNUSED(arg6) Q_UNUSED(arg7) Q_UNUSED(arg8) Q_UNUSED(arg9) Q_UNUSED(arg10) return 0; } QJsonRpcSocket::QJsonRpcSocket(QIODevice *device, QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QJsonRpcAbstractSocket(*new QJsonRpcSocketPrivate(this), parent) #else : QJsonRpcAbstractSocket(parent), d_ptr(new QJsonRpcSocketPrivate(this)) #endif { Q_D(QJsonRpcSocket); connect(device, SIGNAL(readyRead()), this, SLOT(_q_processIncomingData())); d->device = device; } QJsonRpcSocket::QJsonRpcSocket(QJsonRpcSocketPrivate &dd, QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QJsonRpcAbstractSocket(dd, parent) #else : QJsonRpcAbstractSocket(parent), d_ptr(&dd) #endif { Q_D(QJsonRpcSocket); connect(d->device, SIGNAL(readyRead()), this, SLOT(_q_processIncomingData())); } QJsonRpcSocket::~QJsonRpcSocket() { } bool QJsonRpcSocket::isValid() const { Q_D(const QJsonRpcSocket); return d->device && d->device.data()->isOpen(); } /* void QJsonRpcSocket::sendMessage(const QList &messages) { QJsonArray array; foreach (QJsonRpcMessage message, messages) { array.append(message.toObject()); } QJsonDocument doc = QJsonDocument(array); m_device.data()->write(doc.toBinaryData()); } */ QJsonRpcMessage QJsonRpcSocket::sendMessageBlocking(const QJsonRpcMessage &message, int msecs) { Q_D(QJsonRpcSocket); QJsonRpcServiceReply *reply = sendMessage(message); QScopedPointer replyPtr(reply); QEventLoop responseLoop; connect(reply, SIGNAL(finished()), &responseLoop, SLOT(quit())); QTimer::singleShot(msecs, &responseLoop, SLOT(quit())); responseLoop.exec(); if (!reply->response().isValid()) { d->replies.remove(message.id()); return message.createErrorResponse(QJsonRpc::TimeoutError, "request timed out"); } return reply->response(); } QJsonRpcServiceReply *QJsonRpcSocket::sendMessage(const QJsonRpcMessage &message) { Q_D(QJsonRpcSocket); if (!d->device) { qJsonRpcDebug() << Q_FUNC_INFO << "trying to send message without device"; return 0; } notify(message); QPointer reply(new QJsonRpcServiceReply); reply->d_func()->request = message; d->replies.insert(message.id(), reply); return reply; } void QJsonRpcSocket::notify(const QJsonRpcMessage &message) { Q_D(QJsonRpcSocket); if (!d->device) { qJsonRpcDebug() << Q_FUNC_INFO << "trying to send message without device"; return; } // disconnect the result message if we need to QJsonRpcService *service = qobject_cast(sender()); if (service) disconnect(service, SIGNAL(result(QJsonRpcMessage)), this, SLOT(notify(QJsonRpcMessage))); d->writeData(message); } QJsonRpcMessage QJsonRpcSocket::invokeRemoteMethodBlocking(const QString &method, int msecs, const QVariant ¶m1, const QVariant ¶m2, const QVariant ¶m3, const QVariant ¶m4, const QVariant ¶m5, const QVariant ¶m6, const QVariant ¶m7, const QVariant ¶m8, const QVariant ¶m9, const QVariant ¶m10) { QVariantList params; if (param1.isValid()) params.append(param1); if (param2.isValid()) params.append(param2); if (param3.isValid()) params.append(param3); if (param4.isValid()) params.append(param4); if (param5.isValid()) params.append(param5); if (param6.isValid()) params.append(param6); if (param7.isValid()) params.append(param7); if (param8.isValid()) params.append(param8); if (param9.isValid()) params.append(param9); if (param10.isValid()) params.append(param10); QJsonRpcMessage request = QJsonRpcMessage::createRequest(method, QJsonArray::fromVariantList(params)); return sendMessageBlocking(request, msecs); } QJsonRpcMessage QJsonRpcSocket::invokeRemoteMethodBlocking(const QString &method, const QVariant ¶m1, const QVariant ¶m2, const QVariant ¶m3, const QVariant ¶m4, const QVariant ¶m5, const QVariant ¶m6, const QVariant ¶m7, const QVariant ¶m8, const QVariant ¶m9, const QVariant ¶m10) { Q_D(QJsonRpcSocket); return invokeRemoteMethodBlocking(method, d->defaultRequestTimeout, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); } QJsonRpcServiceReply *QJsonRpcSocket::invokeRemoteMethod(const QString &method, const QVariant ¶m1, const QVariant ¶m2, const QVariant ¶m3, const QVariant ¶m4, const QVariant ¶m5, const QVariant ¶m6, const QVariant ¶m7, const QVariant ¶m8, const QVariant ¶m9, const QVariant ¶m10) { QVariantList params; if (param1.isValid()) params.append(param1); if (param2.isValid()) params.append(param2); if (param3.isValid()) params.append(param3); if (param4.isValid()) params.append(param4); if (param5.isValid()) params.append(param5); if (param6.isValid()) params.append(param6); if (param7.isValid()) params.append(param7); if (param8.isValid()) params.append(param8); if (param9.isValid()) params.append(param9); if (param10.isValid()) params.append(param10); QJsonRpcMessage request = QJsonRpcMessage::createRequest(method, QJsonArray::fromVariantList(params)); return sendMessage(request); } void QJsonRpcSocketPrivate::_q_processIncomingData() { Q_Q(QJsonRpcSocket); if (!device) { qJsonRpcDebug() << Q_FUNC_INFO << "called without device"; return; } buffer.append(device.data()->readAll()); while (!buffer.isEmpty()) { int dataSize = findJsonDocumentEnd(buffer); if (dataSize == -1) { // incomplete data, wait for more return; } QJsonParseError error; QJsonDocument document = QJsonDocument::fromJson(buffer.mid(0, dataSize + 1), &error); if (document.isEmpty()) { if (error.error != QJsonParseError::NoError) { qJsonRpcDebug() << Q_FUNC_INFO << error.errorString(); } break; } buffer = buffer.mid(dataSize + 1); if (document.isArray()) { qJsonRpcDebug() << Q_FUNC_INFO << "bulk support is current disabled"; /* for (int i = 0; i < document.array().size(); ++i) { QJsonObject messageObject = document.array().at(i).toObject(); if (!messageObject.isEmpty()) { QJsonRpcMessage message(messageObject); Q_EMIT messageReceived(message); } } */ } else if (document.isObject()){ qJsonRpcDebug() << "received(" << q << "): " << document.toJson(QJsonDocument::Compact); QJsonRpcMessage message = QJsonRpcMessage::fromObject(document.object()); Q_EMIT q->messageReceived(message); if (message.type() == QJsonRpcMessage::Response || message.type() == QJsonRpcMessage::Error) { if (replies.contains(message.id())) { QPointer reply = replies.take(message.id()); if (!reply.isNull()) { reply->d_func()->response = message; reply->finished(); } } } else { q->processRequestMessage(message); } } } } void QJsonRpcSocket::processRequestMessage(const QJsonRpcMessage &message) { Q_UNUSED(message) // we don't do anything the default case with requests and notifications, // these are only handled by the provider } QJsonRpcServiceSocket::QJsonRpcServiceSocket(QIODevice *device, QObject *parent) : QJsonRpcSocket(device, parent) { } QJsonRpcServiceSocket::~QJsonRpcServiceSocket() { } void QJsonRpcServiceSocket::processRequestMessage(const QJsonRpcMessage &message) { QJsonRpcServiceProvider::processMessage(this, message); } #include "moc_qjsonrpcsocket.cpp" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcsocket.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSOCKET_H #define QJSONRPCSOCKET_H #include #include #include "qjsonrpcabstractserver.h" #include "qjsonrpcservice.h" #include "qjsonrpcmessage.h" #include "qjsonrpcglobal.h" #define DEFAULT_MSECS_REQUEST_TIMEOUT (30000) class QJsonRpcServiceReply; class QJsonRpcAbstractSocketPrivate; class QJSONRPC_EXPORT QJsonRpcAbstractSocket : public QObject { Q_OBJECT public: explicit QJsonRpcAbstractSocket(QObject *parent = 0); ~QJsonRpcAbstractSocket(); virtual bool isValid() const; void setDefaultRequestTimeout(int msecs); int getDefaultRequestTimeout() const; Q_SIGNALS: void messageReceived(const QJsonRpcMessage &message); public Q_SLOTS: virtual void notify(const QJsonRpcMessage &message) = 0; virtual QJsonRpcMessage sendMessageBlocking(const QJsonRpcMessage &message, int msecs = DEFAULT_MSECS_REQUEST_TIMEOUT); virtual QJsonRpcServiceReply *sendMessage(const QJsonRpcMessage &message); virtual QJsonRpcMessage invokeRemoteMethodBlocking(const QString &method, int msecs, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); virtual QJsonRpcMessage invokeRemoteMethodBlocking(const QString &method, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); virtual QJsonRpcServiceReply *invokeRemoteMethod(const QString &method, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); protected: QJsonRpcAbstractSocket(QJsonRpcAbstractSocketPrivate &dd, QObject *parent = 0); #if !defined(USE_QT_PRIVATE_HEADERS) QScopedPointer d_ptr; #endif private: Q_DECLARE_PRIVATE(QJsonRpcAbstractSocket) Q_DISABLE_COPY(QJsonRpcAbstractSocket) }; class QJsonRpcSocketPrivate; class QJSONRPC_EXPORT QJsonRpcSocket : public QJsonRpcAbstractSocket { Q_OBJECT public: explicit QJsonRpcSocket(QIODevice *device, QObject *parent = 0); ~QJsonRpcSocket(); virtual bool isValid() const; public Q_SLOTS: virtual void notify(const QJsonRpcMessage &message); virtual QJsonRpcMessage sendMessageBlocking(const QJsonRpcMessage &message, int msecs = DEFAULT_MSECS_REQUEST_TIMEOUT); virtual QJsonRpcServiceReply *sendMessage(const QJsonRpcMessage &message); QJsonRpcMessage invokeRemoteMethodBlocking(const QString &method, int msecs, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); QJsonRpcMessage invokeRemoteMethodBlocking(const QString &method, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); QJsonRpcServiceReply *invokeRemoteMethod(const QString &method, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); protected: QJsonRpcSocket(QJsonRpcSocketPrivate &dd, QObject *parent); virtual void processRequestMessage(const QJsonRpcMessage &message); private: Q_DECLARE_PRIVATE(QJsonRpcSocket) Q_DISABLE_COPY(QJsonRpcSocket) Q_PRIVATE_SLOT(d_func(), void _q_processIncomingData()) #if !defined(USE_QT_PRIVATE_HEADERS) QScopedPointer d_ptr; #endif }; class QJSONRPC_EXPORT QJsonRpcServiceSocket : public QJsonRpcSocket, public QJsonRpcServiceProvider { Q_OBJECT public: explicit QJsonRpcServiceSocket(QIODevice *device, QObject *parent = 0); ~QJsonRpcServiceSocket(); private: virtual void processRequestMessage(const QJsonRpcMessage &message); }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpcsocket_p.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSOCKET_P_H #define QJSONRPCSOCKET_P_H #include #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcmessage.h" #include "qjsonrpcglobal.h" #if defined(USE_QT_PRIVATE_HEADERS) #include class QJSONRPC_EXPORT QJsonRpcAbstractSocketPrivate : public QObjectPrivate #else class QJSONRPC_EXPORT QJsonRpcAbstractSocketPrivate #endif { public: QJsonRpcAbstractSocketPrivate() : defaultRequestTimeout(DEFAULT_MSECS_REQUEST_TIMEOUT) {} int defaultRequestTimeout; #if !defined(USE_QT_PRIVATE_HEADERS) virtual ~QJsonRpcAbstractSocketPrivate() {} #endif }; class QJsonRpcServiceReply; class QJSONRPC_EXPORT QJsonRpcSocketPrivate : public QJsonRpcAbstractSocketPrivate { public: QJsonRpcSocketPrivate(QJsonRpcSocket *socket) : q_ptr(socket) {} #if !defined(USE_QT_PRIVATE_HEADERS) virtual ~QJsonRpcSocketPrivate() {} #endif // slots virtual void _q_processIncomingData(); int findJsonDocumentEnd(const QByteArray &jsonData); void writeData(const QJsonRpcMessage &message); QPointer device; QByteArray buffer; QHash > replies; QJsonRpcSocket * const q_ptr; Q_DECLARE_PUBLIC(QJsonRpcSocket) }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpctcpserver.cpp ================================================ #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcabstractserver_p.h" #include "qjsonrpctcpserver.h" class QJsonRpcTcpServerPrivate : public QJsonRpcAbstractServerPrivate { public: QHash socketLookup; }; QJsonRpcTcpServer::QJsonRpcTcpServer(QObject *parent) #if defined(USE_QT_PRIVATE_HEADERS) : QTcpServer(*new QJsonRpcTcpServerPrivate, parent) #else : QTcpServer(parent), d_ptr(new QJsonRpcTcpServerPrivate) #endif { } QJsonRpcTcpServer::~QJsonRpcTcpServer() { Q_D(QJsonRpcTcpServer); foreach (QTcpSocket *socket, d->socketLookup.keys()) { socket->flush(); socket->deleteLater(); } d->socketLookup.clear(); foreach (QJsonRpcSocket *client, d->clients) client->deleteLater(); d->clients.clear(); } bool QJsonRpcTcpServer::addService(QJsonRpcService *service) { if (!QJsonRpcServiceProvider::addService(service)) return false; connect(service, SIGNAL(notifyConnectedClients(QJsonRpcMessage)), this, SLOT(notifyConnectedClients(QJsonRpcMessage))); connect(service, SIGNAL(notifyConnectedClients(QString,QJsonArray)), this, SLOT(notifyConnectedClients(QString,QJsonArray))); return true; } bool QJsonRpcTcpServer::removeService(QJsonRpcService *service) { if (!QJsonRpcServiceProvider::removeService(service)) return false; disconnect(service, SIGNAL(notifyConnectedClients(QJsonRpcMessage)), this, SLOT(notifyConnectedClients(QJsonRpcMessage))); disconnect(service, SIGNAL(notifyConnectedClients(QString,QJsonArray)), this, SLOT(notifyConnectedClients(QString,QJsonArray))); return true; } int QJsonRpcTcpServer::connectedClientCount() const { Q_D(const QJsonRpcTcpServer); return d->clients.size(); } #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) void QJsonRpcTcpServer::incomingConnection(qintptr socketDescriptor) #else void QJsonRpcTcpServer::incomingConnection(int socketDescriptor) #endif { Q_D(QJsonRpcTcpServer); QTcpSocket *tcpSocket = new QTcpSocket(this); if (!tcpSocket->setSocketDescriptor(socketDescriptor)) { qJsonRpcDebug() << Q_FUNC_INFO << "can't set socket descriptor"; tcpSocket->deleteLater(); return; } QIODevice *device = qobject_cast(tcpSocket); QJsonRpcSocket *socket = new QJsonRpcSocket(device, this); connect(socket, SIGNAL(messageReceived(QJsonRpcMessage)), this, SLOT(_q_processMessage(QJsonRpcMessage))); d->clients.append(socket); connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(_q_clientDisconnected())); d->socketLookup.insert(tcpSocket, socket); Q_EMIT clientConnected(); } void QJsonRpcTcpServer::_q_clientDisconnected() { Q_D(QJsonRpcTcpServer); QTcpSocket *tcpSocket = static_cast(sender()); if (!tcpSocket) { qJsonRpcDebug() << Q_FUNC_INFO << "called with invalid socket"; return; } if (d->socketLookup.contains(tcpSocket)) { QJsonRpcSocket *socket = d->socketLookup.take(tcpSocket); d->clients.removeAll(socket); socket->deleteLater(); } tcpSocket->deleteLater(); Q_EMIT clientDisconnected(); } void QJsonRpcTcpServer::_q_processMessage(const QJsonRpcMessage &message) { QJsonRpcSocket *socket = static_cast(sender()); if (!socket) { qJsonRpcDebug() << Q_FUNC_INFO << "called without service socket"; return; } processMessage(socket, message); } void QJsonRpcTcpServer::notifyConnectedClients(const QJsonRpcMessage &message) { Q_D(QJsonRpcTcpServer); d->_q_notifyConnectedClients(message); } void QJsonRpcTcpServer::notifyConnectedClients(const QString &method, const QJsonArray ¶ms) { Q_D(QJsonRpcTcpServer); d->_q_notifyConnectedClients(method, params); } #include "moc_qjsonrpctcpserver.cpp" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/qjsonrpctcpserver.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCTCPSERVER_H #define QJSONRPCTCPSERVER_H #include #include "qjsonrpcabstractserver.h" class QJsonRpcTcpServerPrivate; class QJSONRPC_EXPORT QJsonRpcTcpServer : public QTcpServer, public QJsonRpcAbstractServer { Q_OBJECT public: explicit QJsonRpcTcpServer(QObject *parent = 0); ~QJsonRpcTcpServer(); virtual int connectedClientCount() const; // reimp bool addService(QJsonRpcService *service); bool removeService(QJsonRpcService *service); Q_SIGNALS: void clientConnected(); void clientDisconnected(); public Q_SLOTS: void notifyConnectedClients(const QJsonRpcMessage &message); void notifyConnectedClients(const QString &method, const QJsonArray ¶ms); protected: #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) virtual void incomingConnection(qintptr socketDescriptor); #else virtual void incomingConnection(int socketDescriptor); #endif private Q_SLOTS: void _q_clientDisconnected(); void _q_processMessage(const QJsonRpcMessage &message); private: Q_DECLARE_PRIVATE(QJsonRpcTcpServer) Q_DISABLE_COPY(QJsonRpcTcpServer) #if !defined(USE_QT_PRIVATE_HEADERS) QScopedPointer d_ptr; #endif }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/src/src.pro ================================================ include(http-parser/http-parser.pri) INCLUDEPATH += . TEMPLATE = lib TARGET = qjsonrpc QT += core gui network DEFINES += QJSONRPC_BUILD CONFIG += $${QJSONRPC_LIBRARY_TYPE} VERSION = $${QJSONRPC_VERSION} CONFIG += staticlib include(../../../liteideutils.pri) #win32:DESTDIR = $$OUT_PWD #macx:QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/ # check if we need to build qjson lessThan(QT_MAJOR_VERSION, 5) { include(json/json.pri) } PRIVATE_HEADERS += \ qjsonrpcservice_p.h \ qjsonrpcsocket_p.h \ qjsonrpcabstractserver_p.h \ qjsonrpcservicereply_p.h \ qjsonrpchttpserver_p.h INSTALL_HEADERS += \ qjsonrpcmessage.h \ qjsonrpcservice.h \ qjsonrpcsocket.h \ qjsonrpcserviceprovider.h \ qjsonrpcabstractserver.h \ qjsonrpclocalserver.h \ qjsonrpctcpserver.h \ qjsonrpcglobal.h \ qjsonrpcservicereply.h \ qjsonrpchttpclient.h \ qjsonrpchttpserver.h greaterThan(QT_MAJOR_VERSION, 4) { greaterThan(QT_MINOR_VERSION, 1) { INSTALL_HEADERS += qjsonrpcmetatype.h } } HEADERS += \ $${INSTALL_HEADERS} \ $${PRIVATE_HEADERS} SOURCES += \ qjsonrpcmessage.cpp \ qjsonrpcservice.cpp \ qjsonrpcsocket.cpp \ qjsonrpcserviceprovider.cpp \ qjsonrpcabstractserver.cpp \ qjsonrpclocalserver.cpp \ qjsonrpctcpserver.cpp \ qjsonrpcservicereply.cpp \ qjsonrpchttpclient.cpp \ qjsonrpchttpserver.cpp # install #headers.files = $${INSTALL_HEADERS} #headers.path = $${PREFIX}/include/qjsonrpc #qjson_headers.files = $${QJSON_INSTALL_HEADERS} #qjson_headers.path = $${PREFIX}/include/qjsonrpc/json #private_headers.files = $${PRIVATE_HEADERS} #private_headers.path = $${PREFIX}/include/qjsonrpc/private #target.path = $${PREFIX}/$${LIBDIR} #INSTALLS += headers qjson_headers private_headers target # pkg-config support #CONFIG += create_pc create_prl no_install_prl #QMAKE_PKGCONFIG_DESTDIR = pkgconfig #QMAKE_PKGCONFIG_LIBDIR = $$target.path #QMAKE_PKGCONFIG_INCDIR = $$headers.path equals(QJSONRPC_LIBRARY_TYPE, staticlib) { QMAKE_PKGCONFIG_CFLAGS = -DQJSONRPC_STATIC } else { QMAKE_PKGCONFIG_CFLAGS = -DQJSONRPC_SHARED } #unix:QMAKE_CLEAN += -r pkgconfig lib$${TARGET}.prl ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/auto.pro ================================================ TEMPLATE = subdirs SUBDIRS += \ qjsonrpcmessage \ qjsonrpcsocket \ qjsonrpcserver \ qjsonrpcservice \ qjsonrpchttpclient \ qjsonrpchttpserver \ issue22 lessThan(QT_MAJOR_VERSION, 5) { SUBDIRS += json } greaterThan(QT_MAJOR_VERSION, 4) { greaterThan(QT_MINOR_VERSION, 1) { SUBDIRS += qjsonrpcmetatype } } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/issue22/issue22.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_issue22 SOURCES = tst_issue22.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/issue22/tst_issue22.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcabstractserver.h" #include "qjsonrpctcpserver.h" #include "qjsonrpcsocket.h" #include "qjsonrpcmessage.h" #include "signalspy.h" class TestIssue22: public QObject { Q_OBJECT public: TestIssue22(); private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); void testIssue21(); private: QThread serverThread; QScopedPointer tcpServer; quint16 tcpServerPort; }; TestIssue22::TestIssue22() { tcpServerPort = quint16(8118 + qrand() % 1000); } void TestIssue22::initTestCase() { serverThread.start(); } void TestIssue22::cleanupTestCase() { serverThread.quit(); QVERIFY(serverThread.wait()); } void TestIssue22::init() { tcpServer.reset(new QJsonRpcTcpServer); QVERIFY(tcpServer->listen(QHostAddress::LocalHost, tcpServerPort)); tcpServer->moveToThread(&serverThread); } void TestIssue22::cleanup() { tcpServer->close(); } class Issue21Service : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service") public: Issue21Service(QObject *parent = 0) : QJsonRpcService(parent) {} public Q_SLOTS: QString fastMethod(const QString &name) { QEventLoop loop; QTimer::singleShot(150, &loop, SLOT(quit())); loop.exec(); return QString("fast %1").arg(name); } QString slowMethod(const QString &name) { QEventLoop loop; QTimer::singleShot(2000, &loop, SLOT(quit())); loop.exec(); return QString("slow %1").arg(name); } }; class TestClientRunnable : public QObject, public QRunnable { Q_OBJECT public: TestClientRunnable(bool slow, quint16 port) : m_slow(slow), m_port(port) { setAutoDelete(true); } virtual void run() { QTcpSocket socket; socket.connectToHost(QHostAddress::LocalHost, m_port); QVERIFY(socket.waitForConnected()); // run tests QJsonRpcSocket client(&socket); QJsonRpcMessage request = m_slow ? QJsonRpcMessage::createRequest("service.slowMethod", QLatin1String("slow")) : QJsonRpcMessage::createRequest("service.fastMethod", QLatin1String("fast")); QJsonRpcMessage response = client.sendMessageBlocking(request); Q_EMIT messageReceived(request, response); socket.disconnectFromHost(); } Q_SIGNALS: void messageReceived(const QJsonRpcMessage &request, const QJsonRpcMessage &response); private: bool m_slow; quint16 m_port; QJsonRpcMessage m_message; }; void TestIssue22::testIssue21() { QVERIFY(tcpServer->addService(new Issue21Service)); TestClientRunnable *fastClient = new TestClientRunnable(false, tcpServerPort); SignalSpy fastClientSpy(fastClient, SIGNAL(messageReceived(QJsonRpcMessage, QJsonRpcMessage))); TestClientRunnable *slowClient = new TestClientRunnable(true, tcpServerPort); SignalSpy slowClientSpy(slowClient, SIGNAL(messageReceived(QJsonRpcMessage, QJsonRpcMessage))); QThreadPool::globalInstance()->setMaxThreadCount(10); QThreadPool::globalInstance()->start(fastClient); QThreadPool::globalInstance()->start(slowClient); fastClientSpy.wait(); slowClientSpy.wait(); QCOMPARE(fastClientSpy.length(), slowClientSpy.length()); QList fastClientPair = fastClientSpy.first(); QJsonRpcMessage fastRequest = fastClientPair.at(0).value(); QJsonRpcMessage fastResponse = fastClientPair.at(1).value(); QCOMPARE(fastRequest.id(), fastResponse.id()); QList slowClientPair = slowClientSpy.first(); QJsonRpcMessage slowRequest = slowClientPair.at(0).value(); QJsonRpcMessage slowResponse = slowClientPair.at(1).value(); QCOMPARE(slowRequest.id(), slowResponse.id()); } QTEST_MAIN(TestIssue22) #include "tst_issue22.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/json/bom.json ================================================ { "info-version": "1.0" } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/json/json.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_qtjson QT = core testlib CONFIG -= app_bundle CONFIG += testcase TESTDATA += test.json test.bjson test3.json test2.json SOURCES += tst_qtjson.cpp RESOURCES += tst_qtjson.qrc ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/json/test.json ================================================ [ "JSON Test Pattern pass1", {"object with 1 member":["array with 1 element"]}, {}, [], -42, true, false, null, { "integer": 1234567890, "real": -9876.543210, "e": 0.123456789e-12, "E": 1.234567890E+34, "": 23456789012E66, "zero": 0, "one": 1, "space": " ", "quote": "\"", "backslash": "\\", "controls": "\b\f\n\r\t", "slash": "/ & \/", "alpha": "abcdefghijklmnopqrstuvwxyz", "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "digit": "0123456789", "0123456789": "digit", "special": "`1~!@#$%^&*()_+-={\':[,]}|;.?", "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", "true": true, "false": false, "null": null, "array":[ ], "object":{ }, "address": "50 St. James Street", "url": "http://www.JSON.org/", "comment": "// /* */": " ", " s p a c e d " :[1,2 , 3 , 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", "quotes": "" \u0022 %22 0x22 034 "", "\/\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?" : "A key can be any string" }, 0.5 ,98.6 , 99.44 , 1066, 1e1, 0.1e1, 1e-1, 1e00, 2e+00, 2e-00, "rosebud", {"foo": "bar"}, {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}}, {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}}, {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}}, {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}} ] ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/json/test2.json ================================================ { "foo": ["ab"] } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/json/test3.json ================================================ { "firstName": "John", "lastName" : "Smith", "age" : 25, "address" : { "streetAddress": "21 2nd Street", "city" : "New York", "state" : "NY", "postalCode" : "10021" }, "phoneNumber": [ { "type" : "home", "number": "212 555-1234" }, { "type" : "fax", "number": "646 555-4567" } ] } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/json/tst_qtjson.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "json/qjsonarray.h" #include "json/qjsonobject.h" #include "json/qjsonvalue.h" #include "json/qjsondocument.h" #include #define INVALID_UNICODE "\xCE\xBA\xE1" #define UNICODE_NON_CHARACTER "\xEF\xBF\xBF" #define UNICODE_DJE "\320\202" // Character from the Serbian Cyrillic alphabet class tst_QtJson: public QObject { Q_OBJECT public: tst_QtJson(QObject *parent = 0); private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); void testValueSimple(); void testNumbers(); void testNumbers_2(); void testNumbers_3(); void testObjectSimple(); void testObjectSmallKeys(); void testArraySimple(); void testValueObject(); void testValueArray(); void testObjectNested(); void testArrayNested(); void testArrayNestedEmpty(); void testArrayComfortOperators(); void testObjectNestedEmpty(); void testValueRef(); void testObjectIteration(); void testArrayIteration(); void testObjectFind(); void testDocument(); void nullValues(); void nullArrays(); void nullObject(); void constNullObject(); void keySorting(); void undefinedValues(); void fromVariant(); void fromVariantMap(); void toVariantMap(); void toVariantList(); void toJson(); void toJsonSillyNumericValues(); void toJsonLargeNumericValues(); void fromJson(); void fromJsonErrors(); void fromBinary(); void toAndFromBinary_data(); void toAndFromBinary(); void parseNumbers(); void parseStrings(); void parseDuplicateKeys(); void testParser(); void compactArray(); void compactObject(); void validation(); void assignToDocument(); void testDuplicateKeys(); void testCompaction(); void testDebugStream(); void testCompactionError(); void parseUnicodeEscapes(); void assignObjects(); void assignArrays(); void testTrailingComma(); void testDetachBug(); void testJsonValueRefDefault(); void valueEquals(); void objectEquals_data(); void objectEquals(); void arrayEquals_data(); void arrayEquals(); void bom(); void nesting(); void longStrings(); void arrayInitializerList(); void objectInitializerList(); void unicodeKeys(); void garbageAtEnd(); }; tst_QtJson::tst_QtJson(QObject *parent) : QObject(parent) { } void tst_QtJson::initTestCase() { } void tst_QtJson::cleanupTestCase() { } void tst_QtJson::init() { } void tst_QtJson::cleanup() { } void tst_QtJson::testValueSimple() { QJsonObject object; object.insert("number", 999.); QJsonArray array; for (int i = 0; i < 10; ++i) array.append((double)i); QJsonValue value(true); QCOMPARE(value.type(), QJsonValue::Bool); QCOMPARE(value.toDouble(), 0.); QCOMPARE(value.toString(), QString()); QCOMPARE(value.toBool(), true); QCOMPARE(value.toObject(), QJsonObject()); QCOMPARE(value.toArray(), QJsonArray()); QCOMPARE(value.toDouble(99.), 99.); QCOMPARE(value.toString(QString("test")), QString("test")); QCOMPARE(value.toObject(object), object); QCOMPARE(value.toArray(array), array); value = 999.; QCOMPARE(value.type(), QJsonValue::Double); QCOMPARE(value.toDouble(), 999.); QCOMPARE(value.toString(), QString()); QCOMPARE(value.toBool(), false); QCOMPARE(value.toBool(true), true); QCOMPARE(value.toObject(), QJsonObject()); QCOMPARE(value.toArray(), QJsonArray()); value = QLatin1String("test"); QCOMPARE(value.toDouble(), 0.); QCOMPARE(value.toString(), QLatin1String("test")); QCOMPARE(value.toBool(), false); QCOMPARE(value.toObject(), QJsonObject()); QCOMPARE(value.toArray(), QJsonArray()); } void tst_QtJson::testNumbers() { { int numbers[] = { 0, -1, 1, (1<<26), (1<<27), (1<<28), -(1<<26), -(1<<27), -(1<<28), (1<<26) - 1, (1<<27) - 1, (1<<28) - 1, -((1<<26) - 1), -((1<<27) - 1), -((1<<28) - 1) }; int n = sizeof(numbers)/sizeof(int); QJsonArray array; for (int i = 0; i < n; ++i) array.append((double)numbers[i]); QByteArray serialized = QJsonDocument(array).toJson(); QJsonDocument json = QJsonDocument::fromJson(serialized); QJsonArray array2 = json.array(); QCOMPARE(array.size(), array2.size()); for (int i = 0; i < array.size(); ++i) { QCOMPARE(array.at(i).type(), QJsonValue::Double); QCOMPARE(array.at(i).toDouble(), (double)numbers[i]); QCOMPARE(array2.at(i).type(), QJsonValue::Double); QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]); } } { qint64 numbers[] = { 0, -1, 1, (1ll<<54), (1ll<<55), (1ll<<56), -(1ll<<54), -(1ll<<55), -(1ll<<56), (1ll<<54) - 1, (1ll<<55) - 1, (1ll<<56) - 1, -((1ll<<54) - 1), -((1ll<<55) - 1), -((1ll<<56) - 1) }; int n = sizeof(numbers)/sizeof(qint64); QJsonArray array; for (int i = 0; i < n; ++i) array.append((double)numbers[i]); QByteArray serialized = QJsonDocument(array).toJson(); QJsonDocument json = QJsonDocument::fromJson(serialized); QJsonArray array2 = json.array(); QCOMPARE(array.size(), array2.size()); for (int i = 0; i < array.size(); ++i) { QCOMPARE(array.at(i).type(), QJsonValue::Double); QCOMPARE(array.at(i).toDouble(), (double)numbers[i]); QCOMPARE(array2.at(i).type(), QJsonValue::Double); QCOMPARE(array2.at(i).toDouble(), (double)numbers[i]); } } { double numbers[] = { 0, -1, 1, double(1ll<<54), double(1ll<<55), double(1ll<<56), double(-(1ll<<54)), double(-(1ll<<55)), double(-(1ll<<56)), double((1ll<<54) - 1), double((1ll<<55) - 1), double((1ll<<56) - 1), double(-((1ll<<54) - 1)), double(-((1ll<<55) - 1)), double(-((1ll<<56) - 1)), 1.1, 0.1, -0.1, -1.1, 1e200, -1e200 }; int n = sizeof(numbers)/sizeof(double); QJsonArray array; for (int i = 0; i < n; ++i) array.append(numbers[i]); QByteArray serialized = QJsonDocument(array).toJson(); QJsonDocument json = QJsonDocument::fromJson(serialized); QJsonArray array2 = json.array(); QCOMPARE(array.size(), array2.size()); for (int i = 0; i < array.size(); ++i) { QCOMPARE(array.at(i).type(), QJsonValue::Double); QCOMPARE(array.at(i).toDouble(), numbers[i]); QCOMPARE(array2.at(i).type(), QJsonValue::Double); QCOMPARE(array2.at(i).toDouble(), numbers[i]); } } } void tst_QtJson::testNumbers_2() { // test cases from TC39 test suite for ECMAScript // http://hg.ecmascript.org/tests/test262/file/d067d2f0ca30/test/suite/ch08/8.5/8.5.1.js // Fill an array with 2 to the power of (0 ... -1075) double value = 1; double floatValues[1076], floatValues_1[1076]; QJsonObject jObject; for (int power = 0; power <= 1075; power++) { floatValues[power] = value; jObject.insert(QString::number(power), QJsonValue(floatValues[power])); // Use basic math operations for testing, which are required to support 'gradual underflow' rather // than Math.pow etc..., which are defined as 'implementation dependent'. value = value * 0.5; } QJsonDocument jDocument1(jObject); QByteArray ba(jDocument1.toJson()); QJsonDocument jDocument2(QJsonDocument::fromJson(ba)); for (int power = 0; power <= 1075; power++) { floatValues_1[power] = jDocument2.object().value(QString::number(power)).toDouble(); #ifdef Q_OS_QNX if (power >= 970) QEXPECT_FAIL("", "See QTBUG-37066", Abort); #endif QVERIFY2(floatValues[power] == floatValues_1[power], QString("floatValues[%1] != floatValues_1[%1]").arg(power).toLatin1()); } // The last value is below min denorm and should round to 0, everything else should contain a value QVERIFY2(floatValues_1[1075] == 0, "Value after min denorm should round to 0"); // Validate the last actual value is min denorm QVERIFY2(floatValues_1[1074] == 4.9406564584124654417656879286822e-324, QString("Min denorm value is incorrect: %1").arg(floatValues_1[1074]).toLatin1()); // Validate that every value is half the value before it up to 1 for (int index = 1074; index > 0; index--) { QVERIFY2(floatValues_1[index] != 0, QString("2**- %1 should not be 0").arg(index).toLatin1()); QVERIFY2(floatValues_1[index - 1] == (floatValues_1[index] * 2), QString("Value should be double adjacent value at index %1").arg(index).toLatin1()); } } void tst_QtJson::testNumbers_3() { // test case from QTBUG-31926 double d1 = 1.123451234512345; double d2 = 1.123451234512346; QJsonObject jObject; jObject.insert("d1", QJsonValue(d1)); jObject.insert("d2", QJsonValue(d2)); QJsonDocument jDocument1(jObject); QByteArray ba(jDocument1.toJson()); QJsonDocument jDocument2(QJsonDocument::fromJson(ba)); double d1_1(jDocument2.object().value("d1").toDouble()); double d2_1(jDocument2.object().value("d2").toDouble()); QVERIFY(d1_1 != d2_1); } void tst_QtJson::testObjectSimple() { QJsonObject object; object.insert("number", 999.); QCOMPARE(object.value("number").type(), QJsonValue::Double); QCOMPARE(object.value("number").toDouble(), 999.); object.insert("string", QString::fromLatin1("test")); QCOMPARE(object.value("string").type(), QJsonValue::String); QCOMPARE(object.value("string").toString(), QString("test")); object.insert("boolean", true); QCOMPARE(object.value("boolean").toBool(), true); QStringList keys = object.keys(); QVERIFY2(keys.contains("number"), "key number not found"); QVERIFY2(keys.contains("string"), "key string not found"); QVERIFY2(keys.contains("boolean"), "key boolean not found"); // if we put a JsonValue into the JsonObject and retrieve // it, it should be identical. QJsonValue value(QLatin1String("foo")); object.insert("value", value); QCOMPARE(object.value("value"), value); int size = object.size(); object.remove("boolean"); QCOMPARE(object.size(), size - 1); QVERIFY2(!object.contains("boolean"), "key boolean should have been removed"); QJsonValue taken = object.take("value"); QCOMPARE(taken, value); QVERIFY2(!object.contains("value"), "key value should have been removed"); QString before = object.value("string").toString(); object.insert("string", QString::fromLatin1("foo")); QVERIFY2(object.value("string").toString() != before, "value should have been updated"); size = object.size(); QJsonObject subobject; subobject.insert("number", 42); subobject.insert(QLatin1String("string"), QLatin1String("foobar")); object.insert("subobject", subobject); QCOMPARE(object.size(), size+1); QJsonValue subvalue = object.take(QLatin1String("subobject")); QCOMPARE(object.size(), size); QCOMPARE(subvalue.toObject(), subobject); // make object detach by modifying it many times for (int i = 0; i < 64; ++i) object.insert(QLatin1String("string"), QLatin1String("bar")); QCOMPARE(object.size(), size); QCOMPARE(subvalue.toObject(), subobject); } void tst_QtJson::testObjectSmallKeys() { QJsonObject data1; data1.insert(QLatin1String("1"), 123); QVERIFY(data1.contains(QLatin1String("1"))); QCOMPARE(data1.value(QLatin1String("1")).toDouble(), (double)123); data1.insert(QLatin1String("12"), 133); QCOMPARE(data1.value(QLatin1String("12")).toDouble(), (double)133); QVERIFY(data1.contains(QLatin1String("12"))); data1.insert(QLatin1String("123"), 323); QCOMPARE(data1.value(QLatin1String("12")).toDouble(), (double)133); QVERIFY(data1.contains(QLatin1String("123"))); QCOMPARE(data1.value(QLatin1String("123")).type(), QJsonValue::Double); QCOMPARE(data1.value(QLatin1String("123")).toDouble(), (double)323); } void tst_QtJson::testArraySimple() { QJsonArray array; array.append(999.); array.append(QString::fromLatin1("test")); array.append(true); QJsonValue val = array.at(0); QCOMPARE(array.at(0).toDouble(), 999.); QCOMPARE(array.at(1).toString(), QString("test")); QCOMPARE(array.at(2).toBool(), true); QCOMPARE(array.size(), 3); // if we put a JsonValue into the JsonArray and retrieve // it, it should be identical. QJsonValue value(QLatin1String("foo")); array.append(value); QCOMPARE(array.at(3), value); int size = array.size(); array.removeAt(2); --size; QCOMPARE(array.size(), size); QJsonValue taken = array.takeAt(0); --size; QCOMPARE(taken.toDouble(), 999.); QCOMPARE(array.size(), size); // check whether null values work array.append(QJsonValue()); ++size; QCOMPARE(array.size(), size); QCOMPARE(array.last().type(), QJsonValue::Null); QCOMPARE(array.last(), QJsonValue()); QCOMPARE(array.first().type(), QJsonValue::String); QCOMPARE(array.first(), QJsonValue(QLatin1String("test"))); array.prepend(false); QCOMPARE(array.first().type(), QJsonValue::Bool); QCOMPARE(array.first(), QJsonValue(false)); QCOMPARE(array.at(-1), QJsonValue(QJsonValue::Undefined)); QCOMPARE(array.at(array.size()), QJsonValue(QJsonValue::Undefined)); array.replace(0, -555.); QCOMPARE(array.first().type(), QJsonValue::Double); QCOMPARE(array.first(), QJsonValue(-555.)); QCOMPARE(array.at(1).type(), QJsonValue::String); QCOMPARE(array.at(1), QJsonValue(QLatin1String("test"))); } void tst_QtJson::testValueObject() { QJsonObject object; object.insert("number", 999.); object.insert("string", QLatin1String("test")); object.insert("boolean", true); QJsonValue value(object); // if we don't modify the original JsonObject, toObject() // on the JsonValue should return the same object (non-detached). QCOMPARE(value.toObject(), object); // if we modify the original object, it should detach object.insert("test", QJsonValue(QLatin1String("test"))); QVERIFY2(value.toObject() != object, "object should have detached"); } void tst_QtJson::testValueArray() { QJsonArray array; array.append(999.); array.append(QLatin1String("test")); array.append(true); QJsonValue value(array); // if we don't modify the original JsonArray, toArray() // on the JsonValue should return the same object (non-detached). QCOMPARE(value.toArray(), array); // if we modify the original array, it should detach array.append(QLatin1String("test")); QVERIFY2(value.toArray() != array, "array should have detached"); } void tst_QtJson::testObjectNested() { QJsonObject inner, outer; inner.insert("number", 999.); outer.insert("nested", inner); // if we don't modify the original JsonObject, value() // should return the same object (non-detached). QJsonObject value = outer.value("nested").toObject(); QCOMPARE(value, inner); QCOMPARE(value.value("number").toDouble(), 999.); // if we modify the original object, it should detach and not // affect the nested object inner.insert("number", 555.); value = outer.value("nested").toObject(); QVERIFY2(inner.value("number").toDouble() != value.value("number").toDouble(), "object should have detached"); // array in object QJsonArray array; array.append(123.); array.append(456.); outer.insert("array", array); QCOMPARE(outer.value("array").toArray(), array); QCOMPARE(outer.value("array").toArray().at(1).toDouble(), 456.); // two deep objects QJsonObject twoDeep; twoDeep.insert("boolean", true); inner.insert("nested", twoDeep); outer.insert("nested", inner); QCOMPARE(outer.value("nested").toObject().value("nested").toObject(), twoDeep); QCOMPARE(outer.value("nested").toObject().value("nested").toObject().value("boolean").toBool(), true); } void tst_QtJson::testArrayNested() { QJsonArray inner, outer; inner.append(999.); outer.append(inner); // if we don't modify the original JsonArray, value() // should return the same array (non-detached). QJsonArray value = outer.at(0).toArray(); QCOMPARE(value, inner); QCOMPARE(value.at(0).toDouble(), 999.); // if we modify the original array, it should detach and not // affect the nested array inner.append(555.); value = outer.at(0).toArray(); QVERIFY2(inner.size() != value.size(), "array should have detached"); // objects in arrays QJsonObject object; object.insert("boolean", true); outer.append(object); QCOMPARE(outer.last().toObject(), object); QCOMPARE(outer.last().toObject().value("boolean").toBool(), true); // two deep arrays QJsonArray twoDeep; twoDeep.append(QJsonValue(QString::fromLatin1("nested"))); inner.append(twoDeep); outer.append(inner); QCOMPARE(outer.last().toArray().last().toArray(), twoDeep); QCOMPARE(outer.last().toArray().last().toArray().at(0).toString(), QString("nested")); } void tst_QtJson::testArrayNestedEmpty() { QJsonObject object; QJsonArray inner; object.insert("inner", inner); QJsonValue val = object.value("inner"); QJsonArray value = object.value("inner").toArray(); QCOMPARE(value.size(), 0); QCOMPARE(value, inner); QCOMPARE(value.size(), 0); object.insert("count", 0.); QCOMPARE(object.value("inner").toArray().size(), 0); QVERIFY(object.value("inner").toArray().isEmpty()); QJsonDocument(object).toBinaryData(); QCOMPARE(object.value("inner").toArray().size(), 0); } void tst_QtJson::testObjectNestedEmpty() { QJsonObject object; QJsonObject inner; QJsonObject inner2; object.insert("inner", inner); object.insert("inner2", inner2); QJsonObject value = object.value("inner").toObject(); QCOMPARE(value.size(), 0); QCOMPARE(value, inner); QCOMPARE(value.size(), 0); object.insert("count", 0.); QCOMPARE(object.value("inner").toObject().size(), 0); QCOMPARE(object.value("inner").type(), QJsonValue::Object); QJsonDocument(object).toBinaryData(); QVERIFY(object.value("inner").toObject().isEmpty()); QVERIFY(object.value("inner2").toObject().isEmpty()); QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(object).toBinaryData()); QVERIFY(!doc.isNull()); QJsonObject reconstituted(doc.object()); QCOMPARE(reconstituted.value("inner").toObject().size(), 0); QCOMPARE(reconstituted.value("inner").type(), QJsonValue::Object); QCOMPARE(reconstituted.value("inner2").type(), QJsonValue::Object); } void tst_QtJson::testArrayComfortOperators() { QJsonArray first; first.append(123.); first.append(QLatin1String("foo")); QJsonArray second = QJsonArray() << 123. << QLatin1String("foo"); QCOMPARE(first, second); first = first + QLatin1String("bar"); second += QLatin1String("bar"); QCOMPARE(first, second); } void tst_QtJson::testValueRef() { QJsonArray array; array.append(1.); array.append(2.); array.append(3.); array.append(4); array.append(4.1); array[1] = false; QCOMPARE(array.size(), 5); QCOMPARE(array.at(0).toDouble(), 1.); QCOMPARE(array.at(2).toDouble(), 3.); #if QT_VERSION >= 0x050200 QCOMPARE(array.at(3).toInt(), 4); QCOMPARE(array.at(4).toInt(), 0); #endif QCOMPARE(array.at(1).type(), QJsonValue::Bool); QCOMPARE(array.at(1).toBool(), false); QJsonObject object; object[QLatin1String("key")] = true; QCOMPARE(object.size(), 1); object.insert(QLatin1String("null"), QJsonValue()); QCOMPARE(object.value(QLatin1String("null")), QJsonValue()); object[QLatin1String("null")] = 100.; QCOMPARE(object.value(QLatin1String("null")).type(), QJsonValue::Double); QJsonValue val = object[QLatin1String("null")]; QCOMPARE(val.toDouble(), 100.); QCOMPARE(object.size(), 2); array[1] = array[2] = object[QLatin1String("key")] = 42; QCOMPARE(array[1], array[2]); QCOMPARE(array[2], object[QLatin1String("key")]); QCOMPARE(object.value(QLatin1String("key")), QJsonValue(42)); } void tst_QtJson::testObjectIteration() { QJsonObject object; for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) QVERIFY(false); const QString property = "kkk"; object.insert(property, 11); object.take(property); for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) QVERIFY(false); for (int i = 0; i < 10; ++i) object[QString::number(i)] = (double)i; QCOMPARE(object.size(), 10); QCOMPARE(object.begin()->toDouble(), object.constBegin()->toDouble()); for (QJsonObject::iterator it = object.begin(); it != object.end(); ++it) { QJsonValue value = it.value(); QCOMPARE((double)it.key().toInt(), value.toDouble()); } { QJsonObject object2 = object; QVERIFY(object == object2); QJsonValue val = *object2.begin(); object2.erase(object2.begin()); QCOMPARE(object.size(), 10); QCOMPARE(object2.size(), 9); for (QJsonObject::const_iterator it = object2.constBegin(); it != object2.constEnd(); ++it) { QJsonValue value = it.value(); QVERIFY(it.value() != val); QCOMPARE((double)it.key().toInt(), value.toDouble()); } } { QJsonObject object2 = object; QVERIFY(object == object2); QJsonObject::iterator it = object2.find(QString::number(5)); object2.erase(it); QCOMPARE(object.size(), 10); QCOMPARE(object2.size(), 9); } { QJsonObject::Iterator it = object.begin(); it += 5; QCOMPARE(QJsonValue(it.value()).toDouble(), 5.); it -= 3; QCOMPARE(QJsonValue(it.value()).toDouble(), 2.); QJsonObject::Iterator it2 = it + 5; QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.); it2 = it - 1; QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.); } { QJsonObject::ConstIterator it = object.constBegin(); it += 5; QCOMPARE(QJsonValue(it.value()).toDouble(), 5.); it -= 3; QCOMPARE(QJsonValue(it.value()).toDouble(), 2.); QJsonObject::ConstIterator it2 = it + 5; QCOMPARE(QJsonValue(it2.value()).toDouble(), 7.); it2 = it - 1; QCOMPARE(QJsonValue(it2.value()).toDouble(), 1.); } QJsonObject::Iterator it = object.begin(); while (!object.isEmpty()) it = object.erase(it); QCOMPARE(object.size() , 0); QVERIFY(it == object.end()); } void tst_QtJson::testArrayIteration() { QJsonArray array; for (int i = 0; i < 10; ++i) array.append(i); QCOMPARE(array.size(), 10); int i = 0; for (QJsonArray::iterator it = array.begin(); it != array.end(); ++it, ++i) { QJsonValue value = (*it); QCOMPARE((double)i, value.toDouble()); } QCOMPARE(array.begin()->toDouble(), array.constBegin()->toDouble()); { QJsonArray array2 = array; QVERIFY(array == array2); QJsonValue val = *array2.begin(); array2.erase(array2.begin()); QCOMPARE(array.size(), 10); QCOMPARE(array2.size(), 9); i = 1; for (QJsonArray::const_iterator it = array2.constBegin(); it != array2.constEnd(); ++it, ++i) { QJsonValue value = (*it); QCOMPARE((double)i, value.toDouble()); } } { QJsonArray::Iterator it = array.begin(); it += 5; QCOMPARE(QJsonValue((*it)).toDouble(), 5.); it -= 3; QCOMPARE(QJsonValue((*it)).toDouble(), 2.); QJsonArray::Iterator it2 = it + 5; QCOMPARE(QJsonValue(*it2).toDouble(), 7.); it2 = it - 1; QCOMPARE(QJsonValue(*it2).toDouble(), 1.); } { QJsonArray::ConstIterator it = array.constBegin(); it += 5; QCOMPARE(QJsonValue((*it)).toDouble(), 5.); it -= 3; QCOMPARE(QJsonValue((*it)).toDouble(), 2.); QJsonArray::ConstIterator it2 = it + 5; QCOMPARE(QJsonValue(*it2).toDouble(), 7.); it2 = it - 1; QCOMPARE(QJsonValue(*it2).toDouble(), 1.); } QJsonArray::Iterator it = array.begin(); while (!array.isEmpty()) it = array.erase(it); QCOMPARE(array.size() , 0); QVERIFY(it == array.end()); } void tst_QtJson::testObjectFind() { QJsonObject object; for (int i = 0; i < 10; ++i) object[QString::number(i)] = i; QCOMPARE(object.size(), 10); QJsonObject::iterator it = object.find(QLatin1String("1")); QCOMPARE((*it).toDouble(), 1.); it = object.find(QLatin1String("11")); QVERIFY((*it).type() == QJsonValue::Undefined); QVERIFY(it == object.end()); QJsonObject::const_iterator cit = object.constFind(QLatin1String("1")); QCOMPARE((*cit).toDouble(), 1.); cit = object.constFind(QLatin1String("11")); QVERIFY((*it).type() == QJsonValue::Undefined); QVERIFY(it == object.end()); } void tst_QtJson::testDocument() { QJsonDocument doc; QCOMPARE(doc.isEmpty(), true); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), false); QJsonObject object; doc.setObject(object); QCOMPARE(doc.isEmpty(), false); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), true); object.insert(QLatin1String("Key"), QLatin1String("Value")); doc.setObject(object); QCOMPARE(doc.isEmpty(), false); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), true); QVERIFY(doc.object() == object); QVERIFY(doc.array() == QJsonArray()); doc = QJsonDocument(); QCOMPARE(doc.isEmpty(), true); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), false); QJsonArray array; doc.setArray(array); QCOMPARE(doc.isEmpty(), false); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); array.append(QLatin1String("Value")); doc.setArray(array); QCOMPARE(doc.isEmpty(), false); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QVERIFY(doc.array() == array); QVERIFY(doc.object() == QJsonObject()); QJsonObject outer; outer.insert(QLatin1String("outerKey"), 22); QJsonObject inner; inner.insert(QLatin1String("innerKey"), 42); outer.insert(QLatin1String("innter"), inner); QJsonArray innerArray; innerArray.append(23); outer.insert(QLatin1String("innterArray"), innerArray); QJsonDocument doc2(outer.value(QLatin1String("innter")).toObject()); QVERIFY(doc2.object().contains(QLatin1String("innerKey"))); QCOMPARE(doc2.object().value(QLatin1String("innerKey")), QJsonValue(42)); QJsonDocument doc3; doc3.setObject(outer.value(QLatin1String("innter")).toObject()); QCOMPARE(doc3.isArray(), false); QCOMPARE(doc3.isObject(), true); QVERIFY(doc3.object().contains(QLatin1String("innerKey"))); QCOMPARE(doc3.object().value(QLatin1String("innerKey")), QJsonValue(42)); QJsonDocument doc4(outer.value(QLatin1String("innterArray")).toArray()); QCOMPARE(doc4.isArray(), true); QCOMPARE(doc4.isObject(), false); QCOMPARE(doc4.array().size(), 1); QCOMPARE(doc4.array().at(0), QJsonValue(23)); QJsonDocument doc5; doc5.setArray(outer.value(QLatin1String("innterArray")).toArray()); QCOMPARE(doc5.isArray(), true); QCOMPARE(doc5.isObject(), false); QCOMPARE(doc5.array().size(), 1); QCOMPARE(doc5.array().at(0), QJsonValue(23)); } void tst_QtJson::nullValues() { QJsonArray array; array.append(QJsonValue()); QCOMPARE(array.size(), 1); QCOMPARE(array.at(0), QJsonValue()); QJsonObject object; object.insert(QString("key"), QJsonValue()); QCOMPARE(object.contains("key"), true); QCOMPARE(object.size(), 1); QCOMPARE(object.value("key"), QJsonValue()); } void tst_QtJson::nullArrays() { QJsonArray nullArray; QJsonArray nonNull; nonNull.append(QLatin1String("bar")); QCOMPARE(nullArray, QJsonArray()); QVERIFY(nullArray != nonNull); QVERIFY(nonNull != nullArray); QCOMPARE(nullArray.size(), 0); QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined)); QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined)); QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined)); nullArray.removeAt(0); nullArray.removeAt(-1); nullArray.append(QString("bar")); nullArray.removeAt(0); QCOMPARE(nullArray.size(), 0); QCOMPARE(nullArray.takeAt(0), QJsonValue(QJsonValue::Undefined)); QCOMPARE(nullArray.first(), QJsonValue(QJsonValue::Undefined)); QCOMPARE(nullArray.last(), QJsonValue(QJsonValue::Undefined)); nullArray.removeAt(0); nullArray.removeAt(-1); } void tst_QtJson::nullObject() { QJsonObject nullObject; QJsonObject nonNull; nonNull.insert(QLatin1String("foo"), QLatin1String("bar")); QCOMPARE(nullObject, QJsonObject()); QVERIFY(nullObject != nonNull); QVERIFY(nonNull != nullObject); QCOMPARE(nullObject.size(), 0); QCOMPARE(nullObject.keys(), QStringList()); nullObject.remove("foo"); QCOMPARE(nullObject, QJsonObject()); QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined)); QCOMPARE(nullObject.contains("foo"), false); nullObject.insert("foo", QString("bar")); nullObject.remove("foo"); QCOMPARE(nullObject.size(), 0); QCOMPARE(nullObject.keys(), QStringList()); nullObject.remove("foo"); QCOMPARE(nullObject, QJsonObject()); QCOMPARE(nullObject.take("foo"), QJsonValue(QJsonValue::Undefined)); QCOMPARE(nullObject.contains("foo"), false); } void tst_QtJson::constNullObject() { const QJsonObject nullObject; QJsonObject nonNull; nonNull.insert(QLatin1String("foo"), QLatin1String("bar")); QCOMPARE(nullObject, QJsonObject()); QVERIFY(nullObject != nonNull); QVERIFY(nonNull != nullObject); QCOMPARE(nullObject.size(), 0); QCOMPARE(nullObject.keys(), QStringList()); QCOMPARE(nullObject, QJsonObject()); QCOMPARE(nullObject.contains("foo"), false); QCOMPARE(nullObject["foo"], QJsonValue(QJsonValue::Undefined)); } void tst_QtJson::keySorting() { const char *json = "{ \"B\": true, \"A\": false }"; QJsonDocument doc = QJsonDocument::fromJson(json); QCOMPARE(doc.isObject(), true); QJsonObject o = doc.object(); QCOMPARE(o.size(), 2); QJsonObject::const_iterator it = o.constBegin(); QCOMPARE(it.key(), QLatin1String("A")); ++it; QCOMPARE(it.key(), QLatin1String("B")); } void tst_QtJson::undefinedValues() { QJsonObject object; object.insert("Key", QJsonValue(QJsonValue::Undefined)); QCOMPARE(object.size(), 0); object.insert("Key", QLatin1String("Value")); QCOMPARE(object.size(), 1); QCOMPARE(object.value("Key").type(), QJsonValue::String); QCOMPARE(object.value("foo").type(), QJsonValue::Undefined); object.insert("Key", QJsonValue(QJsonValue::Undefined)); QCOMPARE(object.size(), 0); QCOMPARE(object.value("Key").type(), QJsonValue::Undefined); QJsonArray array; array.append(QJsonValue(QJsonValue::Undefined)); QCOMPARE(array.size(), 1); QCOMPARE(array.at(0).type(), QJsonValue::Null); QCOMPARE(array.at(1).type(), QJsonValue::Undefined); QCOMPARE(array.at(-1).type(), QJsonValue::Undefined); } void tst_QtJson::fromVariant() { bool boolValue = true; int intValue = -1; uint uintValue = 1; long long longlongValue = -2; unsigned long long ulonglongValue = 2; float floatValue = 3.3f; double doubleValue = 4.4; QString stringValue("str"); QStringList stringList; stringList.append(stringValue); stringList.append("str2"); QJsonArray jsonArray_string; jsonArray_string.append(stringValue); jsonArray_string.append("str2"); QVariantList variantList; variantList.append(boolValue); variantList.append(floatValue); variantList.append(doubleValue); variantList.append(stringValue); variantList.append(stringList); variantList.append(QVariant()); QJsonArray jsonArray_variant; jsonArray_variant.append(boolValue); jsonArray_variant.append(floatValue); jsonArray_variant.append(doubleValue); jsonArray_variant.append(stringValue); jsonArray_variant.append(jsonArray_string); jsonArray_variant.append(QJsonValue()); QVariantMap variantMap; variantMap["bool"] = boolValue; variantMap["float"] = floatValue; variantMap["string"] = stringValue; variantMap["array"] = variantList; QJsonObject jsonObject; jsonObject["bool"] = boolValue; jsonObject["float"] = floatValue; jsonObject["string"] = stringValue; jsonObject["array"] = jsonArray_variant; QCOMPARE(QJsonValue::fromVariant(QVariant(boolValue)), QJsonValue(boolValue)); QCOMPARE(QJsonValue::fromVariant(QVariant(intValue)), QJsonValue(intValue)); QCOMPARE(QJsonValue::fromVariant(QVariant(uintValue)), QJsonValue(static_cast(uintValue))); QCOMPARE(QJsonValue::fromVariant(QVariant(longlongValue)), QJsonValue(longlongValue)); QCOMPARE(QJsonValue::fromVariant(QVariant(ulonglongValue)), QJsonValue(static_cast(ulonglongValue))); QCOMPARE(QJsonValue::fromVariant(QVariant(floatValue)), QJsonValue(static_cast(floatValue))); QCOMPARE(QJsonValue::fromVariant(QVariant(doubleValue)), QJsonValue(doubleValue)); QCOMPARE(QJsonValue::fromVariant(QVariant(stringValue)), QJsonValue(stringValue)); QCOMPARE(QJsonValue::fromVariant(QVariant(stringList)), QJsonValue(jsonArray_string)); QCOMPARE(QJsonValue::fromVariant(QVariant(variantList)), QJsonValue(jsonArray_variant)); QCOMPARE(QJsonValue::fromVariant(QVariant(variantMap)), QJsonValue(jsonObject)); } void tst_QtJson::fromVariantMap() { QVariantMap map; map.insert(QLatin1String("key1"), QLatin1String("value1")); map.insert(QLatin1String("key2"), QLatin1String("value2")); QJsonObject object = QJsonObject::fromVariantMap(map); QCOMPARE(object.size(), 2); QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1"))); QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2"))); QVariantList list; list.append(true); list.append(QVariant()); list.append(999.); list.append(QLatin1String("foo")); map.insert("list", list); object = QJsonObject::fromVariantMap(map); QCOMPARE(object.size(), 3); QCOMPARE(object.value(QLatin1String("key1")), QJsonValue(QLatin1String("value1"))); QCOMPARE(object.value(QLatin1String("key2")), QJsonValue(QLatin1String("value2"))); QCOMPARE(object.value(QLatin1String("list")).type(), QJsonValue::Array); QJsonArray array = object.value(QLatin1String("list")).toArray(); QCOMPARE(array.size(), 4); QCOMPARE(array.at(0).type(), QJsonValue::Bool); QCOMPARE(array.at(0).toBool(), true); QCOMPARE(array.at(1).type(), QJsonValue::Null); QCOMPARE(array.at(2).type(), QJsonValue::Double); QCOMPARE(array.at(2).toDouble(), 999.); QCOMPARE(array.at(3).type(), QJsonValue::String); QCOMPARE(array.at(3).toString(), QLatin1String("foo")); } void tst_QtJson::toVariantMap() { QCOMPARE(QMetaType::Type(QJsonValue(QJsonObject()).toVariant().type()), QMetaType::QVariantMap); // QTBUG-32524 QJsonObject object; QVariantMap map = object.toVariantMap(); QVERIFY(map.isEmpty()); object.insert("Key", QString("Value")); object.insert("null", QJsonValue()); QJsonArray array; array.append(true); array.append(999.); array.append(QLatin1String("string")); array.append(QJsonValue()); object.insert("Array", array); map = object.toVariantMap(); QCOMPARE(map.size(), 3); QCOMPARE(map.value("Key"), QVariant(QString("Value"))); QCOMPARE(map.value("null"), QVariant()); QCOMPARE(map.value("Array").type(), QVariant::List); QVariantList list = map.value("Array").toList(); QCOMPARE(list.size(), 4); QCOMPARE(list.at(0), QVariant(true)); QCOMPARE(list.at(1), QVariant(999.)); QCOMPARE(list.at(2), QVariant(QLatin1String("string"))); QCOMPARE(list.at(3), QVariant()); } void tst_QtJson::toVariantList() { QCOMPARE(QMetaType::Type(QJsonValue(QJsonArray()).toVariant().type()), QMetaType::QVariantList); // QTBUG-32524 QJsonArray array; QVariantList list = array.toVariantList(); QVERIFY(list.isEmpty()); array.append(QString("Value")); array.append(QJsonValue()); QJsonArray inner; inner.append(true); inner.append(999.); inner.append(QLatin1String("string")); inner.append(QJsonValue()); array.append(inner); list = array.toVariantList(); QCOMPARE(list.size(), 3); QCOMPARE(list[0], QVariant(QString("Value"))); QCOMPARE(list[1], QVariant()); QCOMPARE(list[2].type(), QVariant::List); QVariantList vlist = list[2].toList(); QCOMPARE(vlist.size(), 4); QCOMPARE(vlist.at(0), QVariant(true)); QCOMPARE(vlist.at(1), QVariant(999.)); QCOMPARE(vlist.at(2), QVariant(QLatin1String("string"))); QCOMPARE(vlist.at(3), QVariant()); } void tst_QtJson::toJson() { // Test QJsonDocument::Indented format { QJsonObject object; object.insert("\\Key\n", QString("Value")); object.insert("null", QJsonValue()); QJsonArray array; array.append(true); array.append(999.); array.append(QLatin1String("string")); array.append(QJsonValue()); array.append(QLatin1String("\\\a\n\r\b\tabcABC\"")); object.insert("Array", array); QByteArray json = QJsonDocument(object).toJson(); QByteArray expected = "{\n" " \"Array\": [\n" " true,\n" " 999,\n" " \"string\",\n" " null,\n" " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" " ],\n" " \"\\\\Key\\n\": \"Value\",\n" " \"null\": null\n" "}\n"; QCOMPARE(json, expected); QJsonDocument doc; doc.setObject(object); json = doc.toJson(); QCOMPARE(json, expected); doc.setArray(array); json = doc.toJson(); expected = "[\n" " true,\n" " 999,\n" " \"string\",\n" " null,\n" " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" "]\n"; QCOMPARE(json, expected); } // Test QJsonDocument::Compact format { QJsonObject object; object.insert("\\Key\n", QString("Value")); object.insert("null", QJsonValue()); QJsonArray array; array.append(true); array.append(999.); array.append(QLatin1String("string")); array.append(QJsonValue()); array.append(QLatin1String("\\\a\n\r\b\tabcABC\"")); object.insert("Array", array); QByteArray json = QJsonDocument(object).toJson(QJsonDocument::Compact); QByteArray expected = "{\"Array\":[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\":\"Value\",\"null\":null}"; QCOMPARE(json, expected); QJsonDocument doc; doc.setObject(object); json = doc.toJson(QJsonDocument::Compact); QCOMPARE(json, expected); doc.setArray(array); json = doc.toJson(QJsonDocument::Compact); expected = "[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"]"; QCOMPARE(json, expected); } } void tst_QtJson::toJsonSillyNumericValues() { QJsonObject object; QJsonArray array; array.append(QJsonValue(std::numeric_limits::infinity())); // encode to: null array.append(QJsonValue(-std::numeric_limits::infinity())); // encode to: null array.append(QJsonValue(std::numeric_limits::quiet_NaN())); // encode to: null object.insert("Array", array); QByteArray json = QJsonDocument(object).toJson(); QByteArray expected = "{\n" " \"Array\": [\n" " null,\n" " null,\n" " null\n" " ]\n" "}\n"; QCOMPARE(json, expected); QJsonDocument doc; doc.setObject(object); json = doc.toJson(); QCOMPARE(json, expected); } void tst_QtJson::toJsonLargeNumericValues() { QJsonObject object; QJsonArray array; array.append(QJsonValue(1.234567)); // actual precision bug in Qt 5.0.0 array.append(QJsonValue(1.7976931348623157e+308)); // JS Number.MAX_VALUE array.append(QJsonValue(5e-324)); // JS Number.MIN_VALUE array.append(QJsonValue(std::numeric_limits::min())); array.append(QJsonValue(std::numeric_limits::max())); array.append(QJsonValue(std::numeric_limits::epsilon())); array.append(QJsonValue(std::numeric_limits::denorm_min())); array.append(QJsonValue(0.0)); array.append(QJsonValue(-std::numeric_limits::min())); array.append(QJsonValue(-std::numeric_limits::max())); array.append(QJsonValue(-std::numeric_limits::epsilon())); array.append(QJsonValue(-std::numeric_limits::denorm_min())); array.append(QJsonValue(-0.0)); array.append(QJsonValue(9007199254740992LL)); // JS Number max integer array.append(QJsonValue(-9007199254740992LL)); // JS Number min integer object.insert("Array", array); QByteArray json = QJsonDocument(object).toJson(); QByteArray expected = "{\n" " \"Array\": [\n" " 1.234567,\n" " 1.7976931348623157e+308,\n" // ((4.9406564584124654e-324 == 5e-324) == true) // I can only think JavaScript has a special formatter to // emit this value for this IEEE754 bit pattern. " 4.9406564584124654e-324,\n" " 2.2250738585072014e-308,\n" " 1.7976931348623157e+308,\n" " 2.2204460492503131e-16,\n" " 4.9406564584124654e-324,\n" " 0,\n" " -2.2250738585072014e-308,\n" " -1.7976931348623157e+308,\n" " -2.2204460492503131e-16,\n" " -4.9406564584124654e-324,\n" " 0,\n" " 9007199254740992,\n" " -9007199254740992\n" " ]\n" "}\n"; #ifdef Q_OS_QNX QEXPECT_FAIL("", "See QTBUG-37066", Continue); #endif QCOMPARE(json, expected); QJsonDocument doc; doc.setObject(object); json = doc.toJson(); #ifdef Q_OS_QNX QEXPECT_FAIL("", "See QTBUG-37066", Continue); #endif QCOMPARE(json, expected); } void tst_QtJson::fromJson() { { QByteArray json = "[\n true\n]\n"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 1); QCOMPARE(array.at(0).type(), QJsonValue::Bool); QCOMPARE(array.at(0).toBool(), true); QCOMPARE(doc.toJson(), json); } /*{ //regression test: test if unicode_control_characters are correctly decoded QByteArray json = "[\n \"" UNICODE_NON_CHARACTER "\"\n]\n"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 1); QCOMPARE(array.at(0).type(), QJsonValue::String); QCOMPARE(array.at(0).toString(), QString::fromUtf8(UNICODE_NON_CHARACTER)); QCOMPARE(doc.toJson(), json); }*/ { QByteArray json = "[]"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 0); } { QByteArray json = "{}"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), true); QJsonObject object = doc.object(); QCOMPARE(object.size(), 0); } { QByteArray json = "{\n \"Key\": true\n}\n"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), true); QJsonObject object = doc.object(); QCOMPARE(object.size(), 1); QCOMPARE(object.value("Key"), QJsonValue(true)); QCOMPARE(doc.toJson(), json); } { QByteArray json = "[ null, true, false, \"Foo\", 1, [], {} ]"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 7); QCOMPARE(array.at(0).type(), QJsonValue::Null); QCOMPARE(array.at(1).type(), QJsonValue::Bool); QCOMPARE(array.at(1).toBool(), true); QCOMPARE(array.at(2).type(), QJsonValue::Bool); QCOMPARE(array.at(2).toBool(), false); QCOMPARE(array.at(3).type(), QJsonValue::String); QCOMPARE(array.at(3).toString(), QLatin1String("Foo")); QCOMPARE(array.at(4).type(), QJsonValue::Double); QCOMPARE(array.at(4).toDouble(), 1.); QCOMPARE(array.at(5).type(), QJsonValue::Array); QCOMPARE(array.at(5).toArray().size(), 0); QCOMPARE(array.at(6).type(), QJsonValue::Object); QCOMPARE(array.at(6).toObject().size(), 0); } { QByteArray json = "{ \"0\": null, \"1\": true, \"2\": false, \"3\": \"Foo\", \"4\": 1, \"5\": [], \"6\": {} }"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), true); QJsonObject object = doc.object(); QCOMPARE(object.size(), 7); QCOMPARE(object.value("0").type(), QJsonValue::Null); QCOMPARE(object.value("1").type(), QJsonValue::Bool); QCOMPARE(object.value("1").toBool(), true); QCOMPARE(object.value("2").type(), QJsonValue::Bool); QCOMPARE(object.value("2").toBool(), false); QCOMPARE(object.value("3").type(), QJsonValue::String); QCOMPARE(object.value("3").toString(), QLatin1String("Foo")); QCOMPARE(object.value("4").type(), QJsonValue::Double); QCOMPARE(object.value("4").toDouble(), 1.); QCOMPARE(object.value("5").type(), QJsonValue::Array); QCOMPARE(object.value("5").toArray().size(), 0); QCOMPARE(object.value("6").type(), QJsonValue::Object); QCOMPARE(object.value("6").toObject().size(), 0); } { QByteArray compactJson = "{\"Array\": [true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\": \"Value\",\"null\": null}"; QJsonDocument doc = QJsonDocument::fromJson(compactJson); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), true); QJsonObject object = doc.object(); QCOMPARE(object.size(), 3); QCOMPARE(object.value("\\Key\n").isString(), true); QCOMPARE(object.value("\\Key\n").toString(), QString("Value")); QCOMPARE(object.value("null").isNull(), true); QCOMPARE(object.value("Array").isArray(), true); QJsonArray array = object.value("Array").toArray(); QCOMPARE(array.size(), 5); QCOMPARE(array.at(0).isBool(), true); QCOMPARE(array.at(0).toBool(), true); QCOMPARE(array.at(1).isDouble(), true); QCOMPARE(array.at(1).toDouble(), 999.); QCOMPARE(array.at(2).isString(), true); QCOMPARE(array.at(2).toString(), QLatin1String("string")); QCOMPARE(array.at(3).isNull(), true); QCOMPARE(array.at(4).isString(), true); QCOMPARE(array.at(4).toString(), QLatin1String("\\\a\n\r\b\tabcABC\"")); } } void tst_QtJson::fromJsonErrors() { { QJsonParseError error; QByteArray json = "{\n \n\n"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::UnterminatedObject); QCOMPARE(error.offset, 8); } { QJsonParseError error; QByteArray json = "{\n \"key\" 10\n"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::MissingNameSeparator); QCOMPARE(error.offset, 13); } { QJsonParseError error; QByteArray json = "[\n \n\n"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::UnterminatedArray); QCOMPARE(error.offset, 8); } { QJsonParseError error; QByteArray json = "[\n 1, true\n\n"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::UnterminatedArray); QCOMPARE(error.offset, 14); } { QJsonParseError error; QByteArray json = "[\n 1 true\n\n"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::MissingValueSeparator); QCOMPARE(error.offset, 7); } { QJsonParseError error; QByteArray json = "[\n nul"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalValue); QCOMPARE(error.offset, 7); } { QJsonParseError error; QByteArray json = "[\n nulzz"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalValue); QCOMPARE(error.offset, 10); } { QJsonParseError error; QByteArray json = "[\n tru"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalValue); QCOMPARE(error.offset, 7); } { QJsonParseError error; QByteArray json = "[\n trud]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalValue); QCOMPARE(error.offset, 10); } { QJsonParseError error; QByteArray json = "[\n fal"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalValue); QCOMPARE(error.offset, 7); } { QJsonParseError error; QByteArray json = "[\n falsd]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalValue); QCOMPARE(error.offset, 11); } { QJsonParseError error; QByteArray json = "[\n 11111"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::TerminationByNumber); QCOMPARE(error.offset, 11); } { QJsonParseError error; QByteArray json = "[\n -1E10000]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalNumber); QCOMPARE(error.offset, 14); } { QJsonParseError error; QByteArray json = "[\n -1e-10000]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalNumber); QCOMPARE(error.offset, 15); } { QJsonParseError error; QByteArray json = "[\n \"\\u12\"]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence); QCOMPARE(error.offset, 11); } { QJsonParseError error; QByteArray json = "[\n \"foo" INVALID_UNICODE "bar\"]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalUTF8String); QCOMPARE(error.offset, 14); } { QJsonParseError error; QByteArray json = "[\n \""; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::UnterminatedString); QCOMPARE(error.offset, 8); } { QJsonParseError error; QByteArray json = "[\n \"c" UNICODE_DJE "a\\u12\"]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalEscapeSequence); QCOMPARE(error.offset, 15); } { QJsonParseError error; QByteArray json = "[\n \"c" UNICODE_DJE "a" INVALID_UNICODE "bar\"]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::IllegalUTF8String); QCOMPARE(error.offset, 15); } { QJsonParseError error; QByteArray json = "[\n \"c" UNICODE_DJE "a ]"; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isEmpty()); QCOMPARE(error.error, QJsonParseError::UnterminatedString); QCOMPARE(error.offset, 14); } } void tst_QtJson::fromBinary() { QFile file(":/test.json"); file.open(QFile::ReadOnly); QByteArray testJson = file.readAll(); QJsonDocument doc = QJsonDocument::fromJson(testJson); QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData()); QVERIFY(!outdoc.isNull()); QVERIFY(doc == outdoc); QFile bfile(":/test.bjson"); bfile.open(QFile::ReadOnly); QByteArray binary = bfile.readAll(); QJsonDocument bdoc = QJsonDocument::fromBinaryData(binary); QVERIFY(!bdoc.isNull()); QVERIFY(doc.toVariant() == bdoc.toVariant()); QVERIFY(doc == bdoc); } void tst_QtJson::toAndFromBinary_data() { QTest::addColumn("filename"); QTest::newRow("test.json") << (":/test.json"); QTest::newRow("test2.json") << (":/test2.json"); } void tst_QtJson::toAndFromBinary() { QFETCH(QString, filename); QFile file(filename); QVERIFY(file.open(QFile::ReadOnly)); QByteArray data = file.readAll(); QJsonDocument doc = QJsonDocument::fromJson(data); QVERIFY(!doc.isNull()); QJsonDocument outdoc = QJsonDocument::fromBinaryData(doc.toBinaryData()); QVERIFY(!outdoc.isNull()); QVERIFY(doc == outdoc); } void tst_QtJson::parseNumbers() { { // test number parsing struct Numbers { const char *str; int n; }; Numbers numbers [] = { { "0", 0 }, { "1", 1 }, { "10", 10 }, { "-1", -1 }, { "100000", 100000 }, { "-999", -999 } }; int size = sizeof(numbers)/sizeof(Numbers); for (int i = 0; i < size; ++i) { QByteArray json = "[ "; json += numbers[i].str; json += " ]"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 1); QJsonValue val = array.at(0); QCOMPARE(val.type(), QJsonValue::Double); QCOMPARE(val.toDouble(), (double)numbers[i].n); } } { // test number parsing struct Numbers { const char *str; double n; }; Numbers numbers [] = { { "0", 0 }, { "1", 1 }, { "10", 10 }, { "-1", -1 }, { "100000", 100000 }, { "-999", -999 }, { "1.1", 1.1 }, { "1e10", 1e10 }, { "-1.1", -1.1 }, { "-1e10", -1e10 }, { "-1E10", -1e10 }, { "1.1e10", 1.1e10 }, { "1.1e308", 1.1e308 }, { "-1.1e308", -1.1e308 }, { "1.1e-308", 1.1e-308 }, { "-1.1e-308", -1.1e-308 }, { "1.1e+308", 1.1e+308 }, { "-1.1e+308", -1.1e+308 }, { "1.e+308", 1.e+308 }, { "-1.e+308", -1.e+308 } }; int size = sizeof(numbers)/sizeof(Numbers); for (int i = 0; i < size; ++i) { QByteArray json = "[ "; json += numbers[i].str; json += " ]"; QJsonDocument doc = QJsonDocument::fromJson(json); #ifdef Q_OS_QNX if (0 == QString::compare(numbers[i].str, "1.1e-308")) QEXPECT_FAIL("", "See QTBUG-37066", Abort); #endif QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 1); QJsonValue val = array.at(0); QCOMPARE(val.type(), QJsonValue::Double); QCOMPARE(val.toDouble(), numbers[i].n); } } } void tst_QtJson::parseStrings() { const char *strings [] = { "Foo", "abc\\\"abc", "abc\\\\abc", "abc\\babc", "abc\\fabc", "abc\\nabc", "abc\\rabc", "abc\\tabc", "abc\\u0019abc" // "abc" UNICODE_DJE "abc", // UNICODE_NON_CHARACTER }; int size = sizeof(strings)/sizeof(const char *); for (int i = 0; i < size; ++i) { QByteArray json = "[\n \""; json += strings[i]; json += "\"\n]\n"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 1); QJsonValue val = array.at(0); QCOMPARE(val.type(), QJsonValue::String); QCOMPARE(doc.toJson(), json); } struct Pairs { const char *in; const char *out; }; Pairs pairs [] = { { "abc\\/abc", "abc/abc" }, // { "abc\\u0402abc", "abc" UNICODE_DJE "abc" }, { "abc\\u0065abc", "abceabc" } // { "abc\\uFFFFabc", "abc" UNICODE_NON_CHARACTER "abc" } }; size = sizeof(pairs)/sizeof(Pairs); for (int i = 0; i < size; ++i) { QByteArray json = "[\n \""; json += pairs[i].in; json += "\"\n]\n"; QByteArray out = "[\n \""; out += pairs[i].out; out += "\"\n]\n"; QJsonDocument doc = QJsonDocument::fromJson(json); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), true); QCOMPARE(doc.isObject(), false); QJsonArray array = doc.array(); QCOMPARE(array.size(), 1); QJsonValue val = array.at(0); QCOMPARE(val.type(), QJsonValue::String); QCOMPARE(doc.toJson(), out); } } void tst_QtJson::parseDuplicateKeys() { const char *json = "{ \"B\": true, \"A\": null, \"B\": false }"; QJsonDocument doc = QJsonDocument::fromJson(json); QCOMPARE(doc.isObject(), true); QJsonObject o = doc.object(); QCOMPARE(o.size(), 2); QJsonObject::const_iterator it = o.constBegin(); QCOMPARE(it.key(), QLatin1String("A")); QCOMPARE(it.value(), QJsonValue()); ++it; QCOMPARE(it.key(), QLatin1String("B")); QCOMPARE(it.value(), QJsonValue(false)); } void tst_QtJson::testParser() { QFile file(":/test.json"); file.open(QFile::ReadOnly); QByteArray testJson = file.readAll(); QJsonDocument doc = QJsonDocument::fromJson(testJson); QVERIFY(!doc.isEmpty()); } void tst_QtJson::compactArray() { QJsonArray array; array.append(QLatin1String("First Entry")); array.append(QLatin1String("Second Entry")); array.append(QLatin1String("Third Entry")); QJsonDocument doc(array); int s = doc.toBinaryData().size(); array.removeAt(1); doc.setArray(array); QVERIFY(s > doc.toBinaryData().size()); s = doc.toBinaryData().size(); QCOMPARE(doc.toJson(), QByteArray("[\n" " \"First Entry\",\n" " \"Third Entry\"\n" "]\n")); array.removeAt(0); doc.setArray(array); QVERIFY(s > doc.toBinaryData().size()); s = doc.toBinaryData().size(); QCOMPARE(doc.toJson(), QByteArray("[\n" " \"Third Entry\"\n" "]\n")); array.removeAt(0); doc.setArray(array); QVERIFY(s > doc.toBinaryData().size()); s = doc.toBinaryData().size(); QCOMPARE(doc.toJson(), QByteArray("[\n" "]\n")); } void tst_QtJson::compactObject() { QJsonObject object; object.insert(QLatin1String("Key1"), QLatin1String("First Entry")); object.insert(QLatin1String("Key2"), QLatin1String("Second Entry")); object.insert(QLatin1String("Key3"), QLatin1String("Third Entry")); QJsonDocument doc(object); int s = doc.toBinaryData().size(); object.remove(QLatin1String("Key2")); doc.setObject(object); QVERIFY(s > doc.toBinaryData().size()); s = doc.toBinaryData().size(); QCOMPARE(doc.toJson(), QByteArray("{\n" " \"Key1\": \"First Entry\",\n" " \"Key3\": \"Third Entry\"\n" "}\n")); object.remove(QLatin1String("Key1")); doc.setObject(object); QVERIFY(s > doc.toBinaryData().size()); s = doc.toBinaryData().size(); QCOMPARE(doc.toJson(), QByteArray("{\n" " \"Key3\": \"Third Entry\"\n" "}\n")); object.remove(QLatin1String("Key3")); doc.setObject(object); QVERIFY(s > doc.toBinaryData().size()); s = doc.toBinaryData().size(); QCOMPARE(doc.toJson(), QByteArray("{\n" "}\n")); } void tst_QtJson::validation() { // this basically tests that we don't crash on corrupt data QFile file(":/test.json"); QVERIFY(file.open(QFile::ReadOnly)); QByteArray testJson = file.readAll(); QVERIFY(!testJson.isEmpty()); QJsonDocument doc = QJsonDocument::fromJson(testJson); QVERIFY(!doc.isNull()); QByteArray binary = doc.toBinaryData(); // only test the first 1000 bytes. Testing the full file takes too long for (int i = 0; i < 1000; ++i) { QByteArray corrupted = binary; corrupted[i] = char(0xff); QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted); if (doc.isNull()) continue; QByteArray json = doc.toJson(); } QFile file2(":/test3.json"); file2.open(QFile::ReadOnly); testJson = file2.readAll(); QVERIFY(!testJson.isEmpty()); doc = QJsonDocument::fromJson(testJson); QVERIFY(!doc.isNull()); binary = doc.toBinaryData(); for (int i = 0; i < binary.size(); ++i) { QByteArray corrupted = binary; corrupted[i] = char(0xff); QJsonDocument doc = QJsonDocument::fromBinaryData(corrupted); if (doc.isNull()) continue; QByteArray json = doc.toJson(); corrupted = binary; corrupted[i] = 0x00; doc = QJsonDocument::fromBinaryData(corrupted); if (doc.isNull()) continue; json = doc.toJson(); } } void tst_QtJson::assignToDocument() { { const char *json = "{ \"inner\": { \"key\": true } }"; QJsonDocument doc = QJsonDocument::fromJson(json); QJsonObject o = doc.object(); QJsonValue inner = o.value("inner"); QJsonDocument innerDoc(inner.toObject()); QVERIFY(innerDoc != doc); QVERIFY(innerDoc.object() == inner.toObject()); } { const char *json = "[ [ true ] ]"; QJsonDocument doc = QJsonDocument::fromJson(json); QJsonArray a = doc.array(); QJsonValue inner = a.at(0); QJsonDocument innerDoc(inner.toArray()); QVERIFY(innerDoc != doc); QVERIFY(innerDoc.array() == inner.toArray()); } } void tst_QtJson::testDuplicateKeys() { QJsonObject obj; obj.insert(QLatin1String("foo"), QLatin1String("bar")); obj.insert(QLatin1String("foo"), QLatin1String("zap")); QCOMPARE(obj.size(), 1); QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("zap")); } void tst_QtJson::testCompaction() { // modify object enough times to trigger compactionCounter // and make sure the data is still valid QJsonObject obj; for (int i = 0; i < 33; ++i) { obj.remove(QLatin1String("foo")); obj.insert(QLatin1String("foo"), QLatin1String("bar")); } QCOMPARE(obj.size(), 1); QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("bar")); QJsonDocument doc = QJsonDocument::fromBinaryData(QJsonDocument(obj).toBinaryData()); QVERIFY(!doc.isNull()); QVERIFY(!doc.isEmpty()); QCOMPARE(doc.isArray(), false); QCOMPARE(doc.isObject(), true); QVERIFY(doc.object() == obj); } void tst_QtJson::testDebugStream() { { // QJsonObject QJsonObject object; QTest::ignoreMessage(QtDebugMsg, "QJsonObject() "); qDebug() << object; object.insert(QLatin1String("foo"), QLatin1String("bar")); QTest::ignoreMessage(QtDebugMsg, "QJsonObject({\"foo\":\"bar\"}) "); qDebug() << object; } { // QJsonArray QJsonArray array; QTest::ignoreMessage(QtDebugMsg, "QJsonArray() "); qDebug() << array; array.append(1); array.append(QLatin1String("foo")); QTest::ignoreMessage(QtDebugMsg, "QJsonArray([1,\"foo\"]) "); qDebug() << array; } { // QJsonDocument QJsonDocument doc; QTest::ignoreMessage(QtDebugMsg, "QJsonDocument() "); qDebug() << doc; QJsonObject object; object.insert(QLatin1String("foo"), QLatin1String("bar")); doc.setObject(object); QTest::ignoreMessage(QtDebugMsg, "QJsonDocument({\"foo\":\"bar\"}) "); qDebug() << doc; QJsonArray array; array.append(1); array.append(QLatin1String("foo")); QTest::ignoreMessage(QtDebugMsg, "QJsonDocument([1,\"foo\"]) "); doc.setArray(array); qDebug() << doc; } { // QJsonValue QJsonValue value; QTest::ignoreMessage(QtDebugMsg, "QJsonValue(null) "); qDebug() << value; value = QJsonValue(true); // bool QTest::ignoreMessage(QtDebugMsg, "QJsonValue(bool, true) "); qDebug() << value; value = QJsonValue((double)4.2); // double QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 4.2) "); qDebug() << value; value = QJsonValue((int)42); // int QTest::ignoreMessage(QtDebugMsg, "QJsonValue(double, 42) "); qDebug() << value; value = QJsonValue(QLatin1String("foo")); // string QTest::ignoreMessage(QtDebugMsg, "QJsonValue(string, \"foo\") "); qDebug() << value; QJsonArray array; array.append(1); array.append(QLatin1String("foo")); value = QJsonValue(array); // array QTest::ignoreMessage(QtDebugMsg, "QJsonValue(array, QJsonArray([1,\"foo\"]) ) "); qDebug() << value; QJsonObject object; object.insert(QLatin1String("foo"), QLatin1String("bar")); value = QJsonValue(object); // object QTest::ignoreMessage(QtDebugMsg, "QJsonValue(object, QJsonObject({\"foo\":\"bar\"}) ) "); qDebug() << value; } } void tst_QtJson::testCompactionError() { QJsonObject schemaObject; schemaObject.insert("_Type", QLatin1String("_SchemaType")); schemaObject.insert("name", QLatin1String("Address")); schemaObject.insert("schema", QJsonObject()); { QJsonObject content(schemaObject); QJsonDocument doc(content); QVERIFY(!doc.isNull()); QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex(); schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size())); } QJsonObject schema; schema.insert("streetNumber", schema.value("number").toObject()); schemaObject.insert("schema", schema); { QJsonObject content(schemaObject); content.remove("_Uuid"); content.remove("_Version"); QJsonDocument doc(content); QVERIFY(!doc.isNull()); QByteArray hash = QCryptographicHash::hash(doc.toBinaryData(), QCryptographicHash::Md5).toHex(); schemaObject.insert("_Version", QString::fromLatin1(hash.constData(), hash.size())); } } void tst_QtJson::parseUnicodeEscapes() { const QByteArray json = "[ \"A\\u00e4\\u00C4\" ]"; QJsonDocument doc = QJsonDocument::fromJson(json); QJsonArray array = doc.array(); QString result = QLatin1String("A"); result += QChar(0xe4); result += QChar(0xc4); QCOMPARE(array.first().toString(), result); } void tst_QtJson::assignObjects() { const char *json = "[ { \"Key\": 1 }, { \"Key\": 2 } ]"; QJsonDocument doc = QJsonDocument::fromJson(json); QJsonArray array = doc.array(); QJsonObject object = array.at(0).toObject(); QCOMPARE(object.value("Key").toDouble(), 1.); object = array.at(1).toObject(); QCOMPARE(object.value("Key").toDouble(), 2.); } void tst_QtJson::assignArrays() { const char *json = "[ [ 1 ], [ 2 ] ]"; QJsonDocument doc = QJsonDocument::fromJson(json); QJsonArray array = doc.array(); QJsonArray inner = array.at(0).toArray() ; QCOMPARE(inner.at(0).toDouble(), 1.); inner= array.at(1).toArray(); QCOMPARE(inner.at(0).toDouble(), 2.); } void tst_QtJson::testTrailingComma() { const char *jsons[] = { "{ \"Key\": 1, }", "[ { \"Key\": 1 }, ]" }; for (unsigned i = 0; i < sizeof(jsons)/sizeof(jsons[0]); ++i) { QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(jsons[i], &error); QCOMPARE(error.error, QJsonParseError::MissingObject); } } void tst_QtJson::testDetachBug() { QJsonObject dynamic; QJsonObject embedded; QJsonObject local; embedded.insert("Key1", QString("Value1")); embedded.insert("Key2", QString("Value2")); dynamic.insert(QLatin1String("Bogus"), QString("bogusValue")); dynamic.insert("embedded", embedded); local = dynamic.value("embedded").toObject(); dynamic.remove("embedded"); QCOMPARE(local.keys().size(),2); local.remove("Key1"); local.remove("Key2"); QCOMPARE(local.keys().size(), 0); local.insert("Key1", QString("anotherValue")); QCOMPARE(local.keys().size(), 1); } void tst_QtJson::valueEquals() { QVERIFY(QJsonValue() == QJsonValue()); QVERIFY(QJsonValue() != QJsonValue(QJsonValue::Undefined)); QVERIFY(QJsonValue() != QJsonValue(true)); QVERIFY(QJsonValue() != QJsonValue(1.)); QVERIFY(QJsonValue() != QJsonValue(QJsonArray())); QVERIFY(QJsonValue() != QJsonValue(QJsonObject())); QVERIFY(QJsonValue(true) == QJsonValue(true)); QVERIFY(QJsonValue(true) != QJsonValue(false)); QVERIFY(QJsonValue(true) != QJsonValue(QJsonValue::Undefined)); QVERIFY(QJsonValue(true) != QJsonValue()); QVERIFY(QJsonValue(true) != QJsonValue(1.)); QVERIFY(QJsonValue(true) != QJsonValue(QJsonArray())); QVERIFY(QJsonValue(true) != QJsonValue(QJsonObject())); QVERIFY(QJsonValue(1) == QJsonValue(1)); QVERIFY(QJsonValue(1) != QJsonValue(2)); QVERIFY(QJsonValue(1) == QJsonValue(1.)); QVERIFY(QJsonValue(1) != QJsonValue(1.1)); QVERIFY(QJsonValue(1) != QJsonValue(QJsonValue::Undefined)); QVERIFY(QJsonValue(1) != QJsonValue()); QVERIFY(QJsonValue(1) != QJsonValue(true)); QVERIFY(QJsonValue(1) != QJsonValue(QJsonArray())); QVERIFY(QJsonValue(1) != QJsonValue(QJsonObject())); QVERIFY(QJsonValue(1.) == QJsonValue(1.)); QVERIFY(QJsonValue(1.) != QJsonValue(2.)); QVERIFY(QJsonValue(1.) != QJsonValue(QJsonValue::Undefined)); QVERIFY(QJsonValue(1.) != QJsonValue()); QVERIFY(QJsonValue(1.) != QJsonValue(true)); QVERIFY(QJsonValue(1.) != QJsonValue(QJsonArray())); QVERIFY(QJsonValue(1.) != QJsonValue(QJsonObject())); QVERIFY(QJsonValue(QJsonArray()) == QJsonValue(QJsonArray())); QJsonArray nonEmptyArray; nonEmptyArray.append(true); QVERIFY(QJsonValue(QJsonArray()) != nonEmptyArray); QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonValue::Undefined)); QVERIFY(QJsonValue(QJsonArray()) != QJsonValue()); QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(true)); QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(1.)); QVERIFY(QJsonValue(QJsonArray()) != QJsonValue(QJsonObject())); QVERIFY(QJsonValue(QJsonObject()) == QJsonValue(QJsonObject())); QJsonObject nonEmptyObject; nonEmptyObject.insert("Key", true); QVERIFY(QJsonValue(QJsonObject()) != nonEmptyObject); QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonValue::Undefined)); QVERIFY(QJsonValue(QJsonObject()) != QJsonValue()); QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(true)); QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(1.)); QVERIFY(QJsonValue(QJsonObject()) != QJsonValue(QJsonArray())); QVERIFY(QJsonValue("foo") == QJsonValue(QLatin1String("foo"))); QVERIFY(QJsonValue("foo") == QJsonValue(QString("foo"))); QVERIFY(QJsonValue("\x66\x6f\x6f") == QJsonValue(QString("foo"))); QVERIFY(QJsonValue("\x62\x61\x72") == QJsonValue("bar")); /* QVERIFY(QJsonValue(UNICODE_NON_CHARACTER) == QJsonValue(QString(UNICODE_NON_CHARACTER))); QVERIFY(QJsonValue(UNICODE_DJE) == QJsonValue(QString(UNICODE_DJE))); QVERIFY(QJsonValue("\xc3\xa9") == QJsonValue(QString("\xc3\xa9"))); */ } void tst_QtJson::objectEquals_data() { QTest::addColumn("left"); QTest::addColumn("right"); QTest::addColumn("result"); QTest::newRow("two defaults") << QJsonObject() << QJsonObject() << true; QJsonObject object1; object1.insert("property", 1); QJsonObject object2; object2["property"] = 1; QJsonObject object3; object3.insert("property1", 1); object3.insert("property2", 2); QTest::newRow("the same object (1 vs 2)") << object1 << object2 << true; QTest::newRow("the same object (3 vs 3)") << object3 << object3 << true; QTest::newRow("different objects (2 vs 3)") << object2 << object3 << false; QTest::newRow("object vs default") << object1 << QJsonObject() << false; QJsonObject empty; empty.insert("property", 1); empty.take("property"); QTest::newRow("default vs empty") << QJsonObject() << empty << true; QTest::newRow("empty vs empty") << empty << empty << true; QTest::newRow("object vs empty") << object1 << empty << false; QJsonObject referencedEmpty; referencedEmpty["undefined"]; QTest::newRow("referenced empty vs referenced empty") << referencedEmpty << referencedEmpty << true; QTest::newRow("referenced empty vs object") << referencedEmpty << object1 << false; QJsonObject referencedObject1; referencedObject1.insert("property", 1); referencedObject1["undefined"]; QJsonObject referencedObject2; referencedObject2.insert("property", 1); referencedObject2["aaaaaaaaa"]; // earlier then "property" referencedObject2["zzzzzzzzz"]; // after "property" QTest::newRow("referenced object vs default") << referencedObject1 << QJsonObject() << false; QTest::newRow("referenced object vs referenced object") << referencedObject1 << referencedObject1 << true; QTest::newRow("referenced object vs object (different)") << referencedObject1 << object3 << false; } void tst_QtJson::objectEquals() { QFETCH(QJsonObject, left); QFETCH(QJsonObject, right); QFETCH(bool, result); QCOMPARE(left == right, result); QCOMPARE(right == left, result); // invariants checks QCOMPARE(left, left); QCOMPARE(right, right); QCOMPARE(left != right, !result); QCOMPARE(right != left, !result); // The same but from QJsonValue perspective QCOMPARE(QJsonValue(left) == QJsonValue(right), result); QCOMPARE(QJsonValue(left) != QJsonValue(right), !result); QCOMPARE(QJsonValue(right) == QJsonValue(left), result); QCOMPARE(QJsonValue(right) != QJsonValue(left), !result); } void tst_QtJson::arrayEquals_data() { QTest::addColumn("left"); QTest::addColumn("right"); QTest::addColumn("result"); QTest::newRow("two defaults") << QJsonArray() << QJsonArray() << true; QJsonArray array1; array1.append(1); QJsonArray array2; array2.append(2111); array2[0] = 1; QJsonArray array3; array3.insert(0, 1); array3.insert(1, 2); QTest::newRow("the same array (1 vs 2)") << array1 << array2 << true; QTest::newRow("the same array (3 vs 3)") << array3 << array3 << true; QTest::newRow("different arrays (2 vs 3)") << array2 << array3 << false; QTest::newRow("array vs default") << array1 << QJsonArray() << false; QJsonArray empty; empty.append(1); empty.takeAt(0); QTest::newRow("default vs empty") << QJsonArray() << empty << true; QTest::newRow("empty vs default") << empty << QJsonArray() << true; QTest::newRow("empty vs empty") << empty << empty << true; QTest::newRow("array vs empty") << array1 << empty << false; } void tst_QtJson::arrayEquals() { QFETCH(QJsonArray, left); QFETCH(QJsonArray, right); QFETCH(bool, result); QCOMPARE(left == right, result); QCOMPARE(right == left, result); // invariants checks QCOMPARE(left, left); QCOMPARE(right, right); QCOMPARE(left != right, !result); QCOMPARE(right != left, !result); // The same but from QJsonValue perspective QCOMPARE(QJsonValue(left) == QJsonValue(right), result); QCOMPARE(QJsonValue(left) != QJsonValue(right), !result); QCOMPARE(QJsonValue(right) == QJsonValue(left), result); QCOMPARE(QJsonValue(right) != QJsonValue(left), !result); } void tst_QtJson::bom() { QFile file(":/bom.json"); file.open(QFile::ReadOnly); QByteArray json = file.readAll(); // Import json document into a QJsonDocument QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(!doc.isNull()); QVERIFY(error.error == QJsonParseError::NoError); } void tst_QtJson::nesting() { // check that we abort parsing too deeply nested json documents. // this is to make sure we don't crash because the parser exhausts the // stack. const char *array_data = "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]" "]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"; QByteArray json(array_data); QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(!doc.isNull()); QVERIFY(error.error == QJsonParseError::NoError); json.prepend("["); json.append("]"); doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isNull()); QVERIFY(error.error == QJsonParseError::DeepNesting); json = QByteArray("true "); for (int i = 0; i < 1024; ++i) { json.prepend("{ \"Key\": "); json.append(" }"); } doc = QJsonDocument::fromJson(json, &error); QVERIFY(!doc.isNull()); QVERIFY(error.error == QJsonParseError::NoError); json.prepend("["); json.append("]"); doc = QJsonDocument::fromJson(json, &error); QVERIFY(doc.isNull()); QVERIFY(error.error == QJsonParseError::DeepNesting); } void tst_QtJson::longStrings() { // test around 15 and 16 bit boundaries, as these are limits // in the data structures (for Latin1String in qjson_p.h) QString s(0x7ff0, 'a'); for (int i = 0x7ff0; i < 0x8010; i++) { s.append("c"); QMap map; map["key"] = s; /* Create a QJsonDocument from the QMap ... */ QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map)); /* ... and a QByteArray from the QJsonDocument */ QByteArray a1 = d1.toJson(); /* Create a QJsonDocument from the QByteArray ... */ QJsonDocument d2 = QJsonDocument::fromJson(a1); /* ... and a QByteArray from the QJsonDocument */ QByteArray a2 = d2.toJson(); QVERIFY(a1 == a2); } s = QString(0xfff0, 'a'); for (int i = 0xfff0; i < 0x10010; i++) { s.append("c"); QMap map; map["key"] = s; /* Create a QJsonDocument from the QMap ... */ QJsonDocument d1 = QJsonDocument::fromVariant(QVariant(map)); /* ... and a QByteArray from the QJsonDocument */ QByteArray a1 = d1.toJson(); /* Create a QJsonDocument from the QByteArray ... */ QJsonDocument d2 = QJsonDocument::fromJson(a1); /* ... and a QByteArray from the QJsonDocument */ QByteArray a2 = d2.toJson(); QVERIFY(a1 == a2); } } void tst_QtJson::testJsonValueRefDefault() { QJsonObject empty; QCOMPARE(empty["n/a"].toString(), QString()); QCOMPARE(empty["n/a"].toString("default"), QLatin1String("default")); QCOMPARE(empty["n/a"].toBool(), false); QCOMPARE(empty["n/a"].toBool(true), true); QCOMPARE(empty["n/a"].toInt(), 0); QCOMPARE(empty["n/a"].toInt(42), 42); QCOMPARE(empty["n/a"].toDouble(), 0.0); QCOMPARE(empty["n/a"].toDouble(42.0), 42.0); } void tst_QtJson::arrayInitializerList() { #ifndef Q_COMPILER_INITIALIZER_LISTS QSKIP("initializer_list is enabled only with c++11 support", SkipSingle); #else QVERIFY(QJsonArray{}.isEmpty()); QCOMPARE(QJsonArray{"one"}.count(), 1); QCOMPARE(QJsonArray{1}.count(), 1); { QJsonArray a{1.3, "hello", 0}; QCOMPARE(QJsonValue(a[0]), QJsonValue(1.3)); QCOMPARE(QJsonValue(a[1]), QJsonValue("hello")); QCOMPARE(QJsonValue(a[2]), QJsonValue(0)); QCOMPARE(a.count(), 3); } { QJsonObject o; o["property"] = 1; QJsonArray a1 {o}; QCOMPARE(a1.count(), 1); QCOMPARE(a1[0].toObject(), o); QJsonArray a2 {o, 23}; QCOMPARE(a2.count(), 2); QCOMPARE(a2[0].toObject(), o); QCOMPARE(QJsonValue(a2[1]), QJsonValue(23)); QJsonArray a3 { a1, o, a2 }; QCOMPARE(QJsonValue(a3[0]), QJsonValue(a1)); QCOMPARE(QJsonValue(a3[1]), QJsonValue(o)); QCOMPARE(QJsonValue(a3[2]), QJsonValue(a2)); QJsonArray a4 { 1, QJsonArray{1,2,3}, QJsonArray{"hello", 2}, QJsonObject{{"one", 1}} }; QCOMPARE(a4.count(), 4); QCOMPARE(QJsonValue(a4[0]), QJsonValue(1)); { QJsonArray a41 = a4[1].toArray(); QJsonArray a42 = a4[2].toArray(); QJsonObject a43 = a4[3].toObject(); QCOMPARE(a41.count(), 3); QCOMPARE(a42.count(), 2); QCOMPARE(a43.count(), 1); QCOMPARE(QJsonValue(a41[2]), QJsonValue(3)); QCOMPARE(QJsonValue(a42[1]), QJsonValue(2)); QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1)); } } #endif } void tst_QtJson::objectInitializerList() { #ifndef Q_COMPILER_INITIALIZER_LISTS QSKIP("initializer_list is enabled only with c++11 support", SkipSingle); #else QVERIFY(QJsonObject{}.isEmpty()); { // one property QJsonObject one {{"one", 1}}; QCOMPARE(one.count(), 1); QVERIFY(one.contains("one")); QCOMPARE(QJsonValue(one["one"]), QJsonValue(1)); } { // two properties QJsonObject two { {"one", 1}, {"two", 2} }; QCOMPARE(two.count(), 2); QVERIFY(two.contains("one")); QVERIFY(two.contains("two")); QCOMPARE(QJsonValue(two["one"]), QJsonValue(1)); QCOMPARE(QJsonValue(two["two"]), QJsonValue(2)); } { // nested object QJsonObject object{{"nested", QJsonObject{{"innerProperty", 2}}}}; QCOMPARE(object.count(), 1); QVERIFY(object.contains("nested")); QVERIFY(object["nested"].isObject()); QJsonObject nested = object["nested"].toObject(); QCOMPARE(QJsonValue(nested["innerProperty"]), QJsonValue(2)); } { // nested array QJsonObject object{{"nested", QJsonArray{"innerValue", 2.1, "bum cyk cyk"}}}; QCOMPARE(object.count(), 1); QVERIFY(object.contains("nested")); QVERIFY(object["nested"].isArray()); QJsonArray nested = object["nested"].toArray(); QCOMPARE(nested.count(), 3); QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue")); QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1)); } #endif } void tst_QtJson::unicodeKeys() { QByteArray json = "{" "\"x\\u2090_1\": \"hello_1\"," "\"y\\u2090_2\": \"hello_2\"," "\"T\\u2090_3\": \"hello_3\"," "\"xyz_4\": \"hello_4\"," "\"abc_5\": \"hello_5\"" "}"; QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(json, &error); QVERIFY(error.error == QJsonParseError::NoError); QJsonObject o = doc.object(); QCOMPARE(o.keys().size(), 5); Q_FOREACH (const QString &key, o.keys()) { QString suffix = key.mid(key.indexOf(QLatin1Char('_'))); QCOMPARE(o[key].toString(), QString("hello") + suffix); } } void tst_QtJson::garbageAtEnd() { QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson("{},", &error); QVERIFY(error.error == QJsonParseError::GarbageAtEnd); QVERIFY(error.offset == 2); QVERIFY(doc.isEmpty()); doc = QJsonDocument::fromJson("{} ", &error); QVERIFY(error.error == QJsonParseError::NoError); QVERIFY(!doc.isEmpty()); } QTEST_MAIN(tst_QtJson) #include "tst_qtjson.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/json/tst_qtjson.qrc ================================================ test.bjson test.json test2.json test3.json bom.json ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpclient/qjsonrpchttpclient.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) include($${DEPTH}/src/http-parser/http-parser.pri) TARGET = tst_qjsonrpchttpclient HEADERS += \ testhttpserver.h SOURCES += \ testhttpserver.cpp \ tst_qjsonrpchttpclient.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpclient/testhttpserver.cpp ================================================ #include #include #include #include "http_parser.h" #include "testhttpserver.h" class TestHttpServerPrivate { public: TestHttpServerPrivate(); virtual ~TestHttpServerPrivate(); // http parsing http_parser *httpParser; http_parser_settings httpParserSettings; QByteArray currentHeaderField; QByteArray currentHeaderValue; static int onMessageBegin(http_parser *parser); static int onUrl(http_parser *parser, const char *at, size_t length); static int onHeaderField(http_parser *parser, const char *at, size_t length); static int onHeaderValue(http_parser *parser, const char *at, size_t length); static int onHeadersComplete(http_parser *parser); static int onBody(http_parser *parser, const char *at, size_t length); static int onMessageComplete(http_parser *parser); // private slots void _q_socketReadyRead(); void _q_socketError(QAbstractSocket::SocketError error); void _q_handleRequest(); TestHttpServerRequestHandler *requestHandler; QPointer socket; QNetworkAccessManager::Operation operation; QNetworkRequest request; QByteArray body; }; TestHttpServerPrivate::TestHttpServerPrivate() : httpParser(0), requestHandler(0) { // initialize request parser httpParser = (http_parser*)malloc(sizeof(http_parser)); http_parser_init(httpParser, HTTP_REQUEST); httpParserSettings.on_message_begin = onMessageBegin; httpParserSettings.on_url = onUrl; httpParserSettings.on_header_field = onHeaderField; httpParserSettings.on_header_value = onHeaderValue; httpParserSettings.on_headers_complete = onHeadersComplete; httpParserSettings.on_body = onBody; httpParserSettings.on_message_complete = onMessageComplete; httpParser->data = this; } TestHttpServerPrivate::~TestHttpServerPrivate() { free(httpParser); } int TestHttpServerPrivate::onMessageBegin(http_parser *parser) { TestHttpServerPrivate *priv = (TestHttpServerPrivate *)parser->data; priv->request = QNetworkRequest(); priv->currentHeaderField.clear(); priv->currentHeaderValue.clear(); priv->body.clear(); return 0; } int TestHttpServerPrivate::onUrl(http_parser *parser, const char *at, size_t length) { TestHttpServerPrivate *priv = (TestHttpServerPrivate *)parser->data; QUrl requestUrl = priv->request.url(); requestUrl.setPath(QByteArray(at, length)); priv->request.setUrl(requestUrl); return 0; } int TestHttpServerPrivate::onHeaderField(http_parser *parser, const char *at, size_t length) { TestHttpServerPrivate *priv = (TestHttpServerPrivate *)parser->data; if (!priv->currentHeaderField.isEmpty() && !priv->currentHeaderValue.isEmpty()) { priv->request.setRawHeader(priv->currentHeaderField, priv->currentHeaderValue); priv->currentHeaderField.clear(); priv->currentHeaderValue.clear(); } priv->currentHeaderField.append(at, length); return 0; } int TestHttpServerPrivate::onHeaderValue(http_parser *parser, const char *at, size_t length) { TestHttpServerPrivate *priv = (TestHttpServerPrivate *)parser->data; priv->currentHeaderValue.append(at, length); return 0; } int TestHttpServerPrivate::onHeadersComplete(http_parser *parser) { Q_UNUSED(parser); return 0; } int TestHttpServerPrivate::onBody(http_parser *parser, const char *at, size_t length) { TestHttpServerPrivate *priv = (TestHttpServerPrivate *)parser->data; priv->body.append(at, length); return 0; } int TestHttpServerPrivate::onMessageComplete(http_parser *parser) { TestHttpServerPrivate *priv = (TestHttpServerPrivate *)parser->data; switch (parser->method) { case HTTP_HEAD: priv->operation = QNetworkAccessManager::HeadOperation; break; case HTTP_GET: priv->operation = QNetworkAccessManager::GetOperation; break; case HTTP_PUT: priv->operation = QNetworkAccessManager::PutOperation; break; case HTTP_POST: priv->operation = QNetworkAccessManager::PostOperation; break; case HTTP_DELETE: priv->operation = QNetworkAccessManager::DeleteOperation; break; default: priv->operation = QNetworkAccessManager::CustomOperation; break; } priv->_q_handleRequest(); return 0; } void TestHttpServerPrivate::_q_socketReadyRead() { Q_ASSERT(httpParser); Q_ASSERT(!socket.isNull()); QByteArray buffer = socket->readAll(); http_parser_execute(httpParser, &httpParserSettings, buffer.constData(), buffer.size()); } void TestHttpServerPrivate::_q_socketError(QAbstractSocket::SocketError error) { Q_UNUSED(error) Q_ASSERT(!socket.isNull()); socket->close(); socket->deleteLater(); } void TestHttpServerPrivate::_q_handleRequest() { if (!requestHandler) { qDebug() << Q_FUNC_INFO << "no request handler installed"; return; } QByteArray response = requestHandler->handleRequest(operation, request, body); QCOMPARE(socket->write(response), (qint64)response.size()); } class TestHttpServerSimpleRequestHandler : public TestHttpServerRequestHandler { public: explicit TestHttpServerSimpleRequestHandler(const QByteArray &d) : data(d) { } virtual QByteArray handleRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &body) { Q_UNUSED(operation); Q_UNUSED(request); Q_UNUSED(body); return data; } private: QByteArray data; }; TestHttpServer::TestHttpServer(QObject *parent) : QTcpServer(parent), d_ptr(new TestHttpServerPrivate) { } TestHttpServer::TestHttpServer(TestHttpServerRequestHandler *requestHandler, QObject *parent) : QTcpServer(parent), d_ptr(new TestHttpServerPrivate) { d_func()->requestHandler = requestHandler; } TestHttpServer::~TestHttpServer() { Q_D(TestHttpServer); if (d->requestHandler) { delete d->requestHandler; d->requestHandler = 0; } } TestHttpServerRequestHandler *TestHttpServer::requestHandler() const { Q_D(const TestHttpServer); return d->requestHandler; } void TestHttpServer::setRequestHandler(TestHttpServerRequestHandler *requestHandler) { Q_D(TestHttpServer); if (d->requestHandler) { delete d->requestHandler; d->requestHandler = 0; } d->requestHandler = requestHandler; } void TestHttpServer::setResponseData(const QByteArray &data) { setRequestHandler(new TestHttpServerSimpleRequestHandler(data)); } #if QT_VERSION >= 0x050000 void TestHttpServer::incomingConnection(qintptr socketDescriptor) #else void TestHttpServer::incomingConnection(int socketDescriptor) #endif { Q_D(TestHttpServer); d->socket = new QTcpSocket(this); QVERIFY(d->socket->setSocketDescriptor(socketDescriptor)); connect(d->socket.data(), SIGNAL(readyRead()), this, SLOT(_q_socketReadyRead())); connect(d->socket.data(), SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(_q_socketError(QAbstractSocket::SocketError))); } #include "moc_testhttpserver.cpp" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpclient/testhttpserver.h ================================================ #ifndef TESTHTTPSERVER_H #define TESTHTTPSERVER_H #include #include #include class TestHttpServerRequestHandler { public: virtual ~TestHttpServerRequestHandler() {} virtual QByteArray handleRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &body) = 0; }; class TestHttpServerPrivate; class TestHttpServer : public QTcpServer { Q_OBJECT public: explicit TestHttpServer(QObject *parent = 0); TestHttpServer(TestHttpServerRequestHandler *requestHandler, QObject *parent = 0); virtual ~TestHttpServer(); TestHttpServerRequestHandler *requestHandler() const; void setRequestHandler(TestHttpServerRequestHandler *requestHandler); void setResponseData(const QByteArray &data); protected: #if QT_VERSION >= 0x050000 virtual void incomingConnection(qintptr socketDescriptor); #else virtual void incomingConnection(int socketDescriptor); #endif private: Q_DISABLE_COPY(TestHttpServer) Q_DECLARE_PRIVATE(TestHttpServer) QScopedPointer d_ptr; Q_PRIVATE_SLOT(d_func(), void _q_socketReadyRead()) Q_PRIVATE_SLOT(d_func(), void _q_socketError(QAbstractSocket::SocketError)) }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpclient/tst_qjsonrpchttpclient.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include "testhttpserver.h" #include "qjsonrpcmessage.h" #include "qjsonrpchttpclient.h" #if QT_VERSION < 0x050000 template struct QScopedPointerObjectDeleteLater { static inline void cleanup(T *pointer) { if (pointer) pointer->deleteLater(); } }; class QObject; typedef QScopedPointerObjectDeleteLater QScopedPointerDeleteLater; #endif class TestQJsonRpcHttpClient : public QObject { Q_OBJECT private Q_SLOTS: void init(); void properties(); void basicRequest(); void invalidResponse_data(); void invalidResponse(); void connectionRefused(); void requestTimedOut(); void issue23_doubleFinishedEmitted(); }; void TestQJsonRpcHttpClient::init() { } class JsonRpcRequestHandler : public TestHttpServerRequestHandler { public: virtual QByteArray handleRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &body) { Q_UNUSED(operation) Q_UNUSED(request) QJsonRpcMessage requestMessage = QJsonRpcMessage::fromJson(body); QJsonRpcMessage responseMessage = requestMessage.createResponse(QLatin1String("some response data")); QByteArray responseData = responseMessage.toJson(); QByteArray reply; reply += "HTTP/1.0 200\r\n"; reply += "Content-Type: application/json\r\n"; reply += "Content-length: " + QByteArray::number(responseData.size()) + "\r\n"; reply += "\r\n"; reply += responseData; return reply; } }; void TestQJsonRpcHttpClient::properties() { QJsonRpcHttpClient client; client.setEndPoint("testing"); QCOMPARE(client.endPoint(), QUrl("http://testing")); client.setEndPoint(QUrl("http://www.google.com")); QCOMPARE(client.endPoint(), QUrl("http://www.google.com")); QNetworkAccessManager manager; QJsonRpcHttpClient withManager(&manager); QCOMPARE(withManager.networkAccessManager(), &manager); } void TestQJsonRpcHttpClient::basicRequest() { TestHttpServer server; server.setRequestHandler(new JsonRpcRequestHandler); QVERIFY(server.listen()); QString url = QString("%1://localhost:%2").arg("http").arg(server.serverPort()); QJsonRpcHttpClient client(url); QJsonRpcMessage message = QJsonRpcMessage::createRequest("testMethod"); QJsonRpcMessage response = client.sendMessageBlocking(message); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toString(), QLatin1String("some response data")); } void TestQJsonRpcHttpClient::invalidResponse_data() { QTest::addColumn("responseData"); QTest::addColumn("expectedError"); QTest::newRow("empty-data") << QByteArray("HTTP/1.0 200\r\nContent-Type: application/json\r\nContent-length: 0\r\n\r\n") << QJsonRpc::ParseError; QTest::newRow("invalid-json") << QByteArray("HTTP/1.0 200\r\nContent-Type: application/json\r\nContent-length: 2\r\n\r\n{}") << QJsonRpc::InternalError; } void TestQJsonRpcHttpClient::invalidResponse() { QFETCH(QByteArray, responseData); QFETCH(QJsonRpc::ErrorCode, expectedError); TestHttpServer server; server.setResponseData(responseData); QVERIFY(server.listen()); QString url = QString("%1://localhost:%2").arg("http").arg(server.serverPort()); QJsonRpcHttpClient client(url); QJsonRpcMessage message = QJsonRpcMessage::createRequest("someMethod"); QJsonRpcMessage response = client.sendMessageBlocking(message); QCOMPARE(response.type(), QJsonRpcMessage::Error); QCOMPARE(response.errorCode(), int(expectedError)); } void TestQJsonRpcHttpClient::connectionRefused() { QString url = QString("%1://localhost:%2").arg("http").arg(9191); QJsonRpcHttpClient client(url); QJsonRpcMessage message = QJsonRpcMessage::createRequest("someMethod"); QJsonRpcMessage response = client.sendMessageBlocking(message); QCOMPARE(response.type(), QJsonRpcMessage::Error); QCOMPARE(response.errorCode(), int(QJsonRpc::InternalError)); } void TestQJsonRpcHttpClient::requestTimedOut() { TestHttpServer server; server.setResponseData("HTTP/1.0 200\r\n\r\n"); QVERIFY(server.listen()); QString url = QString("%1://localhost:%2").arg("http").arg(server.serverPort()); QJsonRpcHttpClient client(url); QJsonRpcMessage message = QJsonRpcMessage::createRequest("someMethod"); QJsonRpcMessage response = client.sendMessageBlocking(message, 1); QCOMPARE(response.type(), QJsonRpcMessage::Error); QCOMPARE(response.errorCode(), int(QJsonRpc::TimeoutError)); } void TestQJsonRpcHttpClient::issue23_doubleFinishedEmitted() { QString url = QString("%1://localhost:%2").arg("http").arg(9191); QJsonRpcHttpClient client(url); QJsonRpcMessage message = QJsonRpcMessage::createRequest("someMethod"); QJsonRpcServiceReply *reply = client.sendMessage(message); QScopedPointer replyPtr(reply); QSignalSpy spy(reply, SIGNAL(finished())); QEventLoop responseLoop; connect(reply, SIGNAL(finished()), &responseLoop, SLOT(quit())); QTimer::singleShot(10000, &responseLoop, SLOT(quit())); responseLoop.exec(); QJsonRpcMessage response = reply->response(); QCOMPARE(response.type(), QJsonRpcMessage::Error); QCOMPARE(response.errorCode(), int(QJsonRpc::InternalError)); QCOMPARE(spy.size(), 1); } QTEST_MAIN(TestQJsonRpcHttpClient) #include "tst_qjsonrpchttpclient.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/certificates.qrc ================================================ certs/aspiriniks.ca.crt certs/fake-login.live.com.pem certs/fake-login.live.com.key certs/fluke.key certs/fluke.cert certs/qt-test-server-cacert.pem ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/certs/aspiriniks.ca.crt ================================================ -----BEGIN CERTIFICATE----- MIIDnDCCAoQCCQDV3otC4hs2KTANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMC Tk8xDTALBgNVBAgTBE9zbG8xDTALBgNVBAcTBE9zbG8xDzANBgNVBAoTBlRUIEFT QTEOMAwGA1UECxMFUVQgU1cxHDAaBgNVBAMTE2FzcGlyaW5pa3MudHJvbGwubm8x IzAhBgkqhkiG9w0BCQEWFGFiYWJpY0B0cm9sbHRlY2guY29tMB4XDTA4MTEwMTA4 NTcyOFoXDTA5MTEwMTA4NTcyOFowgY8xCzAJBgNVBAYTAk5PMQ0wCwYDVQQIEwRP c2xvMQ0wCwYDVQQHEwRPc2xvMQ8wDQYDVQQKEwZUVCBBU0ExDjAMBgNVBAsTBVFU IFNXMRwwGgYDVQQDExNhc3BpcmluaWtzLnRyb2xsLm5vMSMwIQYJKoZIhvcNAQkB FhRhYmFiaWNAdHJvbGx0ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAMV2bMD1DN3DMgbxU3DXw2i7EWGDXcWjTDtdHvqgIb+9nHqo3MJSrzJy qgEPoOsXqswMla9wDPZAsWv5gVAmVSqpy2lfEgfY7LaSHiGD75seF7zIy+CxREHW DofHXpJGGJpBCZEKQt2HfHu3+yAYNPucN78tWNZAcPbUg5tfxMZeepRimAZNIxBI 93SDrl/f9Ka7hvPSzUQsnp8hfdpHlFPFznKfD6yPrjxgz2mT9efavJ4DhtyIa4m+ paiX515CidDz4A8CFxKZbYvuqq1ilibF/si2so9VhALC77ZcAJP1IMuT8T+WUCxq skJqiSCncl0Hgr+ba8MDGF9UQYowgjMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA KcJuNUHvjB8ok3cnTmQEeF0LPPkgj28Tqb5TFB8xpVfRI+wvTYsHsmGdOKCgYJ3a 7VflIsr63ojG8/rXK8H/cx2o2f2Hr3liJdi1UnoLDDRjBqGGz7JNuMreYokPvIbm eP01mVyK4PO2iYRwHUIAw5eeB1vMWKX2z95MupD+HRLtmGyaLALg8aQxj5N84Ewl eU2PQfhv8A1wj7aL17kfEUxDerQ1kUzlThJMV1J8Dl0l4C9N8evQkelROJU00i46 oJikA8BW6EpgbnGyNyyj5Loy4wLPKew9nTS8MCJ5xPMQc0urbY/VzuOeUK7WQof7 xOFSsRAVyQv+yqgmcZMCtg== -----END CERTIFICATE----- ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/certs/fake-login.live.com.key ================================================ -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDOtxdvMa0VHUQYG5q7Tsi1Jj4qKEJppyZEkmuRXOi0fDbd1SwE bwHrLGMvDO6OMrYBbq3WDNrtnIfF9CvzUOEch+gjr4hEVQqecU5fb45Wor7yNel3 /C/gxfbzuXHrsj/gUjNghL2i10+c2NW+hUo/sWO6OusaBT6d6s7ee+YBcQIDAQAB AoGAb8cVhu0HuLkgjyCuJMbPRRUu3ED02Iin6sB6JhplQuNAD+grayJTmUVhRJnr jTziqhedLHe7Em1oBaSo92MutfMpXvWiccSlbNygI61VgmrJpVB+qIN5H9cQc9ql Zymc+nIPa1+i5rsrOzlpUytTh7AsbZ27QG4tQXR/kQejEiECQQD6BgTxBeT8D7x9 DuukoBaSCkLwx7U7P1NXx15EI3lA1nO51t6UHfvk/jGPp8Sl4wv4alJ7AQxr5uQ/ vC3kzA/1AkEA06gNu10se8pe3n8qL2RRt+FmVjHkQdD9Mm2Dx9oWCs2A4wOSOrlo 6/nKYF1CaQNYn9HgsNbHVEUpnICVO18qDQJBALEw/uOJ1+TDikPfBSWgxx4s45Ad GNWqZXh6NNZ5hX9r/IwiOZAjR9fcRmeW8IjYRi2BvH6sGY+HDRAWXzgdXtkCQCma dOiJTf8fLjqp4E7kdzOfuI/kyqstOze4Uxjrgz2oW1dEEnA8laUcumzqp+0gXUE8 7d+UuCWWWrGKjMrYz9kCQQDh5E5+b6Djn082Jo6gvyuXWC5eXju6IdmihlJ2SMzD s2y3IDjOUtTeQQRDymLneteMz0ha79KeUp6VnAvZCOVe -----END RSA PRIVATE KEY----- ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/certs/fake-login.live.com.pem ================================================ -----BEGIN CERTIFICATE----- MIIDDjCCAnegAwIBAgIRALC3Ez7Qlvm1b66RyHS9OsAwDQYJKoZIhvcNAQEFBQAw XjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMObG9naW4ubGl2ZS5jb20w HhcNMTEwMzI1MTMyODUwWhcNMTEwNDI0MTMyODUwWjBeMQswCQYDVQQGEwJBVTET MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ dHkgTHRkMRcwFQYDVQQDEw5sb2dpbi5saXZlLmNvbTCBnzANBgkqhkiG9w0BAQEF AAOBjQAwgYkCgYEAzrcXbzGtFR1EGBuau07ItSY+KihCaacmRJJrkVzotHw23dUs BG8B6yxjLwzujjK2AW6t1gza7ZyHxfQr81DhHIfoI6+IRFUKnnFOX2+OVqK+8jXp d/wv4MX287lx67I/4FIzYIS9otdPnNjVvoVKP7FjujrrGgU+nerO3nvmAXECAwEA AaOByzCByDAdBgNVHQ4EFgQUpSOEcmtkQITvBdM2IDfcXnJ0FCAwgZgGA1UdIwSB kDCBjYAUpSOEcmtkQITvBdM2IDfcXnJ0FCChYqRgMF4xCzAJBgNVBAYTAkFVMRMw EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 eSBMdGQxFzAVBgNVBAMTDmxvZ2luLmxpdmUuY29tghEAsLcTPtCW+bVvrpHIdL06 wDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAD+2HT4GSHHKCdbl9VkX zsl+D+drMm2b0ksxz9SgPihP7aW50EEIJDEEihNMTa27mhpeOXHc/sLqDi4ECUao /0Ns/5uoVuAIrAKCydmtPsonVFh9XWjyrfUzPOHAc9p2bmJ1i9a3kTsLB6jlrVDO VufGzsowHlHZ0TtKf5omojU5 -----END CERTIFICATE----- ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/certs/fluke.cert ================================================ Certificate: Data: Version: 3 (0x2) Serial Number: 0 (0x0) Signature Algorithm: sha1WithRSAEncryption Issuer: C=NO, ST=Oslo, L=Nydalen, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com Validity Not Before: Dec 4 01:10:32 2007 GMT Not After : Apr 21 01:10:32 2035 GMT Subject: C=NO, ST=Oslo, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:a7:c8:a0:4a:c4:19:05:1b:66:ba:32:e2:d2:f1: 1c:6f:17:82:e4:39:2e:01:51:90:db:04:34:32:11: 21:c2:0d:6f:59:d8:53:90:54:3f:83:8f:a9:d3:b3: d5:ee:1a:9b:80:ae:c3:25:c9:5e:a5:af:4b:60:05: aa:a0:d1:91:01:1f:ca:04:83:e3:58:1c:99:32:45: 84:70:72:58:03:98:4a:63:8b:41:f5:08:49:d2:91: 02:60:6b:e4:64:fe:dd:a0:aa:74:08:e9:34:4c:91: 5f:12:3d:37:4d:54:2c:ad:7f:5b:98:60:36:02:8c: 3b:f6:45:f3:27:6a:9b:94:9d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: 21:85:04:3D:23:01:66:E5:F7:9F:1A:84:24:8A:AF:0A:79:F4:E5:AC X509v3 Authority Key Identifier: DirName:/C=NO/ST=Oslo/L=Nydalen/O=Nokia Corporation and/or its subsidiary(-ies)/OU=Development/CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com serial:8E:A8:B4:E8:91:B7:54:2E Signature Algorithm: sha1WithRSAEncryption 6d:57:5f:d1:05:43:f0:62:05:ec:2a:71:a5:dc:19:08:f2:c4: a6:bd:bb:25:d9:ca:89:01:0e:e4:cf:1f:c1:8c:c8:24:18:35: 53:59:7b:c0:43:b4:32:e6:98:b2:a6:ef:15:05:0b:48:5f:e1: a0:0c:97:a9:a1:77:d8:35:18:30:bc:a9:8f:d3:b7:54:c7:f1: a9:9e:5d:e6:19:bf:f6:3c:5b:2b:d8:e4:3e:62:18:88:8b:d3: 24:e1:40:9b:0c:e6:29:16:62:ab:ea:05:24:70:36:aa:55:93: ef:02:81:1b:23:10:a2:04:eb:56:95:75:fc:f8:94:b1:5d:42: c5:3f:36:44:85:5d:3a:2e:90:46:8a:a2:b9:6f:87:ae:0c:15: 40:19:31:90:fc:3b:25:bb:ae:f1:66:13:0d:85:90:d9:49:34: 8f:f2:5d:f9:7a:db:4d:5d:27:f6:76:9d:35:8c:06:a6:4c:a3: b1:b2:b6:6f:1d:d7:a3:00:fd:72:eb:9e:ea:44:a1:af:21:34: 7d:c7:42:e2:49:91:19:8b:c0:ad:ba:82:80:a8:71:70:f4:35: 31:91:63:84:20:95:e9:60:af:64:8b:cc:ff:3d:8a:76:74:3d: c8:55:6d:e4:8e:c3:2b:1c:e8:42:18:ae:9f:e6:6b:9c:34:06: ec:6a:f2:c3 -----BEGIN CERTIFICATE----- MIIEEzCCAvugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMCTk8x DTALBgNVBAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xs dGVjaCBBU0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50 cm9sbC5ubzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbTAe Fw0wNzEyMDQwMTEwMzJaFw0zNTA0MjEwMTEwMzJaMGMxCzAJBgNVBAYTAk5PMQ0w CwYDVQQIEwRPc2xvMRYwFAYDVQQKEw1Ucm9sbHRlY2ggQVNBMRQwEgYDVQQLEwtE ZXZlbG9wbWVudDEXMBUGA1UEAxMOZmx1a2UudHJvbGwubm8wgZ8wDQYJKoZIhvcN AQEBBQADgY0AMIGJAoGBAKfIoErEGQUbZroy4tLxHG8XguQ5LgFRkNsENDIRIcIN b1nYU5BUP4OPqdOz1e4am4CuwyXJXqWvS2AFqqDRkQEfygSD41gcmTJFhHByWAOY SmOLQfUISdKRAmBr5GT+3aCqdAjpNEyRXxI9N01ULK1/W5hgNgKMO/ZF8ydqm5Sd AgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUIYUEPSMBZuX3nxqEJIqv Cnn05awwgbsGA1UdIwSBszCBsKGBoqSBnzCBnDELMAkGA1UEBhMCTk8xDTALBgNV BAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xsdGVjaCBB U0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50cm9sbC5u bzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbYIJAI6otOiR t1QuMA0GCSqGSIb3DQEBBQUAA4IBAQBtV1/RBUPwYgXsKnGl3BkI8sSmvbsl2cqJ AQ7kzx/BjMgkGDVTWXvAQ7Qy5piypu8VBQtIX+GgDJepoXfYNRgwvKmP07dUx/Gp nl3mGb/2PFsr2OQ+YhiIi9Mk4UCbDOYpFmKr6gUkcDaqVZPvAoEbIxCiBOtWlXX8 +JSxXULFPzZEhV06LpBGiqK5b4euDBVAGTGQ/Dslu67xZhMNhZDZSTSP8l35ettN XSf2dp01jAamTKOxsrZvHdejAP1y657qRKGvITR9x0LiSZEZi8CtuoKAqHFw9DUx kWOEIJXpYK9ki8z/PYp2dD3IVW3kjsMrHOhCGK6f5mucNAbsavLD -----END CERTIFICATE----- ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/certs/fluke.key ================================================ -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCnyKBKxBkFG2a6MuLS8RxvF4LkOS4BUZDbBDQyESHCDW9Z2FOQ VD+Dj6nTs9XuGpuArsMlyV6lr0tgBaqg0ZEBH8oEg+NYHJkyRYRwclgDmEpji0H1 CEnSkQJga+Rk/t2gqnQI6TRMkV8SPTdNVCytf1uYYDYCjDv2RfMnapuUnQIDAQAB AoGANFzLkanTeSGNFM0uttBipFT9F4a00dqHz6JnO7zXAT26I5r8sU1pqQBb6uLz /+Qz5Zwk8RUAQcsMRgJetuPQUb0JZjF6Duv24hNazqXBCu7AZzUenjafwmKC/8ri KpX3fTwqzfzi//FKGgbXQ80yykSSliDL3kn/drATxsLCgQECQQDXhEFWLJ0vVZ1s 1Ekf+3NITE+DR16X+LQ4W6vyEHAjTbaNWtcTKdAWLA2l6N4WAAPYSi6awm+zMxx4 VomVTsjdAkEAx0z+e7natLeFcrrq8pbU+wa6SAP1VfhQWKitxL1e7u/QO90NCpxE oQYKzMkmmpOOFjQwEMAy1dvFMbm4LHlewQJAC/ksDBaUcQHHqjktCtrUb8rVjAyW A8lscckeB2fEYyG5J6dJVaY4ClNOOs5yMDS2Afk1F6H/xKvtQ/5CzInA/QJATDub K+BPU8jO9q+gpuIi3VIZdupssVGmCgObVCHLakG4uO04y9IyPhV9lA9tALtoIf4c VIvv5fWGXBrZ48kZAQJBAJmVCdzQxd9LZI5vxijUCj5EI4e+x5DRqVUvyP8KCZrC AiNyoDP85T+hBZaSXK3aYGpVwelyj3bvo1GrTNwNWLw= -----END RSA PRIVATE KEY----- ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/certs/qt-test-server-cacert.pem ================================================ -----BEGIN CERTIFICATE----- MIICrTCCAhYCCQCdDn5rci6VDjANBgkqhkiG9w0BAQQFADCBmjEOMAwGA1UEChMF Tm9raWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2Jv ZHlAbm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQsw CQYDVQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQw HhcNMDkwNzEwMDc0MTIzWhcNMTkwNzA4MDc0MTIzWjCBmjEOMAwGA1UEChMFTm9r aWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2JvZHlA bm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQswCQYD VQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwgZ8w DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6 Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt 93CxGBXMIChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJr gsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAy7YOLCZABQy2Ygkchq1I +TUpvMn+gLwAyW8TNErM1V4lNY2+K78RawzKx3SqM97ymCy4TD45EA3A2gmi32NI xSKBNjFyzngUqsXBdcSasALiowlZCiJrGwlGX5qCkBlxXvJeUEbuJLPYVl5FBjXZ 6o00K4cSPCqtqUez7WSmDZU= -----END CERTIFICATE----- ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/qjsonrpchttpserver.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_qjsonrpchttpserver SOURCES = tst_qjsonrpchttpserver.cpp RESOURCES = certificates.qrc ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpchttpserver/tst_qjsonrpchttpserver.cpp ================================================ #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpchttpclient.h" #include "qjsonrpcservice.h" #include "qjsonrpchttpserver.h" #include "qjsonrpcmessage.h" class TestQJsonRpcHttpServer: public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void quickTest(); void statusCodes_data(); void statusCodes(); void invalidMethod_data(); void invalidMethod(); void missingHeaders_data(); void missingHeaders(); void testAccessControlHeader(); void testMissingAccessControlHeader(); private: // temporarily disabled void sslTest(); private: QSslConfiguration serverSslConfiguration; QSslConfiguration clientSslConfiguration; }; Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service") public: TestService(QObject *parent = 0) : QJsonRpcService(parent), m_called(0) {} void resetCount() { m_called = 0; } int callCount() const { return m_called; } public Q_SLOTS: void noParam() const {} QString singleParam(const QString &string) const { return string; } QString multipleParam(const QString &first, const QString &second, const QString &third) const { return first + second + third; } void numberParameters(int intParam, double doubleParam, float floatParam) { Q_UNUSED(intParam) Q_UNUSED(doubleParam) Q_UNUSED(floatParam) } bool variantParameter(const QVariant &variantParam) const { return variantParam.toBool(); } QVariant variantStringResult() { return "hello"; } QVariantList variantListResult() { return QVariantList() << "one" << 2 << 3.0; } QVariantMap variantMapResult() { QVariantMap result; result["one"] = 1; result["two"] = 2.0; return result; } void increaseCalled() { m_called++; } private: int m_called; }; void TestQJsonRpcHttpServer::initTestCase() { // setup ssl configuration for tests QList caCerts = QSslCertificate::fromPath(QLatin1String(":/certs/qt-test-server-cacert.pem")); serverSslConfiguration.setCaCertificates(caCerts); serverSslConfiguration.setProtocol(QSsl::AnyProtocol); } void TestQJsonRpcHttpServer::quickTest() { QJsonRpcHttpServer server; server.addService(new TestService); QVERIFY(server.listen(QHostAddress::LocalHost, 8118)); QJsonRpcHttpClient client; client.setEndPoint("http://127.0.0.1:8118"); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.noParam"); QJsonRpcMessage response = client.sendMessageBlocking(request); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(request.id(), response.id()); } void TestQJsonRpcHttpServer::sslTest() { QJsonRpcHttpServer server; server.setSslConfiguration(serverSslConfiguration); server.addService(new TestService); server.listen(QHostAddress::LocalHost, 8118); QJsonRpcHttpClient client; client.setEndPoint("http://127.0.0.1:8118"); client.setSslConfiguration(serverSslConfiguration); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.noParam"); QJsonRpcMessage response = client.sendMessageBlocking(request); qDebug() << response; QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(request.id(), response.id()); } void TestQJsonRpcHttpServer::statusCodes_data() { QTest::addColumn("body"); QTest::addColumn("statusCode"); QTest::addColumn("statusReason"); QTest::addColumn("contentType"); { QJsonRpcMessage invalidMethod = QJsonRpcMessage::createRequest("invalidMethod"); QTest::newRow("404-not-found") << invalidMethod.toJson() << 404 << QByteArray("Not Found") << QByteArray("application/json"); } { QTest::newRow("400-bad-request") << QByteArray("{\"jsonrpc\": \"2.0\", \"id\": 666}") << 400 << QByteArray("Bad Request") << QByteArray("application/json"); } { QJsonRpcMessage invalidParameters = QJsonRpcMessage::createRequest("service.numberParameters", false); QTest::newRow("500-internal-server-error") << invalidParameters.toJson() << 500 << QByteArray("Internal Server Error") << QByteArray("application/json"); } { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.noParam"); QTest::newRow("200-ok") << request.toJson() << 200 << QByteArray("OK") << QByteArray("application/json"); } { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.noParam"); QTest::newRow("200-composite-content-type") << request.toJson() << 200 << QByteArray("OK") << QByteArray("application/json;charset=UTF-8"); } /* * TODO: support notifications { QJsonRpcMessage notification = QJsonRpcMessage::createNotification("service.noParam"); QTest::newRow("204-no-content") << notification.toJson() << 204 << QByteArray("No Content") << QByteArray("OK") << QByteArray("application/json"); } */ } void TestQJsonRpcHttpServer::statusCodes() { QFETCH(QByteArray, body); QFETCH(int, statusCode); QFETCH(QByteArray, statusReason); QFETCH(QByteArray, contentType); QJsonRpcHttpServer server; server.addService(new TestService); QVERIFY(server.listen(QHostAddress::LocalHost, 8118)); QNetworkAccessManager manager; QNetworkRequest request(QUrl("http://127.0.0.1:8118")); request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); request.setRawHeader("Accept", "application/json-rpc"); QScopedPointer reply(manager.post(request, body)); connect(reply.data(), SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); connect(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), statusCode); QCOMPARE(reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray(), statusReason); } void TestQJsonRpcHttpServer::invalidMethod_data() { QTest::addColumn("operation"); QTest::newRow("head-request") << QNetworkAccessManager::HeadOperation; QTest::newRow("put-request") << QNetworkAccessManager::PutOperation; QTest::newRow("delete-request") << QNetworkAccessManager::DeleteOperation; } void TestQJsonRpcHttpServer::invalidMethod() { QJsonRpcHttpServer server; server.addService(new TestService); QVERIFY(server.listen(QHostAddress::LocalHost, 8118)); QNetworkAccessManager manager; QNetworkRequest request(QUrl("http://127.0.0.1:8118")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/json-rpc"); QJsonRpcMessage requestMessage = QJsonRpcMessage::createRequest("service.noParam"); QScopedPointer reply; QFETCH(QNetworkAccessManager::Operation, operation); switch (operation) { case QNetworkAccessManager::HeadOperation: reply.reset(manager.head(request)); break; case QNetworkAccessManager::PutOperation: reply.reset(manager.put(request, requestMessage.toJson())); break; case QNetworkAccessManager::DeleteOperation: reply.reset(manager.deleteResource(request)); break; default: QFAIL("untested operation"); } connect(reply.data(), SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); connect(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 405); QCOMPARE(reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray(), QByteArray("Method Not Allowed")); } void TestQJsonRpcHttpServer::missingHeaders_data() { QTest::addColumn("request"); { QNetworkRequest request(QUrl("http://127.0.0.1:8118")); request.setRawHeader("Accept", "application/json-rpc"); QTest::newRow("no-content-type") << request; } { QNetworkRequest request(QUrl("http://127.0.0.1:8118")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); QTest::newRow("no-accept") << request; } { QNetworkRequest request(QUrl("http://127.0.0.1:8118")); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Accept", "application/invalid"); QTest::newRow("no-invalid-accept") << request; } { QNetworkRequest request(QUrl("http://127.0.0.1:8118")); QTest::newRow("no-jsonpc-headers") << request; } } void TestQJsonRpcHttpServer::missingHeaders() { QJsonRpcHttpServer server; server.addService(new TestService); QVERIFY(server.listen(QHostAddress::LocalHost, 8118)); QFETCH(QNetworkRequest, request); QNetworkAccessManager manager; QJsonRpcMessage requestMessage = QJsonRpcMessage::createRequest("service.noParam"); QScopedPointer reply(manager.post(request, requestMessage.toJson())); connect(reply.data(), SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); connect(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 400); QCOMPARE(reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray(), QByteArray("Bad Request")); } void TestQJsonRpcHttpServer::testMissingAccessControlHeader() { QJsonRpcHttpServer server; server.addService(new TestService); QVERIFY(server.listen(QHostAddress::LocalHost, 8118)); //OPTIONS call *missing* headers on reply QNetworkAccessManager manager; QNetworkRequest request(QUrl("http://127.0.0.1:8118")); request.setRawHeader("content-type", "text/plain"); QScopedPointer reply(manager.sendCustomRequest(request,QByteArray("OPTIONS"))); QJsonRpcMessage request_client = QJsonRpcMessage::createRequest("service.noParam"); connect(reply.data(), SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); connect(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(reply->rawHeader("Access-Control-Allow-Origin"), QByteArray("")); QCOMPARE(reply->rawHeader("Access-Control-Allow-Methods"), QByteArray("")); QCOMPARE(reply->rawHeader("Access-Control-Allow-Headers"), QByteArray("")); QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); } void TestQJsonRpcHttpServer::testAccessControlHeader() { QJsonRpcHttpServer server; server.addService(new TestService); QVERIFY(server.listen(QHostAddress::LocalHost, 8118)); //OPTIONS call check headers on reply QNetworkAccessManager manager; QNetworkRequest request(QUrl("http://127.0.0.1:8118")); request.setRawHeader("access-control-request-method", "POST"); request.setRawHeader("access-control-request-headers", "accept, content-type"); request.setRawHeader("content-type", "text/plain"); request.setRawHeader("origin", "http://127.0.0.1:8118"); QScopedPointer reply(manager.sendCustomRequest(request,QByteArray("OPTIONS"))); QJsonRpcMessage request_client = QJsonRpcMessage::createRequest("service.noParam"); connect(reply.data(), SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); connect(reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(1); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(reply->hasRawHeader("Access-Control-Allow-Origin")); QCOMPARE(reply->rawHeader("Access-Control-Allow-Origin"), QByteArray("http://127.0.0.1:8118")); QVERIFY(reply->hasRawHeader("Access-Control-Allow-Methods")); QCOMPARE(reply->rawHeader("Access-Control-Allow-Methods"), QByteArray("POST")); QVERIFY(reply->hasRawHeader("Access-Control-Allow-Headers")); QCOMPARE(reply->rawHeader("Access-Control-Allow-Headers"), QByteArray("accept, content-type")); } QTEST_MAIN(TestQJsonRpcHttpServer) #include "tst_qjsonrpchttpserver.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcmessage/qjsonrpcmessage.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_qjsonrpcmessage SOURCES = tst_qjsonrpcmessage.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcmessage/tst_qjsonrpcmessage.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcmessage.h" class TestQJsonRpcMessage: public QObject { Q_OBJECT private slots: void debugStreams_data(); void debugStreams(); void invalidData(); void invalidStringData_data(); void invalidStringData(); void invalidDataResponseWithId(); void invalidDataResponseWithoutId(); void responseSameId(); void notificationNoId(); void messageTypes(); void positionalParameters(); void equivalence_data(); void equivalence(); void withVariantListArgs(); void idSentAsString(); }; void TestQJsonRpcMessage::debugStreams_data() { QTest::addColumn("message"); QTest::addColumn("expectedOutput"); QTest::newRow("invalid-message") << QJsonRpcMessage() << "QJsonRpcMessage(type=QJsonRpcMessage::Invalid, id=0)"; QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.method"); QTest::newRow("request-message") << request << "QJsonRpcMessage(type=QJsonRpcMessage::Request, id=1, method=\"service.method\", params=QJsonValue(undefined) )"; QJsonRpcMessage response = request.createResponse(QLatin1String("response")); QTest::newRow("response-message") << response << "QJsonRpcMessage(type=QJsonRpcMessage::Response, id=1, result=QJsonValue(string, \"response\") )"; QJsonRpcMessage error = request.createErrorResponse(QJsonRpc::MethodNotFound); QTest::newRow("error-message") << error << "QJsonRpcMessage(type=QJsonRpcMessage::Error, id=1, code=-32601, message=\"\", data=QJsonValue(null) )"; QJsonRpcMessage notification = QJsonRpcMessage::createNotification("service.notification"); QTest::newRow("notification-message") << notification << "QJsonRpcMessage(type=QJsonRpcMessage::Notification, method=\"service.notification\", params=QJsonValue(undefined) )"; } void TestQJsonRpcMessage::debugStreams() { QFETCH(QJsonRpcMessage, message); QFETCH(QString, expectedOutput); QString actualOutput; QDebug debug(&actualOutput); debug << message; QCOMPARE(actualOutput.trimmed(), expectedOutput.trimmed()); } void TestQJsonRpcMessage::invalidData() { QJsonObject invalidData; QJsonRpcMessage message = QJsonRpcMessage::fromObject(invalidData); QCOMPARE(message.isValid(), false); QCOMPARE(message.type(), QJsonRpcMessage::Invalid); QVERIFY(message.toObject().isEmpty()); } void TestQJsonRpcMessage::invalidStringData_data() { QTest::addColumn("stringData"); QTest::newRow("not-json") << QByteArray("invalid json string"); QTest::newRow("not-an-object") << QByteArray("[\"string\"]"); } void TestQJsonRpcMessage::invalidStringData() { QFETCH(QByteArray, stringData); QJsonRpcMessage message = QJsonRpcMessage::fromJson(stringData); QCOMPARE(message.isValid(), false); QCOMPARE(message.type(), QJsonRpcMessage::Invalid); QVERIFY(message.toObject().isEmpty()); QVERIFY(message.params().isUndefined() || message.params().isNull()); QVERIFY(message.result().isUndefined() || message.params().isNull()); QVERIFY(message.errorData().isUndefined() || message.params().isNull()); } void TestQJsonRpcMessage::invalidDataResponseWithId() { // invalid with id const char *invalid = "{\"jsonrpc\": \"2.0\", \"params\": [], \"id\": 666}"; QJsonRpcMessage request = QJsonRpcMessage::fromJson(invalid); QJsonRpcMessage error = request.createErrorResponse(QJsonRpc::NoError, QString()); QJsonRpcMessage response = request.createResponse(QString()); QCOMPARE(request.type(), QJsonRpcMessage::Invalid); QCOMPARE(response.id(), request.id()); QCOMPARE(error.type(), QJsonRpcMessage::Error); } void TestQJsonRpcMessage::invalidDataResponseWithoutId() { // invalid without id const char *invalid = "{\"jsonrpc\": \"2.0\", \"params\": []}"; QJsonRpcMessage request = QJsonRpcMessage::fromJson(invalid); QJsonRpcMessage error = request.createErrorResponse(QJsonRpc::NoError, QString()); QJsonRpcMessage response = request.createResponse(QString()); QCOMPARE(request.type(), QJsonRpcMessage::Invalid); QCOMPARE(response.type(), QJsonRpcMessage::Invalid); QCOMPARE(error.id(), 0); } void TestQJsonRpcMessage::responseSameId() { QJsonRpcMessage request = QJsonRpcMessage::createRequest("testMethod"); QJsonRpcMessage response = request.createResponse(QLatin1String("testResponse")); QCOMPARE(response.id(), request.id()); } void TestQJsonRpcMessage::notificationNoId() { QJsonRpcMessage notification = QJsonRpcMessage::createNotification("testNotification"); QCOMPARE(notification.id(), -1); } void TestQJsonRpcMessage::messageTypes() { QJsonRpcMessage invalid; QCOMPARE(invalid.type(), QJsonRpcMessage::Invalid); QJsonRpcMessage request = QJsonRpcMessage::createRequest("testMethod"); QCOMPARE(request.type(), QJsonRpcMessage::Request); QJsonRpcMessage response = request.createResponse(QLatin1String("testResponse")); QCOMPARE(response.type(), QJsonRpcMessage::Response); QJsonRpcMessage error = request.createErrorResponse(QJsonRpc::NoError); QCOMPARE(error.type(), QJsonRpcMessage::Error); QJsonRpcMessage notification = QJsonRpcMessage::createNotification("testNotification"); QCOMPARE(notification.type(), QJsonRpcMessage::Notification); } // this is from the spec, I don't think it proves much.. void TestQJsonRpcMessage::positionalParameters() { const char *first = "{\"jsonrpc\": \"2.0\", \"method\": \"subtract\", \"params\": [42, 23], \"id\": 1}"; QJsonObject firstObject = QJsonDocument::fromJson(first).object(); const char *second = "{\"jsonrpc\": \"2.0\", \"method\": \"subtract\", \"params\": [23, 42], \"id\": 2}"; QJsonObject secondObject = QJsonDocument::fromJson(second).object(); QVERIFY2(firstObject.value("params").toArray() != secondObject.value("params").toArray(), "params should maintain order"); } void TestQJsonRpcMessage::equivalence_data() { QTest::addColumn("lhs"); QTest::addColumn("rhs"); QTest::addColumn("equal"); QJsonRpcMessage invalid; { // REQUESTS const char *simpleData = "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"request\" }"; QJsonRpcMessage simpleRequest = QJsonRpcMessage::fromJson(simpleData); QJsonRpcMessage simpleRequestCopyCtor(simpleRequest); QJsonRpcMessage simpleRequestEqualsOp = simpleRequest; const char *withParametersData = "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"request\", \"params\": [\"with\", \"parameters\"]}"; QJsonRpcMessage simpleRequestWithParameters = QJsonRpcMessage::fromJson(withParametersData); const char *withNamedParametersData = "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"request\", \"params\": {\"firstName\": \"yogi\", \"lastName\": \"thebear\"}}"; QJsonRpcMessage simpleRequestWithNamedParameters = QJsonRpcMessage::fromJson(withNamedParametersData); QTest::newRow("simpleRequestCopiesEqual_1") << simpleRequest << simpleRequestCopyCtor << true; QTest::newRow("simpleRequestCopiesEqual_2") << simpleRequest << simpleRequestEqualsOp << true; QTest::newRow("simpleRequestAndSimpleRequestWithParamsNotEqual") << simpleRequest << simpleRequestWithParameters << false; QTest::newRow("simpleRequestAndSimpleRequestWithNamedParamsNotEqual") << simpleRequest << simpleRequestWithNamedParameters << false; QTest::newRow("requestWithParamsNotEqualWithNamedParameters") << simpleRequestWithParameters << simpleRequestWithNamedParameters << false; QTest::newRow("simpleRequestNotEqualInvalid") << simpleRequest << invalid << false; } { // NOTIFICATIONS QJsonRpcMessage simpleNotification = QJsonRpcMessage::createNotification("notification"); QJsonRpcMessage simpleNotificationCopyCtor(simpleNotification); QJsonRpcMessage simpleNotificationEqualsOp = simpleNotification; QJsonArray params; params.append(QLatin1String("yogi")); params.append(QLatin1String("thebear")); QJsonRpcMessage simpleNotificationWithParams = QJsonRpcMessage::createNotification("notification", params); QJsonObject namedParameters; namedParameters.insert("firstName", QLatin1String("yogi")); namedParameters.insert("lastName", QLatin1String("thebear")); QJsonRpcMessage simpleNotificationWithNamedParameters = QJsonRpcMessage::createNotification("notification", namedParameters); QTest::newRow("simpleNotificationCopiesEqual_1") << simpleNotification << simpleNotificationCopyCtor << true; QTest::newRow("simpleNotificationCopiesEqual_2") << simpleNotification << simpleNotificationEqualsOp << true; QTest::newRow("simpleNotificationNotEqualNotificationWithParams") << simpleNotification << simpleNotificationWithParams << false; QTest::newRow("simpleNotificationNotEqualNotificationWithNamedParameters") << simpleNotification << simpleNotificationWithNamedParameters << false; QTest::newRow("notificationWithParamsNotEqualWithNamedParameters") << simpleNotificationWithParams << simpleNotificationWithNamedParameters << false; QTest::newRow("simpleNotificationNotEqualInvalid") << simpleNotification << invalid << false; } { // ERRORS QJsonRpcMessage basicRequest = QJsonRpcMessage::createRequest("blah", QLatin1String("first")); QJsonRpcMessage lhs = basicRequest.createErrorResponse(QJsonRpc::InternalError, "some error"); QJsonRpcMessage rhs = basicRequest.createErrorResponse(QJsonRpc::InternalError, "some error"); QJsonRpcMessage invalidRhs = basicRequest.createErrorResponse(QJsonRpc::InvalidRequest, "some error"); QTest::newRow("errorResponseEqual") << lhs << rhs << true; QTest::newRow("errorResponseNotEqual") << lhs << invalidRhs << false; } } void TestQJsonRpcMessage::equivalence() { QFETCH(QJsonRpcMessage, lhs); QFETCH(QJsonRpcMessage, rhs); QFETCH(bool, equal); if (equal) QCOMPARE(lhs, rhs); else QVERIFY(lhs != rhs); } void TestQJsonRpcMessage::withVariantListArgs() { const char *varListArgsFormat = "{ " \ "\"id\": %1, " \ "\"jsonrpc\": \"2.0\", " \ "\"method\": \"service.variantListParameter\", " \ "\"params\": [[ 1, 20, \"hello\", false ]] " \ "}"; QVariantList firstParameter; firstParameter << 1 << 20 << "hello" << false; QJsonArray params; params.append(QJsonArray::fromVariantList(firstParameter)); QJsonRpcMessage requestFromQJsonRpc = QJsonRpcMessage::createRequest("service.variantListParameter", params); // QJsonRpcMessage::createRequest is creating objects with an unique id, // and to allow a random test execution order - json data must have the same id int id = requestFromQJsonRpc.id(); QByteArray varListArgs = QString(varListArgsFormat).arg(id).toLatin1(); QJsonRpcMessage requestFromData = QJsonRpcMessage::fromJson(varListArgs); QCOMPARE(requestFromQJsonRpc, requestFromData); } void TestQJsonRpcMessage::idSentAsString() { const char *messageWithStringId = "{ " \ "\"id\": \"%1\", " \ "\"jsonrpc\": \"2.0\", " \ "\"method\": \"service.someMethod\", " \ "\"params\": [[ 1, 20, \"hello\", false ]] " \ "}"; const char *errorMessageWithStringId = "{ " \ "\"id\": \"%1\", " \ "\"jsonrpc\": \"2.0\", " \ "\"error\": { \"code\": \"-32601\", \"data\": null } " \ "}"; QVariantList firstParameter; firstParameter << 1 << 20 << "hello" << false; QJsonArray params; params.append(QJsonArray::fromVariantList(firstParameter)); QJsonRpcMessage requestFromQJsonRpc = QJsonRpcMessage::createRequest("service.someMethod", params); int id = requestFromQJsonRpc.id(); QByteArray messageData = QString(messageWithStringId).arg(id).toLatin1(); QJsonRpcMessage requestFromData = QJsonRpcMessage::fromJson(messageData); QJsonRpcMessage errorFromQJsonRpc = requestFromQJsonRpc.createErrorResponse(QJsonRpc::MethodNotFound); QByteArray errorData = QString(errorMessageWithStringId).arg(id).toLatin1(); QJsonRpcMessage errorFromData = QJsonRpcMessage::fromJson(errorData); QCOMPARE(requestFromQJsonRpc, requestFromData); QCOMPARE(errorFromQJsonRpc, errorFromData); } QTEST_MAIN(TestQJsonRpcMessage) #include "tst_qjsonrpcmessage.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcmetatype/qjsonrpcmetatype.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_qjsonrpcmetatype SOURCES = \ tst_qjsonrpcmetatype.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcmetatype/tst_qjsonrpcmetatype.cpp ================================================ /* * Copyright (C) 2013 Fargier Sylvain * Copyright (C) 2014 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcmetatype.h" #include "qjsonrpcabstractserver.h" #include "qjsonrpcmessage.h" #include "qjsonrpcservice.h" class TestQJsonRpcMetaType: public QObject { Q_OBJECT private slots: void initTestCase(); void customParameterTypes(); void customReturnTypes(); void invalidParameterTypes(); void enums(); private: /* * There's no way to guess which method is the best to dispatch a custom type * for the moment, something like a signature, or a typetesting functor might * be good. * * This test will fail until then */ void commonMethodName(); }; class CustomClass : public QObject { public: CustomClass(int data = 0, QObject *parent = 0) : QObject(parent), data(data) {} CustomClass(const CustomClass &other) : QObject(), data(other.data) {} CustomClass &operator=(const CustomClass &other) { if (&other != this) data = other.data; return *this; } QJsonValue toJson() const { return QJsonValue(data); } static CustomClass fromJson(const QJsonValue &value) { return CustomClass(value.toInt()); } int data; }; Q_DECLARE_METATYPE(CustomClass) class AnotherCustomClass { public: explicit AnotherCustomClass(const QString &str = QString()) : data(str) {} QJsonValue toJson() const { return QJsonValue(data); } static AnotherCustomClass fromJson(const QJsonValue &value) { return AnotherCustomClass(value.toString()); } QString data; }; Q_DECLARE_METATYPE(AnotherCustomClass) class UnboundClass : public QObject { public: UnboundClass(QObject *parent = 0) : QObject(parent) {} }; class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service") Q_ENUMS(TestEnum) public: TestService(QObject *parent = 0) : QJsonRpcService(parent) {} QJsonRpcMessage testDispatch(const QJsonRpcMessage &message) { return QJsonRpcService::dispatch(message); } enum TestEnum { ZERO = 0, ONE = 1, TWO = 2, THREE = 3 }; static QMetaEnum TestMetaEnum() { static int i = TestService::staticMetaObject.indexOfEnumerator("TestEnum"); return TestService::staticMetaObject.enumerator(i); } public Q_SLOTS: void customParameterType(const CustomClass ¶m) const { QCOMPARE(param.data, 42); } CustomClass customReturnType(const CustomClass ¶m) const { CustomClass ret(param); ++ret.data; return ret; } void invalidParameterType(const UnboundClass &) const { QVERIFY(false); } void enums(TestService::TestEnum) { QVERIFY(true); } int commonMethodName(const CustomClass &c) { return c.data; } QString commonMethodName(const AnotherCustomClass &c) { return c.data; } }; Q_DECLARE_METATYPE(TestService::TestEnum) QJsonValue toJson(TestService::TestEnum e) { return QString(TestService::TestMetaEnum().valueToKey(e)); } TestService::TestEnum fromJson(const QJsonValue &val) { if (val.isString()) { QString str(val.toString()); if (str.isEmpty()) return TestService::ZERO; return (TestService::TestEnum) TestService::TestMetaEnum().keysToValue(str.toLatin1().constData()); } else if (val.isDouble()) { int idx = (int) val.toDouble(); if (!TestService::TestMetaEnum().valueToKey(idx)) return TestService::ZERO; return (TestService::TestEnum) idx; } return TestService::ZERO; } class TestServiceProvider : public QObject, public QJsonRpcServiceProvider { public: TestServiceProvider() {} }; void TestQJsonRpcMetaType::initTestCase() { qRegisterJsonRpcMetaType("CustomClass"); qRegisterJsonRpcMetaType("CustomClass"); // TODO: incorporate enums into qRegisterJsonRpcMetaType QMetaType::registerConverter(&toJson); QMetaType::registerConverter(&fromJson); } /* * Custom class parameter */ void TestQJsonRpcMetaType::customParameterTypes() { TestServiceProvider provider; TestService service; provider.addService(&service); CustomClass custom(42); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.customParameterType", custom.toJson()); QJsonRpcMessage response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); } void TestQJsonRpcMetaType::customReturnTypes() { TestServiceProvider provider; TestService service; provider.addService(&service); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.customReturnType", CustomClass().toJson()); QJsonRpcMessage response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); QVariant result = response.result(); QVERIFY(result.canConvert()); QCOMPARE(result.value().data, 1); } void TestQJsonRpcMetaType::invalidParameterTypes() { TestServiceProvider provider; TestService service; provider.addService(&service); UnboundClass custom; QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.invalidParameterType", QJsonValue::fromVariant(QVariant::fromValue(CustomClass()))); QJsonRpcMessage response = service.testDispatch(request); QVERIFY(response.type() == QJsonRpcMessage::Error); QCOMPARE(response.errorCode(), (int) QJsonRpc::MethodNotFound); } void TestQJsonRpcMetaType::enums() { TestServiceProvider provider; TestService service; provider.addService(&service); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.enums", TestService::ONE); QJsonRpcMessage response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); request = QJsonRpcMessage::createRequest("service.enums", QLatin1String("ONE")); response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); } void TestQJsonRpcMetaType::commonMethodName() { TestServiceProvider provider; TestService service; provider.addService(&service); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.commonMethodName", CustomClass(42).toJson()); QJsonRpcMessage response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); CustomClass c(CustomClass::fromJson(response.result())); QCOMPARE(c.data, 42); request = QJsonRpcMessage::createRequest("service.commonMethodName", AnotherCustomClass("test string").toJson()); response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); AnotherCustomClass ac(AnotherCustomClass::fromJson(response.result())); QCOMPARE(ac.data, QLatin1String("test string")); } QTEST_MAIN(TestQJsonRpcMetaType) #include "tst_qjsonrpcmetatype.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcserver/qjsonrpcserver.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_qjsonrpcserver HEADERS = \ testservices.h SOURCES = \ testservices.cpp \ tst_qjsonrpcserver.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcserver/testservices.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include "qjsonrpcsocket.h" #include "testservices.h" TestService::TestService(QObject *parent) : QJsonRpcService(parent), m_called(0) { } void TestService::resetCount() { m_called = 0; } int TestService::callCount() const { return m_called; } void TestService::noParam() const { } QString TestService::singleParam(const QString &string) const { return string; } QString TestService::multipleParam(const QString &first, const QString &second, const QString &third) const { return first + second + third; } void TestService::numberParameters(int intParam, double doubleParam) { if (intParam == 10 && doubleParam == 3.14159) { m_called++; Q_EMIT numberParametersCalled(); } } bool TestService::variantParameter(const QVariant &variantParam) const { return variantParam.toBool(); } QVariantList TestService::variantListParameter(const QVariantList &data) { return data; } QVariant TestService::variantStringResult() { return QLatin1String("hello"); } QVariantList TestService::variantListResult() { return QVariantList() << "one" << 2 << 3.0; } QVariantMap TestService::variantMapResult() { QVariantMap result; result["one"] = 1; result["two"] = 2.0; return result; } /* NOTE: suppress binding warnings bool TestService::methodWithListOfInts(const QList &list) { if (list.size() < 3) return false; if (list.at(0) != 300) return false; if (list.at(1) != 30) return false; if (list.at(2) != 3) return false; return true; } */ QString TestService::variantMapInvalidParam(const QVariantMap &map) { return map["foo"].toString(); } void TestService::outputParameter(int in1, int &out, int in2) { out = in1 + out + in2; } void TestService::outputParameterWithStrings(const QString &first, QString &output, const QString &last) { if (output.isEmpty()) output = QString("%1 %2").arg(first).arg(last); else output.append(QString(" %1 %2").arg(first).arg(last)); } bool TestService::overloadedMethod(int input) { Q_UNUSED(input) return true; } bool TestService::overloadedMethod(const QString &input) { Q_UNUSED(input) return false; } bool TestService::stringListParameter(int one, const QString &two, const QString &three, const QStringList &list) { Q_UNUSED(one); Q_UNUSED(two); Q_UNUSED(three); Q_UNUSED(list); return true; } QJsonArray TestService::returnQJsonArray() { QJsonArray array; array.append(1); array.append(QLatin1String("two")); array.append(true); return array; } QJsonObject TestService::returnQJsonObject() { QJsonObject object; object.insert("one", QLatin1String("one")); object.insert("two", 2); object.insert("three", true); return object; } QVariantMap TestService::hugeResponse() { QVariantMap result; for (int i = 0; i < 1000; i++) { QString key = QString("testKeyForHugeResponse%1").arg(i); result[key] = "some sample data to make the response larger"; } return result; } QString TestService::defaultParametersMethod(const QString &name) { if (name.isEmpty()) return "empty string"; return QString("hello %1").arg(name); } QString TestService::defaultParametersMethod2(const QString &name, int year) { return QString("%1%2").arg(name).arg(year); } TestServiceWithoutServiceName::TestServiceWithoutServiceName(QObject *parent) : QJsonRpcService(parent) { } QString TestServiceWithoutServiceName::testMethod(const QString &string) const { return string; } TestComplexMethodService::TestComplexMethodService(QObject *parent) : QJsonRpcService(parent) { } void TestComplexMethodService::testMethod() { } TestDelayedResponseService::TestDelayedResponseService(QObject *parent) : QJsonRpcService(parent) { } void TestDelayedResponseService::delayedResponse() { QVERIFY(currentRequest().isValid()); beginDelayedResponse(); m_request = currentRequest(); QTimer::singleShot(250, this, SLOT(delayedResponseComplete())); } void TestDelayedResponseService::delayedResponseWithClosedSocket() { QVERIFY(currentRequest().isValid()); beginDelayedResponse(); m_request = currentRequest(); QTimer::singleShot(250, this, SLOT(delayedResponseWithClosedSocketComplete())); } QString TestDelayedResponseService::immediateResponse() { return QLatin1String("immediate"); } void TestDelayedResponseService::delayedResponseComplete() { m_request.respond(QLatin1String("delayed")); } void TestDelayedResponseService::delayedResponseWithClosedSocketComplete() { QJsonRpcMessage requestMessage = m_request.request(); QJsonRpcMessage responseMessage = requestMessage.createResponse(QLatin1String("delayed")); bool result = m_request.respond(responseMessage); Q_EMIT responseResult(result); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcserver/testservices.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef TESTSERVICES_H #define TESTSERVICES_H #include "qjsonrpcservice.h" class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service") public: explicit TestService(QObject *parent = 0); void resetCount(); int callCount() const; Q_SIGNALS: void numberParametersCalled(); public Q_SLOTS: void noParam() const; QString singleParam(const QString &string) const; QString multipleParam(const QString &first, const QString &second, const QString &third) const; void numberParameters(int intParam, double doubleParam); bool variantParameter(const QVariant &variantParam) const; QVariantList variantListParameter(const QVariantList &data); QVariant variantStringResult(); QVariantList variantListResult(); QVariantMap variantMapResult(); QVariantMap hugeResponse(); QString defaultParametersMethod(const QString &name = QString()); QString defaultParametersMethod2(const QString &name = QString(), int year = 2012); // NOTE: suppress binding warnings // bool methodWithListOfInts(const QList &list); QString variantMapInvalidParam(const QVariantMap &map); void outputParameter(int in1, int &out, int in2); void outputParameterWithStrings(const QString &first, QString &output, const QString &last); bool overloadedMethod(int input); bool overloadedMethod(const QString &input); bool stringListParameter(int one, const QString &two, const QString &three, const QStringList &list); // return values QJsonArray returnQJsonArray(); QJsonObject returnQJsonObject(); private: int m_called; }; class TestServiceWithoutServiceName : public QJsonRpcService { Q_OBJECT public: TestServiceWithoutServiceName(QObject *parent = 0); public Q_SLOTS: QString testMethod(const QString &string) const; }; class TestComplexMethodService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service.complex.prefix.for") public: TestComplexMethodService(QObject *parent = 0); public Q_SLOTS: void testMethod(); }; class TestDelayedResponseService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service") public: TestDelayedResponseService(QObject *parent = 0); Q_SIGNALS: void responseResult(bool result); public Q_SLOTS: void delayedResponse(); void delayedResponseWithClosedSocket(); QString immediateResponse(); private Q_SLOTS: void delayedResponseComplete(); void delayedResponseWithClosedSocketComplete(); private: QJsonRpcServiceRequest m_request; }; #endif // TESTSERVICES_H ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcserver/tst_qjsonrpcserver.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcabstractserver.h" #include "qjsonrpclocalserver.h" #include "qjsonrpctcpserver.h" #include "qjsonrpchttpserver.h" #include "qjsonrpchttpclient.h" #include "qjsonrpcsocket.h" #include "qjsonrpcmessage.h" #include "qjsonrpcservicereply.h" #include "testservices.h" class TestQJsonRpcServer: public QObject { Q_OBJECT public: TestQJsonRpcServer(); enum ServerType { TcpServer, LocalServer, HttpServer }; private Q_SLOTS: void initTestCase_data(); void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); void noParameter(); void singleParameter(); void multiParameter(); void variantParameter(); void variantListParameter(); void variantResult(); void invalidArgs(); void methodNotFound(); void invalidRequest(); void notifyConnectedClients_data(); void notifyConnectedClients(); void numberParameters(); void hugeResponse(); void complexMethod(); void defaultParameters(); void overloadedMethod(); void qVariantMapInvalidParam(); void stringListParameter(); void outputParameter(); #if QT_VERSION >= 0x050200 void jsonReturnTypes(); #endif void notifyServiceSocket(); void userDeletesReplyOnDelayedResponse(); void delayedResponseBasic(); void delayedResponseSocketClosed(); void addRemoveService(); void serviceWithNoGivenName(); void cantRemoveInvalidService(); void cantAddServiceTwice(); private: QJsonRpcAbstractSocket *createClient(); // client related QScopedPointer clientSocket; QList tcpSockets; QList localSockets; // server related QJsonRpcAbstractServer *server; QThread serverThread; QScopedPointer tcpServer; QScopedPointer localServer; QScopedPointer httpServer; quint16 tcpServerPort; quint16 httpServerPort; private: // temporarily disabled // void testListOfInts(); }; Q_DECLARE_METATYPE(TestQJsonRpcServer::ServerType) Q_DECLARE_METATYPE(QJsonRpcMessage::Type) TestQJsonRpcServer::TestQJsonRpcServer() : server(0) { } void TestQJsonRpcServer::initTestCase_data() { QTest::addColumn("serverType"); QTest::newRow("tcp") << TcpServer; QTest::newRow("local") << LocalServer; QTest::newRow("http") << HttpServer; } void TestQJsonRpcServer::initTestCase() { serverThread.start(); } void TestQJsonRpcServer::cleanupTestCase() { serverThread.quit(); QVERIFY(serverThread.wait()); } QJsonRpcAbstractSocket *TestQJsonRpcServer::createClient() { QFETCH_GLOBAL(ServerType, serverType); QJsonRpcAbstractSocket *socket = 0; if (serverType == LocalServer) { QLocalSocket *localSocket = new QLocalSocket; connect(localServer.data(), SIGNAL(clientConnected()), &QTestEventLoop::instance(), SLOT(exitLoop())); localSocket->connectToServer("qjsonrpc-test-local-server"); QTestEventLoop::instance().enterLoop(5); if (QTestEventLoop::instance().timeout() || !localSocket->waitForConnected()) { delete localSocket; return 0; } socket = new QJsonRpcSocket(localSocket); localSockets.append(localSocket); } else if (serverType == TcpServer) { QTcpSocket *tcpSocket = new QTcpSocket; connect(tcpServer.data(), SIGNAL(clientConnected()), &QTestEventLoop::instance(), SLOT(exitLoop())); tcpSocket->connectToHost(QHostAddress::LocalHost, tcpServerPort); QTestEventLoop::instance().enterLoop(5); if (QTestEventLoop::instance().timeout() || !tcpSocket->waitForConnected()) { delete tcpSocket; return 0; } socket = new QJsonRpcSocket(tcpSocket); tcpSockets.append(tcpSocket); } else if (serverType == HttpServer) { QJsonRpcHttpClient *client = new QJsonRpcHttpClient; client->setEndPoint("http://127.0.0.1:" + QString::number(httpServerPort)); socket = client; } return socket; } void TestQJsonRpcServer::init() { QFETCH_GLOBAL(ServerType, serverType); if (serverType == LocalServer) { localServer.reset(new QJsonRpcLocalServer); QVERIFY(localServer->listen("qjsonrpc-test-local-server")); localServer->moveToThread(&serverThread); server = localServer.data(); } else if (serverType == TcpServer) { tcpServer.reset(new QJsonRpcTcpServer); tcpServerPort = quint16(91919 + qrand() % 1000); QVERIFY(tcpServer->listen(QHostAddress::LocalHost, tcpServerPort)); tcpServer->moveToThread(&serverThread); server = tcpServer.data(); } else if (serverType == HttpServer) { httpServer.reset(new QJsonRpcHttpServer); httpServerPort = quint16(8118 + qrand() % 1000); QVERIFY(httpServer->listen(QHostAddress::LocalHost, httpServerPort)); httpServer->moveToThread(&serverThread); server = httpServer.data(); } clientSocket.reset(createClient()); QVERIFY(!clientSocket.isNull()); if (serverType == LocalServer || serverType == TcpServer) QCOMPARE(server->connectedClientCount(), 1); } void TestQJsonRpcServer::cleanup() { QFETCH_GLOBAL(ServerType, serverType); if (serverType == TcpServer) { // disconnect clients while (!tcpSockets.isEmpty()) { QTcpSocket *tcpSocket = tcpSockets.takeFirst(); connect(tcpServer.data(), SIGNAL(clientDisconnected()), &QTestEventLoop::instance(), SLOT(exitLoop())); if (tcpSocket->state() == QAbstractSocket::ConnectedState) { tcpSocket->disconnectFromHost(); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } delete tcpSocket; } // close server tcpServer->close(); } else if (serverType == LocalServer) { // disconnect clients while (!localSockets.isEmpty()) { QLocalSocket *localSocket = localSockets.takeFirst(); connect(localServer.data(), SIGNAL(clientDisconnected()), &QTestEventLoop::instance(), SLOT(exitLoop())); if (localSocket->state() == QLocalSocket::ConnectedState) { localSocket->disconnectFromServer(); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } delete localSocket; } // close server localServer->close(); } else if (serverType == HttpServer) { httpServer->close(); } QCOMPARE(server->connectedClientCount(), 0); } void TestQJsonRpcServer::noParameter() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.noParam"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); QCOMPARE(spyMessageReceived.count(), 1); } void TestQJsonRpcServer::singleParameter() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.singleParam", QString("single")); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); QCOMPARE(response.result().toString(), QLatin1String("single")); } void TestQJsonRpcServer::overloadedMethod() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage stringRequest = QJsonRpcMessage::createRequest("service.overloadedMethod", QString("single")); QJsonRpcMessage stringResponse = clientSocket->sendMessageBlocking(stringRequest); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(stringResponse.errorCode() == QJsonRpc::NoError); QCOMPARE(stringRequest.id(), stringResponse.id()); QCOMPARE(stringResponse.result().toBool(), false); QJsonRpcMessage intRequest = QJsonRpcMessage::createRequest("service.overloadedMethod", 10); QJsonRpcMessage intResponse = clientSocket->sendMessageBlocking(intRequest); QCOMPARE(spyMessageReceived.count(), 2); QVERIFY(intResponse.errorCode() == QJsonRpc::NoError); QCOMPARE(intRequest.id(), intResponse.id()); QCOMPARE(intResponse.result().toBool(), true); QVariantMap testMap; testMap["one"] = 1; testMap["two"] = 2; testMap["three"] = 3; QJsonRpcMessage mapRequest = QJsonRpcMessage::createRequest("service.overloadedMethod", QJsonValue::fromVariant(testMap)); QJsonRpcMessage mapResponse = clientSocket->sendMessageBlocking(mapRequest); QCOMPARE(spyMessageReceived.count(), 3); QVERIFY(mapResponse.errorCode() == QJsonRpc::InvalidParams); QCOMPARE(mapRequest.id(), mapResponse.id()); } void TestQJsonRpcServer::multiParameter() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonArray params; params.append(QLatin1String("a")); params.append(QLatin1String("b")); params.append(QLatin1String("c")); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.multipleParam", params); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); QCOMPARE(response.result().toString(), QLatin1String("abc")); } void TestQJsonRpcServer::variantParameter() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonArray params; params.append(QJsonValue::fromVariant(QVariant(true))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.variantParameter", params); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); QVERIFY(response.result() == true); } void TestQJsonRpcServer::variantListParameter() { QVERIFY(server->addService(new TestService)); QJsonArray data; data.append(1); data.append(20); data.append(QLatin1String("hello")); data.append(false); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonArray params; params.append(data); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.variantListParameter", params); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); QCOMPARE(response.result().toArray(), data); } void TestQJsonRpcServer::variantResult() { QVERIFY(server->addService(new TestService)); QJsonRpcMessage response = clientSocket->invokeRemoteMethodBlocking("service.variantStringResult"); QVERIFY(response.errorCode() == QJsonRpc::NoError); QString stringResult = response.result().toString(); QCOMPARE(stringResult, QLatin1String("hello")); } void TestQJsonRpcServer::invalidArgs() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.noParam", false); clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVariant message = spyMessageReceived.takeFirst().at(0); QJsonRpcMessage error = message.value(); QCOMPARE(request.id(), error.id()); QVERIFY(error.errorCode() == QJsonRpc::InvalidParams); } void TestQJsonRpcServer::methodNotFound() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.doesNotExist"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(response.isValid()); QVariant message = spyMessageReceived.takeFirst().at(0); QJsonRpcMessage error = message.value(); QCOMPARE(request.id(), error.id()); QVERIFY(error.errorCode() == QJsonRpc::MethodNotFound); } void TestQJsonRpcServer::invalidRequest() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::fromJson("{\"jsonrpc\": \"2.0\", \"id\": 666}"); clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVariant message = spyMessageReceived.takeFirst().at(0); QJsonRpcMessage error = message.value(); QCOMPARE(request.id(), error.id()); QVERIFY(error.errorCode() == QJsonRpc::InvalidRequest); } void TestQJsonRpcServer::qVariantMapInvalidParam() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); const char *invalid = "{\"jsonrpc\": \"2.0\", \"id\": 0, \"method\": \"service.variantMapInvalidParam\",\"params\": [[{\"foo\":\"bar\",\"baz\":\"quux\"}, {\"foo\":\"bar\"}]]}"; QJsonRpcMessage request = QJsonRpcMessage::fromJson(invalid); clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVariant message = spyMessageReceived.takeFirst().at(0); QJsonRpcMessage error = message.value(); QCOMPARE(request.id(), error.id()); QVERIFY(error.errorCode() == QJsonRpc::InvalidParams); } class ServerNotificationHelper : public QObject { Q_OBJECT public: ServerNotificationHelper(const QJsonRpcMessage &message, QJsonRpcAbstractServer *provider) : m_provider(provider), m_notification(message) {} public Q_SLOTS: void activate() { m_provider->notifyConnectedClients(m_notification); } private: QJsonRpcAbstractServer *m_provider; QJsonRpcMessage m_notification; }; void TestQJsonRpcServer::notifyConnectedClients_data() { QTest::addColumn("method"); QTest::addColumn("type"); QTest::addColumn("parameters"); QTest::addColumn("sendAsMessage"); QTest::newRow("notification-message") << "testNotification" << QJsonRpcMessage::Notification << QJsonArray() << true; QTest::newRow("notification-direct") << "testNotification" << QJsonRpcMessage::Notification << QJsonArray() << false; QJsonArray parameters; parameters.append(QLatin1String("test")); QTest::newRow("request-message") << "testRequest" << QJsonRpcMessage::Request << parameters << true; QTest::newRow("request-direct") << "testRequest" << QJsonRpcMessage::Request << parameters << false; } void TestQJsonRpcServer::notifyConnectedClients() { QFETCH(QString, method); QFETCH(QJsonRpcMessage::Type, type); QFETCH(QJsonArray, parameters); QFETCH(bool, sendAsMessage); QFETCH_GLOBAL(ServerType, serverType); if (serverType == HttpServer) { #if QT_VERSION >= 0x050000 QSKIP("Not supported for HTTP connections"); #else QSKIP("Not supported for HTTP connections", SkipAll); #endif } QVERIFY(server->addService(new TestService)); QEventLoop loop; connect(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage)), &loop, SLOT(quit())); QSignalSpy spy(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage message; if (sendAsMessage) { switch (type) { case QJsonRpcMessage::Request: message = QJsonRpcMessage::createRequest(method, parameters); break; case QJsonRpcMessage::Notification: message = QJsonRpcMessage::createNotification(method, parameters); break; default: break; } if (serverType == TcpServer) QMetaObject::invokeMethod(tcpServer.data(), "notifyConnectedClients", Q_ARG(QJsonRpcMessage, message)); else if (serverType == LocalServer) QMetaObject::invokeMethod(localServer.data(), "notifyConnectedClients", Q_ARG(QJsonRpcMessage, message)); // server->notifyConnectedClients(message); } else { if (serverType == TcpServer) QMetaObject::invokeMethod(tcpServer.data(), "notifyConnectedClients", Q_ARG(QString, method), Q_ARG(QJsonArray, parameters)); else if (serverType == LocalServer) QMetaObject::invokeMethod(localServer.data(), "notifyConnectedClients", Q_ARG(QString, method), Q_ARG(QJsonArray, parameters)); // server->notifyConnectedClients(method, parameters); } QTimer::singleShot(2000, &loop, SLOT(quit())); loop.exec(); QCOMPARE(spy.count(), 1); QJsonRpcMessage receivedMessage = spy.takeFirst().first().value(); if (sendAsMessage) { QCOMPARE(receivedMessage, message); } else { QCOMPARE(receivedMessage.method(), method); QCOMPARE(receivedMessage.params().toArray(), parameters); } } void TestQJsonRpcServer::numberParameters() { TestService *service = new TestService; QVERIFY(server->addService(service)); QJsonArray params; params.append(10); params.append(3.14159); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.numberParameters", params); clientSocket->sendMessageBlocking(request); QCOMPARE(service->callCount(), 1); } void TestQJsonRpcServer::hugeResponse() { QVERIFY(server->addService(new TestService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.hugeResponse"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(response.isValid()); } void TestQJsonRpcServer::complexMethod() { QVERIFY(server->addService(new TestComplexMethodService)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.complex.prefix.for.testMethod"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); } void TestQJsonRpcServer::defaultParameters() { QVERIFY(server->addService(new TestService)); // test without name QJsonRpcMessage noNameRequest = QJsonRpcMessage::createRequest("service.defaultParametersMethod"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(noNameRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toString(), QLatin1String("empty string")); // test with name QJsonRpcMessage nameRequest = QJsonRpcMessage::createRequest("service.defaultParametersMethod", QLatin1String("matt")); response = clientSocket->sendMessageBlocking(nameRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toString(), QLatin1String("hello matt")); // test multiparameter QJsonRpcMessage konyRequest = QJsonRpcMessage::createRequest("service.defaultParametersMethod2", QLatin1String("KONY")); response = clientSocket->sendMessageBlocking(konyRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toString(), QLatin1String("KONY2012")); } void TestQJsonRpcServer::notifyServiceSocket() { QFETCH_GLOBAL(ServerType, serverType); if (serverType == HttpServer) { #if QT_VERSION >= 0x050000 QSKIP("Not supported for HTTP connections"); #else QSKIP("Not supported for HTTP connections", SkipAll); #endif } QScopedPointer serviceSocket; clientSocket.reset(); // we only want a service socket, this would override that if (serverType == TcpServer) { serviceSocket.reset(new QJsonRpcServiceSocket(tcpSockets.first())); } else if (serverType == LocalServer) { serviceSocket.reset(new QJsonRpcServiceSocket(localSockets.first())); } TestService *service = new TestService; QVERIFY(serviceSocket->addService(service)); QCOMPARE(service->callCount(), 0); connect(service, SIGNAL(numberParametersCalled()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); QJsonArray params; params.append(10); params.append(3.14159); QJsonRpcMessage notification = QJsonRpcMessage::createNotification("service.numberParameters", params); if (serverType == TcpServer) QMetaObject::invokeMethod(tcpServer.data(), "notifyConnectedClients", Q_ARG(QJsonRpcMessage, notification)); else if (serverType == LocalServer) QMetaObject::invokeMethod(localServer.data(), "notifyConnectedClients", Q_ARG(QJsonRpcMessage, notification)); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); QCOMPARE(service->callCount(), 1); } /* Q_DECLARE_METATYPE(QList) void TestQJsonRpcServer::testListOfInts() { server->addService(new TestService); qRegisterMetaType >("QList"); QList intList = QList() << 300 << 30 << 3; QVariant variant = QVariant::fromValue(intList); QJsonRpcMessage intRequest = QJsonRpcMessage::createRequest("service.methodWithListOfInts", variant); QJsonRpcMessage response = clientSocket->sendMessageBlocking(intRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QVERIFY(response.result().toBool()); } */ void TestQJsonRpcServer::stringListParameter() { QVERIFY(server->addService(new TestService)); QStringList strings = QStringList() << "one" << "two" << "three"; QJsonArray params; params.append(1); params.append(QLatin1String("A")); params.append(QLatin1String("B")); params.append(QJsonValue::fromVariant(strings)); QJsonRpcMessage strRequest = QJsonRpcMessage::createRequest("service.stringListParameter", params); QJsonRpcMessage response = clientSocket->sendMessageBlocking(strRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QVERIFY(response.result().toBool()); } void TestQJsonRpcServer::outputParameter() { QVERIFY(server->addService(new TestService)); // use argument 2 as in/out parameter QJsonArray arrParams; arrParams.push_back(1); arrParams.push_back(0); arrParams.push_back(2); QJsonRpcMessage strRequest = QJsonRpcMessage::createRequest("service.outputParameter", arrParams); QJsonRpcMessage response = clientSocket->sendMessageBlocking(strRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE((int) response.result().toDouble(), 3); // only input parameters are provided QJsonObject objParams; objParams["in1"] = 1; objParams["in2"] = 3; strRequest = QJsonRpcMessage::createRequest("service.outputParameter", objParams); response = clientSocket->sendMessageBlocking(strRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE((int) response.result().toDouble(), 4); // also provide the in/out parameter objParams["out"] = 2; strRequest = QJsonRpcMessage::createRequest("service.outputParameter", objParams); response = clientSocket->sendMessageBlocking(strRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE((int) response.result().toDouble(), 6); // test strings QJsonArray stringParams; stringParams.push_back(QLatin1String("Sherlock")); stringParams.push_back(QLatin1String("")); stringParams.push_back(QLatin1String("Holmes")); strRequest = QJsonRpcMessage::createRequest("service.outputParameterWithStrings", stringParams); response = clientSocket->sendMessageBlocking(strRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toString(), QLatin1String("Sherlock Holmes")); // only input parameters are provided QJsonObject stringObjectParams; stringObjectParams["first"] = QLatin1String("Sherlock"); stringObjectParams["output"] = QLatin1String("Hello"); stringObjectParams["last"] = QLatin1String("Holmes"); strRequest = QJsonRpcMessage::createRequest("service.outputParameterWithStrings", stringObjectParams); response = clientSocket->sendMessageBlocking(strRequest); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toString(), QLatin1String("Hello Sherlock Holmes")); } void TestQJsonRpcServer::userDeletesReplyOnDelayedResponse() { QVERIFY(server->addService(new TestService)); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.delayedResponse"); connect(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage)), &QTestEventLoop::instance(), SLOT(exitLoop())); QJsonRpcServiceReply *reply = clientSocket->sendMessage(request); delete reply; // While this is not applicable for HTTP connections, I've left the code // up until this point to ensure that no memory is leaked QFETCH_GLOBAL(ServerType, serverType); if (serverType == HttpServer) { #if QT_VERSION >= 0x050000 QSKIP("Not applicable for HTTP connections"); #else QSKIP("Not applicable for HTTP connections", SkipAll); #endif } QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); } #if QT_VERSION >= 0x050200 void TestQJsonRpcServer::jsonReturnTypes() { QVERIFY(server->addService(new TestService)); { QJsonArray array; array.append(1); array.append(QLatin1String("two")); array.append(true); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.returnQJsonArray"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toArray(), array); } { QJsonObject object; object.insert("one", QLatin1String("one")); object.insert("two", 2); object.insert("three", true); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.returnQJsonObject"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QVERIFY(response.type() != QJsonRpcMessage::Error); QCOMPARE(response.result().toObject(), object); } } #endif class QJsonRpcServiceReplySpy : public QObject { Q_OBJECT public: explicit QJsonRpcServiceReplySpy(int expectedReplies, QObject *parent = 0) : QObject(parent), m_expectedReplies(expectedReplies) { } QList responses() const { return m_responses; } Q_SIGNALS: void finished(); public Q_SLOTS: void replyFinished() { QJsonRpcServiceReply *reply = qobject_cast(sender()); if (!reply) return; m_responses.append(reply->response()); reply->deleteLater(); if (m_responses.size() == m_expectedReplies) Q_EMIT finished(); } private: int m_expectedReplies; QList m_responses; }; void TestQJsonRpcServer::delayedResponseBasic() { QFETCH_GLOBAL(ServerType, serverType); if (serverType == HttpServer) { #if QT_VERSION >= 0x050000 QSKIP("QNAM makes deterministic order impossible here"); #else QSKIP("QNAM makes deterministic order impossible here", SkipAll); #endif } QVERIFY(server->addService(new TestDelayedResponseService)); QJsonRpcServiceReplySpy spy(6); connect(&spy, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); int delayedMessageId = 0; { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.delayedResponse"); QJsonRpcServiceReply *reply = clientSocket->sendMessage(request); connect(reply, SIGNAL(finished()), &spy, SLOT(replyFinished())); delayedMessageId = request.id(); } QList expectedMessageOrder; for (int i = 0; i < 5; ++i) { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.immediateResponse"); QJsonRpcServiceReply *reply = clientSocket->sendMessage(request); connect(reply, SIGNAL(finished()), &spy, SLOT(replyFinished())); expectedMessageOrder.append(request.id()); } expectedMessageOrder.append(delayedMessageId); QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); QList actualMessageOrder; foreach (QJsonRpcMessage response, spy.responses()) actualMessageOrder.append(response.id()); QCOMPARE(expectedMessageOrder, actualMessageOrder); } void TestQJsonRpcServer::delayedResponseSocketClosed() { QFETCH_GLOBAL(ServerType, serverType); if (serverType == HttpServer) { #if QT_VERSION >= 0x050000 QSKIP("Not applicable for HTTP connections"); #else QSKIP("Not applicable for HTTP connections", SkipAll); #endif } TestDelayedResponseService *service = new TestDelayedResponseService; QVERIFY(server->addService(service)); QSignalSpy spy(service, SIGNAL(responseResult(bool))); connect(service, SIGNAL(responseResult(bool)), &QTestEventLoop::instance(), SLOT(exitLoop())); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.delayedResponseWithClosedSocket"); QScopedPointer reply(clientSocket->sendMessage(request)); if (serverType == TcpServer) tcpSockets.first()->disconnectFromHost(); else if (serverType == LocalServer) localSockets.first()->disconnectFromServer(); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toBool(), false); } void TestQJsonRpcServer::addRemoveService() { TestService service; QVERIFY(server->addService(&service)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.noParam"); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); QCOMPARE(spyMessageReceived.count(), 1); QVERIFY(server->removeService(&service)); response = clientSocket->sendMessageBlocking(request); QVERIFY(response.errorCode() == QJsonRpc::MethodNotFound); QFETCH_GLOBAL(ServerType, serverType); if (serverType == TcpServer) QVERIFY(tcpServer->errorString().isEmpty()); else if (serverType == LocalServer) QVERIFY(localServer->errorString().isEmpty()); } void TestQJsonRpcServer::serviceWithNoGivenName() { QVERIFY(server->addService(new TestServiceWithoutServiceName)); QSignalSpy spyMessageReceived(clientSocket.data(), SIGNAL(messageReceived(QJsonRpcMessage))); QJsonRpcMessage request = QJsonRpcMessage::createRequest("testservicewithoutservicename.testMethod", QLatin1String("foo")); QJsonRpcMessage response = clientSocket->sendMessageBlocking(request); QVERIFY(response.errorCode() == QJsonRpc::NoError); QCOMPARE(request.id(), response.id()); QCOMPARE(spyMessageReceived.count(), 1); } void TestQJsonRpcServer::cantRemoveInvalidService() { TestService service; QCOMPARE(server->removeService(&service), false); } void TestQJsonRpcServer::cantAddServiceTwice() { TestService service; QVERIFY(server->addService(&service)); QCOMPARE(server->addService(&service), false); } QTEST_MAIN(TestQJsonRpcServer) #include "tst_qjsonrpcserver.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcservice/qjsonrpcservice.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_qjsonrpcservice SOURCES = tst_qjsonrpcservice.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcservice/tst_qjsonrpcservice.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcabstractserver.h" #include "qjsonrpcmessage.h" #include "qjsonrpcservice.h" class TestQJsonRpcService: public QObject { Q_OBJECT private slots: void dispatch_data(); void dispatch(); void ambiguousDispatch(); void dispatchSignals_data(); void dispatchSignals(); }; class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service") public: TestService(QObject *parent = 0) : QJsonRpcService(parent), m_stringCount(0), m_intCount(0), m_variantCount(0) {} QJsonRpcMessage testDispatch(const QJsonRpcMessage &message) { return QJsonRpcService::dispatch(message); } int stringCount() const { return m_stringCount; } int intCount() const { return m_intCount; } int variantCount() const { return m_variantCount; } void resetCounters() { m_stringCount = m_intCount = m_variantCount = 0; } Q_SIGNALS: void testSignal(); void testSignalWithParameter(const QString ¶m); public Q_SLOTS: QString testMethod(const QString &string) const { return string; } // note: order of definition matters here for ambiguousDispatch test void ambiguousMethod(const QString &) { m_stringCount++; } void ambiguousMethod(int) { m_intCount++; } void ambiguousMethod(const QVariant &) { m_variantCount++; } private: int m_stringCount; int m_intCount; int m_variantCount; }; class TestServiceProvider : public QJsonRpcServiceProvider { public: TestServiceProvider() {} }; void TestQJsonRpcService::dispatch_data() { QTest::addColumn("request"); QTest::addColumn("shouldSucceed"); { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.testMethod", QLatin1String("testParam")); QTest::newRow("valid-request-dispatch") << request << true; QJsonRpcMessage response = request.createResponse(QLatin1String("testResult")); QTest::newRow("invalid-response-dispatch") << response << false; } { QJsonObject namedParameters; namedParameters.insert("string", QLatin1String("testParam")); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.testMethod", namedParameters); QTest::newRow("valid-request-dispatch-with-named-parameters") << request << true; } { QJsonObject invalidNamedParameters; invalidNamedParameters.insert("testParameter", QLatin1String("testParam")); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.testMethod", invalidNamedParameters); QTest::newRow("invalid-request-dispatch-with-named-parameters") << request << false; } { QJsonRpcMessage request = QJsonRpcMessage::createNotification("service.testMethod", QLatin1String("testParam")); QTest::newRow("valid-notification-dispatch") << request << true; } { QJsonObject namedParameters; namedParameters.insert("string", QLatin1String("testParam")); QJsonRpcMessage request = QJsonRpcMessage::createNotification("service.testMethod", namedParameters); QTest::newRow("valid-notification-dispatch-with-named-parameters") << request << true; } QTest::newRow("invalid-dispatch") << QJsonRpcMessage() << false; } void TestQJsonRpcService::dispatch() { QFETCH(QJsonRpcMessage, request); QFETCH(bool, shouldSucceed); TestServiceProvider provider; TestService service; provider.addService(&service); QJsonRpcMessage response = service.testDispatch(request); if (shouldSucceed) QVERIFY(response.type() != QJsonRpcMessage::Error); else QVERIFY(response.type() == QJsonRpcMessage::Error); } void TestQJsonRpcService::ambiguousDispatch() { TestServiceProvider provider; TestService service; provider.addService(&service); QJsonRpcMessage stringDispatch = QJsonRpcMessage::createRequest("service.ambiguousMethod", QLatin1String("testParam")); service.testDispatch(stringDispatch); QCOMPARE(service.stringCount(), 1); QCOMPARE(service.intCount(), 0); QCOMPARE(service.variantCount(), 0); QJsonRpcMessage intDispatch = QJsonRpcMessage::createRequest("service.ambiguousMethod", 10); service.testDispatch(intDispatch); QCOMPARE(service.stringCount(), 1); QCOMPARE(service.intCount(), 1); QCOMPARE(service.variantCount(), 0); QStringList stringList = QStringList() << "test" << "string" << "list"; QJsonRpcMessage stringListDispatch = QJsonRpcMessage::createRequest("service.ambiguousMethod", QJsonValue::fromVariant(stringList)); service.testDispatch(stringListDispatch); QCOMPARE(service.stringCount(), 1); QCOMPARE(service.intCount(), 1); QCOMPARE(service.variantCount(), 1); } void TestQJsonRpcService::dispatchSignals_data() { QTest::addColumn("request"); QTest::addColumn("shouldSucceed"); { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.testSignal"); QTest::newRow("valid-request-signal-dispatch") << request << true; } { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.testSignalWithParameter", QLatin1String("testParam")); QTest::newRow("valid-request-signal-with-param-dispatch") << request << true; } { QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.testSignal", QLatin1String("testParam")); QTest::newRow("invalid-request-signal-dispatch") << request << false; } } void TestQJsonRpcService::dispatchSignals() { QFETCH(QJsonRpcMessage, request); QFETCH(bool, shouldSucceed); TestServiceProvider provider; TestService service; provider.addService(&service); QJsonRpcMessage response = service.testDispatch(request); QJsonRpcMessage::Type messageType = shouldSucceed ? QJsonRpcMessage::Response : QJsonRpcMessage::Error; QCOMPARE(response.type(), messageType); } QTEST_MAIN(TestQJsonRpcService) #include "tst_qjsonrpcservice.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcsocket/qjsonrpcsocket.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) TARGET = tst_qjsonrpcsocket SOURCES = tst_qjsonrpcsocket.cpp RESOURCES = tst_qjsonrpcsocket.qrc ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcsocket/testwire.json ================================================ {"object with 1 member":["array with 1 element"]} {} { "integer": 1234567890, "real": -9876.543210, "e": 0.123456789e-12, "E": 1.234567890E+34, "": 23456789012E66, "zero": 0, "one": 1, "space": " ", "quote": "\"", "backslash": "\\", "controls": "\b\f\n\r\t", "slash": "/ & \/", "alpha": "abcdefghijklmnopqrstuvwxyz", "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "digit": "0123456789", "0123456789": "digit", "special": "`1~!@#$%^&*()_+-={\':[,]}|;.?", "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", "true": true, "false": false, "null": null, "array":[ ], "object":{ }, "address": "50 St. James Street", "url": "http://www.JSON.org/", "comment": "// /* */": " ", " s p a c e d " :[1,2 , 3 , 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", "quotes": "" \u0022 %22 0x22 034 "", "\/\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?" : "A key can be any string" } {"foo": "bar"} {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}} {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}} {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}} {"classification":{"relevancyScore":1000,"searchUrl":{"value":"http://www.bizrate.com/iphone-cases/index__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"}},"products":{"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$4,833.99","integral":483399}},"product":[{"type":"PRODUCT","title":"Silicone case for iPhone 3G/ 3GS","description":"Elite Horizontal Leather Pouch for Apple iPhone 3G/3Gs - Premium quality horizontal case for your Apple iPhone 3G/3Gs. This pouch is ideal for the style conscious on the go. This great looking case is made from high-quality leather with classic black...","manufacturer":"Apple","url":{"value":"http://www.bizrate.com/silicone-case-for-iphone-3g-3gs--pid1968262863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1968262863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1968262863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1968262863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1968262863","xsize":400,"ysize":400}]},"relevancy":310711221747712.000000,"priceSet":{"minPrice":{"value":"$1.56","integral":156},"maxPrice":{"value":"$29.99","integral":2999},"stores":14},"id":1968262863,"categoryId":8515},{"type":"PRODUCT","title":"Nonslip Checkered Silicone Skin Soft Case for iPhone 4 4G","description":"Specification:Product Name Silicone Skin Case Model for Apple iPhone 4 Color Black Material Soft Silicone Skin Weight 26g Package 1 x Case for Apple iPhone 4 Description:This is a non-OEM product.Accessory Only, Phone is not included.","manufacturer":"H&B","url":{"value":"http://www.bizrate.com/nonslip-checkered-silicone-skin-soft-case-for-iphone-4-4g--pid2534935499/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2534935499","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2534935499","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2534935499","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2534935499","xsize":400,"ysize":400}]},"relevancy":175580930637824.000000,"priceSet":{"minPrice":{"value":"$0.45","integral":45},"maxPrice":{"value":"$194.95","integral":19495},"stores":34},"id":2534935499,"categoryId":8515},{"type":"PRODUCT","title":"Plastic Case for iPhone 4 - Black","description":"Description:Detachable Windmill Type Matte Hard Plastic Case Cover for iPhone 4 (Black / Magenta)Customised your iPhone with this wonderful Plastic Case which is a accessory for your iPhone 4 which is made of high quality and durable plastic, protect","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/plastic-case-for-iphone-4-black--pid2305624670/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2305624670","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2305624670","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2305624670","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2305624670","xsize":400,"ysize":400}]},"relevancy":132488642953216.000000,"priceSet":{"minPrice":{"value":"$0.99","integral":99},"maxPrice":{"value":"$303.68","integral":30368},"stores":33},"id":2305624670,"categoryId":8515},{"type":"PRODUCT","title":"Protective Silicone Case for iPhone 4","description":"Made of high quality PVC material Protects your iPhone 4 from any scratch and dirt Easy to install and remove, no any tool needed Cut-out design allows user can access all keypad / button and slot without having to remove the case","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/protective-silicone-case-for-iphone-4--pid2120981405/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2120981405","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2120981405","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2120981405","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2120981405","xsize":400,"ysize":400}]},"relevancy":108614681362432.000000,"priceSet":{"minPrice":{"value":"$1.70","integral":170},"maxPrice":{"value":"$99.99","integral":9999},"stores":11},"id":2120981405,"categoryId":8515},{"type":"PRODUCT","title":"Iphone® 4 Aerosport Case","description":"Do more than just protect your iPhone 4 with this case bundle from rooCASE. This 3 in 1 bundle include a snap-on case, screen protector and a Nike+ sensor shoe pouch that can be use on most running shoes. Color: Purple Design: Love Provides protection...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/iphone-4-aerosport-case--pid2203798762/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2203798762","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2203798762","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2203798762","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2203798762","xsize":400,"ysize":400}]},"relevancy":96203484168192.000000,"priceSet":{"minPrice":{"value":"$2.49","integral":249},"maxPrice":{"value":"$79.95","integral":7995},"stores":16},"id":2203798762,"categoryId":8515},{"type":"PRODUCT","title":"Case Reflect For Iphone 3G","description":"NCAA iPhone 3G faceplate features the schools primary logo silk screened on the front of the case.","manufacturer":"Griffin","url":{"value":"http://www.bizrate.com/case-reflect-for-iphone-3g--pid1114627445/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=1114627445","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=1114627445","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=1114627445","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=1114627445","xsize":400,"ysize":400}]},"relevancy":84727583211520.000000,"priceSet":{"minPrice":{"value":"$0.69","integral":69},"maxPrice":{"value":"$75.52","integral":7552},"stores":59},"id":1114627445,"categoryId":8515},{"type":"PRODUCT","title":"Infuse Protector Case for iPhone 4 Black","description":"Protect and personalize your iPhone 4 with this front and back image design Protector Case. Form-fitting front and back hard plastic covers Protects your cell phone without adding a lot of bulk Smooth glossy finish Snaps on to the front edges, sides...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/infuse-protector-case-for-iphone-4-black--pid2557462717/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2557462717","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2557462717","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2557462717","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2557462717","xsize":400,"ysize":400}]},"relevancy":80831066406912.000000,"priceSet":{"minPrice":{"value":"$0.59","integral":59},"maxPrice":{"value":"$79.00","integral":7900},"stores":24},"id":2557462717,"categoryId":8515},{"type":"PRODUCT","title":"Dragonfly iPhone 4 Kream Case - Black","description":"DF-0030219 - White, Kream Case for iPhone 4 by Dragon-Fly","url":{"value":"http://www.bizrate.com/dragonfly-iphone-4-kream-case-black--pid2442061740/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2442061740","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2442061740","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2442061740","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2442061740","xsize":400,"ysize":400}]},"relevancy":70900229603328.000000,"priceSet":{"minPrice":{"value":"$1.05","integral":105},"maxPrice":{"value":"$94.49","integral":9449},"stores":30},"id":2442061740,"categoryId":8515},{"type":"PRODUCT","title":"Apple iPhone 3G/3GS Silicone Case (Black)","description":"Snap on Apple iPhone 3G 3GS Synthetic Leather Hardshell Case! Premium Qualtiy Synthetic Leather cover provides style, comfort, and protection to your iPhone 3G & 3GS. It also adds a sophisticated elegance and cool to your fashion. The case allows Quick...","manufacturer":"Luxmo","url":{"value":"http://www.bizrate.com/apple-iphone-3g3gs-silicone-case-black--pid2004746863/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2004746863","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2004746863","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2004746863","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2004746863","xsize":400,"ysize":400}]},"relevancy":65194915004416.000000,"priceSet":{"minPrice":{"value":"$0.01","integral":1},"maxPrice":{"value":"$414.99","integral":41499},"stores":39},"id":2004746863,"categoryId":8515},{"type":"PRODUCT","title":"Otterbox iPhone 4 Defender Case - Black","description":"Your iPhone 4 has become a big part of your life. With FaceTime video, retina display, multitasking, HD video recording and more - you've got a lot to lose. You won't find a tougher case than the OtterBox Defender Series for iPhone 4. This three-layer...","manufacturer":"Universal","url":{"value":"http://www.bizrate.com/otterbox-iphone-4-defender-case-black--pid2584611575/compareprices__rf--af1__af_assettype_id--10__af_creative_id--6__af_id--50085__af_placement_id--1.html"},"images":{"image":[{"value":"http://image10.bizrate-images.com/resize?sq=60&uid=2584611575","xsize":60,"ysize":60},{"value":"http://image10.bizrate-images.com/resize?sq=100&uid=2584611575","xsize":100,"ysize":100},{"value":"http://image10.bizrate-images.com/resize?sq=160&uid=2584611575","xsize":160,"ysize":160},{"value":"http://image10.bizrate-images.com/resize?sq=400&uid=2584611575","xsize":400,"ysize":400}]},"relevancy":61515478597632.000000,"priceSet":{"minPrice":{"value":"$3.28","integral":328},"maxPrice":{"value":"$110.65","integral":11065},"stores":25},"id":2584611575,"categoryId":8515}],"includedResults":10,"totalResults":2000}} ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcsocket/tst_qjsonrpcsocket.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcservice_p.h" #include "qjsonrpcservice.h" #include "qjsonrpcmessage.h" #include "qjsonrpcservicereply.h" #include "qjsonrpcsocket_p.h" #include "qjsonrpcsocket.h" class QBufferBackedQJsonRpcSocketPrivate : public QJsonRpcSocketPrivate { public: QBufferBackedQJsonRpcSocketPrivate(QBuffer *b, QJsonRpcSocket *q) : QJsonRpcSocketPrivate(q), buffer(b) { device = b; } virtual void _q_processIncomingData() { buffer->seek(0); QJsonRpcSocketPrivate::_q_processIncomingData(); } QBuffer *buffer; }; class QBufferBackedQJsonRpcSocket : public QJsonRpcSocket { Q_OBJECT public: QBufferBackedQJsonRpcSocket(QBuffer *buffer, QObject *parent = 0) : QJsonRpcSocket(*new QBufferBackedQJsonRpcSocketPrivate(buffer, this), parent) { } }; class TestQJsonRpcSocket: public QObject { Q_OBJECT public: enum InvokeType { SendMessage, InvokeRemoteMethod }; private Q_SLOTS: void initTestCase_data(); void noParameters(); void multiParameter(); void notification(); void response(); void delayedMessageReceive(); private: // benchmark parsing speed void jsonParsingBenchmark(); }; Q_DECLARE_METATYPE(TestQJsonRpcSocket::InvokeType) void TestQJsonRpcSocket::initTestCase_data() { QTest::addColumn("invokeType"); QTest::newRow("sendMessage") << SendMessage; QTest::newRow("invokeRemoteMethod") << InvokeRemoteMethod; } void TestQJsonRpcSocket::noParameters() { QFETCH_GLOBAL(InvokeType, invokeType); QBuffer buffer; buffer.open(QIODevice::ReadWrite); QJsonRpcSocket serviceSocket(&buffer, this); QSignalSpy spyMessageReceived(&serviceSocket, SIGNAL(messageReceived(QJsonRpcMessage))); QVERIFY(serviceSocket.isValid()); QJsonRpcMessage request; QScopedPointer reply; if (invokeType == SendMessage) { request = QJsonRpcMessage::createRequest(QString("test.noParam")); reply.reset(serviceSocket.sendMessage(request)); } else if (invokeType == InvokeRemoteMethod) { reply.reset(serviceSocket.invokeRemoteMethod("test.noParam")); request = reply->request(); } QJsonRpcMessage bufferMessage = QJsonRpcMessage::fromJson(buffer.data()); QCOMPARE(request.id(), bufferMessage.id()); QCOMPARE(request.type(), bufferMessage.type()); QCOMPARE(request.method(), bufferMessage.method()); QCOMPARE(request.params(), bufferMessage.params()); QCOMPARE(spyMessageReceived.count(), 0); } void TestQJsonRpcSocket::multiParameter() { QFETCH_GLOBAL(InvokeType, invokeType); QBuffer buffer; buffer.open(QIODevice::ReadWrite); QJsonRpcSocket serviceSocket(&buffer, this); QSignalSpy spyMessageReceived(&serviceSocket, SIGNAL(messageReceived(QJsonRpcMessage))); QVERIFY(serviceSocket.isValid()); QJsonArray params; params.append(false); params.append(true); QJsonRpcMessage request; QScopedPointer reply; if (invokeType == SendMessage) { request = QJsonRpcMessage::createRequest("test.multiParam", params); reply.reset(serviceSocket.sendMessage(request)); } else if (invokeType == InvokeRemoteMethod) { #if QT_VERSION <= 0x050000 QVariant paramsVariant = QVariant::fromValue(params); reply.reset(serviceSocket.invokeRemoteMethod("test.multiParam", paramsVariant)); #else reply.reset(serviceSocket.invokeRemoteMethod("test.multiParam", params)); #endif request = reply->request(); } QJsonRpcMessage bufferMessage = QJsonRpcMessage::fromJson(buffer.data()); QCOMPARE(request.id(), bufferMessage.id()); QCOMPARE(request.type(), bufferMessage.type()); QCOMPARE(request.method(), bufferMessage.method()); QCOMPARE(request.params(), bufferMessage.params()); QCOMPARE(spyMessageReceived.count(), 0); } void TestQJsonRpcSocket::notification() { QFETCH_GLOBAL(InvokeType, invokeType); QBuffer buffer; buffer.open(QIODevice::ReadWrite); QJsonRpcSocket serviceSocket(&buffer, this); QSignalSpy spyMessageReceived(&serviceSocket, SIGNAL(messageReceived(QJsonRpcMessage))); QVERIFY(serviceSocket.isValid()); QJsonRpcMessage notification; QScopedPointer reply; if (invokeType == SendMessage) { notification = QJsonRpcMessage::createRequest("test.notify"); reply.reset(serviceSocket.sendMessage(notification)); } else if (invokeType == InvokeRemoteMethod) { reply.reset(serviceSocket.invokeRemoteMethod("test.notify")); notification = reply->request(); } QJsonRpcMessage bufferMessage = QJsonRpcMessage::fromJson(buffer.data()); QCOMPARE(notification.id(), bufferMessage.id()); QCOMPARE(notification.type(), bufferMessage.type()); QCOMPARE(notification.method(), bufferMessage.method()); QCOMPARE(notification.params(), bufferMessage.params()); QCOMPARE(spyMessageReceived.count(), 0); } void TestQJsonRpcSocket::response() { QBuffer buffer; buffer.open(QIODevice::ReadWrite); QJsonRpcSocket serviceSocket(&buffer, this); QSignalSpy spyMessageReceived(&serviceSocket, SIGNAL(messageReceived(QJsonRpcMessage))); QVERIFY(serviceSocket.isValid()); QJsonRpcMessage response = QJsonRpcMessage::createRequest("test.response"); response = response.createResponse(QJsonValue()); QScopedPointer reply; reply.reset(serviceSocket.sendMessage(response)); QJsonRpcMessage bufferMessage = QJsonRpcMessage::fromJson(buffer.data()); QCOMPARE(response.id(), bufferMessage.id()); QCOMPARE(response.type(), bufferMessage.type()); QCOMPARE(response.method(), bufferMessage.method()); QCOMPARE(response.params(), bufferMessage.params()); QCOMPARE(spyMessageReceived.count(), 0); } void TestQJsonRpcSocket::jsonParsingBenchmark() { QFile testData(":/testwire.json"); QVERIFY(testData.open(QIODevice::ReadOnly)); QByteArray jsonData = testData.readAll(); QJsonRpcSocketPrivate socketPrivate(0); int messageCount = 0; while (!jsonData.isEmpty()) { int pos = 0; QBENCHMARK { pos = socketPrivate.findJsonDocumentEnd(jsonData); } if (pos > -1) { messageCount++; jsonData = jsonData.mid(pos + 1); } else { break; } } QCOMPARE(messageCount, 8); } void TestQJsonRpcSocket::delayedMessageReceive() { QBuffer buffer; buffer.open(QIODevice::ReadWrite); QBufferBackedQJsonRpcSocket serviceSocket(&buffer, this); QSignalSpy spyMessageReceived(&serviceSocket, SIGNAL(messageReceived(QJsonRpcMessage))); QVERIFY(serviceSocket.isValid()); QJsonRpcMessage request = QJsonRpcMessage::createRequest("test.multiParam"); QJsonRpcMessage response = serviceSocket.sendMessageBlocking(request, 1); QVERIFY(response.type() == QJsonRpcMessage::Error); spyMessageReceived.removeLast(); // this should cause a crash, before the fix const char *fakeDelayedResult = "{" \ "\"id\": %1," \ "\"jsonrpc\": \"2.0\"," \ "\"result\": true" \ "}"; buffer.write(QString(fakeDelayedResult).arg(request.id()).toLatin1()); while (!spyMessageReceived.size()) qApp->processEvents(); } QTEST_MAIN(TestQJsonRpcSocket) #include "tst_qjsonrpcsocket.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/auto/qjsonrpcsocket/tst_qjsonrpcsocket.qrc ================================================ testwire.json ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/common/signalspy.h ================================================ #ifndef SIGNALSPY_H #define SIGNALSPY_H #if QT_VERSION >= 0x050000 typedef QSignalSpy SignalSpy; #else #include #include #include #include #include #include #include class QVariant; class SignalSpy: public QObject, public QList > { public: explicit SignalSpy(const QObject *obj, const char *aSignal) : m_waiting(false) { static const int memberOffset = QObject::staticMetaObject.methodCount(); if (!obj) { qWarning("SignalSpy: Cannot spy on a null object"); return; } if (!aSignal) { qWarning("SignalSpy: Null signal name is not valid"); return; } if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE) { qWarning("SignalSpy: Not a valid signal, use the SIGNAL macro"); return; } const QByteArray ba = QMetaObject::normalizedSignature(aSignal + 1); const QMetaObject * const mo = obj->metaObject(); const int sigIndex = mo->indexOfMethod(ba.constData()); if (sigIndex < 0) { qWarning("SignalSpy: No such signal: '%s'", ba.constData()); return; } if (!QMetaObject::connect(obj, sigIndex, this, memberOffset, Qt::DirectConnection, 0)) { qWarning("SignalSpy: QMetaObject::connect returned false. Unable to connect."); return; } sig = ba; initArgs(mo->method(sigIndex), obj); } inline bool isValid() const { return !sig.isEmpty(); } inline QByteArray signal() const { return sig; } bool wait(int timeout = 5) { Q_ASSERT(!m_waiting); const int origCount = count(); m_waiting = true; m_loop.enterLoop(timeout); m_waiting = false; return count() > origCount; } int qt_metacall(QMetaObject::Call call, int methodId, void **a) { methodId = QObject::qt_metacall(call, methodId, a); if (methodId < 0) return methodId; if (call == QMetaObject::InvokeMetaMethod) { if (methodId == 0) { appendArgs(a); } --methodId; } return methodId; } private: void initArgs(const QMetaMethod &member) { initArgs(member, 0); } void initArgs(const QMetaMethod &member, const QObject *obj) { Q_UNUSED(obj) QList params = member.parameterTypes(); for (int i = 0; i < params.count(); ++i) { int tp = QMetaType::type(params.at(i).constData()); if (tp == QMetaType::Void) qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.", params.at(i).constData()); args << tp; } } void appendArgs(void **a) { QList list; for (int i = 0; i < args.count(); ++i) { QMetaType::Type type = static_cast(args.at(i)); list << QVariant(type, a[i + 1]); } append(list); if (m_waiting) m_loop.exitLoop(); } // the full, normalized signal name QByteArray sig; // holds the QMetaType types for the argument list of the signal QVector args; QTestEventLoop m_loop; bool m_waiting; }; #endif #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/gen-coverage.sh ================================================ #!/bin/bash lcov --capture --directory . --output-file coverage-gcov.info --no-external lcov --output-file coverage-gcov.info --remove coverage-gcov.info 'moc_*.cpp' '*.moc*' '.*rcc*' '*3rdparty*' 'qrc_*' genhtml coverage-gcov.info --output-directory doc/coverage ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/benchmark/benchmark.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TARGET = benchmark SOURCES = \ tst_benchmark.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/benchmark/tst_benchmark.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #else #include "json/qjsondocument.h" #endif #include "qjsonrpcabstractserver.h" #include "qjsonrpcsocket.h" #include "qjsonrpcservice.h" #include "qjsonrpcmessage.h" class TestBenchmark: public QObject { Q_OBJECT private Q_SLOTS: void simple(); void namedParameters(); }; class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "service") public: TestService(QObject *parent = 0) : QJsonRpcService(parent) {} QJsonRpcMessage testDispatch(const QJsonRpcMessage &message) { return QJsonRpcService::dispatch(message); } public Q_SLOTS: QString singleParam(int i) const { return QString::number(i); } QString singleParam(const QString &string) const { return string; } QString singleParam(const QVariant &k) const { return k.toString(); } QString namedParams(int integer, const QString &string, double doub) { (void) integer; (void) doub; return string; } }; class TestServiceProvider : public QJsonRpcServiceProvider { public: TestServiceProvider() {} }; void TestBenchmark::simple() { TestServiceProvider provider; TestService service; provider.addService(&service); QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.singleParam", QString("test")); QBENCHMARK { QJsonRpcMessage response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); } } void TestBenchmark::namedParameters() { TestServiceProvider provider; TestService service; provider.addService(&service); QJsonObject obj; obj["integer"] = 1; obj["string"] = QLatin1String("str"); obj["doub"] = 1.2; QJsonRpcMessage request = QJsonRpcMessage::createRequest("service.namedParams", obj); QBENCHMARK { QJsonRpcMessage response = service.testDispatch(request); QVERIFY(response.type() != QJsonRpcMessage::Error); } } QTEST_MAIN(TestBenchmark) #include "tst_benchmark.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/console/console.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app QT += script core HEADERS = interface.h SOURCES = interface.cpp \ main.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/console/interface.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcservice.h" #include "qjsonrpcservicereply.h" #include "interface.h" QJsonRpcServiceSocketPrototype::QJsonRpcServiceSocketPrototype(QObject *parent) : QObject(parent), m_socket(0) { } QJsonRpcServiceSocketPrototype::~QJsonRpcServiceSocketPrototype() { } void QJsonRpcServiceSocketPrototype::connectToLocalService(const QString &service) { if (m_socket) { context()->throwError("already connected to local service"); return; } QLocalSocket *localSocket = new QLocalSocket(this); localSocket->connectToServer(service); if (!localSocket->waitForConnected()) { context()->throwError("could not connect to local sevice: " + service); localSocket->deleteLater(); return; } m_socket = new QJsonRpcSocket(localSocket, this); } QVariant QJsonRpcServiceSocketPrototype::invokeRemoteMethod(const QString &method, const QVariant ¶m1, const QVariant ¶m2, const QVariant ¶m3, const QVariant ¶m4, const QVariant ¶m5, const QVariant ¶m6, const QVariant ¶m7, const QVariant ¶m8, const QVariant ¶m9, const QVariant ¶m10) { QVariantList params; if (param1.isValid()) params.append(param1); if (param2.isValid()) params.append(param2); if (param3.isValid()) params.append(param3); if (param4.isValid()) params.append(param4); if (param5.isValid()) params.append(param5); if (param6.isValid()) params.append(param6); if (param7.isValid()) params.append(param7); if (param8.isValid()) params.append(param8); if (param9.isValid()) params.append(param9); if (param10.isValid()) params.append(param10); QJsonRpcMessage request = QJsonRpcMessage::createRequest(method, QJsonArray::fromVariantList(params)); QJsonRpcServiceReply *reply = m_socket->sendMessage(request); QEventLoop loop; connect(m_socket, SIGNAL(messageReceived(QJsonRpcMessage)), &loop, SLOT(quit())); connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); if (reply->response().type() == QJsonRpcMessage::Invalid) { context()->throwError("request timed out"); return QVariant(); } return reply->response().result().toVariant(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/console/interface.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef QJSONRPCSERVICESCRIPT_H #define QJSONRPCSERVICESCRIPT_H #include #include #include #include class QJsonRpcSocket; class QJsonRpcServiceSocketPrototype : public QObject, protected QScriptable { Q_OBJECT public: QJsonRpcServiceSocketPrototype(QObject *parent = 0); ~QJsonRpcServiceSocketPrototype(); public Q_SLOTS: void connectToLocalService(const QString &service); QVariant invokeRemoteMethod(const QString &method, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QVariant &arg3 = QVariant(), const QVariant &arg4 = QVariant(), const QVariant &arg5 = QVariant(), const QVariant &arg6 = QVariant(), const QVariant &arg7 = QVariant(), const QVariant &arg8 = QVariant(), const QVariant &arg9 = QVariant(), const QVariant &arg10 = QVariant()); private: QJsonRpcSocket *m_socket; }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/console/main.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include #include #include "interface.h" static bool wantsToQuit; static QScriptValue qtscript_quit(QScriptContext *ctx, QScriptEngine *eng) { Q_UNUSED(ctx); wantsToQuit = true; return eng->undefinedValue(); } static void interactive(QScriptEngine *eng) { QScriptValue global = eng->globalObject(); QScriptValue quitFunction = eng->newFunction(qtscript_quit); if (!global.property(QLatin1String("exit")).isValid()) global.setProperty(QLatin1String("exit"), quitFunction); if (!global.property(QLatin1String("quit")).isValid()) global.setProperty(QLatin1String("quit"), quitFunction); wantsToQuit = false; QTextStream qin(stdin, QFile::ReadOnly); const char *qscript_prompt = "console> "; const char *dot_prompt = ".... "; const char *prompt = qscript_prompt; QString code; forever { QString line; printf("%s", prompt); fflush(stdout); line = qin.readLine(); if (line.isNull()) break; code += line; code += QLatin1Char('\n'); if (line.trimmed().isEmpty()) { continue; } else if (! eng->canEvaluate(code)) { prompt = dot_prompt; } else { QScriptValue result = eng->evaluate(code, QLatin1String("typein")); code.clear(); prompt = qscript_prompt; if (! result.isUndefined()) fprintf(stderr, "%s\n", qPrintable(result.toString())); if (wantsToQuit) break; } } } static QScriptValue importExtension(QScriptContext *context, QScriptEngine *engine) { return engine->importExtension(context->argument(0).toString()); } static QScriptValue loadScripts(QScriptContext *context, QScriptEngine *engine) { for (int i = 0; i < context->argumentCount(); ++i) { QString fileName = context->argument(0).toString(); QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) return context->throwError(QString::fromLatin1("could not open %0 for reading").arg(fileName)); QTextStream ts(&file); QString contents = ts.readAll(); file.close(); QScriptContext *pc = context->parentContext(); context->setActivationObject(pc->activationObject()); context->setThisObject(pc->thisObject()); QScriptValue ret = engine->evaluate(contents); if (engine->hasUncaughtException()) return ret; } return engine->undefinedValue(); } int main(int argc, char *argv[]) { QCoreApplication *app; if (argc >= 2 && !qstrcmp(argv[1], "-tty")) { ++argv; --argc; app = new QCoreApplication(argc, argv); } else { app = new QCoreApplication(argc, argv); } QScriptEngine *eng = new QScriptEngine(); QScriptValue globalObject = eng->globalObject(); globalObject.setProperty("load", eng->newFunction(loadScripts, /*length=*/1)); { if (!globalObject.property("qt").isObject()) globalObject.setProperty("qt", eng->newObject()); QScriptValue qscript = eng->newObject(); qscript.setProperty("importExtension", eng->newFunction(importExtension)); globalObject.property("qt").setProperty("script", qscript); } // ByteArrayClass *byteArrayClass = new ByteArrayClass(eng); // globalObject.setProperty("ByteArray", byteArrayClass->constructor()); QScriptValue rpcObject = eng->newQObject(new QJsonRpcServiceSocketPrototype); globalObject.setProperty("qjsonrpc", rpcObject); if (! *++argv) { interactive(eng); return EXIT_SUCCESS; } while (const char *arg = *argv++) { QString fn = QString::fromLocal8Bit(arg); if (fn == QLatin1String("-i")) { interactive(eng); break; } QString contents; int lineNumber = 1; if (fn == QLatin1String("-")) { QTextStream stream(stdin, QFile::ReadOnly); contents = stream.readAll(); } else { QFile file(fn); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); contents = stream.readAll(); file.close(); // strip off #!/usr/bin/env qscript line if (contents.startsWith("#!")) { contents.remove(0, contents.indexOf("\n")); ++lineNumber; } } } if (contents.isEmpty()) continue; QScriptValue r = eng->evaluate(contents, fn, lineNumber); if (eng->hasUncaughtException()) { QStringList backtrace = eng->uncaughtExceptionBacktrace(); fprintf (stderr, " %s\n%s\n\n", qPrintable(r.toString()), qPrintable(backtrace.join("\n"))); return EXIT_FAILURE; } } delete eng; delete app; return EXIT_SUCCESS; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/httpclient/httpclient.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app TARGET = httpclient SOURCES = \ main.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/httpclient/main.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include "qjsonrpchttpclient.h" class HttpClient : public QJsonRpcHttpClient { Q_OBJECT public: HttpClient(const QString &endpoint, QObject *parent = 0) : QJsonRpcHttpClient(endpoint, parent) { // defaults added for my local test server m_username = "bitcoinrpc"; m_password = "232fb3276bbb7437d265298ea48bdc46"; } void setUsername(const QString &username) { m_username = username; } void setPassword(const QString &password) { m_password = password; } private Q_SLOTS: virtual void handleAuthenticationRequired(QNetworkReply *reply, QAuthenticator * authenticator) { Q_UNUSED(reply) authenticator->setUser(m_username); authenticator->setPassword(m_password); } private: QString m_username; QString m_password; }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); if (app.arguments().size() < 2) { qDebug() << "usage: " << argv[0] << "[-u username] [-p password] "; return -1; } HttpClient client("http://127.0.0.1:8332"); if (app.arguments().contains("-u")) { int idx = app.arguments().indexOf("-u"); app.arguments().removeAt(idx); client.setUsername(app.arguments().takeAt(idx)); } if (app.arguments().contains("-p")) { int idx = app.arguments().indexOf("-p"); app.arguments().removeAt(idx); client.setPassword(app.arguments().takeAt(idx)); } QJsonRpcMessage message = QJsonRpcMessage::createRequest(app.arguments().at(1)); QJsonRpcMessage response = client.sendMessageBlocking(message); if (response.type() == QJsonRpcMessage::Error) { qDebug() << response.errorData(); return -1; } qDebug() << response.toJson(); } #include "main.moc" ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/httpserver/httpserver.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include "qjsonrpchttpserver.h" #include "testservice.h" int main(int argc, char **argv) { QCoreApplication app(argc, argv); QJsonRpcHttpServer rpcServer; rpcServer.addService(new TestService); if (!rpcServer.listen(QHostAddress::LocalHost, 5555)) { qDebug() << "can't start tcp server: " << rpcServer.errorString(); return -1; } return app.exec(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/httpserver/httpserver.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app TARGET = httpserver HEADERS = \ testservice.h SOURCES = \ testservice.cpp \ httpserver.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/httpserver/testservice.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include #include "testservice.h" TestService::TestService(QObject *parent) : QJsonRpcService(parent) { QThreadPool::globalInstance()->setMaxThreadCount(10); } void TestService::testMethod() { qDebug() << Q_FUNC_INFO << "called" << endl; } void TestService::testMethodWithParams(const QString &first, bool second, double third) { qDebug() << Q_FUNC_INFO << "called with parameters: " << endl << " first: " << first << endl << "second: " << second << endl << " third: " << third << endl; } void TestService::testMethodWithVariantParams(const QString &first, bool second, double third, const QVariant &fourth) { qDebug() << Q_FUNC_INFO << "called with variant parameters: " << endl << " first: " << first << endl << "second: " << second << endl << " third: " << third << endl << "fourth: " << fourth << endl; } QString TestService::testMethodWithParamsAndReturnValue(const QString &name) { return QString("Hello %1").arg(name); } void TestService::testMethodWithDefaultParameter(const QString &first, const QString &second) { qDebug() << Q_FUNC_INFO << endl << "first: " << first << endl << (second.isEmpty() ? "not defined, default parameter" : second) << endl; } QString TestService::immediateResponse() { return "immediate"; } QString TestService::longTaskWithImmediateResponse() { QEventLoop loop; QTimer::singleShot(1000, &loop, SLOT(quit())); loop.exec(); return "long immediate"; } class DelayedResponseJob : public QRunnable { public: DelayedResponseJob(const QJsonRpcServiceRequest &request) : m_request(request) { } protected: virtual void run() { // do some work QEventLoop loop; QTimer::singleShot(1000, &loop, SLOT(quit())); loop.exec(); // respond QJsonRpcMessage response = m_request.request().createResponse(QLatin1String("long delayed")); m_request.respond(response); } private: QJsonRpcServiceRequest m_request; }; QString TestService::longTaskWithDelayedResponse() { beginDelayedResponse(); QThreadPool::globalInstance()->start(new DelayedResponseJob(currentRequest())); return QString(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/httpserver/testservice.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef TESTSERVICE_H #define TESTSERVICE_H #include "qjsonrpcservice.h" class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "agent") public: TestService(QObject *parent = 0); public Q_SLOTS: void testMethod(); void testMethodWithParams(const QString &first, bool second, double third); void testMethodWithVariantParams(const QString &first, bool second, double third, const QVariant &fourth); QString testMethodWithParamsAndReturnValue(const QString &name); void testMethodWithDefaultParameter(const QString &first, const QString &second = QString()); QString immediateResponse(); QString longTaskWithImmediateResponse(); QString longTaskWithDelayedResponse(); }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localclient/localclient.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcservice.h" #include "qjsonrpcservicereply.h" #include "localclient.h" LocalClient::LocalClient(QObject *parent) : QObject(parent), m_client(0) { } void LocalClient::run() { QLocalSocket *socket = new QLocalSocket(this); QString serviceName = QDir::temp().absoluteFilePath("testservice"); socket->connectToServer(serviceName); if (!socket->waitForConnected()) { qDebug() << "could not connect to server: " << socket->errorString(); return; } m_client = new QJsonRpcSocket(socket, this); QJsonRpcServiceReply *reply = m_client->invokeRemoteMethod("agent.testMethod"); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); reply = m_client->invokeRemoteMethod("agent.testMethodWithParams", "one", false, 10); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); reply = m_client->invokeRemoteMethod("agent.testMethodWithVariantParams", "one", false, 10, QVariant(2.5)); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); reply = m_client->invokeRemoteMethod("agent.testMethodWithParamsAndReturnValue", "matt"); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); } void LocalClient::processResponse() { QJsonRpcServiceReply *reply = static_cast(sender()); if (!reply) { qDebug() << "invalid response received"; return; } qDebug() << "response received: " << reply->response(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localclient/localclient.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef CLIENT_H #define CLIENT_H #include #include "qjsonrpcmessage.h" class QJsonRpcSocket; class LocalClient : public QObject { Q_OBJECT public: LocalClient(QObject *parent = 0); void run(); private Q_SLOTS: void processResponse(); private: QJsonRpcSocket *m_client; }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localclient/localclient.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app TARGET = localclient HEADERS = \ localclient.h SOURCES = \ localclient.cpp \ main.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localclient/main.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include "localclient.h" int main(int argc, char **argv) { QCoreApplication app(argc, argv); LocalClient client; client.run(); return app.exec(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localclient/runclientmac ================================================ #!/bin/bash DYLD_FRAMEWORK_PATH=../../../qjson/lib:../../../lib ./client ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localserver/localserver.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include "qjsonrpclocalserver.h" #include "testservice.h" int main(int argc, char **argv) { QCoreApplication app(argc, argv); QString serviceName = QDir::temp().absoluteFilePath("testservice"); if (QFile::exists(serviceName)) { if (!QFile::remove(serviceName)) { qDebug() << "couldn't delete temporary service"; return -1; } } QJsonRpcLocalServer rpcServer; rpcServer.addService(new TestService); if (!rpcServer.listen(serviceName)) { qDebug() << "could not start server: " << rpcServer.errorString(); return -1; } return app.exec(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localserver/localserver.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app TARGET = localserver HEADERS = \ testservice.h SOURCES = \ testservice.cpp \ localserver.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localserver/runservermac ================================================ #!/bin/bash DYLD_FRAMEWORK_PATH=../../../qjson/lib:../../../lib ./server ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localserver/testservice.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include "testservice.h" TestService::TestService(QObject *parent) : QJsonRpcService(parent) { } void TestService::testMethod() { qDebug() << Q_FUNC_INFO << "called" << endl; } void TestService::testMethodWithParams(const QString &first, bool second, double third) { qDebug() << Q_FUNC_INFO << "called with parameters: " << endl << " first: " << first << endl << "second: " << second << endl << " third: " << third << endl; } void TestService::testMethodWithVariantParams(const QString &first, bool second, double third, const QVariant &fourth) { qDebug() << Q_FUNC_INFO << "called with variant parameters: " << endl << " first: " << first << endl << "second: " << second << endl << " third: " << third << endl << "fourth: " << fourth << endl; } QString TestService::testMethodWithParamsAndReturnValue(const QString &name) { qDebug() << Q_FUNC_INFO << "called" << endl; return QString("Hello %1").arg(name); } void TestService::testMethodWithDefaultParameter(const QString &first, const QString &second) { qDebug() << Q_FUNC_INFO << endl << "first: " << first << endl << (second.isEmpty() ? "not defined, default parameter" : second) << endl; } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/localserver/testservice.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef TESTSERVICE_H #define TESTSERVICE_H #include "qjsonrpcservice.h" class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "agent") public: TestService(QObject *parent = 0); public Q_SLOTS: void testMethod(); void testMethodWithParams(const QString &first, bool second, double third); void testMethodWithVariantParams(const QString &first, bool second, double third, const QVariant &fourth); QString testMethodWithParamsAndReturnValue(const QString &name); void testMethodWithDefaultParameter(const QString &first, const QString &second = QString()); }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/manual.pro ================================================ TEMPLATE = subdirs SUBDIRS += localserver \ localclient \ tcpserver \ tcpclient \ qjsonrpc \ httpclient \ httpserver \ benchmark greaterThan(QT_MAJOR_VERSION, 4) { qtHaveModule(script): SUBDIRS += console } else { SUBDIRS += console } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/python/jsonrpc.py ================================================ #!/usr/bin/env python # -*- coding: ascii -*- """ JSON-RPC (remote procedure call). It consists of 3 (independent) parts: - proxy/dispatcher - data structure / serializer - transport It's intended for JSON-RPC, but since the above 3 parts are independent, it could be used for other RPCs as well. Currently, JSON-RPC 2.0(pre) and JSON-RPC 1.0 are implemented :Version: 2008-08-31-beta :Status: experimental :Example: simple Client with JsonRPC2.0 and TCP/IP:: >>> proxy = ServerProxy( JsonRpc20(), TransportTcpIp(addr=("127.0.0.1",31415)) ) >>> proxy.echo( "hello world" ) u'hello world' >>> proxy.echo( "bye." ) u'bye.' simple Server with JsonRPC2.0 and TCP/IP with logging to STDOUT:: >>> server = Server( JsonRpc20(), TransportTcpIp(addr=("127.0.0.1",31415), logfunc=log_stdout) ) >>> def echo( s ): ... return s >>> server.register_function( echo ) >>> server.serve( 2 ) # serve 2 requests # doctest: +ELLIPSIS listen ('127.0.0.1', 31415) ('127.0.0.1', ...) connected ('127.0.0.1', ...) <-- {"jsonrpc": "2.0", "method": "echo", "params": ["hello world"], "id": 0} ('127.0.0.1', ...) --> {"jsonrpc": "2.0", "result": "hello world", "id": 0} ('127.0.0.1', ...) close ('127.0.0.1', ...) connected ('127.0.0.1', ...) <-- {"jsonrpc": "2.0", "method": "echo", "params": ["bye."], "id": 0} ('127.0.0.1', ...) --> {"jsonrpc": "2.0", "result": "bye.", "id": 0} ('127.0.0.1', ...) close close ('127.0.0.1', 31415) Client with JsonRPC2.0 and an abstract Unix Domain Socket:: >>> proxy = ServerProxy( JsonRpc20(), TransportUnixSocket(addr="\\x00.rpcsocket") ) >>> proxy.hi( message="hello" ) #named parameters u'hi there' >>> proxy.test() #fault Traceback (most recent call last): ... jsonrpc.RPCMethodNotFound: >>> proxy.debug.echo( "hello world" ) #hierarchical procedures u'hello world' Server with JsonRPC2.0 and abstract Unix Domain Socket with a logfile:: >>> server = Server( JsonRpc20(), TransportUnixSocket(addr="\\x00.rpcsocket", logfunc=log_file("mylog.txt")) ) >>> def echo( s ): ... return s >>> def hi( message ): ... return "hi there" >>> server.register_function( hi ) >>> server.register_function( echo, name="debug.echo" ) >>> server.serve( 3 ) # serve 3 requests "mylog.txt" then contains: listen '\\x00.rpcsocket' '' connected '' --> '{"jsonrpc": "2.0", "method": "hi", "params": {"message": "hello"}, "id": 0}' '' <-- '{"jsonrpc": "2.0", "result": "hi there", "id": 0}' '' close '' connected '' --> '{"jsonrpc": "2.0", "method": "test", "id": 0}' '' <-- '{"jsonrpc": "2.0", "error": {"code":-32601, "message": "Method not found."}, "id": 0}' '' close '' connected '' --> '{"jsonrpc": "2.0", "method": "debug.echo", "params": ["hello world"], "id": 0}' '' <-- '{"jsonrpc": "2.0", "result": "hello world", "id": 0}' '' close close '\\x00.rpcsocket' :Note: all exceptions derived from RPCFault are propagated to the client. other exceptions are logged and result in a sent-back "empty" INTERNAL_ERROR. :Uses: simplejson, socket, sys,time,codecs :SeeAlso: JSON-RPC 2.0 proposal, 1.0 specification :Warning: .. Warning:: This is **experimental** code! :Bug: :Author: Roland Koebler (rk(at)simple-is-better.org) :Copyright: 2007-2008 by Roland Koebler (rk(at)simple-is-better.org) :License: see __license__ :Changelog: - 2008-08-31: 1st release TODO: - server: multithreading rpc-server - client: multicall (send several requests) - transport: SSL sockets, maybe HTTP, HTTPS - types: support for date/time (ISO 8601) - errors: maybe customizable error-codes/exceptions - mixed 1.0/2.0 server ? - system description etc. ? - maybe test other json-serializers, like cjson? """ __version__ = "2008-08-31-beta" __author__ = "Roland Koebler " __license__ = """Copyright (c) 2007-2008 by Roland Koebler (rk(at)simple-is-better.org) 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.""" #========================================= #import import sys #========================================= # errors #---------------------- # error-codes + exceptions #JSON-RPC 2.0 error-codes PARSE_ERROR = -32700 INVALID_REQUEST = -32600 METHOD_NOT_FOUND = -32601 INVALID_METHOD_PARAMS = -32602 #invalid number/type of parameters INTERNAL_ERROR = -32603 #"all other errors" #additional error-codes PROCEDURE_EXCEPTION = -32000 AUTHENTIFICATION_ERROR = -32001 PERMISSION_DENIED = -32002 INVALID_PARAM_VALUES = -32003 #human-readable messages ERROR_MESSAGE = { PARSE_ERROR : "Parse error.", INVALID_REQUEST : "Invalid Request.", METHOD_NOT_FOUND : "Method not found.", INVALID_METHOD_PARAMS : "Invalid parameters.", INTERNAL_ERROR : "Internal error.", PROCEDURE_EXCEPTION : "Procedure exception.", AUTHENTIFICATION_ERROR : "Authentification error.", PERMISSION_DENIED : "Permission denied.", INVALID_PARAM_VALUES: "Invalid parameter values." } #---------------------- # exceptions class RPCError(Exception): """Base class for rpc-errors.""" class RPCTransportError(RPCError): """Transport error.""" class RPCTimeoutError(RPCTransportError): """Transport/reply timeout.""" class RPCFault(RPCError): """RPC error/fault package received. This exception can also be used as a class, to generate a RPC-error/fault message. :Variables: - error_code: the RPC error-code - error_string: description of the error - error_data: optional additional information (must be json-serializable) :TODO: improve __str__ """ def __init__(self, error_code, error_message, error_data=None): RPCError.__init__(self) self.error_code = error_code self.error_message = error_message self.error_data = error_data def __str__(self): return repr(self) def __repr__(self): return( "" % (self.error_code, repr(self.error_message), repr(self.error_data)) ) class RPCParseError(RPCFault): """Broken rpc-package. (PARSE_ERROR)""" def __init__(self, error_data=None): RPCFault.__init__(self, PARSE_ERROR, ERROR_MESSAGE[PARSE_ERROR], error_data) class RPCInvalidRPC(RPCFault): """Invalid rpc-package. (INVALID_REQUEST)""" def __init__(self, error_data=None): RPCFault.__init__(self, INVALID_REQUEST, ERROR_MESSAGE[INVALID_REQUEST], error_data) class RPCMethodNotFound(RPCFault): """Method not found. (METHOD_NOT_FOUND)""" def __init__(self, error_data=None): RPCFault.__init__(self, METHOD_NOT_FOUND, ERROR_MESSAGE[METHOD_NOT_FOUND], error_data) class RPCInvalidMethodParams(RPCFault): """Invalid method-parameters. (INVALID_METHOD_PARAMS)""" def __init__(self, error_data=None): RPCFault.__init__(self, INVALID_METHOD_PARAMS, ERROR_MESSAGE[INVALID_METHOD_PARAMS], error_data) class RPCInternalError(RPCFault): """Internal error. (INTERNAL_ERROR)""" def __init__(self, error_data=None): RPCFault.__init__(self, INTERNAL_ERROR, ERROR_MESSAGE[INTERNAL_ERROR], error_data) class RPCProcedureException(RPCFault): """Procedure exception. (PROCEDURE_EXCEPTION)""" def __init__(self, error_data=None): RPCFault.__init__(self, PROCEDURE_EXCEPTION, ERROR_MESSAGE[PROCEDURE_EXCEPTION], error_data) class RPCAuthentificationError(RPCFault): """AUTHENTIFICATION_ERROR""" def __init__(self, error_data=None): RPCFault.__init__(self, AUTHENTIFICATION_ERROR, ERROR_MESSAGE[AUTHENTIFICATION_ERROR], error_data) class RPCPermissionDenied(RPCFault): """PERMISSION_DENIED""" def __init__(self, error_data=None): RPCFault.__init__(self, PERMISSION_DENIED, ERROR_MESSAGE[PERMISSION_DENIED], error_data) class RPCInvalidParamValues(RPCFault): """INVALID_PARAM_VALUES""" def __init__(self, error_data=None): RPCFault.__init__(self, INVALID_PARAM_VALUES, ERROR_MESSAGE[INVALID_PARAM_VALUES], error_data) #========================================= # data structure / serializer try: import simplejson except ImportError, err: print "FATAL: json-module 'simplejson' is missing (%s)" % (err) sys.exit(1) #---------------------- # def dictkeyclean(d): """Convert all keys of the dict 'd' to (ascii-)strings. :Raises: UnicodeEncodeError """ new_d = {} for (k, v) in d.iteritems(): new_d[str(k)] = v return new_d #---------------------- # JSON-RPC 1.0 class JsonRpc10: """JSON-RPC V1.0 data-structure / serializer This implementation is quite liberal in what it accepts: It treats missing "params" and "id" in Requests and missing "result"/"error" in Responses as empty/null. :SeeAlso: JSON-RPC 1.0 specification :TODO: catch simplejson.dumps not-serializable-exceptions """ def __init__(self, dumps=simplejson.dumps, loads=simplejson.loads): """init: set serializer to use :Parameters: - dumps: json-encoder-function - loads: json-decoder-function :Note: The dumps_* functions of this class already directly create the invariant parts of the resulting json-object themselves, without using the given json-encoder-function. """ self.dumps = dumps self.loads = loads def dumps_request( self, method, params=(), id=0 ): """serialize JSON-RPC-Request :Parameters: - method: the method-name (str/unicode) - params: the parameters (list/tuple) - id: if id=None, this results in a Notification :Returns: | {"method": "...", "params": ..., "id": ...} | "method", "params" and "id" are always in this order. :Raises: TypeError if method/params is of wrong type or not JSON-serializable """ if not isinstance(method, (str, unicode)): raise TypeError('"method" must be a string (or unicode string).') if not isinstance(params, (tuple, list)): raise TypeError("params must be a tuple/list.") return '{"method": %s, "params": %s, "id": %s}' % \ (self.dumps(method), self.dumps(params), self.dumps(id)) def dumps_notification( self, method, params=() ): """serialize a JSON-RPC-Notification :Parameters: see dumps_request :Returns: | {"method": "...", "params": ..., "id": null} | "method", "params" and "id" are always in this order. :Raises: see dumps_request """ if not isinstance(method, (str, unicode)): raise TypeError('"method" must be a string (or unicode string).') if not isinstance(params, (tuple, list)): raise TypeError("params must be a tuple/list.") return '{"method": %s, "params": %s, "id": null}' % \ (self.dumps(method), self.dumps(params)) def dumps_response( self, result, id=None ): """serialize a JSON-RPC-Response (without error) :Returns: | {"result": ..., "error": null, "id": ...} | "result", "error" and "id" are always in this order. :Raises: TypeError if not JSON-serializable """ return '{"result": %s, "error": null, "id": %s}' % \ (self.dumps(result), self.dumps(id)) def dumps_error( self, error, id=None ): """serialize a JSON-RPC-Response-error Since JSON-RPC 1.0 does not define an error-object, this uses the JSON-RPC 2.0 error-object. :Parameters: - error: a RPCFault instance :Returns: | {"result": null, "error": {"code": error_code, "message": error_message, "data": error_data}, "id": ...} | "result", "error" and "id" are always in this order, data is omitted if None. :Raises: ValueError if error is not a RPCFault instance, TypeError if not JSON-serializable """ if not isinstance(error, RPCFault): raise ValueError("""error must be a RPCFault-instance.""") if error.error_data is None: return '{"result": null, "error": {"code":%s, "message": %s}, "id": %s}' % \ (self.dumps(error.error_code), self.dumps(error.error_message), self.dumps(id)) else: return '{"result": null, "error": {"code":%s, "message": %s, "data": %s}, "id": %s}' % \ (self.dumps(error.error_code), self.dumps(error.error_message), self.dumps(error.error_data), self.dumps(id)) def loads_request( self, string ): """de-serialize a JSON-RPC Request/Notification :Returns: | [method_name, params, id] or [method_name, params] | params is a tuple/list | if id is missing, this is a Notification :Raises: RPCParseError, RPCInvalidRPC, RPCInvalidMethodParams """ try: data = self.loads(string) except ValueError, err: raise RPCParseError("No valid JSON. (%s)" % str(err)) if not isinstance(data, dict): raise RPCInvalidRPC("No valid RPC-package.") if "method" not in data: raise RPCInvalidRPC("""Invalid Request, "method" is missing.""") if not isinstance(data["method"], (str, unicode)): raise RPCInvalidRPC("""Invalid Request, "method" must be a string.""") if "id" not in data: data["id"] = None #be liberal if "params" not in data: data["params"] = () #be liberal if not isinstance(data["params"], (list, tuple)): raise RPCInvalidRPC("""Invalid Request, "params" must be an array.""") if len(data) != 3: raise RPCInvalidRPC("""Invalid Request, additional fields found.""") # notification / request if data["id"] is None: return data["method"], data["params"] #notification else: return data["method"], data["params"], data["id"] #request def loads_response( self, string ): """de-serialize a JSON-RPC Response/error :Returns: | [result, id] for Responses :Raises: | RPCFault+derivates for error-packages/faults, RPCParseError, RPCInvalidRPC | Note that for error-packages which do not match the V2.0-definition, RPCFault(-1, "Error", RECEIVED_ERROR_OBJ) is raised. """ try: data = self.loads(string) except ValueError, err: raise RPCParseError("No valid JSON. (%s)" % str(err)) if not isinstance(data, dict): raise RPCInvalidRPC("No valid RPC-package.") if "id" not in data: raise RPCInvalidRPC("""Invalid Response, "id" missing.""") if "result" not in data: data["result"] = None #be liberal if "error" not in data: data["error"] = None #be liberal if len(data) != 3: raise RPCInvalidRPC("""Invalid Response, additional or missing fields.""") #error if data["error"] is not None: if data["result"] is not None: raise RPCInvalidRPC("""Invalid Response, one of "result" or "error" must be null.""") #v2.0 error-format if( isinstance(data["error"], dict) and "code" in data["error"] and "message" in data["error"] and (len(data["error"])==2 or ("data" in data["error"] and len(data["error"])==3)) ): if "data" not in data["error"]: error_data = None else: error_data = data["error"]["data"] if data["error"]["code"] == PARSE_ERROR: raise RPCParseError(error_data) elif data["error"]["code"] == INVALID_REQUEST: raise RPCInvalidRPC(error_data) elif data["error"]["code"] == METHOD_NOT_FOUND: raise RPCMethodNotFound(error_data) elif data["error"]["code"] == INVALID_METHOD_PARAMS: raise RPCInvalidMethodParams(error_data) elif data["error"]["code"] == INTERNAL_ERROR: raise RPCInternalError(error_data) elif data["error"]["code"] == PROCEDURE_EXCEPTION: raise RPCProcedureException(error_data) elif data["error"]["code"] == AUTHENTIFICATION_ERROR: raise RPCAuthentificationError(error_data) elif data["error"]["code"] == PERMISSION_DENIED: raise RPCPermissionDenied(error_data) elif data["error"]["code"] == INVALID_PARAM_VALUES: raise RPCInvalidParamValues(error_data) else: raise RPCFault(data["error"]["code"], data["error"]["message"], error_data) #other error-format else: raise RPCFault(-1, "Error", data["error"]) #result else: return data["result"], data["id"] #---------------------- # JSON-RPC 2.0 class JsonRpc20: """JSON-RPC V2.0 data-structure / serializer :SeeAlso: JSON-RPC 2.0 specification :TODO: catch simplejson.dumps not-serializable-exceptions """ def __init__(self, dumps=simplejson.dumps, loads=simplejson.loads): """init: set serializer to use :Parameters: - dumps: json-encoder-function - loads: json-decoder-function :Note: The dumps_* functions of this class already directly create the invariant parts of the resulting json-object themselves, without using the given json-encoder-function. """ self.dumps = dumps self.loads = loads def dumps_request( self, method, params=(), id=0 ): """serialize JSON-RPC-Request :Parameters: - method: the method-name (str/unicode) - params: the parameters (list/tuple/dict) - id: the id (should not be None) :Returns: | {"jsonrpc": "2.0", "method": "...", "params": ..., "id": ...} | "jsonrpc", "method", "params" and "id" are always in this order. | "params" is omitted if empty :Raises: TypeError if method/params is of wrong type or not JSON-serializable """ if not isinstance(method, (str, unicode)): raise TypeError('"method" must be a string (or unicode string).') if not isinstance(params, (tuple, list, dict)): raise TypeError("params must be a tuple/list/dict or None.") if params: return '{"jsonrpc": "2.0", "method": %s, "params": %s, "id": %s}' % \ (self.dumps(method), self.dumps(params), self.dumps(id)) else: return '{"jsonrpc": "2.0", "method": %s, "id": %s}' % \ (self.dumps(method), self.dumps(id)) def dumps_notification( self, method, params=() ): """serialize a JSON-RPC-Notification :Parameters: see dumps_request :Returns: | {"jsonrpc": "2.0", "method": "...", "params": ...} | "jsonrpc", "method" and "params" are always in this order. :Raises: see dumps_request """ if not isinstance(method, (str, unicode)): raise TypeError('"method" must be a string (or unicode string).') if not isinstance(params, (tuple, list, dict)): raise TypeError("params must be a tuple/list/dict or None.") if params: return '{"jsonrpc": "2.0", "method": %s, "params": %s}' % \ (self.dumps(method), self.dumps(params)) else: return '{"jsonrpc": "2.0", "method": %s}' % \ (self.dumps(method)) def dumps_response( self, result, id=None ): """serialize a JSON-RPC-Response (without error) :Returns: | {"jsonrpc": "2.0", "result": ..., "id": ...} | "jsonrpc", "result", and "id" are always in this order. :Raises: TypeError if not JSON-serializable """ return '{"jsonrpc": "2.0", "result": %s, "id": %s}' % \ (self.dumps(result), self.dumps(id)) def dumps_error( self, error, id=None ): """serialize a JSON-RPC-Response-error :Parameters: - error: a RPCFault instance :Returns: | {"jsonrpc": "2.0", "error": {"code": error_code, "message": error_message, "data": error_data}, "id": ...} | "jsonrpc", "result", "error" and "id" are always in this order, data is omitted if None. :Raises: ValueError if error is not a RPCFault instance, TypeError if not JSON-serializable """ if not isinstance(error, RPCFault): raise ValueError("""error must be a RPCFault-instance.""") if error.error_data is None: return '{"jsonrpc": "2.0", "error": {"code":%s, "message": %s}, "id": %s}' % \ (self.dumps(error.error_code), self.dumps(error.error_message), self.dumps(id)) else: return '{"jsonrpc": "2.0", "error": {"code":%s, "message": %s, "data": %s}, "id": %s}' % \ (self.dumps(error.error_code), self.dumps(error.error_message), self.dumps(error.error_data), self.dumps(id)) def loads_request( self, string ): """de-serialize a JSON-RPC Request/Notification :Returns: | [method_name, params, id] or [method_name, params] | params is a tuple/list or dict (with only str-keys) | if id is missing, this is a Notification :Raises: RPCParseError, RPCInvalidRPC, RPCInvalidMethodParams """ try: data = self.loads(string) except ValueError, err: raise RPCParseError("No valid JSON. (%s)" % str(err)) if not isinstance(data, dict): raise RPCInvalidRPC("No valid RPC-package.") if "jsonrpc" not in data: raise RPCInvalidRPC("""Invalid Response, "jsonrpc" missing.""") if not isinstance(data["jsonrpc"], (str, unicode)): raise RPCInvalidRPC("""Invalid Response, "jsonrpc" must be a string.""") if data["jsonrpc"] != "2.0": raise RPCInvalidRPC("""Invalid jsonrpc version.""") if "method" not in data: raise RPCInvalidRPC("""Invalid Request, "method" is missing.""") if not isinstance(data["method"], (str, unicode)): raise RPCInvalidRPC("""Invalid Request, "method" must be a string.""") if "params" not in data: data["params"] = () #convert params-keys from unicode to str elif isinstance(data["params"], dict): try: data["params"] = dictkeyclean(data["params"]) except UnicodeEncodeError: raise RPCInvalidMethodParams("Parameter-names must be in ascii.") elif not isinstance(data["params"], (list, tuple)): raise RPCInvalidRPC("""Invalid Request, "params" must be an array or object.""") if not( len(data)==3 or ("id" in data and len(data)==4) ): raise RPCInvalidRPC("""Invalid Request, additional fields found.""") # notification / request if "id" not in data: return data["method"], data["params"] #notification else: return data["method"], data["params"], data["id"] #request def loads_response( self, string ): """de-serialize a JSON-RPC Response/error :Returns: | [result, id] for Responses :Raises: | RPCFault+derivates for error-packages/faults, RPCParseError, RPCInvalidRPC """ try: data = self.loads(string) except ValueError, err: raise RPCParseError("No valid JSON. (%s)" % str(err)) if not isinstance(data, dict): raise RPCInvalidRPC("No valid RPC-package.") if "jsonrpc" not in data: raise RPCInvalidRPC("""Invalid Response, "jsonrpc" missing.""") if not isinstance(data["jsonrpc"], (str, unicode)): raise RPCInvalidRPC("""Invalid Response, "jsonrpc" must be a string.""") if data["jsonrpc"] != "2.0": raise RPCInvalidRPC("""Invalid jsonrpc version.""") if "id" not in data: raise RPCInvalidRPC("""Invalid Response, "id" missing.""") if "result" not in data: data["result"] = None if "error" not in data: data["error"] = None if len(data) != 4: raise RPCInvalidRPC("""Invalid Response, additional or missing fields.""") #error if data["error"] is not None: if data["result"] is not None: raise RPCInvalidRPC("""Invalid Response, only "result" OR "error" allowed.""") if not isinstance(data["error"], dict): raise RPCInvalidRPC("Invalid Response, invalid error-object.") if "code" not in data["error"] or "message" not in data["error"]: raise RPCInvalidRPC("Invalid Response, invalid error-object.") if "data" not in data["error"]: data["error"]["data"] = None if len(data["error"]) != 3: raise RPCInvalidRPC("Invalid Response, invalid error-object.") error_data = data["error"]["data"] if data["error"]["code"] == PARSE_ERROR: raise RPCParseError(error_data) elif data["error"]["code"] == INVALID_REQUEST: raise RPCInvalidRPC(error_data) elif data["error"]["code"] == METHOD_NOT_FOUND: raise RPCMethodNotFound(error_data) elif data["error"]["code"] == INVALID_METHOD_PARAMS: raise RPCInvalidMethodParams(error_data) elif data["error"]["code"] == INTERNAL_ERROR: raise RPCInternalError(error_data) elif data["error"]["code"] == PROCEDURE_EXCEPTION: raise RPCProcedureException(error_data) elif data["error"]["code"] == AUTHENTIFICATION_ERROR: raise RPCAuthentificationError(error_data) elif data["error"]["code"] == PERMISSION_DENIED: raise RPCPermissionDenied(error_data) elif data["error"]["code"] == INVALID_PARAM_VALUES: raise RPCInvalidParamValues(error_data) else: raise RPCFault(data["error"]["code"], data["error"]["message"], error_data) #result else: return data["result"], data["id"] #========================================= # transports #---------------------- # transport-logging import codecs import time def log_dummy( message ): """dummy-logger: do nothing""" pass def log_stdout( message ): """print message to STDOUT""" print message def log_file( filename ): """return a logfunc which logs to a file (in utf-8)""" def logfile( message ): f = codecs.open( filename, 'a', encoding='utf-8' ) f.write( message+"\n" ) f.close() return logfile def log_filedate( filename ): """return a logfunc which logs date+message to a file (in utf-8)""" def logfile( message ): f = codecs.open( filename, 'a', encoding='utf-8' ) f.write( time.strftime("%Y-%m-%d %H:%M:%S ")+message+"\n" ) f.close() return logfile #---------------------- class Transport: """generic Transport-interface. This class, and especially its methods and docstrings, define the Transport-Interface. """ def __init__(self): pass def send( self, data ): """send all data. must be implemented by derived classes.""" raise NotImplementedError def recv( self ): """receive data. must be implemented by derived classes.""" raise NotImplementedError def sendrecv( self, string ): """send + receive data""" self.send( string ) return self.recv() def serve( self, handler, n=None ): """serve (forever or for n communicaions). - receive data - call result = handler(data) - send back result if not None The serving can be stopped by SIGINT. :TODO: - how to stop? maybe use a .run-file, and stop server if file removed? - maybe make n_current accessible? (e.g. for logging) """ n_current = 0 while 1: if n is not None and n_current >= n: break data = self.recv() result = handler(data) if result is not None: self.send( result ) n_current += 1 class TransportSTDINOUT(Transport): """receive from STDIN, send to STDOUT. Useful e.g. for debugging. """ def send(self, string): """write data to STDOUT with '***SEND:' prefix """ print "***SEND:" print string def recv(self): """read data from STDIN""" print "***RECV (please enter, ^D ends.):" return sys.stdin.read() import socket, select class TransportSocket(Transport): """Transport via socket. :SeeAlso: python-module socket :TODO: - documentation - improve this (e.g. make sure that connections are closed, socket-files are deleted etc.) - exception-handling? (socket.error) """ def __init__( self, addr, limit=4096, sock_type=socket.AF_INET, sock_prot=socket.SOCK_STREAM, timeout=1.0, logfunc=log_dummy ): """ :Parameters: - addr: socket-address - timeout: timeout in seconds - logfunc: function for logging, logfunc(message) :Raises: socket.timeout after timeout """ self.limit = limit self.addr = addr self.s_type = sock_type self.s_prot = sock_prot self.s = None self.timeout = timeout self.log = logfunc def connect( self ): self.close() self.log( "connect to %s" % repr(self.addr) ) self.s = socket.socket( self.s_type, self.s_prot ) self.s.settimeout( self.timeout ) self.s.connect( self.addr ) def close( self ): if self.s is not None: self.log( "close %s" % repr(self.addr) ) self.s.close() self.s = None def __repr__(self): return "" % repr(self.addr) def send( self, string ): if self.s is None: self.connect() self.log( "--> "+repr(string) ) self.s.sendall( string ) def recv( self ): if self.s is None: self.connect() data = self.s.recv( self.limit ) while( select.select((self.s,), (), (), 0.1)[0] ): #TODO: this select is probably not necessary, because server closes this socket d = self.s.recv( self.limit ) if len(d) == 0: break data += d self.log( "<-- "+repr(data) ) return data def sendrecv( self, string ): """send data + receive data + close""" try: self.send( string ) return self.recv() finally: self.close() def serve(self, handler, n=None): """open socket, wait for incoming connections and handle them. :Parameters: - n: serve n requests, None=forever """ self.close() self.s = socket.socket( self.s_type, self.s_prot ) try: self.log( "listen %s" % repr(self.addr) ) self.s.bind( self.addr ) self.s.listen(1) n_current = 0 while 1: if n is not None and n_current >= n: break conn, addr = self.s.accept() self.log( "%s connected" % repr(addr) ) data = conn.recv(self.limit) self.log( "%s --> %s" % (repr(addr), repr(data)) ) result = handler(data) if data is not None: self.log( "%s <-- %s" % (repr(addr), repr(result)) ) conn.send( result ) self.log( "%s close" % repr(addr) ) conn.close() n_current += 1 finally: self.close() if hasattr(socket, 'AF_UNIX'): class TransportUnixSocket(TransportSocket): """Transport via Unix Domain Socket. """ def __init__(self, addr=None, limit=4096, timeout=1.0, logfunc=log_dummy): """ :Parameters: - addr: "socket_file" :Note: | The socket-file is not deleted. | If the socket-file begins with \x00, abstract sockets are used, and no socket-file is created. :SeeAlso: TransportSocket """ TransportSocket.__init__( self, addr, limit, socket.AF_UNIX, socket.SOCK_STREAM, timeout, logfunc ) class TransportTcpIp(TransportSocket): """Transport via TCP/IP. """ def __init__(self, addr=None, limit=4096, timeout=1.0, logfunc=log_dummy): """ :Parameters: - addr: ("host",port) :SeeAlso: TransportSocket """ TransportSocket.__init__( self, addr, limit, socket.AF_INET, socket.SOCK_STREAM, timeout, logfunc ) #========================================= # client side: server proxy class ServerProxy: """RPC-client: server proxy A logical connection to a RPC server. It works with different data/serializers and different transports. Notifications and id-handling/multicall are not yet implemented. :Example: see module-docstring :TODO: verbose/logging? """ def __init__( self, data_serializer, transport ): """ :Parameters: - data_serializer: a data_structure+serializer-instance - transport: a Transport instance """ #TODO: check parameters self.__data_serializer = data_serializer if not isinstance(transport, Transport): raise ValueError('invalid "transport" (must be a Transport-instance)"') self.__transport = transport def __str__(self): return repr(self) def __repr__(self): return "" % (self.__transport, self.__data_serializer) def __req( self, methodname, args=None, kwargs=None, id=0 ): # JSON-RPC 1.0: only positional parameters if len(kwargs) > 0 and isinstance(self.data_serializer, JsonRpc10): raise ValueError("Only positional parameters allowed in JSON-RPC 1.0") # JSON-RPC 2.0: only args OR kwargs allowed! if len(args) > 0 and len(kwargs) > 0: raise ValueError("Only positional or named parameters are allowed!") if len(kwargs) == 0: req_str = self.__data_serializer.dumps_request( methodname, args, id ) else: req_str = self.__data_serializer.dumps_request( methodname, kwargs, id ) try: resp_str = self.__transport.sendrecv( req_str ) except Exception,err: raise RPCTransportError(err) resp = self.__data_serializer.loads_response( resp_str ) return resp[0] def __getattr__(self, name): # magic method dispatcher # note: to call a remote object with an non-standard name, use # result getattr(my_server_proxy, "strange-python-name")(args) return _method(self.__req, name) # request dispatcher class _method: """some "magic" to bind an RPC method to an RPC server. Supports "nested" methods (e.g. examples.getStateName). :Raises: AttributeError for method-names/attributes beginning with '_'. """ def __init__(self, req, name): if name[0] == "_": #prevent rpc-calls for proxy._*-functions raise AttributeError("invalid attribute '%s'" % name) self.__req = req self.__name = name def __getattr__(self, name): if name[0] == "_": #prevent rpc-calls for proxy._*-functions raise AttributeError("invalid attribute '%s'" % name) return _method(self.__req, "%s.%s" % (self.__name, name)) def __call__(self, *args, **kwargs): return self.__req(self.__name, args, kwargs) #========================================= # server side: Server class Server: """RPC-server. It works with different data/serializers and with different transports. :Example: see module-docstring :TODO: - mixed JSON-RPC 1.0/2.0 server? - logging/loglevels? """ def __init__( self, data_serializer, transport, logfile=None ): """ :Parameters: - data_serializer: a data_structure+serializer-instance - transport: a Transport instance - logfile: file to log ("unexpected") errors to """ #TODO: check parameters self.__data_serializer = data_serializer if not isinstance(transport, Transport): raise ValueError('invalid "transport" (must be a Transport-instance)"') self.__transport = transport self.logfile = logfile if self.logfile is not None: #create logfile (or raise exception) f = codecs.open( self.logfile, 'a', encoding='utf-8' ) f.close() self.funcs = {} def __repr__(self): return "" % (self.__transport, self.__data_serializer) def log(self, message): """write a message to the logfile (in utf-8)""" if self.logfile is not None: f = codecs.open( self.logfile, 'a', encoding='utf-8' ) f.write( time.strftime("%Y-%m-%d %H:%M:%S ")+message+"\n" ) f.close() def register_instance(self, myinst, name=None): """Add all functions of a class-instance to the RPC-services. All entries of the instance which do not begin with '_' are added. :Parameters: - myinst: class-instance containing the functions - name: | hierarchical prefix. | If omitted, the functions are added directly. | If given, the functions are added as "name.function". :TODO: - only add functions and omit attributes? - improve hierarchy? """ for e in dir(myinst): if e[0][0] != "_": if name is None: self.register_function( getattr(myinst, e) ) else: self.register_function( getattr(myinst, e), name="%s.%s" % (name, e) ) def register_function(self, function, name=None): """Add a function to the RPC-services. :Parameters: - function: function to add - name: RPC-name for the function. If omitted/None, the original name of the function is used. """ if name is None: self.funcs[function.__name__] = function else: self.funcs[name] = function def handle(self, rpcstr): """Handle a RPC-Request. :Parameters: - rpcstr: the received rpc-string :Returns: the data to send back or None if nothing should be sent back :Raises: RPCFault (and maybe others) """ #TODO: id notification = False try: req = self.__data_serializer.loads_request( rpcstr ) if len(req) == 2: #notification method, params = req notification = True else: #request method, params, id = req except RPCFault, err: return self.__data_serializer.dumps_error( err, id=None ) except Exception, err: self.log( "%d (%s): %s" % (INTERNAL_ERROR, ERROR_MESSAGE[INTERNAL_ERROR], str(err)) ) return self.__data_serializer.dumps_error( RPCFault(INTERNAL_ERROR, ERROR_MESSAGE[INTERNAL_ERROR]), id=None ) if method not in self.funcs: if notification: return None return self.__data_serializer.dumps_error( RPCFault(METHOD_NOT_FOUND, ERROR_MESSAGE[METHOD_NOT_FOUND]), id ) try: if isinstance(params, dict): result = self.funcs[method]( **params ) else: result = self.funcs[method]( *params ) except RPCFault, err: if notification: return None return self.__data_serializer.dumps_error( err, id=None ) except Exception, err: if notification: return None self.log( "%d (%s): %s" % (INTERNAL_ERROR, ERROR_MESSAGE[INTERNAL_ERROR], str(err)) ) return self.__data_serializer.dumps_error( RPCFault(INTERNAL_ERROR, ERROR_MESSAGE[INTERNAL_ERROR]), id ) if notification: return None try: return self.__data_serializer.dumps_response( result, id ) except Exception, err: self.log( "%d (%s): %s" % (INTERNAL_ERROR, ERROR_MESSAGE[INTERNAL_ERROR], str(err)) ) return self.__data_serializer.dumps_error( RPCFault(INTERNAL_ERROR, ERROR_MESSAGE[INTERNAL_ERROR]), id ) def serve(self, n=None): """serve (forever or for n communicaions). :See: Transport """ self.__transport.serve( self.handle, n ) #========================================= ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/python/testqjsonrpc.py ================================================ #!/usr/bin/python import jsonrpc import socket rpc = jsonrpc.ServerProxy(jsonrpc.JsonRpc20(), jsonrpc.TransportSocket(addr="/tmp/testservice", sock_type=socket.AF_UNIX)) print rpc.agent.testMethod() print rpc.agent.testMethodWithParams("one", False, 10) print rpc.agent.testMethodWithParamsAndReturnValue("matt") ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/qjsonrpc/qjsonrpc.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include #include #include #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcservice.h" int main(int argc, char **argv) { QCoreApplication app(argc, argv); QStringList args = app.arguments(); QString appName = args.takeFirst(); bool notification = args.contains("-n"); if (notification) args.removeAll("-n"); if (args.size() < 2) { qDebug("usage: %s [-n] ", appName.toLocal8Bit().data()); return -1; } // try to process socket QIODevice *device = 0; QScopedPointer devicePtr(device); QString service = args.takeFirst(); QUrl serviceUrl = QUrl::fromUserInput(service); QHostAddress serviceAddress(serviceUrl.host()); if (serviceAddress.isNull()) { QLocalSocket *localSocket = new QLocalSocket; device = localSocket; localSocket->connectToServer(service); if (!localSocket->waitForConnected(5000)) { qDebug("could not connect to service: %s", service.toLocal8Bit().data()); return -1; } } else { QTcpSocket *tcpSocket = new QTcpSocket; device = tcpSocket; int servicePort = serviceUrl.port() ? serviceUrl.port() : 5555; tcpSocket->connectToHost(serviceAddress, servicePort); if (!tcpSocket->waitForConnected(5000)) { qDebug("could not connect to host at %s:%d", serviceUrl.host().toLocal8Bit().data(), servicePort); return -1; } } QJsonRpcSocket socket(device); QString method = args.takeFirst(); QVariantList arguments; foreach (QString arg, args) arguments.append(arg); QJsonRpcMessage request = notification ? QJsonRpcMessage::createNotification(method, QJsonArray::fromVariantList(arguments)) : QJsonRpcMessage::createRequest(method, QJsonArray::fromVariantList(arguments)); qDebug() << request.toJson(); QJsonRpcMessage response = socket.sendMessageBlocking(request, 5000); if (response.type() == QJsonRpcMessage::Error) { qDebug("error(%d): %s", response.errorCode(), response.errorMessage().toLocal8Bit().data()); return -1; } qDebug() << response.result(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/qjsonrpc/qjsonrpc.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app TARGET = qjsonrpc SOURCES = \ qjsonrpc.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpclient/main.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include "tcpclient.h" int main(int argc, char **argv) { QCoreApplication app(argc, argv); TcpClient client; client.run(); return app.exec(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpclient/runclientmac ================================================ #!/bin/bash DYLD_FRAMEWORK_PATH=../../../qjson/lib:../../../lib ./client ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpclient/tcpclient.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include #include "qjsonrpcsocket.h" #include "qjsonrpcservice.h" #include "qjsonrpcservicereply.h" #include "tcpclient.h" TcpClient::TcpClient(QObject *parent) : QObject(parent), m_client(0) { } void TcpClient::run() { QTcpSocket *socket = new QTcpSocket(this); socket->connectToHost(QHostAddress::LocalHost, 5555); if (!socket->waitForConnected()) { qDebug() << "could not connect to server: " << socket->errorString(); return; } // run tests m_client = new QJsonRpcSocket(socket, this); QJsonRpcServiceReply *reply = m_client->invokeRemoteMethod("agent.testMethod"); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); reply = m_client->invokeRemoteMethod("agent.testMethodWithParams", "one", false, 10); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); reply = m_client->invokeRemoteMethod("agent.testMethodWithVariantParams", "one", false, 10, QVariant(2.5)); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); reply = m_client->invokeRemoteMethod("agent.testMethodWithParamsAndReturnValue", "matt"); connect(reply, SIGNAL(finished()), this, SLOT(processResponse())); connect(m_client, SIGNAL(messageReceived(QJsonRpcMessage)), this, SLOT(processMessage(QJsonRpcMessage))); reply = m_client->invokeRemoteMethod("agent.testNotifyConnectedClients", "some data"); } void TcpClient::processResponse() { QJsonRpcServiceReply *reply = static_cast(sender()); if (!reply) { qDebug() << "invalid response received"; return; } qDebug() << "response received: " << reply->response(); } void TcpClient::processMessage(const QJsonRpcMessage &message) { if (message.method() == "callback") qDebug() << "received message: " << message.method() << message.params(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpclient/tcpclient.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef TCPCLIENT_H #define TCPCLIENT_H #include #include "qjsonrpcmessage.h" class QJsonRpcSocket; class TcpClient : public QObject { Q_OBJECT public: TcpClient(QObject *parent = 0); void run(); private Q_SLOTS: void processResponse(); void processMessage(const QJsonRpcMessage &message); private: QJsonRpcSocket *m_client; }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpclient/tcpclient.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app TARGET = tcpclient HEADERS = \ tcpclient.h SOURCES = \ tcpclient.cpp \ main.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpserver/runservermac ================================================ #!/bin/bash DYLD_FRAMEWORK_PATH=../../../qjson/lib:../../../lib ./server ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpserver/tcpserver.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include "qjsonrpctcpserver.h" #include "testservice.h" int main(int argc, char **argv) { QCoreApplication app(argc, argv); QJsonRpcTcpServer rpcServer; rpcServer.addService(new TestService); if (!rpcServer.listen(QHostAddress::LocalHost, 5555)) { qDebug() << "can't start tcp server: " << rpcServer.errorString(); return -1; } return app.exec(); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpserver/tcpserver.pro ================================================ DEPTH = ../../.. include($${DEPTH}/qjsonrpc.pri) include($${DEPTH}/tests/tests.pri) CONFIG -= testcase TEMPLATE = app TARGET = tcpserver HEADERS = \ testservice.h SOURCES = \ testservice.cpp \ tcpserver.cpp ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpserver/testservice.cpp ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #include #include "testservice.h" TestService::TestService(QObject *parent) : QJsonRpcService(parent) { } void TestService::testMethod() { qDebug() << Q_FUNC_INFO << "called" << endl; } void TestService::testMethodWithParams(const QString &first, bool second, double third) { qDebug() << Q_FUNC_INFO << "called with parameters: " << endl << " first: " << first << endl << "second: " << second << endl << " third: " << third << endl; } void TestService::testMethodWithVariantParams(const QString &first, bool second, double third, const QVariant &fourth) { qDebug() << Q_FUNC_INFO << "called with variant parameters: " << endl << " first: " << first << endl << "second: " << second << endl << " third: " << third << endl << "fourth: " << fourth << endl; } QString TestService::testMethodWithParamsAndReturnValue(const QString &name) { qDebug() << Q_FUNC_INFO << "called" << endl; return QString("Hello %1").arg(name); } void TestService::testMethodWithDefaultParameter(const QString &first, const QString &second) { qDebug() << Q_FUNC_INFO << endl << "first: " << first << endl << (second.isEmpty() ? "not defined, default parameter" : second) << endl; } void TestService::testNotifyConnectedClients(const QString &message) { QJsonArray args; args.append(message); Q_EMIT notifyConnectedClients("callback", args); } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/manual/tcpserver/testservice.h ================================================ /* * Copyright (C) 2012-2013 Matt Broadstone * Contact: http://bitbucket.org/devonit/qjsonrpc * * This file is part of the QJsonRpc Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ #ifndef TESTSERVICE_H #define TESTSERVICE_H #include "qjsonrpcservice.h" class TestService : public QJsonRpcService { Q_OBJECT Q_CLASSINFO("serviceName", "agent") public: TestService(QObject *parent = 0); public Q_SLOTS: void testMethod(); void testMethodWithParams(const QString &first, bool second, double third); void testMethodWithVariantParams(const QString &first, bool second, double third, const QVariant &fourth); QString testMethodWithParamsAndReturnValue(const QString &name); void testMethodWithDefaultParameter(const QString &first, const QString &second = QString()); void testNotifyConnectedClients(const QString &message); }; #endif ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/tests.pri ================================================ INCLUDEPATH += $${QJSONRPC_INCLUDEPATH} \ $${QJSONRPC_INCLUDEPATH}/json \ $${PWD}/common LIBS += -L$${DEPTH}/src $${QJSONRPC_LIBS} QT = core network testlib QT -= gui CONFIG -= app_bundle CONFIG += testcase no_testcase_installs HEADERS += \ $${PWD}/common/signalspy.h unix:!macx:QMAKE_RPATHDIR += $${OUT_PWD}/$${DEPTH}/src macx { QMAKE_RPATHDIR += @loader_path/$${DEPTH}/src QMAKE_LFLAGS += -Wl,-rpath,@loader_path/$${DEPTH}/src } ================================================ FILE: liteidex/src/3rdparty/qjsonrpc/tests/tests.pro ================================================ TEMPLATE = subdirs SUBDIRS = auto \ manual ================================================ FILE: liteidex/src/3rdparty/qt_browser/chasewidget.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the demonstration applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "chasewidget.h" #include #include #include #include #include #include ChaseWidget::ChaseWidget(QWidget *parent, QPixmap pixmap, bool pixmapEnabled) : QWidget(parent) , m_segment(0) , m_delay(100) , m_step(60) , m_timerId(-1) , m_animated(false) , m_pixmap(pixmap) , m_pixmapEnabled(pixmapEnabled) { } void ChaseWidget::setAnimated(bool value) { if (m_animated == value) return; m_animated = value; if (m_timerId != -1) { killTimer(m_timerId); m_timerId = -1; } if (m_animated) { m_segment = 0; m_timerId = startTimer(m_delay); } update(); } void ChaseWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter p(this); if (m_pixmapEnabled && !m_pixmap.isNull()) { p.drawPixmap(0, 0, m_pixmap); return; } const int extent = qMin(width(), height()); const int displ = extent / 4-1; const int ext = extent / 4;// - 1; p.setRenderHint(QPainter::Antialiasing, true); if(m_animated) p.setPen(Qt::gray); else p.setPen(QPen(palette().dark().color())); p.translate(width() / 2, height() / 2); // center for (int segment = 0; segment < segmentCount(); ++segment) { p.rotate(QApplication::isRightToLeft() ? m_step : -m_step); if(m_animated) p.setBrush(colorForSegment(segment)); else p.setBrush(palette().background()); p.drawEllipse(QRect(displ, -ext / 2, ext, ext)); } } QSize ChaseWidget::sizeHint() const { return QSize(24, 24); } void ChaseWidget::timerEvent(QTimerEvent *event) { if (event->timerId() == m_timerId) { ++m_segment; update(); } QWidget::timerEvent(event); } QColor ChaseWidget::colorForSegment(int seg) const { int index = ((seg + m_segment) % segmentCount()); int comp = qMax(0, 255 - (index * (255 / segmentCount()))); return QColor(comp, comp, comp, 255); } int ChaseWidget::segmentCount() const { return 360 / m_step; } void ChaseWidget::setPixmapEnabled(bool enable) { m_pixmapEnabled = enable; } ================================================ FILE: liteidex/src/3rdparty/qt_browser/chasewidget.h ================================================ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the demonstration applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CHASEWIDGET_H #define CHASEWIDGET_H #include #include #include #include QT_BEGIN_NAMESPACE class QHideEvent; class QShowEvent; class QPaintEvent; class QTimerEvent; QT_END_NAMESPACE class ChaseWidget : public QWidget { Q_OBJECT public: ChaseWidget(QWidget *parent = 0, QPixmap pixmap = QPixmap(), bool pixmapEnabled = false); void setAnimated(bool value); void setPixmapEnabled(bool enable); QSize sizeHint() const; protected: void paintEvent(QPaintEvent *event); void timerEvent(QTimerEvent *event); private: int segmentCount() const; QColor colorForSegment(int segment) const; int m_segment; int m_delay; int m_step; int m_timerId; bool m_animated; QPixmap m_pixmap; bool m_pixmapEnabled; }; #endif ================================================ FILE: liteidex/src/3rdparty/qt_browser/qt_browser.pri ================================================ LIBS *= -l$$qtLibraryName(qt_browser) ================================================ FILE: liteidex/src/3rdparty/qt_browser/qt_browser.pro ================================================ TARGET = qt_browser TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += \ chasewidget.h SOURCES += \ chasewidget.cpp RESOURCES += ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/fancylineedit.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "fancylineedit.h" #include #include #include #include #include #include #include #include #include #ifndef QT_NO_PRINTER #include #endif #include #include enum { margin = 6 }; #define ICONBUTTON_HEIGHT 18 #define FADE_TIME 160 namespace Utils { // --------- FancyLineEditPrivate class FancyLineEditPrivate : public QObject { public: explicit FancyLineEditPrivate(FancyLineEdit *parent); virtual bool eventFilter(QObject *obj, QEvent *event); FancyLineEdit *m_lineEdit; QPixmap m_pixmap[2]; QMenu *m_menu[2]; bool m_menuTabFocusTrigger[2]; IconButton *m_iconbutton[2]; bool m_iconEnabled[2]; }; FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) : QObject(parent), m_lineEdit(parent) { for (int i = 0; i < 2; ++i) { m_menu[i] = 0; m_menuTabFocusTrigger[i] = false; m_iconbutton[i] = new IconButton(parent); m_iconbutton[i]->installEventFilter(this); m_iconbutton[i]->hide(); m_iconbutton[i]->setAutoHide(false); m_iconEnabled[i] = false; } } bool FancyLineEditPrivate::eventFilter(QObject *obj, QEvent *event) { int buttonIndex = -1; for (int i = 0; i < 2; ++i) { if (obj == m_iconbutton[i]) { buttonIndex = i; break; } } if (buttonIndex == -1) return QObject::eventFilter(obj, event); switch (event->type()) { case QEvent::FocusIn: if (m_menuTabFocusTrigger[buttonIndex] && m_menu[buttonIndex]) { m_lineEdit->setFocus(); m_menu[buttonIndex]->exec(m_iconbutton[buttonIndex]->mapToGlobal( m_iconbutton[buttonIndex]->rect().center())); return true; } default: break; } return QObject::eventFilter(obj, event); } // --------- FancyLineEdit FancyLineEdit::FancyLineEdit(QWidget *parent) : QLineEdit(parent), m_d(new FancyLineEditPrivate(this)) { ensurePolished(); updateMargins(); connect(this, SIGNAL(textChanged(QString)), this, SLOT(checkButtons(QString))); connect(m_d->m_iconbutton[Left], SIGNAL(clicked()), this, SLOT(iconClicked())); connect(m_d->m_iconbutton[Right], SIGNAL(clicked()), this, SLOT(iconClicked())); } void FancyLineEdit::checkButtons(const QString &text) { if (m_oldText.isEmpty() || text.isEmpty()) { for (int i = 0; i < 2; ++i) { if (m_d->m_iconbutton[i]->hasAutoHide()) m_d->m_iconbutton[i]->animateShow(!text.isEmpty()); } m_oldText = text; } } FancyLineEdit::~FancyLineEdit() { } void FancyLineEdit::setButtonVisible(Side side, bool visible) { m_d->m_iconbutton[side]->setVisible(visible); m_d->m_iconEnabled[side] = visible; updateMargins(); updateButtonPositions(); } bool FancyLineEdit::isButtonVisible(Side side) const { return m_d->m_iconEnabled[side]; } void FancyLineEdit::iconClicked() { IconButton *button = qobject_cast(sender()); int index = -1; for (int i = 0; i < 2; ++i) if (m_d->m_iconbutton[i] == button) index = i; if (index == -1) return; if (m_d->m_menu[index]) { m_d->m_menu[index]->exec(QCursor::pos()); } else { emit buttonClicked((Side)index); if (index == Left) emit leftButtonClicked(); else if (index == Right) emit rightButtonClicked(); } } void FancyLineEdit::updateMargins() { bool leftToRight = (layoutDirection() == Qt::LeftToRight); Side realLeft = (leftToRight ? Left : Right); Side realRight = (leftToRight ? Right : Left); int leftMargin = m_d->m_iconbutton[realLeft]->pixmap().width() + 8; int rightMargin = m_d->m_iconbutton[realRight]->pixmap().width() + 8; // Note KDE does not reserve space for the highlight color if (style()->inherits("OxygenStyle")) { leftMargin = qMax(24, leftMargin); rightMargin = qMax(24, rightMargin); } QMargins margins((m_d->m_iconEnabled[realLeft] ? leftMargin : 0), 0, (m_d->m_iconEnabled[realRight] ? rightMargin : 0), 0); setTextMargins(margins); } void FancyLineEdit::updateButtonPositions() { QRect contentRect = rect(); for (int i = 0; i < 2; ++i) { Side iconpos = (Side)i; if (layoutDirection() == Qt::RightToLeft) iconpos = (iconpos == Left ? Right : Left); if (iconpos == FancyLineEdit::Right) { const int iconoffset = textMargins().right() + 4; m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(width() - iconoffset, 0, 0, 0)); } else { const int iconoffset = textMargins().left() + 4; m_d->m_iconbutton[i]->setGeometry(contentRect.adjusted(0, 0, -width() + iconoffset, 0)); } } } void FancyLineEdit::resizeEvent(QResizeEvent *) { updateButtonPositions(); } void FancyLineEdit::setButtonPixmap(Side side, const QPixmap &buttonPixmap) { m_d->m_iconbutton[side]->setPixmap(buttonPixmap); updateMargins(); updateButtonPositions(); update(); } QPixmap FancyLineEdit::buttonPixmap(Side side) const { return m_d->m_pixmap[side]; } void FancyLineEdit::setButtonMenu(Side side, QMenu *buttonMenu) { m_d->m_menu[side] = buttonMenu; m_d->m_iconbutton[side]->setIconOpacity(1.0); } QMenu *FancyLineEdit::buttonMenu(Side side) const { return m_d->m_menu[side]; } bool FancyLineEdit::hasMenuTabFocusTrigger(Side side) const { return m_d->m_menuTabFocusTrigger[side]; } void FancyLineEdit::setMenuTabFocusTrigger(Side side, bool v) { if (m_d->m_menuTabFocusTrigger[side] == v) return; m_d->m_menuTabFocusTrigger[side] = v; m_d->m_iconbutton[side]->setFocusPolicy(v ? Qt::TabFocus : Qt::NoFocus); } bool FancyLineEdit::hasAutoHideButton(Side side) const { return m_d->m_iconbutton[side]->hasAutoHide(); } void FancyLineEdit::setAutoHideButton(Side side, bool h) { m_d->m_iconbutton[side]->setAutoHide(h); if (h) m_d->m_iconbutton[side]->setIconOpacity(text().isEmpty() ? 0.0 : 1.0); else m_d->m_iconbutton[side]->setIconOpacity(1.0); } void FancyLineEdit::setButtonToolTip(Side side, const QString &tip) { m_d->m_iconbutton[side]->setToolTip(tip); } void FancyLineEdit::setButtonFocusPolicy(Side side, Qt::FocusPolicy policy) { m_d->m_iconbutton[side]->setFocusPolicy(policy); } // IconButton - helper class to represent a clickable icon IconButton::IconButton(QWidget *parent) : QAbstractButton(parent), m_autoHide(false) { setCursor(Qt::ArrowCursor); setFocusPolicy(Qt::NoFocus); } void IconButton::paintEvent(QPaintEvent *) { QPainter painter(this); // Note isDown should really use the active state but in most styles // this has no proper feedback QIcon::Mode state = QIcon::Disabled; if (isEnabled()) state = isDown() ? QIcon::Selected : QIcon::Normal; QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height()); pixmapRect.moveCenter(rect().center()); if (m_autoHide) painter.setOpacity(m_iconOpacity); painter.drawPixmap(pixmapRect, m_pixmap); } void IconButton::animateShow(bool visible) { if (visible) { QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity"); animation->setDuration(FADE_TIME); animation->setEndValue(1.0); animation->start(QAbstractAnimation::DeleteWhenStopped); } else { QPropertyAnimation *animation = new QPropertyAnimation(this, "iconOpacity"); animation->setDuration(FADE_TIME); animation->setEndValue(0.0); animation->start(QAbstractAnimation::DeleteWhenStopped); } } } // namespace Utils ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/fancylineedit.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #ifndef FANCYLINEEDIT_H #define FANCYLINEEDIT_H #include #include namespace Utils { class FancyLineEditPrivate; class IconButton: public QAbstractButton { Q_OBJECT Q_PROPERTY(float iconOpacity READ iconOpacity WRITE setIconOpacity) Q_PROPERTY(bool autoHide READ hasAutoHide WRITE setAutoHide) Q_PROPERTY(QPixmap pixmap READ pixmap WRITE setPixmap) public: explicit IconButton(QWidget *parent = 0); void paintEvent(QPaintEvent *event); void setPixmap(const QPixmap &pixmap) { m_pixmap = pixmap; update(); } QPixmap pixmap() const { return m_pixmap; } float iconOpacity() { return m_iconOpacity; } void setIconOpacity(float value) { m_iconOpacity = value; update(); } void animateShow(bool visible); void setAutoHide(bool hide) { m_autoHide = hide; } bool hasAutoHide() const { return m_autoHide; } private: float m_iconOpacity; bool m_autoHide; QPixmap m_pixmap; }; /* A line edit with an embedded pixmap on one side that is connected to * a menu. Additionally, it can display a grayed hintText (like "Type Here to") * when not focused and empty. When connecting to the changed signals and * querying text, one has to be aware that the text is set to that hint * text if isShowingHintText() returns true (that is, does not contain * valid user input). */ class FancyLineEdit : public QLineEdit { Q_DISABLE_COPY(FancyLineEdit) Q_OBJECT Q_ENUMS(Side) public: enum Side {Left = 0, Right = 1}; explicit FancyLineEdit(QWidget *parent = 0); ~FancyLineEdit(); QPixmap buttonPixmap(Side side) const; void setButtonPixmap(Side side, const QPixmap &pixmap); QMenu *buttonMenu(Side side) const; void setButtonMenu(Side side, QMenu *menu); void setButtonVisible(Side side, bool visible); bool isButtonVisible(Side side) const; void setButtonToolTip(Side side, const QString &); void setButtonFocusPolicy(Side side, Qt::FocusPolicy policy); // Set whether tabbing in will trigger the menu. void setMenuTabFocusTrigger(Side side, bool v); bool hasMenuTabFocusTrigger(Side side) const; // Set if icon should be hidden when text is empty void setAutoHideButton(Side side, bool h); bool hasAutoHideButton(Side side) const; signals: void buttonClicked(Utils::FancyLineEdit::Side side); void leftButtonClicked(); void rightButtonClicked(); private slots: void checkButtons(const QString &); void iconClicked(); protected: virtual void resizeEvent(QResizeEvent *e); private: void updateMargins(); void updateButtonPositions(); friend class Utils::FancyLineEditPrivate; FancyLineEditPrivate *m_d; QString m_oldText; }; } // namespace Utils #endif // FANCYLINEEDIT_H ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/filterlineedit.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #include "filterlineedit.h" #include namespace Utils { FilterLineEdit::FilterLineEdit(int dly, QWidget *parent) : FancyLineEdit(parent), m_lastFilterText(text()), m_dlytimer(dly) { // KDE has custom icons for this. Notice that icon namings are counter intuitive // If these icons are not avaiable we use the freedesktop standard name before // falling back to a bundled resource QIcon icon = QIcon::fromTheme(layoutDirection() == Qt::LeftToRight ? QLatin1String("edit-clear-locationbar-rtl") : QLatin1String("edit-clear-locationbar-ltr"), QIcon::fromTheme(QLatin1String("edit-clear"), QIcon(QLatin1String("icon:images/editclear.png")))); setButtonPixmap(Right, icon.pixmap(16)); setButtonVisible(Right, true); setPlaceholderText(tr("Filter")); setButtonToolTip(Right, tr("Clear text")); setAutoHideButton(Right, true); m_timer = new QTimer(this); m_timer->setSingleShot(true); connect(m_timer,SIGNAL(timeout()),this,SLOT(dlyTextChanged())); connect(this, SIGNAL(rightButtonClicked()), this, SLOT(clear())); connect(this, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged())); } void FilterLineEdit::slotTextChanged() { const QString newlyTypedText = text(); if (newlyTypedText != m_lastFilterText) { m_lastFilterText = newlyTypedText; if (m_dlytimer == 0) { emit filterChanged(m_lastFilterText); } else { m_timer->start(m_dlytimer); } } } void FilterLineEdit::dlyTextChanged() { emit filterChanged(m_lastFilterText); } } // namespace Utils ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/filterlineedit.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** Commercial Usage ** ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** **************************************************************************/ #ifndef FILTERLINEEDIT_H #define FILTERLINEEDIT_H #include "fancylineedit.h" namespace Utils { /* A fancy line edit customized for filtering purposes with a clear button. */ class FilterLineEdit : public FancyLineEdit { Q_OBJECT public: explicit FilterLineEdit(int dly,QWidget *parent = 0); signals: void filterChanged(const QString &); private slots: void slotTextChanged(); void dlyTextChanged(); private: QString m_lastFilterText; int m_dlytimer; QTimer *m_timer; }; } // namespace Utils #endif // FILTERLINEEDIT_H ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/qtc_editutil.pri ================================================ LIBS *= -l$$qtLibraryName(qtc_editutil) ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/qtc_editutil.pro ================================================ TARGET = qtc_editutil TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += \ filterlineedit.h \ fancylineedit.h \ uncommentselection.h \ utils_global.h SOURCES += \ filterlineedit.cpp \ fancylineedit.cpp \ uncommentselection.cpp RESOURCES += QMAKE_CFLAGS_WARN_ON -= -W -Wextra -Wall QMAKE_CXXFLAGS_WARN_ON -= -W -Wextra -Wall ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/uncommentselection.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** ** GNU Lesser General Public License Usage ** ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this file. ** Please review the following information to ensure the GNU Lesser General ** Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** Other Usage ** ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "uncommentselection.h" #include #include #include #include #include using namespace Utils; CommentDefinition::CommentDefinition() : m_afterWhiteSpaces(true), m_afterWhiteSpacesAddSpace(true), m_singleLine(QLatin1String("//")), m_multiLineStart(QLatin1String("/*")), m_multiLineEnd(QLatin1String("*/")) {} CommentDefinition &CommentDefinition::setAfterWhiteSpaces(const bool afterWhiteSpaces) { m_afterWhiteSpaces = afterWhiteSpaces; return *this; } CommentDefinition &CommentDefinition::setAfterWhiteSpacesAddSpace(const bool afterWhiteSpacesAddSpace) { m_afterWhiteSpacesAddSpace = afterWhiteSpacesAddSpace; return *this; } CommentDefinition &CommentDefinition::setSingleLine(const QString &singleLine) { m_singleLine = singleLine; return *this; } CommentDefinition &CommentDefinition::setMultiLineStart(const QString &multiLineStart) { m_multiLineStart = multiLineStart; return *this; } CommentDefinition &CommentDefinition::setMultiLineEnd(const QString &multiLineEnd) { m_multiLineEnd = multiLineEnd; return *this; } bool CommentDefinition::isAfterWhiteSpaces() const { return m_afterWhiteSpaces; } bool CommentDefinition::isAfterWhiteSpacesAddSpace() const { return m_afterWhiteSpacesAddSpace; } const QString &CommentDefinition::singleLine() const { return m_singleLine; } const QString &CommentDefinition::multiLineStart() const { return m_multiLineStart; } const QString &CommentDefinition::multiLineEnd() const { return m_multiLineEnd; } bool CommentDefinition::hasSingleLineStyle() const { return !m_singleLine.isEmpty(); } bool CommentDefinition::hasMultiLineStyle() const { return !m_multiLineStart.isEmpty() && !m_multiLineEnd.isEmpty(); } void CommentDefinition::clearCommentStyles() { m_singleLine.clear(); m_multiLineStart.clear(); m_multiLineEnd.clear(); } namespace { bool isComment(const QString &text, int index, const CommentDefinition &definition, const QString & (CommentDefinition::* comment) () const) { const QString &commentType = ((definition).*(comment))(); const int length = commentType.length(); Q_ASSERT(text.length() - index >= length); int i = 0; while (i < length) { if (text.at(index + i) != commentType.at(i)) return false; ++i; } return true; } } // namespace anynomous void Utils::unCommentSelection(QPlainTextEdit *edit, CommentFlag flag, const CommentDefinition &definition) { if (!definition.hasSingleLineStyle() && !definition.hasMultiLineStyle()) return; QTextCursor cursor = edit->textCursor(); QTextDocument *doc = cursor.document(); if (!cursor.hasSelection() && (flag == BlockComment) ) { if (definition.hasMultiLineStyle()) { cursor.beginEditBlock(); cursor.insertText(definition.multiLineStart()); cursor.insertText(definition.multiLineEnd()); cursor.movePosition(QTextCursor::Left,QTextCursor::MoveAnchor,definition.multiLineEnd().length()); cursor.endEditBlock(); edit->setTextCursor(cursor); return; } } cursor.beginEditBlock(); int pos = cursor.position(); int anchor = cursor.anchor(); int start = qMin(anchor, pos); int end = qMax(anchor, pos); bool anchorIsStart = (anchor == start); QTextBlock startBlock = doc->findBlock(start); QTextBlock endBlock = doc->findBlock(end); if (end > start && endBlock.position() == end) { --end; endBlock = endBlock.previous(); } bool doMultiLineStyleUncomment = false; bool doMultiLineStyleComment = false; bool doSingleLineStyleUncomment = false; bool hasSelection = cursor.hasSelection(); int firstSpacesOffset = -1; if (hasSelection && definition.hasMultiLineStyle()) { QString startText = startBlock.text(); int startPos = start - startBlock.position(); const int multiLineStartLength = definition.multiLineStart().length(); bool hasLeadingCharacters = !startText.left(startPos).trimmed().isEmpty(); if (startPos >= multiLineStartLength && isComment(startText, startPos - multiLineStartLength, definition, &CommentDefinition::multiLineStart)) { startPos -= multiLineStartLength; start -= multiLineStartLength; } bool hasSelStart = (startPos <= startText.length() - multiLineStartLength && isComment(startText, startPos, definition, &CommentDefinition::multiLineStart)); QString endText = endBlock.text(); int endPos = end - endBlock.position(); const int multiLineEndLength = definition.multiLineEnd().length(); bool hasTrailingCharacters = !endText.left(endPos).remove(definition.singleLine()).trimmed().isEmpty() && !endText.mid(endPos).trimmed().isEmpty(); if (endPos <= endText.length() - multiLineEndLength && isComment(endText, endPos, definition, &CommentDefinition::multiLineEnd)) { endPos += multiLineEndLength; end += multiLineEndLength; } bool hasSelEnd = (endPos >= multiLineEndLength && isComment(endText, endPos - multiLineEndLength, definition, &CommentDefinition::multiLineEnd)); doMultiLineStyleUncomment = hasSelStart && hasSelEnd; doMultiLineStyleComment = !doMultiLineStyleUncomment && (hasLeadingCharacters || hasTrailingCharacters || !definition.hasSingleLineStyle() || (flag == BlockComment)); } else if (!hasSelection && !definition.hasSingleLineStyle()) { QString text = startBlock.text().trimmed(); doMultiLineStyleUncomment = text.startsWith(definition.multiLineStart()) && text.endsWith(definition.multiLineEnd()); doMultiLineStyleComment = !doMultiLineStyleUncomment && !text.isEmpty(); start = startBlock.position(); end = endBlock.position() + endBlock.length() - 1; if (doMultiLineStyleUncomment) { int offset = 0; text = startBlock.text(); const int length = text.length(); while (offset < length && text.at(offset).isSpace()) ++offset; start += offset; } } if (flag == SingleComment) { if (doMultiLineStyleComment) { doMultiLineStyleComment = false; } } if (doMultiLineStyleUncomment) { cursor.setPosition(end); cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, definition.multiLineEnd().length()); cursor.removeSelectedText(); cursor.setPosition(start); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, definition.multiLineStart().length()); cursor.removeSelectedText(); } else if (doMultiLineStyleComment) { cursor.setPosition(end); cursor.insertText(definition.multiLineEnd()); cursor.setPosition(start); cursor.insertText(definition.multiLineStart()); } else { endBlock = endBlock.next(); doSingleLineStyleUncomment = true; for (QTextBlock block = startBlock; block != endBlock; block = block.next()) { QString text = block.text().trimmed(); if (!text.isEmpty() && !text.startsWith(definition.singleLine())) { doSingleLineStyleUncomment = false; break; } } if (!hasSelection && cursor.block().text().isEmpty()) { doSingleLineStyleUncomment = false; } const int singleLineLength = definition.singleLine().length(); for (QTextBlock block = startBlock; block != endBlock; block = block.next()) { if (doSingleLineStyleUncomment) { QString text = block.text(); int i = 0; while (i <= text.size() - singleLineLength) { if (isComment(text, i, definition, &CommentDefinition::singleLine)) { cursor.setPosition(block.position() + i); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, singleLineLength); if (definition.isAfterWhiteSpacesAddSpace()) { if (i < text.size()-singleLineLength) { if (text.at(i+singleLineLength) == 0x0020) { cursor.movePosition(QTextCursor::NextCharacter,QTextCursor::KeepAnchor,1); } } } cursor.removeSelectedText(); break; } if (!text.at(i).isSpace()) break; ++i; } } else { QString text = block.text(); foreach(QChar c, text) { if (!c.isSpace()) { if (definition.isAfterWhiteSpaces()) { int offset = text.indexOf(c); if (firstSpacesOffset != -1 && offset > firstSpacesOffset) { offset = firstSpacesOffset; } cursor.setPosition(block.position() + offset); } else { cursor.setPosition(block.position()); } if (firstSpacesOffset == -1) { firstSpacesOffset = cursor.position()-cursor.block().position(); } if (definition.isAfterWhiteSpaces() && definition.isAfterWhiteSpacesAddSpace()) { cursor.insertText(definition.singleLine()+" "); } else { cursor.insertText(definition.singleLine()); } break; } } } } } // adjust selection when commenting out if (hasSelection && !doMultiLineStyleUncomment && !doSingleLineStyleUncomment) { cursor = edit->textCursor(); if (!doMultiLineStyleComment) start = startBlock.position(); // move the comment into the selection int lastSelPos = anchorIsStart ? cursor.position() : cursor.anchor(); if (anchorIsStart) { cursor.setPosition(start); cursor.setPosition(lastSelPos, QTextCursor::KeepAnchor); } else { cursor.setPosition(lastSelPos); cursor.setPosition(start, QTextCursor::KeepAnchor); } edit->setTextCursor(cursor); } cursor.endEditBlock(); } ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/uncommentselection.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** ** GNU Lesser General Public License Usage ** ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this file. ** Please review the following information to ensure the GNU Lesser General ** Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** Other Usage ** ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef UNCOMMENTSELECTION_H #define UNCOMMENTSELECTION_H #include "utils_global.h" #include QT_BEGIN_NAMESPACE class QPlainTextEdit; QT_END_NAMESPACE namespace Utils { enum CommentFlag { AutoComment = 0, SingleComment, BlockComment, }; class QTCREATOR_UTILS_EXPORT CommentDefinition { public: CommentDefinition(); CommentDefinition &setAfterWhiteSpaces(const bool); CommentDefinition &setAfterWhiteSpacesAddSpace(const bool); CommentDefinition &setAfterMaxSpaces(int spaces); CommentDefinition &setSingleLine(const QString &singleLine); CommentDefinition &setMultiLineStart(const QString &multiLineStart); CommentDefinition &setMultiLineEnd(const QString &multiLineEnd); bool isAfterWhiteSpaces() const; bool isAfterWhiteSpacesAddSpace() const; const QString &singleLine() const; const QString &multiLineStart() const; const QString &multiLineEnd() const; bool hasSingleLineStyle() const; bool hasMultiLineStyle() const; void clearCommentStyles(); private: bool m_afterWhiteSpaces; bool m_afterWhiteSpacesAddSpace; QString m_singleLine; QString m_multiLineStart; QString m_multiLineEnd; }; QTCREATOR_UTILS_EXPORT void unCommentSelection(QPlainTextEdit *edit, CommentFlag flag, const CommentDefinition &definiton = CommentDefinition()); } // namespace Utils #endif // UNCOMMENTSELECTION_H ================================================ FILE: liteidex/src/3rdparty/qtc_editutil/utils_global.h ================================================ #ifndef QTCREATOR_UTILS_GLOBAL_H #define QTCREATOR_UTILS_GLOBAL_H #include #define QTCREATOR_UTILS_EXPORT /* #if defined(TEXTEDITOR_LIBRARY) # define TEXTEDITOR_EXPORT Q_DECL_EXPORT #else # define TEXTEDITOR_EXPORT Q_DECL_IMPORT #endif */ #endif // QTCREATOR_UTILS_GLOBAL_H ================================================ FILE: liteidex/src/3rdparty/qtc_gdbmi/gdbmi.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (info@qt.nokia.com) ** ** ** GNU Lesser General Public License Usage ** ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this file. ** Please review the following information to ensure the GNU Lesser General ** Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** Other Usage ** ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** If you have questions regarding the use of this file, please contact ** Nokia at info@qt.nokia.com. ** **************************************************************************/ #include "gdbmi.h" #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end void skipCommas(const char *&from, const char *to) { while (*from == ',' && from != to) ++from; } QTextStream &operator<<(QTextStream &os, const GdbMiValue &mi) { return os << mi.toString(); } void GdbMiValue::parseResultOrValue(const char *&from, const char *to) { while (from != to && isspace(*from)) ++from; //qDebug() << "parseResultOrValue: " << QByteArray(from, to - from); parseValue(from, to); if (isValid()) { //qDebug() << "no valid result in " << QByteArray(from, to - from); return; } if (from == to || *from == '(') return; const char *ptr = from; while (ptr < to && *ptr != '=') { //qDebug() << "adding" << QChar(*ptr) << "to name"; ++ptr; } m_name = QByteArray(from, ptr - from); from = ptr; if (from < to && *from == '=') { ++from; parseValue(from, to); } } QByteArray GdbMiValue::parseCString(const char *&from, const char *to) { QByteArray result; //qDebug() << "parseCString: " << QByteArray(from, to - from); if (*from != '"') { qDebug() << "MI Parse Error, double quote expected"; ++from; // So we don't hang return QByteArray(); } const char *ptr = from; ++ptr; while (ptr < to) { if (*ptr == '"') { ++ptr; result = QByteArray(from + 1, ptr - from - 2); break; } if (*ptr == '\\') { ++ptr; if (ptr == to) { qDebug() << "MI Parse Error, unterminated backslash escape"; from = ptr; // So we don't hang return QByteArray(); } } ++ptr; } from = ptr; int idx = result.indexOf('\\'); if (idx >= 0) { char *dst = result.data() + idx; const char *src = dst + 1, *end = result.data() + result.length(); do { char c = *src++; switch (c) { case 'a': *dst++ = '\a'; break; case 'b': *dst++ = '\b'; break; case 'f': *dst++ = '\f'; break; case 'n': *dst++ = '\n'; break; case 'r': *dst++ = '\r'; break; case 't': *dst++ = '\t'; break; case 'v': *dst++ = '\v'; break; case '"': *dst++ = '"'; break; case '\\': *dst++ = '\\'; break; default: { int chars = 0; uchar prod = 0; forever { if (c < '0' || c > '7') { --src; break; } prod = prod * 8 + c - '0'; if (++chars == 3 || src == end) break; c = *src++; } if (!chars) { qDebug() << "MI Parse Error, unrecognized backslash escape"; return QByteArray(); } *dst++ = prod; } } while (src != end) { char c = *src++; if (c == '\\') break; *dst++ = c; } } while (src != end); *dst = 0; result.truncate(dst - result.data()); } return result; } void GdbMiValue::parseValue(const char *&from, const char *to) { //qDebug() << "parseValue: " << QByteArray(from, to - from); switch (*from) { case '{': parseTuple(from, to); break; case '[': parseList(from, to); break; case '"': m_type = Const; m_data = parseCString(from, to); break; default: break; } } void GdbMiValue::parseTuple(const char *&from, const char *to) { //qDebug() << "parseTuple: " << QByteArray(from, to - from); if (*from != '{') { return; } ++from; parseTuple_helper(from, to); } void GdbMiValue::parseTuple_helper(const char *&from, const char *to) { skipCommas(from, to); //qDebug() << "parseTuple_helper: " << QByteArray(from, to - from); m_type = Tuple; while (from < to) { if (*from == '}') { ++from; break; } GdbMiValue child; child.parseResultOrValue(from, to); //qDebug() << "\n=======\n" << qPrintable(child.toString()) << "\n========\n"; if (!child.isValid()) return; m_children += child; skipCommas(from, to); } } void GdbMiValue::parseList(const char *&from, const char *to) { //qDebug() << "parseList: " << QByteArray(from, to - from); if (*from != '[') { return; } ++from; m_type = List; skipCommas(from, to); while (from < to) { if (*from == ']') { ++from; break; } GdbMiValue child; child.parseResultOrValue(from, to); if (child.isValid()) m_children += child; skipCommas(from, to); } } static QByteArray ind(int indent) { return QByteArray(2 * indent, ' '); } void GdbMiValue::dumpChildren(QByteArray * str, bool multiline, int indent) const { for (int i = 0; i < m_children.size(); ++i) { if (i != 0) { *str += ','; if (multiline) *str += '\n'; } if (multiline) *str += ind(indent); *str += m_children.at(i).toString(multiline, indent); } } class MyString : public QString { public: ushort at(int i) const { return constData()[i].unicode(); } }; template inline ST escapeCStringTpl(const ST &ba) { ST ret; ret.reserve(ba.length() * 2); for (int i = 0; i < ba.length(); ++i) { CT c = ba.at(i); switch (c) { case '\\': ret += "\\\\"; break; case '\a': ret += "\\a"; break; case '\b': ret += "\\b"; break; case '\f': ret += "\\f"; break; case '\n': ret += "\\n"; break; case '\r': ret += "\\r"; break; case '\t': ret += "\\t"; break; case '\v': ret += "\\v"; break; case '"': ret += "\\\""; break; default: if (c < 32 || c == 127) { ret += '\\'; ret += '0' + (c >> 6); ret += '0' + ((c >> 3) & 7); ret += '0' + (c & 7); } else { ret += c; } } } return ret; } QString GdbMiValue::escapeCString(const QString &ba) { return escapeCStringTpl(static_cast(ba)); } QByteArray GdbMiValue::escapeCString(const QByteArray &ba) { return escapeCStringTpl(ba); } QByteArray GdbMiValue::toString(bool multiline, int indent) const { QByteArray result; switch (m_type) { case Invalid: if (multiline) result += ind(indent) + "Invalid\n"; else result += "Invalid"; break; case Const: if (!m_name.isEmpty()) result += m_name + '='; result += '"' + escapeCString(m_data) + '"'; break; case Tuple: if (!m_name.isEmpty()) result += m_name + '='; if (multiline) { result += "{\n"; dumpChildren(&result, multiline, indent + 1); result += '\n' + ind(indent) + '}'; } else { result += '{'; dumpChildren(&result, multiline, indent + 1); result += '}'; } break; case List: if (!m_name.isEmpty()) result += m_name + '='; if (multiline) { result += "[\n"; dumpChildren(&result, multiline, indent + 1); result += '\n' + ind(indent) + ']'; } else { result += '['; dumpChildren(&result, multiline, indent + 1); result += ']'; } break; } return result; } void GdbMiValue::fromString(const QByteArray &ba) { const char *from = ba.constBegin(); const char *to = ba.constEnd(); parseResultOrValue(from, to); } void GdbMiValue::fromStringMultiple(const QByteArray &ba) { const char *from = ba.constBegin(); const char *to = ba.constEnd(); parseTuple_helper(from, to); } GdbMiValue GdbMiValue::findChild(const char *name) const { for (int i = 0; i < m_children.size(); ++i) if (m_children.at(i).m_name == name) return m_children.at(i); return GdbMiValue(); } qulonglong GdbMiValue::toAddress() const { QByteArray ba = m_data; if (ba.endsWith('L')) ba.chop(1); if (ba.startsWith('*') || ba.startsWith('@')) ba = ba.mid(1); return ba.toULongLong(0, 0); } QByteArray GdbResponse::stringFromResultClass(GdbResultClass resultClass) { switch (resultClass) { case GdbResultDone: return "done"; case GdbResultRunning: return "running"; case GdbResultConnected: return "connected"; case GdbResultError: return "error"; case GdbResultExit: return "exit"; default: return "unknown"; } } QByteArray GdbResponse::toString() const { QByteArray result; if (token != -1) result = QByteArray::number(token); result += '^'; result += stringFromResultClass(resultClass); if (data.isValid()) result += ',' + data.toString(); result += '\n'; return result; } ================================================ FILE: liteidex/src/3rdparty/qtc_gdbmi/gdbmi.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (info@qt.nokia.com) ** ** ** GNU Lesser General Public License Usage ** ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this file. ** Please review the following information to ensure the GNU Lesser General ** Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** Other Usage ** ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** If you have questions regarding the use of this file, please contact ** Nokia at info@qt.nokia.com. ** **************************************************************************/ #ifndef GDBMI_H #define GDBMI_H #include #include #include class GdbMiValue { public: GdbMiValue() : m_type(Invalid) {} QByteArray m_name; QByteArray m_data; QList m_children; enum Type { Invalid, Const, Tuple, List }; Type m_type; inline Type type() const { return m_type; } inline QByteArray name() const { return m_name; } inline bool hasName(const char *name) const { return m_name == name; } inline bool isValid() const { return m_type != Invalid; } inline bool isConst() const { return m_type == Const; } inline bool isTuple() const { return m_type == Tuple; } inline bool isList() const { return m_type == List; } inline QByteArray data() const { return m_data; } inline const QList &children() const { return m_children; } inline int childCount() const { return m_children.size(); } const GdbMiValue &childAt(int index) const { return m_children[index]; } GdbMiValue &childAt(int index) { return m_children[index]; } GdbMiValue findChild(const char *name) const; QByteArray toString(bool multiline = false, int indent = 0) const; qulonglong toAddress() const; void fromString(const QByteArray &str); void fromStringMultiple(const QByteArray &str); public: static QByteArray parseCString(const char *&from, const char *to); static QByteArray escapeCString(const QByteArray &ba); static QString escapeCString(const QString &ba); void parseResultOrValue(const char *&from, const char *to); void parseValue(const char *&from, const char *to); void parseTuple(const char *&from, const char *to); void parseTuple_helper(const char *&from, const char *to); void parseList(const char *&from, const char *to); void dumpChildren(QByteArray *str, bool multiline, int indent) const; }; enum GdbResultClass { // "done" | "running" | "connected" | "error" | "exit" GdbResultUnknown, GdbResultDone, GdbResultRunning, GdbResultConnected, GdbResultError, GdbResultExit }; class GdbResponse { public: GdbResponse() : token(-1), resultClass(GdbResultUnknown) {} QByteArray toString() const; static QByteArray stringFromResultClass(GdbResultClass resultClass); int token; GdbResultClass resultClass; GdbMiValue data; QVariant cookie; QByteArray logStreamOutput; QByteArray consoleStreamOutput; }; #endif // GDBMI_H ================================================ FILE: liteidex/src/3rdparty/qtc_gdbmi/qtc_gdbmi.pri ================================================ LIBS *= -l$$qtLibraryName(qtcgdbmi) ================================================ FILE: liteidex/src/3rdparty/qtc_gdbmi/qtc_gdbmi.pro ================================================ TARGET = qtcgdbmi TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += gdbmi.h SOURCES += gdbmi.cpp ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/itemviews.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "itemviews.h" /*! \class Utils::TreeView \brief The TreeView adds setActivationMode to QTreeView to allow for single click/double click behavior on platforms where the default is different. Use with care. Also adds sane keyboard navigation for mac. */ /*! \class Utils::TreeWidget \brief The TreeWidget adds setActivationMode to QTreeWidget to allow for single click/double click behavior on platforms where the default is different. Use with care. Also adds sane keyboard navigation for mac. */ /*! \class Utils::ListView \brief The ListView adds setActivationMode to QListView to allow for single click/double click behavior on platforms where the default is different. Use with care. Also adds sane keyboard navigation for mac. */ /*! \class Utils::ListWidget \brief The ListWidget adds setActivationMode to QListWidget to allow for single click/double click behavior on platforms where the default is different. Use with care. Also adds sane keyboard navigation for mac. */ ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/itemviews.h ================================================ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TREEVIEW_H #define TREEVIEW_H static const char activationModeC[] = "ActivationMode"; #include #include #include #include #include namespace Utils { enum ActivationMode { DoubleClickActivation = 0, SingleClickActivation = 1, PlatformDefaultActivation = 2 }; template class View : public BaseT { public: View(QWidget *parent = 0) : BaseT(parent) {} void setActivationMode(ActivationMode mode) { if (mode == PlatformDefaultActivation) BaseT::setProperty(activationModeC, QVariant()); else BaseT::setProperty(activationModeC, QVariant(bool(mode))); } ActivationMode activationMode() const { QVariant v = BaseT::property(activationModeC); if (!v.isValid()) return PlatformDefaultActivation; return v.toBool() ? SingleClickActivation : DoubleClickActivation; } void keyPressEvent(QKeyEvent *event) { // Note: This always eats the event // whereas QAbstractItemView never eats it if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && event->modifiers() == 0 && BaseT::currentIndex().isValid() && BaseT::state() != QAbstractItemView::EditingState) { emit BaseT::activated(BaseT::currentIndex()); return; } BaseT::keyPressEvent(event); } }; class TreeView : public View { Q_OBJECT public: TreeView(QWidget *parent = 0) : View(parent) {} }; class TreeWidget : public View { Q_OBJECT public: TreeWidget(QWidget *parent = 0) : View(parent) {} }; class ListView : public View { Q_OBJECT public: ListView(QWidget *parent = 0) : View(parent) {} }; class ListWidget : public View { Q_OBJECT public: ListWidget(QWidget *parent = 0) : View(parent) {} }; } #endif // TREEVIEW_H ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/opendocumentstreeview.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "opendocumentstreeview.h" #include #include #include #include #include namespace Core { namespace Internal { class OpenDocumentsDelegate : public QStyledItemDelegate { public: explicit OpenDocumentsDelegate(QObject *parent = 0); void setCloseButtonVisible(bool visible); void handlePressed(const QModelIndex &index); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; mutable QModelIndex pressedIndex; bool closeButtonVisible; }; OpenDocumentsDelegate::OpenDocumentsDelegate(QObject *parent) : QStyledItemDelegate(parent), closeButtonVisible(true) { } void OpenDocumentsDelegate::setCloseButtonVisible(bool visible) { closeButtonVisible = visible; } void OpenDocumentsDelegate::handlePressed(const QModelIndex &index) { if (index.column() == 0) pressedIndex = index; } void OpenDocumentsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (option.state & QStyle::State_MouseOver) { if ((QApplication::mouseButtons() & Qt::LeftButton) == 0) pressedIndex = QModelIndex(); QBrush brush = option.palette.alternateBase(); if (index == pressedIndex) brush = option.palette.dark(); painter->fillRect(option.rect, brush); } QStyledItemDelegate::paint(painter, option, index); if (closeButtonVisible && index.column() == 0 && option.state & QStyle::State_MouseOver) { //const QIcon icon(QLatin1String((option.state & QStyle::State_Selected) ? // ":/images/closebutton.png" : ":/images/darkclosebutton.png")); const QIcon icon("icon:images/darkclosebutton.png"); QRect iconRect(option.rect.right() - option.rect.height(), option.rect.top(), option.rect.height(), option.rect.height()); icon.paint(painter, iconRect, Qt::AlignRight | Qt::AlignVCenter); } } } // namespace Internal OpenDocumentsTreeView::OpenDocumentsTreeView(QWidget *parent) : Utils::TreeView(parent) { m_delegate = new Internal::OpenDocumentsDelegate(this); setItemDelegate(m_delegate); setIndentation(0); setUniformRowHeights(true); setTextElideMode(Qt::ElideMiddle); setFrameStyle(QFrame::NoFrame); setAttribute(Qt::WA_MacShowFocusRect, false); viewport()->setAttribute(Qt::WA_Hover); setSelectionMode(QAbstractItemView::SingleSelection); setSelectionBehavior(QAbstractItemView::SelectRows); setActivationMode(Utils::SingleClickActivation); installEventFilter(this); viewport()->installEventFilter(this); connect(this,SIGNAL(pressed(QModelIndex)),this,SLOT(handlePressed(QModelIndex))); } void OpenDocumentsTreeView::setModel(QAbstractItemModel *model) { Utils::TreeView::setModel(model); header()->hide(); header()->setStretchLastSection(true); //#if QT_VERSION >= 0x050000 // header()->setSectionResizeMode(0, QHeaderView::Stretch); // //header()->setSectionResizeMode(1, QHeaderView::Fixed); //#else // header()->setResizeMode(0,QHeaderView::Stretch); // //header()->setResizeMode(1,QHeaderView::Fixed); //#endif //header()->resizeSection(1, 16); } void OpenDocumentsTreeView::setCloseButtonVisible(bool visible) { m_delegate->setCloseButtonVisible(visible); } bool OpenDocumentsTreeView::eventFilter(QObject *obj, QEvent *event) { if (obj == this && event->type() == QEvent::KeyPress && currentIndex().isValid()) { QKeyEvent *ke = static_cast(event); if ((ke->key() == Qt::Key_Delete || ke->key() == Qt::Key_Backspace) && ke->modifiers() == 0) { emit closeActivated(currentIndex()); } } else if (obj == viewport() && event->type() == QEvent::MouseButtonRelease) { QMouseEvent * me = static_cast(event); if (me->button() == Qt::MiddleButton && me->modifiers() == Qt::NoModifier) { QModelIndex index = indexAt(me->pos()); if (index.isValid()) { emit closeActivated(index); return true; } } else if (me->button() == Qt::LeftButton && me->modifiers() == Qt::NoModifier) { QModelIndex index = indexAt(me->pos()); if (index.isValid()) { QRect rc = this->visualRect(index); QRect rc2 = QRect(rc.right()-rc.height(),rc.top(),rc.height(),rc.height()); if (rc2.contains(me->pos())) { emit closeActivated(index); return true; } } } } return false; } void OpenDocumentsTreeView::handlePressed(const QModelIndex &index) { m_delegate->handlePressed(index); } } // namespace Core ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/opendocumentstreeview.h ================================================ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef OPENDOCUMENTSTREEVIEW_H #define OPENDOCUMENTSTREEVIEW_H #include "itemviews.h" namespace Core { namespace Internal { class OpenDocumentsDelegate; } class OpenDocumentsTreeView : public Utils::TreeView { Q_OBJECT public: explicit OpenDocumentsTreeView(QWidget *parent = 0); void setModel(QAbstractItemModel *model); void setCloseButtonVisible(bool visible); signals: void closeActivated(const QModelIndex &index); protected: bool eventFilter(QObject *obj, QEvent *event); protected slots: void handlePressed(const QModelIndex &index); private: Internal::OpenDocumentsDelegate *m_delegate; }; } // namespace Core #endif // OPENDOCUMENTSTREEVIEW_H ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/proxymodel.cpp ================================================ #include "proxymodel.h" using namespace Core; ProxyModel::ProxyModel(QObject *parent) : QAbstractProxyModel(parent) { } QModelIndex ProxyModel::mapFromSource(const QModelIndex &sourceIndex) const { // root if (!sourceIndex.isValid()) return QModelIndex(); // hide the int row = sourceIndex.row() - 1; if (row < 0) return QModelIndex(); return createIndex(row, sourceIndex.column()); } QModelIndex ProxyModel::mapToSource(const QModelIndex &proxyIndex) const { if (!proxyIndex.isValid()) return QModelIndex(); // handle missing return sourceModel()->index(proxyIndex.row() + 1, proxyIndex.column()); } QModelIndex ProxyModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid() || row < 0 || row >= sourceModel()->rowCount(mapToSource(parent)) - 1 || column < 0 || column > 1) return QModelIndex(); return createIndex(row, column); } QModelIndex ProxyModel::parent(const QModelIndex &child) const { Q_UNUSED(child) return QModelIndex(); } int ProxyModel::rowCount(const QModelIndex &parent) const { if (!parent.isValid()) return sourceModel()->rowCount(mapToSource(parent)) - 1; return 0; } int ProxyModel::columnCount(const QModelIndex &parent) const { return sourceModel()->columnCount(mapToSource(parent)); } void ProxyModel::setSourceModel(QAbstractItemModel *sm) { QAbstractItemModel *previousModel = sourceModel(); if (previousModel) { disconnect(previousModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); disconnect(previousModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(sourceRowsInserted(QModelIndex,int,int))); disconnect(previousModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); disconnect(previousModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int))); disconnect(previousModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int))); } QAbstractProxyModel::setSourceModel(sm); if (sm) { connect(sm, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); connect(sm, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(sourceRowsInserted(QModelIndex,int,int))); connect(sm, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); connect(sm, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int))); connect(sm, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int))); } } QModelIndex ProxyModel::sibling(int row, int column, const QModelIndex &idx) const { return QAbstractItemModel::sibling(row, column, idx); } Qt::DropActions ProxyModel::supportedDragActions() const { return sourceModel()->supportedDragActions(); } void ProxyModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { QModelIndex topLeftIndex = mapFromSource(topLeft); if (!topLeftIndex.isValid()) topLeftIndex = index(0, topLeft.column()); QModelIndex bottomRightIndex = mapFromSource(bottomRight); if (!bottomRightIndex.isValid()) bottomRightIndex = index(0, bottomRight.column()); emit dataChanged(topLeftIndex, bottomRightIndex); } void ProxyModel::sourceRowsRemoved(const QModelIndex &parent, int start, int end) { Q_UNUSED(parent) Q_UNUSED(start) Q_UNUSED(end) endRemoveRows(); } void ProxyModel::sourceRowsInserted(const QModelIndex &parent, int start, int end) { Q_UNUSED(parent) Q_UNUSED(start) Q_UNUSED(end) endInsertRows(); } void ProxyModel::sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { int realStart = parent.isValid() || start == 0 ? start : start - 1; int realEnd = parent.isValid() || end == 0 ? end : end - 1; beginRemoveRows(parent, realStart, realEnd); } void ProxyModel::sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) { int realStart = parent.isValid() || start == 0 ? start : start - 1; int realEnd = parent.isValid() || end == 0 ? end : end - 1; beginInsertRows(parent, realStart, realEnd); } ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/proxymodel.h ================================================ #ifndef PROXYMODEL_H #define PROXYMODEL_H #include namespace Core { class ProxyModel : public QAbstractProxyModel { Q_OBJECT public: explicit ProxyModel(QObject *parent = 0); QModelIndex mapFromSource(const QModelIndex & sourceIndex) const; QModelIndex mapToSource(const QModelIndex & proxyIndex) const; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &child) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; void setSourceModel(QAbstractItemModel *sourceModel); // QAbstractProxyModel::sibling is broken in Qt 5 QModelIndex sibling(int row, int column, const QModelIndex &idx) const; // QAbstractProxyModel::supportedDragActions delegation is missing in Qt 5 Qt::DropActions supportedDragActions() const; private slots: void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void sourceRowsRemoved(const QModelIndex &parent, int start, int end); void sourceRowsInserted(const QModelIndex &parent, int start, int end); void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); void sourceRowsAboutToBeInserted(const QModelIndex &parent, int start, int end); }; } #endif // PROXYMODEL_H ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/qtc_itemview.pri ================================================ LIBS *= -l$$qtLibraryName(qtc_itemview) ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/qtc_itemview.pro ================================================ TARGET = qtc_itemview TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += \ opendocumentstreeview.h \ itemviews.h \ proxymodel.h SOURCES += \ opendocumentstreeview.cpp \ itemviews.cpp \ proxymodel.cpp RESOURCES += \ qtc_itemview.qrc ================================================ FILE: liteidex/src/3rdparty/qtc_itemview/qtc_itemview.qrc ================================================ images/closebutton.png images/darkclosebutton.png ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/qtc_searchresult.pri ================================================ LIBS *= -l$$qtLibraryName(qtc_searchresult) ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/qtc_searchresult.pro ================================================ TARGET = qtc_searchresult TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += \ searchresultcolor.h \ searchresulttreeitemdelegate.h \ searchresulttreeitemroles.h \ searchresulttreeitems.h \ searchresulttreemodel.h \ searchresulttreeview.h \ searchresultitem.h \ searchresultitem.h \ searchresultwidget.h SOURCES += \ searchresulttreeitemdelegate.cpp \ searchresulttreeitems.cpp \ searchresulttreemodel.cpp \ searchresulttreeview.cpp \ searchresultwidget.cpp RESOURCES += ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresultcolor.h ================================================ #ifndef SEARCHRESULTCOLOR_H #define SEARCHRESULTCOLOR_H #include namespace Find { namespace Internal { class SearchResultColor{ public: QColor textBackground; QColor textForeground; QColor highlightBackground; QColor highlightForeground; }; } // namespace Internal } // namespace Find #endif // SEARCHRESULTCOLOR_H ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresultitem.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SEARCHRESULTITEM_H #define SEARCHRESULTITEM_H #include #include #include namespace Find { enum AddMode { AddSorted, AddOrdered }; class SearchResultItem { public: SearchResultItem() : textMarkPos(-1), textMarkLength(0), lineNumber(-1), useTextEditorFont(false) { } SearchResultItem(const SearchResultItem &other) : path(other.path), text(other.text), textMarkPos(other.textMarkPos), textMarkLength(other.textMarkLength), icon(other.icon), lineNumber(other.lineNumber), useTextEditorFont(other.useTextEditorFont), userData(other.userData) { } QStringList path; // hierarchy to the parent item of this item QString text; // text to show for the item itself int textMarkPos; // 0-based starting position for a mark (-1 for no mark) int textMarkLength; // length of the mark (0 for no mark) QIcon icon; // icon to show in front of the item (by be null icon to hide) int lineNumber; // (0 or -1 for no line number) bool useTextEditorFont; QVariant userData; // user data for identification of the item }; //inline SearchResultItem makeResult(const QString &fileName, int lineNumber, const QString &rowText, // int searchTermStart, int searchTermLength, const QVariant &userData) //{ // SearchResultItem item; // item.path = QStringList() << QDir::toNativeSeparators(fileName); // item.lineNumber = lineNumber; // item.text = rowText; // item.textMarkPos = searchTermStart; // item.textMarkLength = searchTermLength; // item.useTextEditorFont = true; // item.userData = userData; // return item; //} } // namespace Find Q_DECLARE_METATYPE(Find::SearchResultItem) #endif //SEARCHRESULTITEM_H ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreeitemdelegate.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "searchresulttreeitemdelegate.h" #include "searchresulttreeitemroles.h" #include #include #include #include using namespace Find::Internal; SearchResultTreeItemDelegate::SearchResultTreeItemDelegate(QObject *parent) : QItemDelegate(parent) { } void SearchResultTreeItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { static const int iconSize = 16; painter->save(); QStyleOptionViewItemV3 opt = setOptions(index, option); painter->setFont(opt.font); QItemDelegate::drawBackground(painter, opt, index); // ---- do the layout QRect checkRect; QRect pixmapRect; QRect textRect; // check mark bool checkable = (index.model()->flags(index) & Qt::ItemIsUserCheckable); Qt::CheckState checkState = Qt::Unchecked; if (checkable) { QVariant checkStateData = index.data(Qt::CheckStateRole); checkState = static_cast(checkStateData.toInt()); #if QT_VERSION >= 0x050000 checkRect = doCheck(opt, opt.rect, checkStateData); #else // Qt4 checkRect = check(opt, opt.rect, checkStateData); #endif } // icon QIcon icon = index.model()->data(index, ItemDataRoles::ResultIconRole).value(); if (!icon.isNull()) pixmapRect = QRect(0, 0, iconSize, iconSize); // text textRect = opt.rect.adjusted(0, 0, checkRect.width() + pixmapRect.width(), 0); // do layout doLayout(opt, &checkRect, &pixmapRect, &textRect, false); // ---- draw the items // icon if (!icon.isNull()) QItemDelegate::drawDecoration(painter, opt, pixmapRect, icon.pixmap(iconSize)); // line numbers int lineNumberAreaWidth = drawLineNumber(painter, opt, textRect, index); textRect.adjust(lineNumberAreaWidth, 0, 0, 0); // text and focus/selection drawText(painter, opt, textRect, index); QItemDelegate::drawFocus(painter, opt, opt.rect); // check mark if (checkable) QItemDelegate::drawCheck(painter, opt, checkRect, checkState); painter->restore(); } // returns the width of the line number area int SearchResultTreeItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option, const QRect &rect, const QModelIndex &index) const { static const int lineNumberAreaHorizontalPadding = 4; int lineNumber = index.model()->data(index, ItemDataRoles::ResultLineNumberRole).toInt(); if (lineNumber < 1) return 0; const bool isSelected = option.state & QStyle::State_Selected; QString lineText = QString::number(lineNumber); int minimumLineNumberDigits = qMax((int)m_minimumLineNumberDigits, lineText.count()); int fontWidth = painter->fontMetrics().width(QString(minimumLineNumberDigits, QLatin1Char('0'))); int lineNumberAreaWidth = lineNumberAreaHorizontalPadding + fontWidth + lineNumberAreaHorizontalPadding; QRect lineNumberAreaRect(rect); lineNumberAreaRect.setWidth(lineNumberAreaWidth); QPalette::ColorGroup cg = QPalette::Normal; if (!(option.state & QStyle::State_Active)) cg = QPalette::Inactive; else if (!(option.state & QStyle::State_Enabled)) cg = QPalette::Disabled; painter->fillRect(lineNumberAreaRect, QBrush(isSelected ? option.palette.brush(cg, QPalette::Highlight) : option.palette.color(cg, QPalette::Base).darker(111))); QStyleOptionViewItemV3 opt = option; opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; opt.palette.setColor(cg, QPalette::Text, Qt::darkGray); const QStyle *style = QApplication::style(); const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, 0) + 1; const QRect rowRect = lineNumberAreaRect.adjusted(-textMargin, 0, textMargin-lineNumberAreaHorizontalPadding, 0); QItemDelegate::drawDisplay(painter, opt, rowRect, lineText); return lineNumberAreaWidth; } void SearchResultTreeItemDelegate::drawText(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const { QString text = index.model()->data(index, Qt::DisplayRole).toString(); // show number of subresults in displayString if (index.model()->hasChildren(index)) { text += QLatin1String(" (") + QString::number(index.model()->rowCount(index)) + QLatin1Char(')'); } const int searchTermStart = index.model()->data(index, ItemDataRoles::SearchTermStartRole).toInt(); int searchTermLength = index.model()->data(index, ItemDataRoles::SearchTermLengthRole).toInt(); if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) { QItemDelegate::drawDisplay(painter, option, rect, text); return; } // clip searchTermLength to end of line searchTermLength = qMin(searchTermLength, text.length() - searchTermStart); const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; int searchTermStartPixels = painter->fontMetrics().width(text.left(searchTermStart)); int searchTermLengthPixels = painter->fontMetrics().width(text.mid(searchTermStart, searchTermLength)); // rects QRect beforeHighlightRect(rect); beforeHighlightRect.setRight(beforeHighlightRect.left() + searchTermStartPixels); QRect resultHighlightRect(rect); resultHighlightRect.setLeft(beforeHighlightRect.right()); resultHighlightRect.setRight(resultHighlightRect.left() + searchTermLengthPixels); QRect afterHighlightRect(rect); afterHighlightRect.setLeft(resultHighlightRect.right()); // paint all highlight backgrounds // qitemdelegate has problems with painting background when highlighted // (highlighted background at wrong position because text is offset with textMargin) // so we duplicate a lot here, see qitemdelegate for reference bool isSelected = option.state & QStyle::State_Selected; QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) cg = QPalette::Inactive; QStyleOptionViewItem baseOption = option; baseOption.state &= ~QStyle::State_Selected; if (isSelected) { painter->fillRect(beforeHighlightRect.adjusted(textMargin, 0, textMargin, 0), option.palette.brush(cg, QPalette::Highlight)); painter->fillRect(afterHighlightRect.adjusted(textMargin, 0, textMargin, 0), option.palette.brush(cg, QPalette::Highlight)); } const QColor highlightBackground = index.model()->data(index, ItemDataRoles::ResultHighlightBackgroundColor).value(); painter->fillRect(resultHighlightRect.adjusted(textMargin, 0, textMargin - 1, 0), QBrush(highlightBackground)); // Text before the highlighting QStyleOptionViewItem noHighlightOpt = baseOption; noHighlightOpt.rect = beforeHighlightRect; noHighlightOpt.textElideMode = Qt::ElideNone; if (isSelected) noHighlightOpt.palette.setColor(QPalette::Text, noHighlightOpt.palette.color(cg, QPalette::HighlightedText)); QItemDelegate::drawDisplay(painter, noHighlightOpt, beforeHighlightRect, text.mid(0, searchTermStart)); // Highlight text QStyleOptionViewItem highlightOpt = noHighlightOpt; const QColor highlightForeground = index.model()->data(index, ItemDataRoles::ResultHighlightForegroundColor).value(); highlightOpt.palette.setColor(QPalette::Text, highlightForeground); QItemDelegate::drawDisplay(painter, highlightOpt, resultHighlightRect, text.mid(searchTermStart, searchTermLength)); // Text after the Highlight noHighlightOpt.rect = afterHighlightRect; QItemDelegate::drawDisplay(painter, noHighlightOpt, afterHighlightRect, text.mid(searchTermStart + searchTermLength)); } ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreeitemdelegate.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SEARCHRESULTTREEITEMDELEGATE_H #define SEARCHRESULTTREEITEMDELEGATE_H #include namespace Find { namespace Internal { class SearchResultTreeItemDelegate: public QItemDelegate { public: SearchResultTreeItemDelegate(QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; private: int drawLineNumber(QPainter *painter, const QStyleOptionViewItemV3 &option, const QRect &rect, const QModelIndex &index) const; void drawText(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const; static const int m_minimumLineNumberDigits = 6; }; } // namespace Internal } // namespace Find #endif // SEARCHRESULTTREEITEMDELEGATE_H ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreeitemroles.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SEARCHRESULTTREEITEMROLES_H #define SEARCHRESULTTREEITEMROLES_H #include namespace Find { namespace Internal { namespace ItemDataRoles { enum Roles { ResultItemRole = Qt::UserRole, ResultLineRole, ResultLineNumberRole, ResultIconRole, ResultHighlightBackgroundColor, ResultHighlightForegroundColor, SearchTermStartRole, SearchTermLengthRole, IsGeneratedRole }; } // namespace Internal } // namespace Find } // namespace ItemDataRoles #endif // SEARCHRESULTTREEITEMROLES_H ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreeitems.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "searchresulttreeitems.h" namespace Find { namespace Internal { SearchResultTreeItem::SearchResultTreeItem(const SearchResultItem &item, SearchResultTreeItem *parent) : item(item), m_parent(parent), m_isUserCheckable(false), m_isGenerated(false), m_checkState(Qt::Unchecked) { } SearchResultTreeItem::~SearchResultTreeItem() { clearChildren(); } bool SearchResultTreeItem::isLeaf() const { return childrenCount() == 0 && parent() != 0; } bool SearchResultTreeItem::isUserCheckable() const { return m_isUserCheckable; } void SearchResultTreeItem::setIsUserCheckable(bool isUserCheckable) { m_isUserCheckable = isUserCheckable; } Qt::CheckState SearchResultTreeItem::checkState() const { return m_checkState; } void SearchResultTreeItem::setCheckState(Qt::CheckState checkState) { m_checkState = checkState; } void SearchResultTreeItem::clearChildren() { qDeleteAll(m_children); m_children.clear(); } int SearchResultTreeItem::childrenCount() const { return m_children.count(); } int SearchResultTreeItem::rowOfItem() const { return (m_parent ? m_parent->m_children.indexOf(const_cast(this)):0); } SearchResultTreeItem* SearchResultTreeItem::childAt(int index) const { return m_children.at(index); } SearchResultTreeItem *SearchResultTreeItem::parent() const { return m_parent; } static bool lessThanByText(SearchResultTreeItem *a, const QString &b) { return a->item.text < b; } int SearchResultTreeItem::insertionIndex(const QString &text, SearchResultTreeItem **existingItem) const { QList::const_iterator insertionPosition = qLowerBound(m_children.begin(), m_children.end(), text, lessThanByText); if (existingItem) { if (insertionPosition != m_children.end() && (*insertionPosition)->item.text == text) (*existingItem) = (*insertionPosition); else *existingItem = 0; } return insertionPosition - m_children.begin(); } int SearchResultTreeItem::insertionIndex(const SearchResultItem &item, SearchResultTreeItem **existingItem) const { return insertionIndex(item.text, existingItem); } void SearchResultTreeItem::insertChild(int index, SearchResultTreeItem *child) { m_children.insert(index, child); } void SearchResultTreeItem::insertChild(int index, const SearchResultItem &item) { SearchResultTreeItem *child = new SearchResultTreeItem(item, this); if (isUserCheckable()) { child->setIsUserCheckable(true); child->setCheckState(Qt::Checked); } insertChild(index, child); } void SearchResultTreeItem::appendChild(const SearchResultItem &item) { insertChild(m_children.count(), item); } } // namespace Internal } // namespace Find ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreeitems.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SEARCHRESULTTREEITEMS_H #define SEARCHRESULTTREEITEMS_H #include "searchresultitem.h" #include #include namespace Find { namespace Internal { class SearchResultTreeItem { public: explicit SearchResultTreeItem(const SearchResultItem &item = SearchResultItem(), SearchResultTreeItem *parent = NULL); virtual ~SearchResultTreeItem(); bool isLeaf() const; SearchResultTreeItem *parent() const; SearchResultTreeItem *childAt(int index) const; int insertionIndex(const QString &text, SearchResultTreeItem **existingItem) const; int insertionIndex(const SearchResultItem &item, SearchResultTreeItem **existingItem) const; void insertChild(int index, SearchResultTreeItem *child); void insertChild(int index, const SearchResultItem &item); void appendChild(const SearchResultItem &item); int childrenCount() const; int rowOfItem() const; void clearChildren(); bool isUserCheckable() const; void setIsUserCheckable(bool isUserCheckable); Qt::CheckState checkState() const; void setCheckState(Qt::CheckState checkState); bool isGenerated() const { return m_isGenerated; } void setGenerated(bool value) { m_isGenerated = value; } SearchResultItem item; private: SearchResultTreeItem *m_parent; QList m_children; bool m_isUserCheckable; bool m_isGenerated; Qt::CheckState m_checkState; }; } // namespace Internal } // namespace Find #endif // SEARCHRESULTTREEITEMS_H ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreemodel.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "searchresulttreemodel.h" #include "searchresulttreeitems.h" #include "searchresulttreeitemroles.h" #include #include #include #include using namespace Find; using namespace Find::Internal; SearchResultTreeModel::SearchResultTreeModel(QObject *parent) : QAbstractItemModel(parent) , m_currentParent(0) , m_showReplaceUI(false) , m_editorFontIsUsed(false) { m_rootItem = new SearchResultTreeItem; m_textEditorFont = QFont(QLatin1String("Courier")); } SearchResultTreeModel::~SearchResultTreeModel() { delete m_rootItem; } void SearchResultTreeModel::setShowReplaceUI(bool show) { m_showReplaceUI = show; } void SearchResultTreeModel::setTextEditorFont(const QFont &font, const SearchResultColor color) { layoutAboutToBeChanged(); m_textEditorFont = font; m_color = color; layoutChanged(); } Qt::ItemFlags SearchResultTreeModel::flags(const QModelIndex &idx) const { Qt::ItemFlags flags = QAbstractItemModel::flags(idx); if (idx.isValid()) { if (const SearchResultTreeItem *item = treeItemAtIndex(idx)) { if (item->isUserCheckable()) flags |= Qt::ItemIsUserCheckable; } } return flags; } QModelIndex SearchResultTreeModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); const SearchResultTreeItem *parentItem; if (!parent.isValid()) parentItem = m_rootItem; else parentItem = treeItemAtIndex(parent); const SearchResultTreeItem *childItem = parentItem->childAt(row); if (childItem) return createIndex(row, column, (void *)childItem); else return QModelIndex(); } QModelIndex SearchResultTreeModel::index(SearchResultTreeItem *item) const { return createIndex(item->rowOfItem(), 0, (void *)item); } QModelIndex SearchResultTreeModel::parent(const QModelIndex &idx) const { if (!idx.isValid()) return QModelIndex(); const SearchResultTreeItem *childItem = treeItemAtIndex(idx); const SearchResultTreeItem *parentItem = childItem->parent(); if (parentItem == m_rootItem) return QModelIndex(); return createIndex(parentItem->rowOfItem(), 0, (void *)parentItem); } int SearchResultTreeModel::rowCount(const QModelIndex &parent) const { if (parent.column() > 0) return 0; const SearchResultTreeItem *parentItem; if (!parent.isValid()) parentItem = m_rootItem; else parentItem = treeItemAtIndex(parent); return parentItem->childrenCount(); } int SearchResultTreeModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent) return 1; } SearchResultTreeItem *SearchResultTreeModel::treeItemAtIndex(const QModelIndex &idx) const { return static_cast(idx.internalPointer()); } QVariant SearchResultTreeModel::data(const QModelIndex &idx, int role) const { if (!idx.isValid()) return QVariant(); return data(treeItemAtIndex(idx), role); // QVariant result; // if (role == Qt::SizeHintRole) { // int height = QApplication::fontMetrics().height(); // if (m_editorFontIsUsed) { // const int editorFontHeight = QFontMetrics(m_textEditorFont).height(); // height = qMax(height, editorFontHeight); // } // result = QSize(0, height); // } else { // result = data(treeItemAtIndex(idx), role); // } // return result; } bool SearchResultTreeModel::setData(const QModelIndex &idx, const QVariant &value, int role) { if (role == Qt::CheckStateRole) { Qt::CheckState checkState = static_cast(value.toInt()); return setCheckState(idx, checkState); } return QAbstractItemModel::setData(idx, value, role); } bool SearchResultTreeModel::setCheckState(const QModelIndex &idx, Qt::CheckState checkState, bool firstCall) { SearchResultTreeItem *item = treeItemAtIndex(idx); if (item->checkState() == checkState) return false; item->setCheckState(checkState); if (firstCall) { emit dataChanged(idx, idx); // check parents SearchResultTreeItem *currentItem = item; QModelIndex currentIndex = idx; while (SearchResultTreeItem *parent = currentItem->parent()) { if (parent->isUserCheckable()) { bool hasChecked = false; bool hasUnchecked = false; for (int i = 0; i < parent->childrenCount(); ++i) { SearchResultTreeItem *child = parent->childAt(i); if (!child->isUserCheckable()) continue; if (child->checkState() == Qt::Checked) hasChecked = true; else if (child->checkState() == Qt::Unchecked) hasUnchecked = true; else if (child->checkState() == Qt::PartiallyChecked) hasChecked = hasUnchecked = true; } if (hasChecked && hasUnchecked) parent->setCheckState(Qt::PartiallyChecked); else if (hasChecked) parent->setCheckState(Qt::Checked); else parent->setCheckState(Qt::Unchecked); emit dataChanged(idx.parent(), idx.parent()); } currentItem = parent; currentIndex = idx.parent(); } } // check children if (int children = item->childrenCount()) { for (int i = 0; i < children; ++i) { setCheckState(idx.child(i, 0), checkState, false); } emit dataChanged(idx.child(0, 0), idx.child(children-1, 0)); } return true; } void setDataInternal(const QModelIndex &index, const QVariant &value, int role); QVariant SearchResultTreeModel::data(const SearchResultTreeItem *row, int role) const { QVariant result; switch (role) { case Qt::CheckStateRole: if (row->isUserCheckable()) result = row->checkState(); break; case Qt::ToolTipRole: result = row->item.text.trimmed(); break; case Qt::FontRole: if (row->item.useTextEditorFont) result = m_textEditorFont; else result = QVariant(); break; // case Qt::TextColorRole: // result = m_color.textForeground; // break; // case Qt::BackgroundRole: // result = m_color.textBackground; // break; case ItemDataRoles::ResultLineRole: case Qt::DisplayRole: result = row->item.text; break; case ItemDataRoles::ResultItemRole: result = qVariantFromValue(row->item); break; case ItemDataRoles::ResultLineNumberRole: result = row->item.lineNumber; break; case ItemDataRoles::ResultIconRole: result = row->item.icon; break; case ItemDataRoles::ResultHighlightBackgroundColor: result = m_color.highlightBackground; break; case ItemDataRoles::ResultHighlightForegroundColor: result = m_color.highlightForeground; break; case ItemDataRoles::SearchTermStartRole: result = row->item.textMarkPos; break; case ItemDataRoles::SearchTermLengthRole: result = row->item.textMarkLength; break; case ItemDataRoles::IsGeneratedRole: result = row->isGenerated(); break; default: result = QVariant(); break; } return result; } QVariant SearchResultTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_UNUSED(section) Q_UNUSED(orientation) Q_UNUSED(role) return QVariant(); } /** * Makes sure that the nodes for a specific path exist and sets * m_currentParent to the last final */ QSet SearchResultTreeModel::addPath(const QStringList &path) { QSet pathNodes; SearchResultTreeItem *currentItem = m_rootItem; QModelIndex currentItemIndex = QModelIndex(); SearchResultTreeItem *partItem = 0; QStringList currentPath; foreach (const QString &part, path) { const int insertionIndex = currentItem->insertionIndex(part, &partItem); if (!partItem) { SearchResultItem item; item.path = currentPath; item.text = part; partItem = new SearchResultTreeItem(item, currentItem); if (m_showReplaceUI) { partItem->setIsUserCheckable(true); partItem->setCheckState(Qt::Checked); } partItem->setGenerated(true); beginInsertRows(currentItemIndex, insertionIndex, insertionIndex); currentItem->insertChild(insertionIndex, partItem); endInsertRows(); } pathNodes << partItem; currentItemIndex = index(insertionIndex, 0, currentItemIndex); currentItem = partItem; currentPath << part; } m_currentParent = currentItem; m_currentPath = currentPath; m_currentIndex = currentItemIndex; return pathNodes; } void SearchResultTreeModel::addResultsToCurrentParent(const QList &items, AddMode mode) { if (!m_currentParent) return; if (mode == AddOrdered) { // this is the mode for e.g. text search beginInsertRows(m_currentIndex, m_currentParent->childrenCount(), m_currentParent->childrenCount() + items.count()); foreach (const SearchResultItem &item, items) { m_currentParent->appendChild(item); } endInsertRows(); } else if (mode == AddSorted) { foreach (const SearchResultItem &item, items) { SearchResultTreeItem *existingItem; const int insertionIndex = m_currentParent->insertionIndex(item, &existingItem); if (existingItem) { existingItem->setGenerated(false); existingItem->item = item; QModelIndex itemIndex = m_currentIndex.child(insertionIndex, 0); dataChanged(itemIndex, itemIndex); } else { beginInsertRows(m_currentIndex, insertionIndex, insertionIndex); m_currentParent->insertChild(insertionIndex, item); endInsertRows(); } } } dataChanged(m_currentIndex, m_currentIndex); // Make sure that the number after the file name gets updated } static bool lessThanByPath(const SearchResultItem &a, const SearchResultItem &b) { if (a.path.size() < b.path.size()) return true; if (a.path.size() > b.path.size()) return false; for (int i = 0; i < a.path.size(); ++i) { if (a.path.at(i) < b.path.at(i)) return true; if (a.path.at(i) > b.path.at(i)) return false; } return false; } /** * Adds the search result to the list of results, creating nodes for the path when * necessary. */ QList SearchResultTreeModel::addResults(const QList &items, AddMode mode) { QSet pathNodes; QList sortedItems = items; qStableSort(sortedItems.begin(), sortedItems.end(), lessThanByPath); QList itemSet; foreach (const SearchResultItem &item, sortedItems) { m_editorFontIsUsed |= item.useTextEditorFont; if (!m_currentParent || (m_currentPath != item.path)) { // first add all the items from before if (!itemSet.isEmpty()) { addResultsToCurrentParent(itemSet, mode); itemSet.clear(); } // switch parent pathNodes += addPath(item.path); } itemSet << item; } if (!itemSet.isEmpty()) { addResultsToCurrentParent(itemSet, mode); itemSet.clear(); } QList pathIndices; foreach (SearchResultTreeItem *item, pathNodes) pathIndices << index(item); return pathIndices; } void SearchResultTreeModel::clear() { beginResetModel(); m_currentParent = NULL; m_rootItem->clearChildren(); m_editorFontIsUsed = false; endResetModel(); } QModelIndex SearchResultTreeModel::nextIndex(const QModelIndex &idx, bool *wrapped) const { if (wrapped) *wrapped = false; // pathological if (!idx.isValid()) return index(0, 0); if (rowCount(idx) > 0) { // node with children return idx.child(0, 0); } // leaf node QModelIndex nextIndex; QModelIndex current = idx; while (!nextIndex.isValid()) { int row = current.row(); current = current.parent(); if (row + 1 < rowCount(current)) { // Same parent has another child nextIndex = index(row + 1, 0, current); } else { // go up one parent if (!current.isValid()) { // we start from the beginning if (wrapped) *wrapped = true; nextIndex = index(0, 0); } } } return nextIndex; } QModelIndex SearchResultTreeModel::next(const QModelIndex &idx, bool includeGenerated, bool *wrapped) const { QModelIndex value = idx; do { value = nextIndex(value, wrapped); } while (value != idx && !includeGenerated && treeItemAtIndex(value)->isGenerated()); return value; } QModelIndex SearchResultTreeModel::prevIndex(const QModelIndex &idx, bool *wrapped) const { if (wrapped) *wrapped = false; QModelIndex current = idx; bool checkForChildren = true; if (current.isValid()) { int row = current.row(); if (row > 0) { current = index(row - 1, 0, current.parent()); } else { current = current.parent(); checkForChildren = !current.isValid(); if (checkForChildren && wrapped) { // we start from the end *wrapped = true; } } } if (checkForChildren) { // traverse down the hierarchy while (int rc = rowCount(current)) { current = index(rc - 1, 0, current); } } return current; } QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx, bool includeGenerated, bool *wrapped) const { QModelIndex value = idx; do { value = prevIndex(value, wrapped); } while (value != idx && !includeGenerated && treeItemAtIndex(value)->isGenerated()); return value; } ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreemodel.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SEARCHRESULTTREEMODEL_H #define SEARCHRESULTTREEMODEL_H #include "searchresultitem.h" #include "searchresultcolor.h" #include #include namespace Find { namespace Internal { class SearchResultTreeItem; class SearchResultTreeModel : public QAbstractItemModel { Q_OBJECT public: SearchResultTreeModel(QObject *parent = 0); ~SearchResultTreeModel(); void setShowReplaceUI(bool show); void setTextEditorFont(const QFont &font, const SearchResultColor color); Qt::ItemFlags flags(const QModelIndex &index) const; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &child) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); QVariant headerData(int section, Qt::Orientation orientation, int role) const; QModelIndex next(const QModelIndex &idx, bool includeGenerated = false, bool *wrapped = 0) const; QModelIndex prev(const QModelIndex &idx, bool includeGenerated = false, bool *wrapped = 0) const; QList addResults(const QList &items, AddMode mode); signals: void jumpToSearchResult(const QString &fileName, int lineNumber, int searchTermStart, int searchTermLength); public slots: void clear(); private: QModelIndex index(SearchResultTreeItem *item) const; void addResultsToCurrentParent(const QList &items, AddMode mode); QSet addPath(const QStringList &path); QVariant data(const SearchResultTreeItem *row, int role) const; bool setCheckState(const QModelIndex &idx, Qt::CheckState checkState, bool firstCall = true); QModelIndex nextIndex(const QModelIndex &idx, bool *wrapped = 0) const; QModelIndex prevIndex(const QModelIndex &idx, bool *wrapped = 0) const; SearchResultTreeItem *treeItemAtIndex(const QModelIndex &idx) const; SearchResultTreeItem *m_rootItem; SearchResultTreeItem *m_currentParent; SearchResultColor m_color; QModelIndex m_currentIndex; QStringList m_currentPath; // the path that belongs to the current parent QFont m_textEditorFont; bool m_showReplaceUI; bool m_editorFontIsUsed; }; } // namespace Internal } // namespace Find #endif // SEARCHRESULTTREEMODEL_H ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreeview.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "searchresulttreeview.h" #include "searchresulttreeitemroles.h" #include "searchresulttreemodel.h" #include "searchresulttreeitemdelegate.h" #include #include namespace Find { namespace Internal { SearchResultTreeView::SearchResultTreeView(QWidget *parent) : QTreeView(parent) , m_model(new SearchResultTreeModel(this)) , m_autoExpandResults(false) { setModel(m_model); setItemDelegate(new SearchResultTreeItemDelegate(this)); setIndentation(14); setUniformRowHeights(true); setExpandsOnDoubleClick(true); header()->hide(); connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(emitJumpToSearchResult(QModelIndex))); } void SearchResultTreeView::setAutoExpandResults(bool expand) { m_autoExpandResults = expand; } void SearchResultTreeView::setTextEditorFont(const QFont &font, const SearchResultColor color) { m_model->setTextEditorFont(font, color); QPalette p = palette(); p.setColor(QPalette::Base, color.textBackground); setPalette(p); } void SearchResultTreeView::clear() { m_model->clear(); } void SearchResultTreeView::addResults(const QList &items, AddMode mode) { QList addedParents = m_model->addResults(items, mode); if (m_autoExpandResults && !addedParents.isEmpty()) { foreach (const QModelIndex &index, addedParents) setExpanded(index, true); } } void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index) { if (model()->data(index, ItemDataRoles::IsGeneratedRole).toBool()) return; SearchResultItem item = model()->data(index, ItemDataRoles::ResultItemRole).value(); emit jumpToSearchResult(item); } void SearchResultTreeView::keyPressEvent(QKeyEvent *e) { if (!e->modifiers() && e->key() == Qt::Key_Return) { emit activated(currentIndex()); e->accept(); return; } QTreeView::keyPressEvent(e); } SearchResultTreeModel *SearchResultTreeView::model() const { return m_model; } } // namespace Internal } // namespace Find ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresulttreeview.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SEARCHRESULTTREEVIEW_H #define SEARCHRESULTTREEVIEW_H #include "searchresultitem.h" #include namespace Find { namespace Internal { class SearchResultTreeModel; class SearchResultColor; class SearchResultTreeView : public QTreeView { Q_OBJECT public: explicit SearchResultTreeView(QWidget *parent = 0); void setAutoExpandResults(bool expand); void setTextEditorFont(const QFont &font, const SearchResultColor color); SearchResultTreeModel *model() const; void addResults(const QList &items, AddMode mode); signals: void jumpToSearchResult(const SearchResultItem &item); public slots: void clear(); void emitJumpToSearchResult(const QModelIndex &index); protected: void keyPressEvent(QKeyEvent *e); SearchResultTreeModel *m_model; bool m_autoExpandResults; }; } // namespace Internal } // namespace Find #endif // SEARCHRESULTTREEVIEW_H ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresultwidget.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "searchresultwidget.h" #include "searchresulttreeview.h" #include "searchresulttreemodel.h" #include "searchresulttreeitems.h" #include "searchresulttreeitemroles.h" //#include "treeviewfind.h" //#include #include #include #include #include #include #include #include #include #include static const int SEARCHRESULT_WARNING_LIMIT = 200000; static const char SIZE_WARNING_ID[] = "sizeWarningLabel"; namespace Find { namespace Internal { class WideEnoughLineEdit : public QLineEdit { Q_OBJECT public: WideEnoughLineEdit(QWidget *parent):QLineEdit(parent){ connect(this, SIGNAL(textChanged(QString)), this, SLOT(updateGeometry())); } ~WideEnoughLineEdit(){} QSize sizeHint() const { QSize sh = QLineEdit::minimumSizeHint(); sh.rwidth() += qMax(25 * fontMetrics().width(QLatin1Char('x')), fontMetrics().width(text())); return sh; } public slots: void updateGeometry() { QLineEdit::updateGeometry(); } }; } // Internal } // Find using namespace Find; using namespace Find::Internal; SearchResultWidget::SearchResultWidget(QWidget *parent) : QWidget(parent), m_count(0), m_isShowingReplaceUI(false), m_searchAgainSupported(false), m_preserveCaseSupported(false), m_cancelSupported(true) { QVBoxLayout *layout = new QVBoxLayout(this); layout->setMargin(2); layout->setSpacing(1); setLayout(layout); QFrame *topWidget = new QFrame; // QPalette pal = topWidget->palette(); // pal.setColor(QPalette::Window, QColor(255, 255, 225)); // pal.setColor(QPalette::WindowText, Qt::black); // topWidget->setPalette(pal); topWidget->setFrameStyle(QFrame::Panel);// | QFrame::Raised); topWidget->setLineWidth(0); //topWidget->setAutoFillBackground(true); QHBoxLayout *topLayout = new QHBoxLayout(topWidget); topLayout->setMargin(0); topWidget->setLayout(topLayout); layout->addWidget(topWidget); m_infoWidget = new QFrame; // pal = m_infoWidget->palette(); // pal.setColor(QPalette::Window, QColor(255, 255, 225)); // pal.setColor(QPalette::WindowText, Qt::black); // m_infoWidget->setPalette(pal); m_infoWidget->setFrameStyle(QFrame::Panel);// | QFrame::Raised); m_infoWidget->setLineWidth(0); //m_infoWidget->setAutoFillBackground(true); QHBoxLayout *infoLayout = new QHBoxLayout(m_infoWidget); infoLayout->setMargin(2); m_infoLabel = new QLabel(); infoLayout->addWidget(m_infoLabel); layout->addWidget(m_infoWidget); m_messageWidget = new QFrame; // pal.setColor(QPalette::Window, QColor(255, 255, 225)); // pal.setColor(QPalette::WindowText, Qt::red); // m_messageWidget->setPalette(pal); m_messageWidget->setFrameStyle(QFrame::Panel);// | QFrame::Raised); m_messageWidget->setLineWidth(0); //m_messageWidget->setAutoFillBackground(true); QHBoxLayout *messageLayout = new QHBoxLayout(m_messageWidget); messageLayout->setMargin(2); m_messageWidget->setLayout(messageLayout); QLabel *messageLabel = new QLabel(tr("Search was canceled.")); //messageLabel->setPalette(pal); messageLayout->addWidget(messageLabel); layout->addWidget(m_messageWidget); m_messageWidget->setVisible(false); m_searchResultTreeView = new Internal::SearchResultTreeView(this); //m_searchResultTreeView->setFrameStyle(QFrame::NoFrame); //m_searchResultTreeView->setAttribute(Qt::WA_MacShowFocusRect, false); // Aggregation::Aggregate * agg = new Aggregation::Aggregate; // agg->add(m_searchResultTreeView); // agg->add(new TreeViewFind(m_searchResultTreeView, // ItemDataRoles::ResultLineRole)); layout->addWidget(m_searchResultTreeView); // m_infoBarDisplay.setTarget(layout, 2); // m_infoBarDisplay.setInfoBar(&m_infoBar); m_descriptionContainer = new QWidget(topWidget); QHBoxLayout *descriptionLayout = new QHBoxLayout(m_descriptionContainer); m_descriptionContainer->setLayout(descriptionLayout); descriptionLayout->setMargin(0); m_descriptionContainer->setMinimumWidth(200); m_descriptionContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); m_label = new QLabel(m_descriptionContainer); m_label->setVisible(false); m_searchTerm = new QLabel(m_descriptionContainer); m_searchTerm->setVisible(false); descriptionLayout->addWidget(m_label); descriptionLayout->addWidget(m_searchTerm); m_cancelButton = new QToolButton(topWidget); m_cancelButton->setText(tr("Cancel")); m_cancelButton->setToolButtonStyle(Qt::ToolButtonTextOnly); connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(cancel())); m_searchAgainButton = new QToolButton(topWidget); m_searchAgainButton->setToolTip(tr("Repeat the search with same parameters")); m_searchAgainButton->setText(tr("Search again")); m_searchAgainButton->setToolButtonStyle(Qt::ToolButtonTextOnly); m_searchAgainButton->setVisible(false); connect(m_searchAgainButton, SIGNAL(clicked()), this, SLOT(searchAgain())); m_showReplaceModeButton = new QToolButton(topWidget); m_showReplaceModeButton->setToolTip(tr("Set show replace mode ui")); m_showReplaceModeButton->setText(tr("Show Replace")); m_showReplaceModeButton->setToolButtonStyle(Qt::ToolButtonTextOnly); m_showReplaceModeButton->setVisible(false); connect(m_showReplaceModeButton,SIGNAL(clicked()),this,SLOT(showReplaceMode())); m_replaceLabel = new QLabel(tr("Replace with:"), topWidget); m_replaceTextEdit = new WideEnoughLineEdit(topWidget); m_replaceTextEdit->setMinimumWidth(120); m_replaceTextEdit->setEnabled(false); m_replaceTextEdit->setTabOrder(m_replaceTextEdit, m_searchResultTreeView); m_replaceButton = new QToolButton(topWidget); m_replaceButton->setToolTip(tr("Replace all occurrences")); m_replaceButton->setText(tr("Replace")); m_replaceButton->setToolButtonStyle(Qt::ToolButtonTextOnly); m_replaceButton->setEnabled(false); m_preserveCaseCheck = new QCheckBox(topWidget); m_preserveCaseCheck->setText(tr("Preserve case")); m_preserveCaseCheck->setEnabled(false); // if (FindPlugin * plugin = FindPlugin::instance()) { // m_preserveCaseCheck->setChecked(plugin->hasFindFlag(FindPreserveCase)); // connect(m_preserveCaseCheck, SIGNAL(clicked(bool)), plugin, SLOT(setPreserveCase(bool))); // } m_matchesFoundLabel = new QLabel(topWidget); endMatchesFoundLabel(); m_expandAll = new QToolButton; m_expandAll->setText("+"); m_expandAll->setToolTip(tr("Expand all items")); connect(m_expandAll,SIGNAL(clicked()),this,SLOT(expandAll())); m_collapseAll = new QToolButton; m_collapseAll->setText("-"); m_collapseAll->setToolTip(tr("Collapse all items")); connect(m_collapseAll,SIGNAL(clicked()),this,SLOT(collapseAll())); topLayout->addWidget(m_expandAll); topLayout->addWidget(m_collapseAll); topLayout->addWidget(m_descriptionContainer); topLayout->addWidget(m_cancelButton); topLayout->addWidget(m_searchAgainButton); topLayout->addWidget(m_showReplaceModeButton); topLayout->addWidget(m_replaceLabel); topLayout->addWidget(m_replaceTextEdit); topLayout->addWidget(m_replaceButton); topLayout->addWidget(m_preserveCaseCheck); topLayout->addStretch(2); topLayout->addWidget(m_matchesFoundLabel); topWidget->setMinimumHeight(m_cancelButton->sizeHint().height() + topLayout->contentsMargins().top() + topLayout->contentsMargins().bottom() + topWidget->lineWidth()); setShowReplaceUI(false); connect(m_searchResultTreeView, SIGNAL(jumpToSearchResult(SearchResultItem)), this, SLOT(handleJumpToSearchResult(SearchResultItem))); connect(m_replaceTextEdit, SIGNAL(returnPressed()), this, SLOT(handleReplaceButton())); connect(m_replaceButton, SIGNAL(clicked()), this, SLOT(handleReplaceButton())); } SearchResultWidget::~SearchResultWidget() { // if (m_infoBar.containsInfo(Core::Id(SIZE_WARNING_ID))) // cancelAfterSizeWarning(); } void SearchResultWidget::setInfo(const QString &label, const QString &toolTip, const QString &term) { m_label->setText(label); m_label->setVisible(!label.isEmpty()); m_descriptionContainer->setToolTip(toolTip); m_searchTerm->setText(term); m_searchTerm->setVisible(!term.isEmpty()); } QString SearchResultWidget::searchText() const { return m_searchTerm->text(); } void SearchResultWidget::addResult(const QString &fileName, int lineNumber, const QString &rowText, int searchTermStart, int searchTermLength, const QVariant &userData) { SearchResultItem item; item.path = QStringList() << QDir::toNativeSeparators(fileName); item.lineNumber = lineNumber; item.text = rowText; item.textMarkPos = searchTermStart; item.textMarkLength = searchTermLength; item.useTextEditorFont = true; item.userData = userData; addResults(QList() << item, AddOrdered); } void SearchResultWidget::addResults(const QList &items, AddMode mode, bool revert) { bool firstItems = (m_count == 0); m_count += items.size(); m_searchResultTreeView->addResults(items, mode); updateMatchesFoundLabel(revert); if (firstItems) { // if (!m_dontAskAgainGroup.isEmpty()) { // Core::Id undoWarningId = Core::Id("warninglabel/").withSuffix(m_dontAskAgainGroup); // if (m_infoBar.canInfoBeAdded(undoWarningId)) { // Core::InfoBarEntry info(undoWarningId, tr("This change cannot be undone."), // Core::InfoBarEntry::GlobalSuppressionEnabled); // m_infoBar.addInfo(info); // } // } m_replaceTextEdit->setEnabled(true); // We didn't have an item before, set the focus to the search widget or replace text edit if (m_isShowingReplaceUI) { m_replaceTextEdit->setFocus(); m_replaceTextEdit->selectAll(); } else { m_searchResultTreeView->setFocus(); } m_searchResultTreeView->selectionModel()->select(m_searchResultTreeView->model()->index(0, 0, QModelIndex()), QItemSelectionModel::Select); emit navigateStateChanged(); } else if (m_count <= SEARCHRESULT_WARNING_LIMIT) { return; } else { // Core::Id sizeWarningId(SIZE_WARNING_ID); // if (!m_infoBar.canInfoBeAdded(sizeWarningId)) // return; // emit paused(true); // Core::InfoBarEntry info(sizeWarningId, // tr("The search resulted in more than %n items, do you still want to continue?", // 0, SEARCHRESULT_WARNING_LIMIT)); // info.setCancelButtonInfo(tr("Cancel"), this, SLOT(cancelAfterSizeWarning())); // info.setCustomButtonInfo(tr("Continue"), this, SLOT(continueAfterSizeWarning())); // m_infoBar.addInfo(info); // emit requestPopup(false/*no focus*/); } } void SearchResultWidget::setRevertMode(const QString &replaceText, const QString &searchText) { m_searchTerm->setText(replaceText); this->setTextToReplace(searchText); this->m_replaceLabel->setText(tr("Revert with:")); this->m_replaceButton->setText(tr("Revert")); this->m_replaceButton->setToolTip(tr("Revert all occurrences")); } int SearchResultWidget::count() const { return m_count; } QString SearchResultWidget::dontAskAgainGroup() const { return m_dontAskAgainGroup; } void SearchResultWidget::setDontAskAgainGroup(const QString &group) { m_dontAskAgainGroup = group; } void SearchResultWidget::setTextToReplace(const QString &textToReplace) { m_replaceTextEdit->setText(textToReplace); } QString SearchResultWidget::textToReplace() const { return m_replaceTextEdit->text(); } void SearchResultWidget::setShowReplaceUI(bool visible) { m_searchResultTreeView->model()->setShowReplaceUI(visible); m_replaceLabel->setVisible(visible); m_replaceTextEdit->setVisible(visible); m_replaceButton->setVisible(visible); m_preserveCaseCheck->setVisible(m_preserveCaseSupported && visible); m_isShowingReplaceUI = visible; m_infoWidget->setVisible(visible); m_showReplaceModeButton->setVisible(false); } void SearchResultWidget::setReadOnly(bool readOnly) { m_isReadOnly = readOnly; } void SearchResultWidget::setInfoWidgetLabel(const QString &infoText) { m_infoLabel->setText(infoText); } bool SearchResultWidget::hasFocusInternally() const { return m_searchResultTreeView->hasFocus() || (m_isShowingReplaceUI && m_replaceTextEdit->hasFocus()); } void SearchResultWidget::setFocusInternally() { if (m_count > 0) { if (m_isShowingReplaceUI) { if (!focusWidget() || focusWidget() == m_replaceTextEdit) { m_replaceTextEdit->setFocus(); m_replaceTextEdit->selectAll(); } else { m_searchResultTreeView->setFocus(); } } else { m_searchResultTreeView->setFocus(); } } } bool SearchResultWidget::canFocusInternally() const { return m_count > 0; } void SearchResultWidget::notifyVisibilityChanged(bool visible) { emit visibilityChanged(visible); } void SearchResultWidget::setTextEditorFont(const QFont &font, const SearchResultColor color) { m_searchResultTreeView->setTextEditorFont(font, color); } void SearchResultWidget::setAutoExpandResults(bool expand) { m_searchResultTreeView->setAutoExpandResults(expand); } void SearchResultWidget::goToNext() { if (m_count == 0) return; QModelIndex idx = m_searchResultTreeView->model()->next(m_searchResultTreeView->currentIndex()); if (idx.isValid()) { m_searchResultTreeView->setCurrentIndex(idx); m_searchResultTreeView->emitJumpToSearchResult(idx); } } void SearchResultWidget::goToPrevious() { if (!m_searchResultTreeView->model()->rowCount()) return; QModelIndex idx = m_searchResultTreeView->model()->prev(m_searchResultTreeView->currentIndex()); if (idx.isValid()) { m_searchResultTreeView->setCurrentIndex(idx); m_searchResultTreeView->emitJumpToSearchResult(idx); } } void SearchResultWidget::restart() { m_replaceTextEdit->setEnabled(false); m_replaceButton->setEnabled(false); m_searchResultTreeView->clear(); m_count = 0; // Core::Id sizeWarningId(SIZE_WARNING_ID); // m_infoBar.removeInfo(sizeWarningId); // m_infoBar.enableInfo(sizeWarningId); m_cancelButton->setVisible(m_cancelSupported); m_searchAgainButton->setVisible(false); m_messageWidget->setVisible(false); m_replaceLabel->setText(tr("Replace with:")); m_replaceButton->setToolTip(tr("Replace all occurrences")); m_replaceButton->setText(tr("Replace")); //updateMatchesFoundLabel(); beginMatchesFoundLabel(); emit restarted(); } void SearchResultWidget::clear() { m_searchResultTreeView->clear(); m_count = 0; endMatchesFoundLabel(); } void SearchResultWidget::setCancelSupported(bool supported) { m_cancelSupported = supported; } void SearchResultWidget::setSearchAgainSupported(bool supported) { m_searchAgainSupported = supported; m_searchAgainButton->setVisible(supported && !m_cancelButton->isVisible()); } void SearchResultWidget::setSearchAgainEnabled(bool enabled) { m_searchAgainButton->setEnabled(enabled); } void SearchResultWidget::setPreserveCaseSupported(bool supported) { m_preserveCaseSupported = supported; m_preserveCaseCheck->setVisible(supported); } void SearchResultWidget::finishSearch(bool canceled) { endMatchesFoundLabel(); m_replaceTextEdit->setEnabled(m_count > 0); m_replaceButton->setEnabled(m_count > 0); m_preserveCaseCheck->setEnabled(m_count > 0); m_cancelButton->setVisible(false); m_messageWidget->setVisible(canceled); m_searchAgainButton->setVisible(m_searchAgainSupported); m_showReplaceModeButton->setVisible(!this->m_isShowingReplaceUI && !canceled && m_count > 0 && !m_isReadOnly); } void SearchResultWidget::sendRequestPopup() { emit requestPopup(true/*focus*/); } void SearchResultWidget::continueAfterSizeWarning() { //m_infoBar.suppressInfo(Core::Id(SIZE_WARNING_ID)); emit paused(false); } void SearchResultWidget::cancelAfterSizeWarning() { //m_infoBar.suppressInfo(Core::Id(SIZE_WARNING_ID)); emit cancelled(); emit paused(false); } void SearchResultWidget::handleJumpToSearchResult(const SearchResultItem &item) { emit activated(item); } void SearchResultWidget::handleReplaceButton() { // check if button is actually enabled, because this is also triggered // by pressing return in replace line edit if (m_replaceButton->isEnabled()) { //m_infoBar.clear(); emit replaceButtonClicked(m_replaceTextEdit->text(), checkedItems(), m_preserveCaseCheck->isChecked()); } } void SearchResultWidget::cancel() { m_cancelButton->setVisible(false); // if (m_infoBar.containsInfo(Core::Id(SIZE_WARNING_ID))) // cancelAfterSizeWarning(); // else emit cancelled(); } void SearchResultWidget::searchAgain() { emit searchAgainRequested(); } void SearchResultWidget::expandAll() { m_searchResultTreeView->expandAll(); m_searchResultTreeView->repaint(); } void SearchResultWidget::collapseAll() { m_searchResultTreeView->collapseAll(); m_searchResultTreeView->repaint(); } void SearchResultWidget::showReplaceMode() { this->setShowReplaceUI(true); Internal::SearchResultTreeModel *model = m_searchResultTreeView->model(); const int fileCount = model->rowCount(QModelIndex()); for (int i = 0; i < fileCount; ++i) { QModelIndex fileIndex = model->index(i, 0, QModelIndex()); Internal::SearchResultTreeItem *fileItem = static_cast(fileIndex.internalPointer()); fileItem->setIsUserCheckable(true); fileItem->setCheckState(Qt::Checked); for (int rowIndex = 0; rowIndex < fileItem->childrenCount(); ++rowIndex) { QModelIndex textIndex = model->index(rowIndex, 0, fileIndex); Internal::SearchResultTreeItem *rowItem = static_cast(textIndex.internalPointer()); rowItem->setIsUserCheckable(true); rowItem->setCheckState(Qt::Checked); } } this->m_replaceTextEdit->setFocus(); this->m_searchResultTreeView->repaint(); } QList SearchResultWidget::checkedItems() const { QList result; Internal::SearchResultTreeModel *model = m_searchResultTreeView->model(); const int fileCount = model->rowCount(QModelIndex()); for (int i = 0; i < fileCount; ++i) { QModelIndex fileIndex = model->index(i, 0, QModelIndex()); Internal::SearchResultTreeItem *fileItem = static_cast(fileIndex.internalPointer()); Q_ASSERT(fileItem != 0); for (int rowIndex = 0; rowIndex < fileItem->childrenCount(); ++rowIndex) { QModelIndex textIndex = model->index(rowIndex, 0, fileIndex); Internal::SearchResultTreeItem *rowItem = static_cast(textIndex.internalPointer()); if (rowItem->checkState()) result << rowItem->item; } } return result; } void SearchResultWidget::updateMatchesFoundLabel(bool revert) { if (revert) { m_matchesFoundLabel->setText(tr("%n matches replaced.", 0, m_count)); } else { m_matchesFoundLabel->setText(tr("searching... %n matches found.", 0, m_count)); } } void SearchResultWidget::beginMatchesFoundLabel() { m_matchesFoundLabel->setText(tr("searching ...")); } void SearchResultWidget::endMatchesFoundLabel() { if (m_count == 0) m_matchesFoundLabel->setText(tr("No matches found.")); else m_matchesFoundLabel->setText(tr("%n matches found.", 0, m_count)); } #include "searchresultwidget.moc" ================================================ FILE: liteidex/src/3rdparty/qtc_searchresult/searchresultwidget.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SEARCHRESULTWIDGET_H #define SEARCHRESULTWIDGET_H #include "searchresultitem.h" //#include #include QT_BEGIN_NAMESPACE class QFrame; class QLabel; class QLineEdit; class QToolButton; class QCheckBox; QT_END_NAMESPACE namespace Find { namespace Internal { class SearchResultTreeView; class SearchResultColor; class SearchResultWidget : public QWidget { Q_OBJECT public: explicit SearchResultWidget(QWidget *parent = 0); ~SearchResultWidget(); void setInfo(const QString &label, const QString &toolTip, const QString &term); QString searchText() const; void addResult(const QString &fileName, int lineNumber, const QString &lineText, int searchTermStart, int searchTermLength, const QVariant &userData = QVariant()); void addResults(const QList &items, AddMode mode, bool revert = false); void setRevertMode(const QString &replaceText, const QString &searchText); int count() const; QString dontAskAgainGroup() const; void setDontAskAgainGroup(const QString &group); void setTextToReplace(const QString &textToReplace); QString textToReplace() const; void setShowReplaceUI(bool visible); void setReadOnly(bool readOnly); void setInfoWidgetLabel(const QString &infoText); bool hasFocusInternally() const; void setFocusInternally(); bool canFocusInternally() const; void notifyVisibilityChanged(bool visible); void setTextEditorFont(const QFont &font, const SearchResultColor color); void setAutoExpandResults(bool expand); void goToNext(); void goToPrevious(); void restart(); void clear(); void setCancelSupported(bool supported); void setSearchAgainSupported(bool supported); void setSearchAgainEnabled(bool enabled); void setPreserveCaseSupported(bool enabled); public slots: void finishSearch(bool canceled); void sendRequestPopup(); signals: void activated(const Find::SearchResultItem &item); void replaceButtonClicked(const QString &replaceText, const QList &checkedItems, bool preserveCase); void searchAgainRequested(); void cancelled(); void paused(bool paused); void restarted(); void visibilityChanged(bool visible); void requestPopup(bool focus); void navigateStateChanged(); private slots: void continueAfterSizeWarning(); void cancelAfterSizeWarning(); void handleJumpToSearchResult(const SearchResultItem &item); void handleReplaceButton(); void cancel(); void searchAgain(); void showReplaceMode(); void expandAll(); void collapseAll(); private: QList checkedItems() const; void updateMatchesFoundLabel(bool revert); void beginMatchesFoundLabel(); void endMatchesFoundLabel(); SearchResultTreeView *m_searchResultTreeView; int m_count; QString m_dontAskAgainGroup; QFrame *m_messageWidget; // Core::InfoBar m_infoBar; // Core::InfoBarDisplay m_infoBarDisplay; QLabel *m_replaceLabel; QLineEdit *m_replaceTextEdit; QToolButton *m_replaceButton; QToolButton *m_searchAgainButton; QCheckBox *m_preserveCaseCheck; QToolButton *m_showReplaceModeButton; bool m_isShowingReplaceUI; bool m_isReadOnly; bool m_searchAgainSupported; bool m_preserveCaseSupported; bool m_cancelSupported; QWidget *m_descriptionContainer; QLabel *m_label; QLabel *m_searchTerm; QToolButton *m_cancelButton; QLabel *m_matchesFoundLabel; QFrame *m_infoWidget; QLabel *m_infoLabel; QToolButton *m_collapseAll; QToolButton *m_expandAll; }; } // Internal } // Find #endif // SEARCHRESULTWIDGET_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/autocompleter.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "autocompleter.h" #include "basetextdocumentlayout.h" #include "tabsettings.h" #include #include using namespace TextEditor; AutoCompleter::AutoCompleter() : m_allowSkippingOfBlockEnd(false), m_surroundWithEnabled(true), m_autoParenthesesEnabled(true) {} AutoCompleter::~AutoCompleter() {} void AutoCompleter::setAutoParenthesesEnabled(bool b) { m_autoParenthesesEnabled = b; } bool AutoCompleter::isAutoParenthesesEnabled() const { return m_autoParenthesesEnabled; } void AutoCompleter::setSurroundWithEnabled(bool b) { m_surroundWithEnabled = b; } bool AutoCompleter::isSurroundWithEnabled() const { return m_surroundWithEnabled; } void AutoCompleter::countBracket(QChar open, QChar close, QChar c, int *errors, int *stillopen) { if (c == open) ++*stillopen; else if (c == close) --*stillopen; if (*stillopen < 0) { *errors += -1 * (*stillopen); *stillopen = 0; } } void AutoCompleter::countBrackets(QTextCursor cursor, int from, int end, QChar open, QChar close, int *errors, int *stillopen) { cursor.setPosition(from); QTextBlock block = cursor.block(); while (block.isValid() && block.position() < end) { TextEditor::Parentheses parenList = TextEditor::BaseTextDocumentLayout::parentheses(block); if (!parenList.isEmpty() && !TextEditor::BaseTextDocumentLayout::ifdefedOut(block)) { for (int i = 0; i < parenList.count(); ++i) { TextEditor::Parenthesis paren = parenList.at(i); int position = block.position() + paren.pos; if (position < from || position >= end) continue; countBracket(open, close, paren.chr, errors, stillopen); } } block = block.next(); } } QString AutoCompleter::autoComplete(QTextCursor &cursor, const QString &textToInsert) const { const bool checkBlockEnd = m_allowSkippingOfBlockEnd; m_allowSkippingOfBlockEnd = false; // consume blockEnd. if (m_surroundWithEnabled && cursor.hasSelection()) { if (textToInsert == QLatin1String("(")) return cursor.selectedText() + QLatin1String(")"); if (textToInsert == QLatin1String("{")) { //If the text span multiple lines, insert on different lines QString str = cursor.selectedText(); if (str.contains(QChar::ParagraphSeparator)) { //Also, try to simulate auto-indent str = (str.startsWith(QChar::ParagraphSeparator) ? QString() : QString(QChar::ParagraphSeparator)) + str; if (str.endsWith(QChar::ParagraphSeparator)) str += QLatin1String("}") + QString(QChar::ParagraphSeparator); else str += QString(QChar::ParagraphSeparator) + QLatin1String("}"); } else { str += QLatin1String("}"); } return str; } if (textToInsert == QLatin1String("[")) return cursor.selectedText() + QLatin1String("]"); if (textToInsert == QLatin1String("\"")) return cursor.selectedText() + QLatin1String("\""); if (textToInsert == QLatin1String("'")) return cursor.selectedText() + QLatin1String("'"); } if (!m_autoParenthesesEnabled) return QString(); if (!contextAllowsAutoParentheses(cursor, textToInsert)) return QString(); QTextDocument *doc = cursor.document(); const QString text = textToInsert; const QChar lookAhead = doc->characterAt(cursor.selectionEnd()); const QChar character = textToInsert.at(0); const QString parentheses = QLatin1String("()"); const QString brackets = QLatin1String("[]"); if (parentheses.contains(character) || brackets.contains(character)) { QTextCursor tmp= cursor; bool foundBlockStart = TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tmp); int blockStart = foundBlockStart ? tmp.position() : 0; tmp = cursor; bool foundBlockEnd = TextEditor::TextBlockUserData::findNextBlockClosingParenthesis(&tmp); int blockEnd = foundBlockEnd ? tmp.position() : (cursor.document()->characterCount() - 1); const QChar openChar = parentheses.contains(character) ? QLatin1Char('(') : QLatin1Char('['); const QChar closeChar = parentheses.contains(character) ? QLatin1Char(')') : QLatin1Char(']'); int errors = 0; int stillopen = 0; countBrackets(cursor, blockStart, blockEnd, openChar, closeChar, &errors, &stillopen); int errorsBeforeInsertion = errors + stillopen; errors = 0; stillopen = 0; countBrackets(cursor, blockStart, cursor.position(), openChar, closeChar, &errors, &stillopen); countBracket(openChar, closeChar, character, &errors, &stillopen); countBrackets(cursor, cursor.position(), blockEnd, openChar, closeChar, &errors, &stillopen); int errorsAfterInsertion = errors + stillopen; if (errorsAfterInsertion < errorsBeforeInsertion) return QString(); // insertion fixes parentheses or bracket errors, do not auto complete } int skippedChars = 0; const QString autoText = insertMatchingBrace(cursor, text, lookAhead, &skippedChars); if (checkBlockEnd && textToInsert.at(0) == QLatin1Char('}')) { if (textToInsert.length() > 1) qWarning() << "*** handle event compression"; int startPos = cursor.selectionEnd(), pos = startPos; while (doc->characterAt(pos).isSpace()) ++pos; if (doc->characterAt(pos) == QLatin1Char('}')) skippedChars += (pos - startPos) + 1; } if (skippedChars) { const int pos = cursor.position(); cursor.setPosition(pos + skippedChars); cursor.setPosition(pos, QTextCursor::KeepAnchor); } return autoText; } bool AutoCompleter::autoBackspace(QTextCursor &cursor) { m_allowSkippingOfBlockEnd = false; if (!m_autoParenthesesEnabled) return false; int pos = cursor.position(); if (pos == 0) return false; QTextCursor c = cursor; c.setPosition(pos - 1); QTextDocument *doc = cursor.document(); const QChar lookAhead = doc->characterAt(pos); const QChar lookBehind = doc->characterAt(pos - 1); const QChar lookFurtherBehind = doc->characterAt(pos - 2); const QChar character = lookBehind; if (character == QLatin1Char('(') || character == QLatin1Char('[')) { QTextCursor tmp = cursor; TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tmp); int blockStart = tmp.isNull() ? 0 : tmp.position(); tmp = cursor; TextEditor::TextBlockUserData::findNextBlockClosingParenthesis(&tmp); int blockEnd = tmp.isNull() ? (cursor.document()->characterCount()-1) : tmp.position(); QChar openChar = character; QChar closeChar = (character == QLatin1Char('(')) ? QLatin1Char(')') : QLatin1Char(']'); int errors = 0; int stillopen = 0; countBrackets(cursor, blockStart, blockEnd, openChar, closeChar, &errors, &stillopen); int errorsBeforeDeletion = errors + stillopen; errors = 0; stillopen = 0; countBrackets(cursor, blockStart, pos - 1, openChar, closeChar, &errors, &stillopen); countBrackets(cursor, pos, blockEnd, openChar, closeChar, &errors, &stillopen); int errorsAfterDeletion = errors + stillopen; if (errorsAfterDeletion < errorsBeforeDeletion) return false; // insertion fixes parentheses or bracket errors, do not auto complete } // ### this code needs to be generalized if ((lookBehind == QLatin1Char('(') && lookAhead == QLatin1Char(')')) || (lookBehind == QLatin1Char('[') && lookAhead == QLatin1Char(']')) || (lookBehind == QLatin1Char('"') && lookAhead == QLatin1Char('"') && lookFurtherBehind != QLatin1Char('\\')) || (lookBehind == QLatin1Char('\'') && lookAhead == QLatin1Char('\'') && lookFurtherBehind != QLatin1Char('\\'))) { if (! isInComment(c)) { cursor.beginEditBlock(); cursor.deleteChar(); cursor.deletePreviousChar(); cursor.endEditBlock(); return true; } } return false; } int AutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor, const TabSettings &tabSettings) { if (!m_autoParenthesesEnabled) return 0; QTextDocument *doc = cursor.document(); if (doc->characterAt(cursor.position() - 1) != QLatin1Char('{')) return 0; if (!contextAllowsAutoParentheses(cursor)) return 0; // verify that we indeed do have an extra opening brace in the document QTextBlock block = cursor.block(); const QString textFromCusror = block.text().mid(cursor.positionInBlock()).trimmed(); int braceDepth = BaseTextDocumentLayout::braceDepth(doc->lastBlock()); if (braceDepth <= 0 && (textFromCusror.isEmpty() || textFromCusror.at(0) != QLatin1Char('}'))) return 0; // braces are all balanced or worse, no need to do anything and separator inserted not between '{' and '}' // we have an extra brace , let's see if we should close it /* verify that the next block is not further intended compared to the current block. This covers the following case: if (condition) {| statement; */ int indentation = tabSettings.indentationColumn(block.text()); if (block.next().isValid()) { // not the last block block = block.next(); //skip all empty blocks while (block.isValid() && tabSettings.onlySpace(block.text())) block = block.next(); if (block.isValid() && tabSettings.indentationColumn(block.text()) > indentation) return 0; } const QString &textToInsert = insertParagraphSeparator(cursor); int pos = cursor.position(); cursor.insertBlock(); cursor.insertText(textToInsert); cursor.setPosition(pos); // if we actually insert a separator, allow it to be overwritten if // user types it if (!textToInsert.isEmpty()) m_allowSkippingOfBlockEnd = true; return 1; } bool AutoCompleter::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const { Q_UNUSED(cursor); Q_UNUSED(textToInsert); return true; } bool AutoCompleter::contextAllowsElectricCharacters(const QTextCursor &cursor) const { return contextAllowsAutoParentheses(cursor); } bool AutoCompleter::isInComment(const QTextCursor &cursor) const { Q_UNUSED(cursor); return false; } QString AutoCompleter::insertMatchingBrace(const QTextCursor &cursor, const QString &text, QChar la, int *skippedChars) const { Q_UNUSED(cursor); Q_UNUSED(text); Q_UNUSED(la); Q_UNUSED(skippedChars); return QString(); } QString AutoCompleter::insertParagraphSeparator(const QTextCursor &cursor) const { Q_UNUSED(cursor); return QString(); } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/autocompleter.h ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef AUTOCOMPLETER_H #define AUTOCOMPLETER_H #include "texteditor_global.h" #include QT_BEGIN_NAMESPACE class QTextCursor; QT_END_NAMESPACE namespace TextEditor { class TabSettings; class TEXTEDITOR_EXPORT AutoCompleter { public: AutoCompleter(); virtual ~AutoCompleter(); void setAutoParenthesesEnabled(bool b); bool isAutoParenthesesEnabled() const; void setSurroundWithEnabled(bool b); bool isSurroundWithEnabled() const; // Returns the text to complete at the cursor position, or an empty string virtual QString autoComplete(QTextCursor &cursor, const QString &text) const; // Handles backspace. When returning true, backspace processing is stopped virtual bool autoBackspace(QTextCursor &cursor); // Hook to insert special characters on enter. Returns the number of extra blocks inserted. virtual int paragraphSeparatorAboutToBeInserted(QTextCursor &cursor, const TabSettings &tabSettings); virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const; virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; // Returns true if the cursor is inside a comment. virtual bool isInComment(const QTextCursor &cursor) const; virtual QString insertMatchingBrace(const QTextCursor &cursor, const QString &text, QChar la, int *skippedChars) const; // Returns the text that needs to be inserted virtual QString insertParagraphSeparator(const QTextCursor &cursor) const; protected: static void countBracket(QChar open, QChar close, QChar c, int *errors, int *stillopen); static void countBrackets(QTextCursor cursor, int from, int end, QChar open, QChar close, int *errors, int *stillopen); private: mutable bool m_allowSkippingOfBlockEnd; bool m_surroundWithEnabled; bool m_autoParenthesesEnabled; }; } // TextEditor #endif // AUTOCOMPLETER_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/basetextblockselection.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "basetextblockselection.h" #include #include #include using namespace TextEditor; BaseTextBlockSelection::BaseTextBlockSelection() :firstVisualColumn(0), lastVisualColumn(0), anchor(BottomRight) { } void BaseTextBlockSelection::moveAnchor(int blockNumber, int visualColumn) { if (visualColumn >= 0) { if (anchor % 2) { lastVisualColumn = visualColumn; if (lastVisualColumn < firstVisualColumn) { qSwap(firstVisualColumn, lastVisualColumn); anchor = (Anchor) (anchor - 1); } } else { firstVisualColumn = visualColumn; if (firstVisualColumn > lastVisualColumn) { qSwap(firstVisualColumn, lastVisualColumn); anchor = (Anchor) (anchor + 1); } } } if (blockNumber >= 0 && blockNumber < firstBlock.document()->blockCount()) { if (anchor <= TopRight) { firstBlock.setPosition(firstBlock.document()->findBlockByNumber(blockNumber).position()); if (firstBlock.blockNumber() > lastBlock.blockNumber()) { qSwap(firstBlock, lastBlock); anchor = (Anchor) (anchor + 2); } } else { lastBlock.setPosition(firstBlock.document()->findBlockByNumber(blockNumber).position()); if (lastBlock.blockNumber() < firstBlock.blockNumber()) { qSwap(firstBlock, lastBlock); anchor = (Anchor) (anchor - 2); } } } firstBlock.movePosition(QTextCursor::StartOfBlock); lastBlock.movePosition(QTextCursor::EndOfBlock); } int BaseTextBlockSelection::position(const TabSettings &ts) const { const QTextBlock &block = anchor <= TopRight ? lastBlock.block() : firstBlock.block(); const int column = anchor % 2 ? firstVisualColumn : lastVisualColumn; return block.position() + ts.positionAtColumn(block.text(), column); } QTextCursor BaseTextBlockSelection::selection(const TabSettings &ts) const { QTextCursor cursor = firstBlock; if (anchor <= TopRight) { cursor.setPosition(lastBlock.block().position() + ts.positionAtColumn(lastBlock.block().text(), lastVisualColumn)); cursor.setPosition(firstBlock.block().position() + ts.positionAtColumn(firstBlock.block().text(), firstVisualColumn), QTextCursor::KeepAnchor); } else { cursor.setPosition(firstBlock.block().position() + ts.positionAtColumn(firstBlock.block().text(), firstVisualColumn)); cursor.setPosition(lastBlock.block().position() + ts.positionAtColumn(lastBlock.block().text(), lastVisualColumn), QTextCursor::KeepAnchor); } return cursor; } void BaseTextBlockSelection::fromSelection(const TabSettings &ts, const QTextCursor &selection) { firstBlock = selection; firstBlock.setPosition(selection.selectionStart()); firstVisualColumn = ts.columnAt(firstBlock.block().text(), firstBlock.positionInBlock()); lastBlock = selection; lastBlock.setPosition(selection.selectionEnd()); lastVisualColumn = ts.columnAt(lastBlock.block().text(), lastBlock.positionInBlock()); if (selection.anchor() > selection.position()) anchor = TopLeft; else anchor = BottomRight; firstBlock.movePosition(QTextCursor::StartOfBlock); lastBlock.movePosition(QTextCursor::EndOfBlock); } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/basetextblockselection.h ================================================ #ifndef BASETEXTBLOCKSELECTION_H /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #define BASETEXTBLOCKSELECTION_H #include "qtc_texteditor/tabsettings.h" #include #include namespace TextEditor { class BaseTextBlockSelection { public: BaseTextBlockSelection(); bool isValid() const{ return !firstBlock.isNull() && !lastBlock.isNull(); } void clear() { firstBlock = lastBlock = QTextCursor(); } void moveAnchor(int blockNumber, int visualColumn); int position(const TabSettings &ts) const; inline int anchorColumnNumber() const { return (anchor % 2) ? lastVisualColumn : firstVisualColumn; } inline int anchorBlockNumber() const { return (anchor <= TopRight ? firstBlock.blockNumber() : lastBlock.blockNumber()); } QTextCursor selection(const TabSettings &ts) const; void fromSelection(const TabSettings &ts, const QTextCursor &selection); public: QTextCursor firstBlock; // defines the first block QTextCursor lastBlock; // defines the last block int firstVisualColumn; // defines the first visual column of the selection int lastVisualColumn; // defines the last visual column of the selection enum Anchor {TopLeft = 0, TopRight, BottomLeft, BottomRight} anchor; }; } //namespace TextEditor #endif // BASETEXTBLOCKSELECTION_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/basetextdocumentlayout.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "basetextdocumentlayout.h" #include using namespace TextEditor; CodeFormatterData::~CodeFormatterData() { } TextBlockUserData::~TextBlockUserData() { TextMarks marks = m_marks; m_marks.clear(); foreach (ITextMark *mrk, marks) { mrk->removedFromEditor(); } if (m_codeFormatterData) delete m_codeFormatterData; } int TextBlockUserData::braceDepthDelta() const { int delta = 0; for (int i = 0; i < m_parentheses.size(); ++i) { switch (m_parentheses.at(i).chr.unicode()) { case '{': case '+': case '[': ++delta; break; case '}': case '-': case ']': --delta; break; default: break; } } return delta; } void TextBlockUserData::clearSpellCheckZones(bool defaultSpellCheck) { m_spellCheckZones.clear(); addSpellCheckZone(0, defaultSpellCheck); } void TextBlockUserData::addSpellCheckZone(int position, bool spellCheck) { if (m_spellCheckZones.isEmpty() || spellCheck != shouldSpellCheck(position)) { m_spellCheckZones[position] = spellCheck; } } bool TextBlockUserData::shouldSpellCheck(int position) const { bool spellCheck = true; if (!m_spellCheckZones.isEmpty()) { QMap::const_iterator it = m_spellCheckZones.constEnd(); do { --it; spellCheck = it.value(); } while (it.key() >= position && it != m_spellCheckZones.constBegin()); } return spellCheck; } TextBlockUserData::MatchType TextBlockUserData::checkOpenParenthesis(QTextCursor *cursor, QChar c) { QTextBlock block = cursor->block(); if (!BaseTextDocumentLayout::hasParentheses(block) || BaseTextDocumentLayout::ifdefedOut(block)) return NoMatch; Parentheses parenList = BaseTextDocumentLayout::parentheses(block); Parenthesis openParen, closedParen; QTextBlock closedParenParag = block; const int cursorPos = cursor->position() - closedParenParag.position(); int i = 0; int ignore = 0; bool foundOpen = false; for (;;) { if (!foundOpen) { if (i >= parenList.count()) return NoMatch; openParen = parenList.at(i); if (openParen.pos != cursorPos) { ++i; continue; } else { foundOpen = true; ++i; } } if (i >= parenList.count()) { for (;;) { closedParenParag = closedParenParag.next(); if (!closedParenParag.isValid()) return NoMatch; if (BaseTextDocumentLayout::hasParentheses(closedParenParag) && !BaseTextDocumentLayout::ifdefedOut(closedParenParag)) { parenList = BaseTextDocumentLayout::parentheses(closedParenParag); break; } } i = 0; } closedParen = parenList.at(i); if (closedParen.type == Parenthesis::Opened) { ignore++; ++i; continue; } else { if (ignore > 0) { ignore--; ++i; continue; } cursor->clearSelection(); cursor->setPosition(closedParenParag.position() + closedParen.pos + 1, QTextCursor::KeepAnchor); if ((c == QLatin1Char('{') && closedParen.chr != QLatin1Char('}')) || (c == QLatin1Char('(') && closedParen.chr != QLatin1Char(')')) || (c == QLatin1Char('[') && closedParen.chr != QLatin1Char(']')) || (c == QLatin1Char('+') && closedParen.chr != QLatin1Char('-')) ) return Mismatch; return Match; } } } TextBlockUserData::MatchType TextBlockUserData::checkClosedParenthesis(QTextCursor *cursor, QChar c) { QTextBlock block = cursor->block(); if (!BaseTextDocumentLayout::hasParentheses(block) || BaseTextDocumentLayout::ifdefedOut(block)) return NoMatch; Parentheses parenList = BaseTextDocumentLayout::parentheses(block); Parenthesis openParen, closedParen; QTextBlock openParenParag = block; const int cursorPos = cursor->position() - openParenParag.position(); int i = parenList.count() - 1; int ignore = 0; bool foundClosed = false; for (;;) { if (!foundClosed) { if (i < 0) return NoMatch; closedParen = parenList.at(i); if (closedParen.pos != cursorPos - 1) { --i; continue; } else { foundClosed = true; --i; } } if (i < 0) { for (;;) { openParenParag = openParenParag.previous(); if (!openParenParag.isValid()) return NoMatch; if (BaseTextDocumentLayout::hasParentheses(openParenParag) && !BaseTextDocumentLayout::ifdefedOut(openParenParag)) { parenList = BaseTextDocumentLayout::parentheses(openParenParag); break; } } i = parenList.count() - 1; } openParen = parenList.at(i); if (openParen.type == Parenthesis::Closed) { ignore++; --i; continue; } else { if (ignore > 0) { ignore--; --i; continue; } cursor->clearSelection(); cursor->setPosition(openParenParag.position() + openParen.pos, QTextCursor::KeepAnchor); if ((c == '}' && openParen.chr != '{') || (c == ')' && openParen.chr != '(') || (c == ']' && openParen.chr != '[') || (c == '-' && openParen.chr != '+')) return Mismatch; return Match; } } } bool TextBlockUserData::findPreviousOpenParenthesis(QTextCursor *cursor, bool select) { QTextBlock block = cursor->block(); int position = cursor->position(); int ignore = 0; while (block.isValid()) { Parentheses parenList = BaseTextDocumentLayout::parentheses(block); if (!parenList.isEmpty() && !BaseTextDocumentLayout::ifdefedOut(block)) { for (int i = parenList.count()-1; i >= 0; --i) { Parenthesis paren = parenList.at(i); if (block == cursor->block() && (position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0))) continue; if (paren.type == Parenthesis::Closed) { ++ignore; } else if (ignore > 0) { --ignore; } else { cursor->setPosition(block.position() + paren.pos, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); return true; } } } block = block.previous(); } return false; } bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor, bool checkStartPosition) { QTextBlock block = cursor->block(); int position = cursor->position(); int ignore = 0; while (block.isValid()) { Parentheses parenList = BaseTextDocumentLayout::parentheses(block); if (!parenList.isEmpty() && !BaseTextDocumentLayout::ifdefedOut(block)) { for (int i = parenList.count()-1; i >= 0; --i) { Parenthesis paren = parenList.at(i); if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}') && paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-') && paren.chr != QLatin1Char('[') && paren.chr != QLatin1Char(']')) continue; if (block == cursor->block()) { if (position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0)) continue; if (checkStartPosition && paren.type == Parenthesis::Opened && paren.pos== cursor->position()) { return true; } } if (paren.type == Parenthesis::Closed) { ++ignore; } else if (ignore > 0) { --ignore; } else { cursor->setPosition(block.position() + paren.pos); return true; } } } block = block.previous(); } return false; } bool TextBlockUserData::findNextClosingParenthesis(QTextCursor *cursor, bool select) { QTextBlock block = cursor->block(); int position = cursor->position(); int ignore = 0; while (block.isValid()) { Parentheses parenList = BaseTextDocumentLayout::parentheses(block); if (!parenList.isEmpty() && !BaseTextDocumentLayout::ifdefedOut(block)) { for (int i = 0; i < parenList.count(); ++i) { Parenthesis paren = parenList.at(i); if (block == cursor->block() && (position - block.position() > paren.pos - (paren.type == Parenthesis::Opened ? 1 : 0))) continue; if (paren.type == Parenthesis::Opened) { ++ignore; } else if (ignore > 0) { --ignore; } else { cursor->setPosition(block.position() + paren.pos+1, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); return true; } } } block = block.next(); } return false; } bool TextBlockUserData::findNextBlockClosingParenthesis(QTextCursor *cursor) { QTextBlock block = cursor->block(); int position = cursor->position(); int ignore = 0; while (block.isValid()) { Parentheses parenList = BaseTextDocumentLayout::parentheses(block); if (!parenList.isEmpty() && !BaseTextDocumentLayout::ifdefedOut(block)) { for (int i = 0; i < parenList.count(); ++i) { Parenthesis paren = parenList.at(i); if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}') && paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-') && paren.chr != QLatin1Char('[') && paren.chr != QLatin1Char(']')) continue; if (block == cursor->block() && (position - block.position() > paren.pos - (paren.type == Parenthesis::Opened ? 1 : 0))) continue; if (paren.type == Parenthesis::Opened) { ++ignore; } else if (ignore > 0) { --ignore; } else { cursor->setPosition(block.position() + paren.pos+1); return true; } } } block = block.next(); } return false; } TextBlockUserData::MatchType TextBlockUserData::matchCursorBackward(QTextCursor *cursor) { cursor->clearSelection(); const QTextBlock block = cursor->block(); if (!BaseTextDocumentLayout::hasParentheses(block) || BaseTextDocumentLayout::ifdefedOut(block)) return NoMatch; const int relPos = cursor->position() - block.position(); Parentheses parentheses = BaseTextDocumentLayout::parentheses(block); const Parentheses::const_iterator cend = parentheses.constEnd(); for (Parentheses::const_iterator it = parentheses.constBegin();it != cend; ++it) { const Parenthesis &paren = *it; if (paren.pos == relPos - 1 && paren.type == Parenthesis::Closed) { return checkClosedParenthesis(cursor, paren.chr); } } return NoMatch; } TextBlockUserData::MatchType TextBlockUserData::matchCursorForward(QTextCursor *cursor) { cursor->clearSelection(); const QTextBlock block = cursor->block(); if (!BaseTextDocumentLayout::hasParentheses(block) || BaseTextDocumentLayout::ifdefedOut(block)) return NoMatch; const int relPos = cursor->position() - block.position(); Parentheses parentheses = BaseTextDocumentLayout::parentheses(block); const Parentheses::const_iterator cend = parentheses.constEnd(); for (Parentheses::const_iterator it = parentheses.constBegin();it != cend; ++it) { const Parenthesis &paren = *it; if (paren.pos == relPos && paren.type == Parenthesis::Opened) { return checkOpenParenthesis(cursor, paren.chr); } } return NoMatch; } void TextBlockUserData::setCodeFormatterData(CodeFormatterData *data) { if (m_codeFormatterData) delete m_codeFormatterData; m_codeFormatterData = data; } void TextBlockUserData::addMark(ITextMark *mark) { int i = 0; for ( ; i < m_marks.size(); ++i) { if (mark->type() < m_marks.at(i)->type()) break; } m_marks.insert(i, mark); } BaseTextDocumentLayout::BaseTextDocumentLayout(QTextDocument *doc) :QPlainTextDocumentLayout(doc) { lastSaveRevision = 0; hasMarks = 0; maxMarkWidthFactor = 1.0; m_requiredWidth = 0; } BaseTextDocumentLayout::~BaseTextDocumentLayout() { } void BaseTextDocumentLayout::setParentheses(const QTextBlock &block, const Parentheses &parentheses) { if (parentheses.isEmpty()) { if (TextBlockUserData *userData = testUserData(block)) userData->clearParentheses(); } else { userData(block)->setParentheses(parentheses); } } Parentheses BaseTextDocumentLayout::parentheses(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->parentheses(); return Parentheses(); } bool BaseTextDocumentLayout::hasParentheses(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->hasParentheses(); return false; } bool BaseTextDocumentLayout::setIfdefedOut(const QTextBlock &block) { return userData(block)->setIfdefedOut(); } bool BaseTextDocumentLayout::clearIfdefedOut(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->clearIfdefedOut(); return false; } bool BaseTextDocumentLayout::ifdefedOut(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->ifdefedOut(); return false; } int BaseTextDocumentLayout::braceDepthDelta(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->braceDepthDelta(); return 0; } int BaseTextDocumentLayout::braceDepth(const QTextBlock &block) { int state = block.userState(); if (state == -1) return 0; return state >> 8; } void BaseTextDocumentLayout::setBraceDepth(QTextBlock &block, int depth) { int state = block.userState(); if (state == -1) state = 0; state = state & 0xff; block.setUserState((depth << 8) | state); } void BaseTextDocumentLayout::changeBraceDepth(QTextBlock &block, int delta) { if (delta) setBraceDepth(block, braceDepth(block) + delta); } void BaseTextDocumentLayout::setLexerState(const QTextBlock &block, int state) { if (state == 0) { if (TextBlockUserData *userData = testUserData(block)) userData->setLexerState(0); } else { userData(block)->setLexerState(qMax(0,state)); } } int BaseTextDocumentLayout::lexerState(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->lexerState(); return 0; } void BaseTextDocumentLayout::setFoldingIndent(const QTextBlock &block, int indent) { if (indent == 0) { if (TextBlockUserData *userData = testUserData(block)) userData->setFoldingIndent(0); } else { userData(block)->setFoldingIndent(qMax(0,indent)); } } int BaseTextDocumentLayout::foldingIndent(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->foldingIndent(); return 0; } void BaseTextDocumentLayout::changeFoldingIndent(QTextBlock &block, int delta) { if (delta) setFoldingIndent(block, foldingIndent(block) + delta); } bool BaseTextDocumentLayout::canFold(const QTextBlock &block) { return (block.next().isValid() && foldingIndent(block.next()) > foldingIndent(block)); } bool BaseTextDocumentLayout::isFolded(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->folded(); return false; } void BaseTextDocumentLayout::setFolded(const QTextBlock &block, bool folded) { if (folded) userData(block)->setFolded(true); else { if (TextBlockUserData *userData = testUserData(block)) return userData->setFolded(false); } } bool BaseTextDocumentLayout::isFindExpressionMark(const QTextBlock &block) { if (TextBlockUserData *userData = testUserData(block)) return userData->isFindExpressionMark(); return false; } void BaseTextDocumentLayout::doFoldOrUnfold(const QTextBlock& block, bool unfold) { if (!canFold(block)) return; QTextBlock b = block.next(); int indent = foldingIndent(block); while (b.isValid() && foldingIndent(b) > indent && (unfold || b.next().isValid())) { b.setVisible(unfold); b.setLineCount(unfold? qMax(1, b.layout()->lineCount()) : 0); if (unfold) { // do not unfold folded sub-blocks if (isFolded(b) && b.next().isValid()) { int jndent = foldingIndent(b); b = b.next(); while (b.isValid() && foldingIndent(b) > jndent) b = b.next(); continue; } } b = b.next(); } setFolded(block, !unfold); } void BaseTextDocumentLayout::setRequiredWidth(int width) { int oldw = m_requiredWidth; m_requiredWidth = width; int dw = QPlainTextDocumentLayout::documentSize().width(); if (oldw > dw || width > dw) emitDocumentSizeChanged(); } QSizeF BaseTextDocumentLayout::documentSize() const { QSizeF size = QPlainTextDocumentLayout::documentSize(); size.setWidth(qMax((qreal)m_requiredWidth, size.width())); return size; } void BaseTextDocumentLayout::updateMarksLineNumber() { QTextBlock block = document()->begin(); int blockNumber = 0; while (block.isValid()) { if (const TextBlockUserData *userData = testUserData(block)) foreach (ITextMark *mrk, userData->marks()) mrk->updateBlockNumber(blockNumber); block = block.next(); ++blockNumber; } } void BaseTextDocumentLayout::updateMarksBlock(const QTextBlock &block) { if (const TextBlockUserData *userData = testUserData(block)) foreach (ITextMark *mrk, userData->marks()) mrk->updateBlock(block); } BaseTextDocumentLayout::FoldValidator::FoldValidator() : m_layout(0) , m_requestDocUpdate(false) , m_insideFold(0) {} void BaseTextDocumentLayout::FoldValidator::setup(BaseTextDocumentLayout *layout) { m_layout = layout; } void BaseTextDocumentLayout::FoldValidator::reset() { m_insideFold = 0; m_requestDocUpdate = false; } void BaseTextDocumentLayout::FoldValidator::process(QTextBlock block) { if (!m_layout) return; const QTextBlock &previous = block.previous(); if (!previous.isValid()) return; if ((BaseTextDocumentLayout::isFolded(previous) && !BaseTextDocumentLayout::canFold(previous)) || (!BaseTextDocumentLayout::isFolded(previous) && BaseTextDocumentLayout::canFold(previous) && !block.isVisible())) { BaseTextDocumentLayout::setFolded(previous, !BaseTextDocumentLayout::isFolded(previous)); } if (BaseTextDocumentLayout::isFolded(previous) && !m_insideFold) m_insideFold = BaseTextDocumentLayout::foldingIndent(block); bool toggleVisibility = false; if (m_insideFold) { if (BaseTextDocumentLayout::foldingIndent(block) >= m_insideFold) { if (block.isVisible()) toggleVisibility = true; } else { m_insideFold = 0; if (!block.isVisible()) toggleVisibility = true; } } else if (!block.isVisible()) { toggleVisibility = true; } if (toggleVisibility) { block.setVisible(!block.isVisible()); block.setLineCount(block.isVisible() ? qMax(1, block.layout()->lineCount()) : 0); m_requestDocUpdate = true; } } void BaseTextDocumentLayout::FoldValidator::finalize() { if (m_requestDocUpdate && m_layout) { m_layout->requestUpdate(); m_layout->emitDocumentSizeChanged(); } } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/basetextdocumentlayout.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef BASETEXTDOCUMENTLAYOUT_H #define BASETEXTDOCUMENTLAYOUT_H #include "texteditor_global.h" #include "itexteditor.h" #include "tabsettings.h" #include #include namespace TextEditor { struct Parenthesis; typedef QVector Parentheses; struct SyntaxToken { int offset; int count; int id; }; struct TEXTEDITOR_EXPORT Parenthesis { enum Type { Opened, Closed }; inline Parenthesis() : type(Opened), pos(-1) {} inline Parenthesis(Type t, QChar c, int position) : type(t), chr(c), pos(position) {} Type type; QChar chr; int pos; }; class TEXTEDITOR_EXPORT CodeFormatterData { public: virtual ~CodeFormatterData(); }; class TEXTEDITOR_EXPORT TextBlockUserData : public QTextBlockUserData { public: inline TextBlockUserData() : m_folded(false), m_ifdefedOut(false), m_foldingIndent(0), m_lexerState(0), m_foldingStartIncluded(false), m_foldingEndIncluded(false), m_findExpressionMark(false), m_codeFormatterData(0) {} ~TextBlockUserData(); inline TextMarks marks() const { return m_marks; } void addMark(ITextMark *mark); inline bool removeMark(ITextMark *mark) { return m_marks.removeAll(mark); } inline bool hasMark(ITextMark *mark) const { return m_marks.contains(mark); } inline void clearMarks() { m_marks.clear(); } inline void documentClosing() { Q_FOREACH(ITextMark *tm, m_marks) { tm->documentClosing(); } m_marks.clear();} inline void setFolded(bool b) { m_folded = b; } inline bool folded() const { return m_folded; } inline void setParentheses(const Parentheses &parentheses) { m_parentheses = parentheses; } inline void appendParenthese(const Parenthesis &parenthesis) { m_parentheses.append(parenthesis); } inline void clearParentheses() { m_parentheses.clear(); } inline const Parentheses &parentheses() const { return m_parentheses; } inline bool hasParentheses() const { return !m_parentheses.isEmpty(); } int braceDepthDelta() const; void clearSpellCheckZones(bool defaultSpellCheck); void addSpellCheckZone(int position, bool spellCheck); bool shouldSpellCheck(int position) const; inline bool setIfdefedOut() { bool result = m_ifdefedOut; m_ifdefedOut = true; return !result; } inline bool clearIfdefedOut() { bool result = m_ifdefedOut; m_ifdefedOut = false; return result;} inline bool ifdefedOut() const { return m_ifdefedOut; } enum MatchType { NoMatch, Match, Mismatch }; static MatchType checkOpenParenthesis(QTextCursor *cursor, QChar c); static MatchType checkClosedParenthesis(QTextCursor *cursor, QChar c); static MatchType matchCursorBackward(QTextCursor *cursor); static MatchType matchCursorForward(QTextCursor *cursor); static bool findPreviousOpenParenthesis(QTextCursor *cursor, bool select = false); static bool findNextClosingParenthesis(QTextCursor *cursor, bool select = false); static bool findPreviousBlockOpenParenthesis(QTextCursor *cursor, bool checkStartPosition = false); static bool findNextBlockClosingParenthesis(QTextCursor *cursor); // Get the code folding level inline int foldingIndent() const { return m_foldingIndent; } /* Set the code folding level. * * A code folding marker will appear the line *before* the one where the indention * level increases. The code folding reagion will end in the last line that has the same * indention level (or higher). */ inline void setFoldingIndent(int indent) { m_foldingIndent = indent < 0 ? 0 : indent; } // Set whether the first character of the folded region will show when the code is folded. inline void setFoldingStartIncluded(bool included) { m_foldingStartIncluded = included; } inline bool foldingStartIncluded() const { return m_foldingStartIncluded; } // Set whether the last character of the folded region will show when the code is folded. inline void setFoldingEndIncluded(bool included) { m_foldingEndIncluded = included; } inline bool foldingEndIncluded() const { return m_foldingEndIncluded; } inline int lexerState() const { return m_lexerState; } inline void setLexerState(int state) {m_lexerState = state; } inline void setFindExpressionMark(bool b) { m_findExpressionMark = b; } inline bool isFindExpressionMark() { return m_findExpressionMark; } CodeFormatterData *codeFormatterData() const { return m_codeFormatterData; } void setCodeFormatterData(CodeFormatterData *data); void setTokens(const QList &tokens) {m_tokens = tokens; } QList tokens() const { return m_tokens; } private: TextMarks m_marks; uint m_folded : 1; uint m_ifdefedOut : 1; uint m_foldingIndent : 16; uint m_lexerState : 4; uint m_foldingStartIncluded : 1; uint m_foldingEndIncluded : 1; uint m_findExpressionMark:1; Parentheses m_parentheses; QMap m_spellCheckZones; QList m_tokens; CodeFormatterData *m_codeFormatterData; }; class TEXTEDITOR_EXPORT BaseTextDocumentLayout : public QPlainTextDocumentLayout { Q_OBJECT public: BaseTextDocumentLayout(QTextDocument *doc); ~BaseTextDocumentLayout(); static void setParentheses(const QTextBlock &block, const Parentheses &parentheses); static void clearParentheses(const QTextBlock &block) { setParentheses(block, Parentheses());} static Parentheses parentheses(const QTextBlock &block); static bool hasParentheses(const QTextBlock &block); static bool setIfdefedOut(const QTextBlock &block); static bool clearIfdefedOut(const QTextBlock &block); static bool ifdefedOut(const QTextBlock &block); static int braceDepthDelta(const QTextBlock &block); static int braceDepth(const QTextBlock &block); static void setBraceDepth(QTextBlock &block, int depth); static void changeBraceDepth(QTextBlock &block, int delta); static void setFoldingIndent(const QTextBlock &block, int indent); static int foldingIndent(const QTextBlock &block); static void setLexerState(const QTextBlock &block, int state); static int lexerState(const QTextBlock &block); static void changeFoldingIndent(QTextBlock &block, int delta); static bool canFold(const QTextBlock &block); static void doFoldOrUnfold(const QTextBlock& block, bool unfold); static bool isFolded(const QTextBlock &block); static void setFolded(const QTextBlock &block, bool folded); static bool isFindExpressionMark(const QTextBlock &block); static TextBlockUserData *testUserData(const QTextBlock &block) { return static_cast(block.userData()); } static TextBlockUserData *userData(const QTextBlock &block) { TextBlockUserData *data = static_cast(block.userData()); if (!data && block.isValid()) const_cast(block).setUserData((data = new TextBlockUserData)); return data; } class TEXTEDITOR_EXPORT FoldValidator { public: FoldValidator(); void setup(BaseTextDocumentLayout *layout); void reset(); void process(QTextBlock block); void finalize(); bool requestDocUpdate() const { return m_requestDocUpdate; } private: BaseTextDocumentLayout *m_layout; bool m_requestDocUpdate; int m_insideFold; }; public: void emitDocumentSizeChanged() { emit documentSizeChanged(documentSize()); } void setRequiredWidth(int width); QSizeF documentSize() const; void updateMarksLineNumber(); void updateMarksBlock(const QTextBlock &block); public: int lastSaveRevision; bool hasMarks; double maxMarkWidthFactor; int m_requiredWidth; TabSettings m_tabSettings; }; } // namespace TextEditor #endif // BASETEXTDOCUMENTLAYOUT_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/colorscheme.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "colorscheme.h" #include "texteditorconstants.h" #include #include #include using namespace TextEditor; static const char *trueString = "true"; // Format Format::Format() : m_foreground(Qt::black), m_background(Qt::white), m_bold(false), m_italic(false) { } void Format::setForeground(const QColor &foreground) { m_foreground = foreground; } void Format::setBackground(const QColor &background) { m_background = background; } void Format::setBold(bool bold) { m_bold = bold; } void Format::setItalic(bool italic) { m_italic = italic; } static QColor stringToColor(const QString &string) { if (string == QLatin1String("invalid")) return QColor(); return QColor(string); } bool Format::equals(const Format &f) const { return m_foreground == f.m_foreground && m_background == f.m_background && m_bold == f.m_bold && m_italic == f.m_italic; } bool Format::fromString(const QString &str) { *this = Format(); const QStringList lst = str.split(QLatin1Char(';')); if (lst.count() != 4) return false; m_foreground = stringToColor(lst.at(0)); m_background = stringToColor(lst.at(1)); m_bold = lst.at(2) == QLatin1String(trueString); m_italic = lst.at(3) == QLatin1String(trueString); return true; } // ColorScheme ColorScheme::ColorScheme() { } bool ColorScheme::contains(const QString &category) const { return m_formats.contains(category); } Format &ColorScheme::formatFor(const QString &category) { return m_formats[category]; } Format ColorScheme::formatFor(const QString &category) const { return m_formats.value(category); } void ColorScheme::setFormatFor(const QString &category, const Format &format) { m_formats[category] = format; } void ColorScheme::clear() { m_formats.clear(); } bool ColorScheme::save(const QString &fileName) const { QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) return false; QXmlStreamWriter w(&file); w.setAutoFormatting(true); w.setAutoFormattingIndent(2); w.writeStartDocument(); w.writeStartElement(QLatin1String("style-scheme")); w.writeAttribute(QLatin1String("version"), QLatin1String("1.0")); if (!m_displayName.isEmpty()) w.writeAttribute(QLatin1String("name"), m_displayName); QMapIterator i(m_formats); while (i.hasNext()) { const Format &format = i.next().value(); w.writeStartElement(QLatin1String("style")); w.writeAttribute(QLatin1String("name"), i.key()); if (format.foreground().isValid()) w.writeAttribute(QLatin1String("foreground"), format.foreground().name().toLower()); if (format.background().isValid()) w.writeAttribute(QLatin1String("background"), format.background().name().toLower()); if (format.bold()) w.writeAttribute(QLatin1String("bold"), QLatin1String(trueString)); if (format.italic()) w.writeAttribute(QLatin1String("italic"), QLatin1String(trueString)); w.writeEndElement(); } w.writeEndElement(); w.writeEndDocument(); return true; } namespace { class ColorSchemeReader : public QXmlStreamReader { public: ColorSchemeReader() : m_scheme(0) {} bool read(const QString &fileName, ColorScheme *scheme); QString readName(const QString &fileName); private: bool readNextStartElement(); void skipCurrentElement(); void readStyleScheme(); void readStyle(); ColorScheme *m_scheme; QString m_name; }; bool ColorSchemeReader::read(const QString &fileName, ColorScheme *scheme) { m_scheme = scheme; if (m_scheme) m_scheme->clear(); QFile file(fileName); if (!file.open(QFile::ReadOnly | QFile::Text)) return false; setDevice(&file); if (readNextStartElement() && name() == QLatin1String("style-scheme")) readStyleScheme(); else raiseError(QCoreApplication::translate("TextEditor::Internal::ColorScheme", "Not a color scheme file.")); return true; } QString ColorSchemeReader::readName(const QString &fileName) { read(fileName, 0); return m_name; } bool ColorSchemeReader::readNextStartElement() { while (readNext() != Invalid) { if (isStartElement()) return true; else if (isEndElement()) return false; } return false; } void ColorSchemeReader::skipCurrentElement() { while (readNextStartElement()) skipCurrentElement(); } void ColorSchemeReader::readStyleScheme() { Q_ASSERT(isStartElement() && name() == QLatin1String("style-scheme")); const QXmlStreamAttributes attr = attributes(); m_name = attr.value(QLatin1String("name")).toString(); if (!m_scheme) // We're done raiseError(QLatin1String("name loaded")); else m_scheme->setDisplayName(m_name); while (readNextStartElement()) { if (name() == QLatin1String("style")) readStyle(); else skipCurrentElement(); } } void ColorSchemeReader::readStyle() { Q_ASSERT(isStartElement() && name() == QLatin1String("style")); const QXmlStreamAttributes attr = attributes(); QString name = attr.value(QLatin1String("name")).toString(); QString foreground = attr.value(QLatin1String("foreground")).toString(); QString background = attr.value(QLatin1String("background")).toString(); bool bold = attr.value(QLatin1String("bold")) == QLatin1String(trueString); bool italic = attr.value(QLatin1String("italic")) == QLatin1String(trueString); Format format; if (QColor::isValidColor(foreground)) format.setForeground(QColor(foreground)); else format.setForeground(QColor()); if (QColor::isValidColor(background)) format.setBackground(QColor(background)); else format.setBackground(QColor()); format.setBold(bold); format.setItalic(italic); m_scheme->setFormatFor(name, format); skipCurrentElement(); } } // anonymous namespace bool ColorScheme::load(const QString &fileName) { ColorSchemeReader reader; return reader.read(fileName, this) && !reader.hasError(); } QString ColorScheme::readNameOfScheme(const QString &fileName) { return ColorSchemeReader().readName(fileName); } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/colorscheme.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef COLORSCHEME_H #define COLORSCHEME_H #include "texteditor_global.h" #include #include #include namespace TextEditor { /*! Format for a particular piece of text (text/comment, etc). */ class TEXTEDITOR_EXPORT Format { public: Format(); QColor foreground() const { return m_foreground; } void setForeground(const QColor &foreground); QColor background() const { return m_background; } void setBackground(const QColor &background); bool bold() const { return m_bold; } void setBold(bool bold); bool italic() const { return m_italic; } void setItalic(bool italic); bool equals(const Format &f) const; QString toString() const; bool fromString(const QString &str); private: QColor m_foreground; QColor m_background; bool m_bold; bool m_italic; }; inline bool operator==(const Format &f1, const Format &f2) { return f1.equals(f2); } inline bool operator!=(const Format &f1, const Format &f2) { return !f1.equals(f2); } /*! A color scheme combines a set of formats for different highlighting categories. It also provides saving and loading of the scheme to a file. */ class ColorScheme { public: ColorScheme(); void setDisplayName(const QString &name) { m_displayName = name; } QString displayName() const { return m_displayName; } inline bool isEmpty() const { return m_formats.isEmpty(); } bool contains(const QString &category) const; Format &formatFor(const QString &category); Format formatFor(const QString &category) const; void setFormatFor(const QString &category, const Format &format); void clear(); bool save(const QString &fileName) const; bool load(const QString &fileName); inline bool equals(const ColorScheme &cs) const { return m_formats == cs.m_formats && m_displayName == cs.m_displayName; } static QString readNameOfScheme(const QString &fileName); private: QMap m_formats; QString m_displayName; }; inline bool operator==(const ColorScheme &cs1, const ColorScheme &cs2) { return cs1.equals(cs2); } inline bool operator!=(const ColorScheme &cs1, const ColorScheme &cs2) { return !cs1.equals(cs2); } } // namespace TextEditor #endif // COLORSCHEME_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/context.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "context.h" using namespace TextEditor; using namespace Internal; Context::Context() : m_fallthrough(false), m_dynamic(false) {} Context::Context(const Context &context) : m_id(context.m_id), m_name(context.m_name), m_lineBeginContext(context.m_lineBeginContext), m_lineEndContext(context.m_lineEndContext), m_fallthroughContext(context.m_fallthroughContext), m_itemData(context.m_itemData), m_fallthrough(context.m_fallthrough), m_dynamic(context.m_dynamic), m_instructions(context.m_instructions), m_definition(context.m_definition) { // Rules need to be deeply copied because of dynamic contexts. foreach (const QSharedPointer &rule, context.m_rules) m_rules.append(QSharedPointer(rule->clone())); } Context::~Context() {} ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/context.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef CONTEXT_H #define CONTEXT_H #include "includerulesinstruction.h" #include "reuse.h" #include "dynamicrule.h" #include "highlightdefinition.h" #include #include #include namespace TextEditor { namespace Internal { class Context { public: Context(); Context(const Context &context); ~Context(); const Context &operator=(Context copy) { swap(copy); return *this; } void swap(Context &context) { qSwap(m_id, context.m_id); qSwap(m_name, context.m_name); qSwap(m_lineBeginContext, context.m_lineBeginContext); qSwap(m_lineEndContext, context.m_lineEndContext); qSwap(m_fallthroughContext, context.m_fallthroughContext); qSwap(m_itemData, context.m_itemData); qSwap(m_fallthrough, context.m_fallthrough); qSwap(m_dynamic, context.m_dynamic); qSwap(m_rules, context.m_rules); qSwap(m_instructions, context.m_instructions); qSwap(m_definition, context.m_definition); } void configureId(const int unique) { m_id.append(QString::number(unique)); } const QString &id() const { return m_id; } void setName(const QString &name) { m_name = name; m_id = name; } const QString &name() const { return m_name; } void setLineBeginContext(const QString &context) { m_lineBeginContext = context; } const QString &lineBeginContext() const { return m_lineBeginContext; } void setLineEndContext(const QString &context) { m_lineEndContext = context; } const QString &lineEndContext() const { return m_lineEndContext; } void setFallthroughContext(const QString &context) { m_fallthroughContext = context; } const QString &fallthroughContext() const { return m_fallthroughContext; } void setItemData(const QString &itemData) { m_itemData = itemData; } const QString &itemData() const { return m_itemData; } void setFallthrough(const QString &fallthrough) { m_fallthrough = toBool(fallthrough); } bool isFallthrough() const { return m_fallthrough; } void setDynamic(const QString &dynamic) { m_dynamic = toBool(dynamic); } bool isDynamic() const { return m_dynamic; } void updateDynamicRules(const QStringList &captures) const { TextEditor::Internal::updateDynamicRules(m_rules, captures); } void addRule(const QSharedPointer &rule) { m_rules.append(rule); } void addRule(const QSharedPointer &rule, int index) { m_rules.insert(index, rule); } const QList > & rules() const { return m_rules; } void addIncludeRulesInstruction(const IncludeRulesInstruction &instruction) { m_instructions.append(instruction); } const QList &includeRulesInstructions() const { return m_instructions; } void clearIncludeRulesInstructions() { m_instructions.clear(); } void setDefinition(const QSharedPointer &definition) { m_definition = definition; } const QSharedPointer &definition() const { return m_definition; } protected: QString m_id; QString m_name; QString m_lineBeginContext; QString m_lineEndContext; QString m_fallthroughContext; QString m_itemData; bool m_fallthrough; bool m_dynamic; QList > m_rules; QList m_instructions; QSharedPointer m_definition; }; } // namespace Internal } // namespace TextEditor #endif // CONTEXT_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/definitiondownloader.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "definitiondownloader.h" #include #include #include #include #include #include #include using namespace TextEditor; using namespace Internal; DefinitionDownloader::DefinitionDownloader(const QUrl &url, const QString &localPath) : m_url(url), m_localPath(localPath), m_status(Unknown) {} void DefinitionDownloader::run() { QNetworkAccessManager manager; int currentAttempt = 0; const int maxAttempts = 5; while (currentAttempt < maxAttempts) { QScopedPointer reply(getData(&manager)); if (reply->error() != QNetworkReply::NoError) { m_status = NetworkError; return; } ++currentAttempt; QVariant variant = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); if (variant.isValid() && currentAttempt < maxAttempts) { m_url = variant.toUrl(); } else if (!variant.isValid()) { saveData(reply.data()); return; } } } QNetworkReply *DefinitionDownloader::getData(QNetworkAccessManager *manager) const { QNetworkRequest request(m_url); QNetworkReply *reply = manager->get(request); QEventLoop eventLoop; connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); eventLoop.exec(); return reply; } void DefinitionDownloader::saveData(QNetworkReply *reply) { const QString &urlPath = m_url.path(); const QString &fileName = urlPath.right(urlPath.length() - urlPath.lastIndexOf(QLatin1Char('/')) - 1); QFile file(m_localPath + fileName); if (file.open(QIODevice::Text | QIODevice::WriteOnly)) { file.write(reply->readAll()); file.close(); m_status = Ok; } else { m_status = WriteError; } } DefinitionDownloader::Status DefinitionDownloader::status() const { return m_status; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/definitiondownloader.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef DEFINITIONDOWNLOADER_H #define DEFINITIONDOWNLOADER_H #include #include #include QT_BEGIN_NAMESPACE class QNetworkReply; class QNetworkAccessManager; QT_END_NAMESPACE namespace TextEditor { namespace Internal { class DefinitionDownloader : public QObject { Q_OBJECT public: DefinitionDownloader(const QUrl &url, const QString &localPath); enum Status { NetworkError, WriteError, Ok, Unknown }; void run(); Status status() const; private: QNetworkReply *getData(QNetworkAccessManager *manager) const; void saveData(QNetworkReply *reply); QUrl m_url; QString m_localPath; Status m_status; }; // Currently QtConcurrent::map does not support passing member functions for sequence of pointers // (only works for operator.*) which is the case for the downloaders held by the manager. Then the // reason for the following functor. If something is implemented (for example a type traits) to // handle operator->* in QtConcurrent::map this functor will not be necessary since it would be // possible to directly pass DefinitionDownloader::run. struct DownloaderStarter { void operator()(DefinitionDownloader *downloader) { downloader->run(); } }; } // namespace Internal } // namespace TextEditor #endif // DEFINITIONDOWNLOADER_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/dynamicrule.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "dynamicrule.h" #include "reuse.h" using namespace TextEditor; using namespace Internal; DynamicRule::DynamicRule() : m_active(false) {} DynamicRule::~DynamicRule() {} void DynamicRule::setActive(const QString &active) { m_active = toBool(active); } bool DynamicRule::isActive() const { return m_active; } void DynamicRule::replaceExpressions(const QStringList &captures) { doReplaceExpressions(captures); updateDynamicRules(children(), captures); } namespace TextEditor { namespace Internal { void updateDynamicRules(const QList > &rules, const QStringList &captures) { foreach (QSharedPointer rule, rules) { DynamicRule *dynamicRule = dynamic_cast(rule.data()); if (dynamicRule && dynamicRule->isActive()) dynamicRule->replaceExpressions(captures); } } } // namespace Internal } // namespace TextEditor ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/dynamicrule.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef DYNAMICRULE_H #define DYNAMICRULE_H #include "rule.h" QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace TextEditor { namespace Internal { class DynamicRule : public Rule { public: DynamicRule(); virtual ~DynamicRule(); void setActive(const QString &active); bool isActive() const; virtual void replaceExpressions(const QStringList &captures); private: virtual void doReplaceExpressions(const QStringList &captures) = 0; bool m_active; }; void updateDynamicRules(const QList > &rules, const QStringList &captures); } // namespace Internal } // namespace TextEditor #endif // DYNAMICRULE_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlightdefinition.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "highlightdefinition.h" #include "highlighterexception.h" #include "context.h" #include "keywordlist.h" #include "itemdata.h" #include "reuse.h" #include using namespace TextEditor; using namespace Internal; HighlightDefinition::HighlightDefinition() : m_singleLineCommentAfterWhiteSpaces(false), m_keywordCaseSensitivity(Qt::CaseSensitive), m_indentationBasedFolding(false) { QString s(QLatin1String(".():!+,-<=>%&/;?[]^{|}~\\*, \t")); foreach (const QChar &c, s) m_delimiters.insert(c); } HighlightDefinition::~HighlightDefinition() {} template QSharedPointer HighlightDefinition:: GenericHelper::create(const QString &name, Container &container) { if (name.isEmpty()) throw HighlighterException(); if (container.contains(name)) throw HighlighterException(); return container.insert(name, QSharedPointer(new Element)).value(); } template QSharedPointer HighlightDefinition:: GenericHelper::find(const QString &name, const Container &container) const { typename Container::const_iterator it = container.find(name); if (it == container.end()) throw HighlighterException(); return it.value(); } QSharedPointer HighlightDefinition::createKeywordList(const QString &list) { return m_helper.create(list, m_lists); } QSharedPointer HighlightDefinition::keywordList(const QString &list) { return m_helper.find(list, m_lists); } QSharedPointer HighlightDefinition::createContext(const QString &context, bool initial) { if (initial) m_initialContext = context; QSharedPointer newContext = m_helper.create(context, m_contexts); newContext->setName(context); return newContext; } QSharedPointer HighlightDefinition::initialContext() const { return m_helper.find(m_initialContext, m_contexts); } QSharedPointer HighlightDefinition::context(const QString &context) const { return m_helper.find(context, m_contexts); } const QHash > &HighlightDefinition::contexts() const { return m_contexts; } QSharedPointer HighlightDefinition::createItemData(const QString &itemData) { return m_helper.create(itemData, m_itemsData); } QSharedPointer HighlightDefinition::itemData(const QString &itemData) const { return m_helper.find(itemData, m_itemsData); } void HighlightDefinition::setSingleLineComment(const QString &start) { m_singleLineComment = start; } const QString &HighlightDefinition::singleLineComment() const { return m_singleLineComment; } void HighlightDefinition::setCommentAfterWhitespaces(const QString &after) { if (after == QLatin1String("afterwhitespace")) m_singleLineCommentAfterWhiteSpaces = true; } bool HighlightDefinition::isCommentAfterWhiteSpaces() const { return m_singleLineCommentAfterWhiteSpaces; } void HighlightDefinition::setMultiLineCommentStart(const QString &start) { m_multiLineCommentStart = start; } const QString &HighlightDefinition::multiLineCommentStart() const { return m_multiLineCommentStart; } void HighlightDefinition::setMultiLineCommentEnd(const QString &end) { m_multiLineCommentEnd = end; } const QString &HighlightDefinition::multiLineCommentEnd() const { return m_multiLineCommentEnd; } void HighlightDefinition::setMultiLineCommentRegion(const QString ®ion) { m_multiLineCommentRegion = region; } const QString &HighlightDefinition::multiLineCommentRegion() const { return m_multiLineCommentRegion; } void HighlightDefinition::removeDelimiters(const QString &characters) { for (int i = 0; i < characters.length(); ++i) m_delimiters.remove(characters.at(i)); } void HighlightDefinition::addDelimiters(const QString &characters) { for (int i = 0; i < characters.length(); ++i) { if (!m_delimiters.contains(characters.at(i))) m_delimiters.insert(characters.at(i)); } } bool HighlightDefinition::isDelimiter(const QChar &character) const { if (m_delimiters.contains(character)) return true; return false; } void HighlightDefinition::setKeywordsSensitive(const QString &sensitivity) { if (!sensitivity.isEmpty()) m_keywordCaseSensitivity = toCaseSensitivity(toBool(sensitivity)); } Qt::CaseSensitivity HighlightDefinition::keywordsSensitive() const { return m_keywordCaseSensitivity; } void HighlightDefinition::setIndentationBasedFolding(const QString &indentationBasedFolding) { m_indentationBasedFolding = toBool(indentationBasedFolding); } bool HighlightDefinition::isIndentationBasedFolding() const { return m_indentationBasedFolding; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlightdefinition.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef HIGHLIGHTDEFINITION_H #define HIGHLIGHTDEFINITION_H #include #include #include #include namespace TextEditor { namespace Internal { class KeywordList; class Context; class ItemData; class HighlightDefinition { public: HighlightDefinition(); ~HighlightDefinition(); QSharedPointer createKeywordList(const QString &list); QSharedPointer keywordList(const QString &list); QSharedPointer createContext(const QString &context, bool initial); QSharedPointer initialContext() const; QSharedPointer context(const QString &context) const; const QHash > &contexts() const; QSharedPointer createItemData(const QString &itemData); QSharedPointer itemData(const QString &itemData) const; void setKeywordsSensitive(const QString &sensitivity); Qt::CaseSensitivity keywordsSensitive() const; void addDelimiters(const QString &characters); void removeDelimiters(const QString &characters); bool isDelimiter(const QChar &character) const; void setSingleLineComment(const QString &start); const QString &singleLineComment() const; void setCommentAfterWhitespaces(const QString &after); bool isCommentAfterWhiteSpaces() const; void setMultiLineCommentStart(const QString &start); const QString &multiLineCommentStart() const; void setMultiLineCommentEnd(const QString &end); const QString &multiLineCommentEnd() const; void setMultiLineCommentRegion(const QString ®ion); const QString &multiLineCommentRegion() const; void setIndentationBasedFolding(const QString &indentationBasedFolding); bool isIndentationBasedFolding() const; private: Q_DISABLE_COPY(HighlightDefinition) struct GenericHelper { template QSharedPointer create(const QString &name, Container &container); template QSharedPointer find(const QString &name, const Container &container) const; }; GenericHelper m_helper; QHash > m_lists; QHash > m_contexts; QHash > m_itemsData; QString m_initialContext; QString m_singleLineComment; bool m_singleLineCommentAfterWhiteSpaces; QString m_multiLineCommentStart; QString m_multiLineCommentEnd; QString m_multiLineCommentRegion; Qt::CaseSensitivity m_keywordCaseSensitivity; bool m_indentationBasedFolding; QSet m_delimiters; }; } // namespace Internal } // namespace TextEditor #endif // HIGHLIGHTDEFINITION_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlightdefinitionhandler.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "highlightdefinitionhandler.h" #include "highlightdefinition.h" #include "specificrules.h" #include "itemdata.h" #include "keywordlist.h" #include "context.h" #include "reuse.h" #include "manager2.h" #include "highlighterexception.h" #include #include using namespace TextEditor; using namespace Internal; namespace { static const QLatin1String kName("name"); static const QLatin1String kList("list"); static const QLatin1String kItem("item"); static const QLatin1String kContext("context"); static const QLatin1String kAttribute("attribute"); static const QLatin1String kDynamic("dynamic"); static const QLatin1String kFallthrough("fallthrough"); static const QLatin1String kLineEndContext("lineEndContext"); static const QLatin1String kLineBeginContext("lineBeginContext"); static const QLatin1String kFallthroughContext("fallthroughContext"); static const QLatin1String kBeginRegion("beginRegion"); static const QLatin1String kEndRegion("endRegion"); static const QLatin1String kLookAhead("lookAhead"); static const QLatin1String kFirstNonSpace("firstNonSpace"); static const QLatin1String kColumn("column"); static const QLatin1String kItemData("itemData"); static const QLatin1String kDefStyleNum("defStyleNum"); static const QLatin1String kColor("color"); static const QLatin1String kSelColor("selColor"); static const QLatin1String kItalic("italic"); static const QLatin1String kBold("bold"); static const QLatin1String kUnderline("underline"); static const QLatin1String kStrikeout("strikeOut"); static const QLatin1String kSpellChecking("spellChecking"); static const QLatin1String kChar("char"); static const QLatin1String kChar1("char1"); static const QLatin1String kString("String"); static const QLatin1String kInsensitive("insensitive"); static const QLatin1String kMinimal("minimal"); static const QLatin1String kKeywords("keywords"); static const QLatin1String kCaseSensitive("casesensitive"); static const QLatin1String kWeakDeliminator("weakDeliminator"); static const QLatin1String kAdditionalDeliminator("additionalDeliminator"); static const QLatin1String kWordWrapDeliminator("wordWrapDeliminator"); static const QLatin1String kComment("comment"); static const QLatin1String kPosition("position"); static const QLatin1String kSingleLine("singleline"); static const QLatin1String kMultiLine("multiline"); static const QLatin1String kStart("start"); static const QLatin1String kEnd("end"); static const QLatin1String kRegion("region"); static const QLatin1String kDetectChar("DetectChar"); static const QLatin1String kDetect2Chars("Detect2Chars"); static const QLatin1String kAnyChar("AnyChar"); static const QLatin1String kStringDetect("StringDetect"); static const QLatin1String kRegExpr("RegExpr"); static const QLatin1String kKeyword("keyword"); static const QLatin1String kInt("Int"); static const QLatin1String kFloat("Float"); static const QLatin1String kHlCOct("HlCOct"); static const QLatin1String kHlCHex("HlCHex"); static const QLatin1String kHlCStringChar("HlCStringChar"); static const QLatin1String kHlCChar("HlCChar"); static const QLatin1String kRangeDetect("RangeDetect"); static const QLatin1String kLineContinue("LineContinue"); static const QLatin1String kIncludeRules("IncludeRules"); static const QLatin1String kDetectSpaces("DetectSpaces"); static const QLatin1String kDetectIdentifier("DetectIdentifier"); static const QLatin1String kLanguage("language"); static const QLatin1String kExtensions("extensions"); static const QLatin1String kIncludeAttrib("includeAttrib"); static const QLatin1String kFolding("folding"); static const QLatin1String kIndentationSensitive("indentationsensitive"); static const QLatin1String kHash("#"); static const QLatin1String kDoubleHash("##"); } HighlightDefinitionHandler:: HighlightDefinitionHandler(const QSharedPointer &definition) : m_definition(definition), m_processingKeyword(false), m_initialContext(true) {} HighlightDefinitionHandler::~HighlightDefinitionHandler() {} bool HighlightDefinitionHandler::startDocument() { return true; } bool HighlightDefinitionHandler::endDocument() { processIncludeRules(); return true; } bool HighlightDefinitionHandler::startElement(const QString &, const QString &, const QString &qName, const QXmlAttributes &atts) { if (qName == kList) { listElementStarted(atts); } else if (qName == kItem) { itemElementStarted(); } else if (qName == kContext) { contextElementStarted(atts); } else if (qName == kItemData) { itemDataElementStarted(atts); } else if (qName == kComment) { commentElementStarted(atts); } else if (qName == kKeywords) { keywordsElementStarted(atts); } else if (qName == kFolding) { foldingElementStarted(atts); } else if (qName == kDetectChar) { detectCharStarted(atts); } else if (qName == kDetect2Chars) { detect2CharsStarted(atts); } else if (qName == kAnyChar) { anyCharStarted(atts); } else if (qName == kStringDetect) { stringDetectedStarted(atts); } else if (qName == kRegExpr) { regExprStarted(atts); } else if (qName == kKeyword) { keywordStarted(atts); } else if (qName == kInt) { intStarted(atts); } else if (qName == kFloat) { floatStarted(atts); } else if (qName == kHlCOct) { hlCOctStarted(atts); } else if (qName == kHlCHex) { hlCHexStarted(atts); } else if (qName == kHlCStringChar) { hlCStringCharStarted(atts); } else if (qName == kHlCChar) { hlCCharStarted(atts); } else if (qName == kRangeDetect) { rangeDetectStarted(atts); } else if (qName == kLineContinue) { lineContinue(atts); } else if (qName == kIncludeRules) { includeRulesStarted(atts); } else if (qName == kDetectSpaces) { detectSpacesStarted(atts); } else if (qName == kDetectIdentifier) { detectIdentifier(atts); } return true; } bool HighlightDefinitionHandler::endElement(const QString &, const QString &, const QString &qName) { if (qName == kItem) { m_currentList->addKeyword(m_currentKeyword.trimmed()); m_processingKeyword = false; } else if (qName == kDetectChar || qName == kDetect2Chars || qName == kAnyChar || qName == kStringDetect || qName == kRegExpr || qName == kKeyword || qName == kInt || qName == kFloat || qName == kHlCOct || qName == kHlCHex || qName == kHlCStringChar || qName == kHlCChar || qName == kRangeDetect || qName == kLineContinue || qName == kDetectSpaces || qName == kDetectIdentifier) { m_currentRule.pop(); } return true; } bool HighlightDefinitionHandler::characters(const QString& ch) { // Character data of an element may be reported in more than one chunk. if (m_processingKeyword) m_currentKeyword.append(ch); return true; } void HighlightDefinitionHandler::listElementStarted(const QXmlAttributes &atts) { m_currentList = m_definition->createKeywordList(atts.value(kName)); } void HighlightDefinitionHandler::itemElementStarted() { m_currentKeyword.clear(); m_processingKeyword = true; } void HighlightDefinitionHandler::contextElementStarted(const QXmlAttributes &atts) { m_currentContext = m_definition->createContext(atts.value(kName), m_initialContext); m_currentContext->setDefinition(m_definition); m_currentContext->setItemData(atts.value(kAttribute)); m_currentContext->setDynamic(atts.value(kDynamic)); m_currentContext->setFallthrough(atts.value(kFallthrough)); m_currentContext->setFallthroughContext(atts.value(kFallthroughContext)); m_currentContext->setLineBeginContext(atts.value(kLineBeginContext)); m_currentContext->setLineEndContext(atts.value(kLineEndContext)); m_initialContext = false; } void HighlightDefinitionHandler::ruleElementStarted(const QXmlAttributes &atts, const QSharedPointer &rule) { // The definition of a rule is not necessarily the same of its enclosing context because of // externally included rules. rule->setDefinition(m_definition); rule->setItemData(atts.value(kAttribute)); rule->setContext(atts.value(kContext)); rule->setBeginRegion(atts.value(kBeginRegion)); rule->setEndRegion(atts.value(kEndRegion)); rule->setLookAhead(atts.value(kLookAhead)); rule->setFirstNonSpace(atts.value(kFirstNonSpace)); rule->setColumn(atts.value(kColumn)); if (m_currentRule.isEmpty()) m_currentContext->addRule(rule); else m_currentRule.top()->addChild(rule); m_currentRule.push(rule); } void HighlightDefinitionHandler::itemDataElementStarted(const QXmlAttributes &atts) const { QSharedPointer itemData = m_definition->createItemData(atts.value(kName)); itemData->setStyle(atts.value(kDefStyleNum)); itemData->setColor(atts.value(kColor)); itemData->setSelectionColor(atts.value(kSelColor)); itemData->setItalic(atts.value(kItalic)); itemData->setBold(atts.value(kBold)); itemData->setUnderlined(atts.value(kUnderline)); itemData->setStrikeOut(atts.value(kStrikeout)); itemData->setSpellChecking(atts.value(kSpellChecking)); } void HighlightDefinitionHandler::commentElementStarted(const QXmlAttributes &atts) const { const QString &commentType = atts.value(kName); if (commentType.compare(kSingleLine, Qt::CaseInsensitive) == 0) { m_definition->setSingleLineComment(atts.value(kStart)); m_definition->setCommentAfterWhitespaces(atts.value(kPosition)); } else if (commentType.compare(kMultiLine, Qt::CaseInsensitive) == 0) { m_definition->setMultiLineCommentStart(atts.value(kStart)); m_definition->setMultiLineCommentEnd(atts.value(kEnd)); m_definition->setMultiLineCommentRegion(atts.value(kRegion)); } } void HighlightDefinitionHandler::keywordsElementStarted(const QXmlAttributes &atts) const { // Global case sensitivity appears last in the document (required by dtd) and is set here. m_definition->setKeywordsSensitive(atts.value(kCaseSensitive)); m_definition->removeDelimiters(atts.value(kWeakDeliminator)); m_definition->addDelimiters(atts.value(kAdditionalDeliminator)); //@todo: wordWrapDelimiters? } void HighlightDefinitionHandler::foldingElementStarted(const QXmlAttributes &atts) const { m_definition->setIndentationBasedFolding(atts.value(kIndentationSensitive)); } void HighlightDefinitionHandler::detectCharStarted(const QXmlAttributes &atts) { DetectCharRule *rule = new DetectCharRule; rule->setChar(atts.value(kChar)); rule->setActive(atts.value(kDynamic)); ruleElementStarted(atts, QSharedPointer(rule)); } void HighlightDefinitionHandler::detect2CharsStarted(const QXmlAttributes &atts) { Detect2CharsRule *rule = new Detect2CharsRule; rule->setChar(atts.value(kChar)); rule->setChar1(atts.value(kChar1)); rule->setActive(atts.value(kDynamic)); ruleElementStarted(atts, QSharedPointer(rule)); } void HighlightDefinitionHandler::anyCharStarted(const QXmlAttributes &atts) { AnyCharRule *rule = new AnyCharRule; rule->setCharacterSet(atts.value(kString)); ruleElementStarted(atts, QSharedPointer(rule)); } void HighlightDefinitionHandler::stringDetectedStarted(const QXmlAttributes &atts) { StringDetectRule *rule = new StringDetectRule; rule->setString(atts.value(kString)); rule->setInsensitive(atts.value(kInsensitive)); rule->setActive(atts.value(kDynamic)); ruleElementStarted(atts, QSharedPointer(rule)); } void HighlightDefinitionHandler::regExprStarted(const QXmlAttributes &atts) { RegExprRule *rule = new RegExprRule; rule->setPattern(atts.value(kString)); rule->setMinimal(atts.value(kMinimal)); rule->setInsensitive(atts.value(kInsensitive)); rule->setActive(atts.value(kDynamic)); ruleElementStarted(atts, QSharedPointer(rule)); } void HighlightDefinitionHandler::keywordStarted(const QXmlAttributes &atts) { KeywordRule *rule = new KeywordRule(m_definition); rule->setList(atts.value(kString)); rule->setInsensitive(atts.value(kInsensitive)); ruleElementStarted(atts, QSharedPointer(rule)); } void HighlightDefinitionHandler::intStarted(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new IntRule)); } void HighlightDefinitionHandler::floatStarted(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new FloatRule)); } void HighlightDefinitionHandler::hlCOctStarted(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new HlCOctRule)); } void HighlightDefinitionHandler::hlCHexStarted(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new HlCHexRule)); } void HighlightDefinitionHandler::hlCStringCharStarted(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new HlCStringCharRule)); } void HighlightDefinitionHandler::hlCCharStarted(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new HlCCharRule)); } void HighlightDefinitionHandler::rangeDetectStarted(const QXmlAttributes &atts) { RangeDetectRule *rule = new RangeDetectRule; rule->setChar(atts.value(kChar)); rule->setChar1(atts.value(kChar1)); ruleElementStarted(atts, QSharedPointer(rule)); } void HighlightDefinitionHandler::lineContinue(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new LineContinueRule)); } void HighlightDefinitionHandler::includeRulesStarted(const QXmlAttributes &atts) { // Include rules are treated as instructions for latter processing. IncludeRulesInstruction instruction(atts.value(kContext), m_currentContext->rules().size(), atts.value(kIncludeAttrib)); // Include rules (as many others) are not allowed as a child. m_currentContext->addIncludeRulesInstruction(instruction); } void HighlightDefinitionHandler::detectSpacesStarted(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new DetectSpacesRule)); } void HighlightDefinitionHandler::detectIdentifier(const QXmlAttributes &atts) { ruleElementStarted(atts, QSharedPointer(new DetectIdentifierRule)); } void HighlightDefinitionHandler::processIncludeRules() const { const QHash > &allContexts = m_definition->contexts(); foreach (const QSharedPointer &context, allContexts) processIncludeRules(context); } void HighlightDefinitionHandler::processIncludeRules(const QSharedPointer &context) const { if (context->includeRulesInstructions().isEmpty()) return; int rulesIncluded = 0; const QList &instructions = context->includeRulesInstructions(); foreach (const IncludeRulesInstruction &instruction, instructions) { QSharedPointer sourceContext; const QString &sourceName = instruction.sourceContext(); if (sourceName.startsWith(kDoubleHash)) { // This refers to an external definition. The rules included are the ones from its // initial context. Others contexts and rules from the external definition will work // transparently to the highlighter. This is because contexts and rules know the // definition they are from. QString externalName = QString::fromRawData(sourceName.unicode() + 2, sourceName.length() - 2); const QString &id = Manager2::instance()->definitionIdByName(externalName); // If there is an incorrect circular dependency among definitions this is skipped. if (Manager2::instance()->isBuildingDefinition(id)) continue; const QSharedPointer &externalDefinition = Manager2::instance()->definition(id); if (externalDefinition.isNull()) continue; sourceContext = externalDefinition->initialContext(); } else if (!sourceName.startsWith(kHash)) { sourceContext = m_definition->context(sourceName); // Recursion is done only for context direct rules. Child rules are not processed // because they cannot be include rules. processIncludeRules(sourceContext); } else { continue; } if (instruction.replaceItemData()) { context->setItemData(sourceContext->itemData()); context->setDefinition(sourceContext->definition()); } foreach (QSharedPointer rule, sourceContext->rules()) { context->addRule(rule, instruction.indexHint() + rulesIncluded); ++rulesIncluded; } } context->clearIncludeRulesInstructions(); } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlightdefinitionhandler.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef HIGHLIGHTDEFINITIONHANDLER_H #define HIGHLIGHTDEFINITIONHANDLER_H #include #include #include #include #include namespace TextEditor { namespace Internal { class KeywordList; class Context; class Rule; class HighlightDefinition; class HighlightDefinitionHandler : public QXmlDefaultHandler { public: HighlightDefinitionHandler(const QSharedPointer &definition); ~HighlightDefinitionHandler(); bool startDocument(); bool endDocument(); bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts); bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName); bool characters(const QString &ch); private: void listElementStarted(const QXmlAttributes &atts); void itemElementStarted(); void contextElementStarted(const QXmlAttributes &atts); void itemDataElementStarted(const QXmlAttributes &atts) const; void commentElementStarted(const QXmlAttributes &atts) const; void keywordsElementStarted(const QXmlAttributes &atts) const; void foldingElementStarted(const QXmlAttributes &atts) const; void ruleElementStarted(const QXmlAttributes &atts, const QSharedPointer &rule); // Specific rules. void detectCharStarted(const QXmlAttributes &atts); void detect2CharsStarted(const QXmlAttributes &atts); void anyCharStarted(const QXmlAttributes &atts); void stringDetectedStarted(const QXmlAttributes &atts); void regExprStarted(const QXmlAttributes &atts); void keywordStarted(const QXmlAttributes &atts); void intStarted(const QXmlAttributes &atts); void floatStarted(const QXmlAttributes &atts); void hlCOctStarted(const QXmlAttributes &atts); void hlCHexStarted(const QXmlAttributes &atts); void hlCStringCharStarted(const QXmlAttributes &atts); void hlCCharStarted(const QXmlAttributes &atts); void rangeDetectStarted(const QXmlAttributes &atts); void lineContinue(const QXmlAttributes &atts); void includeRulesStarted(const QXmlAttributes &atts); void detectSpacesStarted(const QXmlAttributes &atts); void detectIdentifier(const QXmlAttributes &atts); void processIncludeRules() const; void processIncludeRules(const QSharedPointer &context) const; QSharedPointer m_definition; bool m_processingKeyword; QString m_currentKeyword; QSharedPointer m_currentList; QSharedPointer m_currentContext; QStack > m_currentRule; bool m_initialContext; }; } // namespace Internal } // namespace TextEditor #endif // HIGHLIGHTDEFINITIONHANDLER_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlightdefinitionmetadata.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "highlightdefinitionmetadata.h" using namespace TextEditor; using namespace Internal; const QLatin1String HighlightDefinitionMetaData::kPriority("priority"); const QLatin1String HighlightDefinitionMetaData::kName("name"); const QLatin1String HighlightDefinitionMetaData::kExtensions("extensions"); const QLatin1String HighlightDefinitionMetaData::kMimeType("mimetype"); const QLatin1String HighlightDefinitionMetaData::kVersion("version"); const QLatin1String HighlightDefinitionMetaData::kUrl("url"); HighlightDefinitionMetaData::HighlightDefinitionMetaData() : m_priority(0) {} void HighlightDefinitionMetaData::setPriority(const int priority) { m_priority = priority; } int HighlightDefinitionMetaData::priority() const { return m_priority; } void HighlightDefinitionMetaData::setId(const QString &id) { m_id = id; } const QString &HighlightDefinitionMetaData::id() const { return m_id; } void HighlightDefinitionMetaData::setName(const QString &name) { m_name = name; } const QString &HighlightDefinitionMetaData::name() const { return m_name; } void HighlightDefinitionMetaData::setVersion(const QString &version) { m_version = version; } const QString &HighlightDefinitionMetaData::version() const { return m_version; } void HighlightDefinitionMetaData::setFileName(const QString &fileName) { m_fileName = fileName; } const QString &HighlightDefinitionMetaData::fileName() const { return m_fileName; } void HighlightDefinitionMetaData::setPatterns(const QStringList &patterns) { m_patterns = patterns; } const QStringList &HighlightDefinitionMetaData::patterns() const { return m_patterns; } void HighlightDefinitionMetaData::setMimeTypes(const QStringList &mimeTypes) { m_mimeTypes = mimeTypes; } const QStringList &HighlightDefinitionMetaData::mimeTypes() const { return m_mimeTypes; } void HighlightDefinitionMetaData::setUrl(const QUrl &url) { m_url = url; } const QUrl &HighlightDefinitionMetaData::url() const { return m_url; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlightdefinitionmetadata.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef HIGHLIGHTDEFINITIONMETADATA_H #define HIGHLIGHTDEFINITIONMETADATA_H #include #include #include #include namespace TextEditor { namespace Internal { class HighlightDefinitionMetaData { public: HighlightDefinitionMetaData(); void setPriority(const int priority); int priority() const; void setId(const QString &id); const QString &id() const; void setName(const QString &name); const QString &name() const; void setVersion(const QString &version); const QString &version() const; void setFileName(const QString &fileName); const QString &fileName() const; void setPatterns(const QStringList &patterns); const QStringList &patterns() const; void setMimeTypes(const QStringList &mimeTypes); const QStringList &mimeTypes() const; void setUrl(const QUrl &url); const QUrl &url() const; static const QLatin1String kPriority; static const QLatin1String kName; static const QLatin1String kExtensions; static const QLatin1String kMimeType; static const QLatin1String kVersion; static const QLatin1String kUrl; private: int m_priority; QString m_id; QString m_name; QString m_version; QString m_fileName; QStringList m_patterns; QStringList m_mimeTypes; QUrl m_url; }; } // namespace Internal } // namespace TextEditor #endif // HIGHLIGHTDEFINITIONMETADATA_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlighter.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "highlighter.h" #include "highlightdefinition.h" #include "context.h" #include "rule.h" #include "itemdata.h" #include "highlighterexception.h" #include "progressdata.h" #include "reuse.h" #include "tabsettings.h" #include #include #include using namespace TextEditor; using namespace Internal; namespace { static const QLatin1String kStay("#stay"); static const QLatin1String kPop("#pop"); static const QLatin1Char kBackSlash('\\'); static const QLatin1Char kHash('#'); } Highlighter::Highlighter(QTextDocument *parent) : TextEditor::SyntaxHighlighter(parent), m_regionDepth(0), m_lastRegionDepth(0), m_indentationBasedFolding(false), m_tabSize(4), m_persistentObservableStatesCounter(PersistentsStart), m_dynamicContextsCounter(0), m_isBroken(false), m_stringOrComment(false) {} Highlighter::~Highlighter() {} Highlighter::BlockData::BlockData() : m_foldingIndentDelta(0), m_originalObservableState(-1) {} Highlighter::BlockData::~BlockData() {} void Highlighter::setDefaultContext(const QSharedPointer &defaultContext) { m_defaultContext = defaultContext; m_persistentObservableStates.insert(m_defaultContext->name(), Default); m_indentationBasedFolding = defaultContext->definition()->isIndentationBasedFolding(); } //void Highlighter::setTabSettings(const TabSettings &ts) //{ // m_tabSettings = &ts; //} void Highlighter::setTabSize(int tabSize) { m_tabSize = tabSize; } void Highlighter::highlightBlock(const QString &text) { if (!m_defaultContext.isNull() && !m_isBroken) { try { if (!currentBlockUserData()) initializeBlockData(); setupDataForBlock(text); handleContextChange(m_currentContext->lineBeginContext(), m_currentContext->definition()); ProgressData progress; const int length = text.length(); m_lastRegionChanged = -1; while (progress.offset() < length) iterateThroughRules(text, length, &progress, false, m_currentContext->rules()); handleContextChange(m_currentContext->lineEndContext(), m_currentContext->definition(), false); m_contexts.clear(); if (m_indentationBasedFolding) { applyIndentationBasedFolding(text); } else { applyRegionBasedFolding(); // In the case region depth has changed since the last time the state was set. setCurrentBlockState(computeState(extractObservableState(currentBlockState()))); } } catch (const HighlighterException &) { m_isBroken = true; } } applyFormatToSpaces(text, m_creatorFormats[VisualWhitespace]); } void Highlighter::setupDataForBlock(const QString &text) { if (extractObservableState(currentBlockState()) == WillContinue) analyseConsistencyOfWillContinueBlock(text); if (previousBlockState() == -1) { m_regionDepth = 0; m_lastRegionDepth = 0; setupDefault(); } else { m_regionDepth = extractRegionDepth(previousBlockState()); m_lastRegionDepth = m_regionDepth; const int observablePreviousState = extractObservableState(previousBlockState()); if (observablePreviousState == Default) setupDefault(); else if (observablePreviousState == WillContinue) setupFromWillContinue(); else if (observablePreviousState == Continued) setupFromContinued(); else setupFromPersistent(); blockData(currentBlockUserData())->m_foldingRegions = blockData(currentBlock().previous().userData())->m_foldingRegions; blockData(currentBlockUserData())->clearParentheses(); } blockData(currentBlockUserData())->clearSpellCheckZones(true); assignCurrentContext(); } void Highlighter::setupDefault() { m_contexts.push_back(m_defaultContext); setCurrentBlockState(computeState(Default)); } void Highlighter::setupFromWillContinue() { BlockData *previousData = blockData(currentBlock().previous().userData()); m_contexts.push_back(previousData->m_contextToContinue); BlockData *data = blockData(currentBlock().userData()); data->m_originalObservableState = previousData->m_originalObservableState; if (currentBlockState() == -1 || extractObservableState(currentBlockState()) == Default) setCurrentBlockState(computeState(Continued)); } void Highlighter::setupFromContinued() { BlockData *previousData = blockData(currentBlock().previous().userData()); Q_ASSERT(previousData->m_originalObservableState != WillContinue && previousData->m_originalObservableState != Continued); if (previousData->m_originalObservableState == Default || previousData->m_originalObservableState == -1) { m_contexts.push_back(m_defaultContext); } else { pushContextSequence(previousData->m_originalObservableState); } setCurrentBlockState(computeState(previousData->m_originalObservableState)); } void Highlighter::setupFromPersistent() { pushContextSequence(extractObservableState(previousBlockState())); setCurrentBlockState(previousBlockState()); } void Highlighter::iterateThroughRules(const QString &text, const int length, ProgressData *progress, const bool childRule, const QList > &rules) { typedef QList >::const_iterator RuleIterator; bool contextChanged = false; bool atLeastOneMatch = false; RuleIterator it = rules.begin(); RuleIterator endIt = rules.end(); bool detlaDeptn = false; while (it != endIt && progress->offset() < length) { int startOffset = progress->offset(); const QSharedPointer &rule = *it; if (rule->itemData() == "String" || rule->itemData() == "Comment") { m_stringOrComment = true; } else { m_stringOrComment = false; } if (rule->matchSucceed(text, length, progress)) { atLeastOneMatch = true; if (!m_stringOrComment) { if (!rule->beginRegion().isEmpty()) { QChar ch = text.at(startOffset); if (ch == '{' || ch == '(' || ch == '[' ) { blockData(currentBlockUserData())->appendParenthese(Parenthesis(Parenthesis::Opened,ch,startOffset)); } } if (!rule->endRegion().isEmpty()) { QChar ch = text.at(startOffset); if (ch == '}' || ch == ')' || ch == ']' ) { blockData(currentBlockUserData())->appendParenthese(Parenthesis(Parenthesis::Closed,ch,startOffset)); } } } if (!m_indentationBasedFolding) { if (!rule->endRegion().isEmpty()) { QStack *currentRegions = &blockData(currentBlockUserData())->m_foldingRegions; if (!currentRegions->isEmpty() && rule->endRegion() == currentRegions->top()) { currentRegions->pop(); --m_regionDepth; if (m_lastRegionDepth > m_regionDepth) { detlaDeptn = true; } // if (!m_stringOrComment && progress->isClosingBraceMatchAtNonEnd()) { // --blockData(currentBlockUserData())->m_foldingIndentDelta; // } } } if (!rule->beginRegion().isEmpty()) { blockData(currentBlockUserData())->m_foldingRegions.push(rule->beginRegion()); ++m_regionDepth; // if (!m_stringOrComment && progress->isOpeningBraceMatchAtFirstNonSpace()) { // ++blockData(currentBlockUserData())->m_foldingIndentDelta; // } } progress->clearBracesMatches(); } if (progress->isWillContinueLine()) { createWillContinueBlock(); progress->setWillContinueLine(false); } else { if (rule->hasChildren()) iterateThroughRules(text, length, progress, true, rule->children()); if (!rule->context().isEmpty() && contextChangeRequired(rule->context())) { m_currentCaptures = progress->captures(); changeContext(rule->context(), rule->definition()); contextChanged = true; } } // Format is not applied to child rules directly (but relative to the offset of their // parent) nor to look ahead rules. if (!childRule && !rule->isLookAhead()) { if (rule->itemData().isEmpty()) applyFormat(startOffset, progress->offset() - startOffset, m_currentContext->itemData(), m_currentContext->definition()); else applyFormat(startOffset, progress->offset() - startOffset, rule->itemData(), rule->definition()); } // When there is a match of one child rule the others should be skipped. Otherwise // the highlighting would be incorret in a case like 9ULLLULLLUULLULLUL, for example. if (contextChanged || childRule) { break; } else { it = rules.begin(); continue; } } ++it; } if (!childRule && !atLeastOneMatch) { if (m_currentContext->isFallthrough()) { handleContextChange(m_currentContext->fallthroughContext(), m_currentContext->definition()); iterateThroughRules(text, length, progress, false, m_currentContext->rules()); } else { applyFormat(progress->offset(), 1, m_currentContext->itemData(), m_currentContext->definition()); if (progress->isOnlySpacesSoFar() && !text.at(progress->offset()).isSpace()) progress->setOnlySpacesSoFar(false); progress->incrementOffset(); } } if (m_lastRegionDepth == m_regionDepth && m_lastRegionChanged != m_lastRegionDepth) { m_lastRegionChanged = m_lastRegionDepth; if (detlaDeptn || ( blockData(currentBlockUserData())->hasParentheses() && ( blockData(currentBlockUserData())->parentheses().last().type == Parenthesis::Opened) ) ) { blockData(currentBlockUserData())->m_foldingIndentDelta--; } } // if (detlaDeptn && (m_lastRegionDepth == m_regionDepth)) { // blockData(currentBlockUserData())->m_foldingIndentDelta--; // } } bool Highlighter::contextChangeRequired(const QString &contextName) const { if (contextName == kStay) return false; return true; } void Highlighter::changeContext(const QString &contextName, const QSharedPointer &definition, const bool assignCurrent) { if (contextName.startsWith(kPop)) { QStringList list = contextName.split(kHash, qtSkipEmptyParts); for (int i = 0; i < list.size(); ++i) m_contexts.pop_back(); if (extractObservableState(currentBlockState()) >= PersistentsStart) { // One or more contexts were popped during during a persistent state. const QString ¤tSequence = currentContextSequence(); if (m_persistentObservableStates.contains(currentSequence)) setCurrentBlockState( computeState(m_persistentObservableStates.value(currentSequence))); else setCurrentBlockState( computeState(m_leadingObservableStates.value(currentSequence))); } } else { const QSharedPointer &context = definition->context(contextName); if (context->isDynamic()) pushDynamicContext(context); else m_contexts.push_back(context); if (m_contexts.back()->lineEndContext() == kStay || extractObservableState(currentBlockState()) >= PersistentsStart) { const QString ¤tSequence = currentContextSequence(); mapLeadingSequence(currentSequence); if (m_contexts.back()->lineEndContext() == kStay) { // A persistent context was pushed. mapPersistentSequence(currentSequence); setCurrentBlockState( computeState(m_persistentObservableStates.value(currentSequence))); } } } if (assignCurrent) assignCurrentContext(); } void Highlighter::handleContextChange(const QString &contextName, const QSharedPointer &definition, const bool setCurrent) { if (!contextName.isEmpty() && contextChangeRequired(contextName)) changeContext(contextName, definition, setCurrent); } void Highlighter::applyFormat(int offset, int count, const QString &itemDataName, const QSharedPointer &definition) { if (count == 0) return; QSharedPointer itemData; try { itemData = definition->itemData(itemDataName); } catch (const HighlighterException &) { // There are some broken files. For instance, the Printf context in java.xml points to an // inexistent Printf item data. These cases are considered to have normal text style. return; } blockData(currentBlockUserData())->addSpellCheckZone(offset, itemData->isSpellChecking()); TextFormatId formatId = m_kateFormats.m_ids.value(itemData->style()); if (formatId == Normal && !itemData->isCustomized()) { return; } // if (formatId != Normal) { // QHash::const_iterator cit = // m_creatorFormats.constFind(formatId); // if (cit != m_creatorFormats.constEnd()) { // QTextCharFormat format = cit.value(); QTextCharFormat format = m_creatorFormats[formatId]; //if (itemData->isCustomized()) { // Please notice that the following are applied every time for item datas which have // customizations. The configureFormats method could be used to provide a "one time" // configuration, but it would probably require to traverse all item datas from all // definitions available/loaded (either to set the values or for some "notifying" // strategy). This is because the highlighter does not really know on which // definition(s) it is working. Since not many item datas specify customizations I // think this approach would fit better. If there are other ideas... if (itemData->color().isValid()) format.setForeground(itemData->color()); if (itemData->isItalicSpecified()) format.setFontItalic(itemData->isItalic()); if (itemData->isBoldSpecified()) format.setFontWeight(toFontWeight(itemData->isBold())); if (itemData->isUnderlinedSpecified()) format.setFontUnderline(itemData->isUnderlined()); if (itemData->isStrikeOutSpecified()) format.setFontStrikeOut(itemData->isStrikeOut()); //} setFormat(offset, count, format, formatId); //} //} } void Highlighter::createWillContinueBlock() { BlockData *data = blockData(currentBlockUserData()); const int currentObservableState = extractObservableState(currentBlockState()); if (currentObservableState == Continued) { BlockData *previousData = blockData(currentBlock().previous().userData()); data->m_originalObservableState = previousData->m_originalObservableState; } else if (currentObservableState != WillContinue) { data->m_originalObservableState = currentObservableState; } data->m_contextToContinue = m_currentContext; setCurrentBlockState(computeState(WillContinue)); } void Highlighter::analyseConsistencyOfWillContinueBlock(const QString &text) { if (currentBlock().next().isValid() && ( text.length() == 0 || text.at(text.length() - 1) != kBackSlash) && extractObservableState(currentBlock().next().userState()) != Continued) { currentBlock().next().setUserState(computeState(Continued)); } if (text.length() == 0 || text.at(text.length() - 1) != kBackSlash) { BlockData *data = blockData(currentBlockUserData()); data->m_contextToContinue.clear(); setCurrentBlockState(computeState(data->m_originalObservableState)); } } void Highlighter::mapPersistentSequence(const QString &contextSequence) { if (!m_persistentObservableStates.contains(contextSequence)) { int newState = m_persistentObservableStatesCounter; m_persistentObservableStates.insert(contextSequence, newState); m_persistentContexts.insert(newState, m_contexts); ++m_persistentObservableStatesCounter; } } void Highlighter::mapLeadingSequence(const QString &contextSequence) { if (!m_leadingObservableStates.contains(contextSequence)) m_leadingObservableStates.insert(contextSequence, extractObservableState(currentBlockState())); } void Highlighter::pushContextSequence(int state) { const QVector > &contexts = m_persistentContexts.value(state); for (int i = 0; i < contexts.size(); ++i) m_contexts.push_back(contexts.at(i)); } QString Highlighter::currentContextSequence() const { QString sequence; for (int i = 0; i < m_contexts.size(); ++i) sequence.append(m_contexts.at(i)->id()); return sequence; } Highlighter::BlockData *Highlighter::initializeBlockData() { BlockData *data = new BlockData; setCurrentBlockUserData(data); return data; } Highlighter::BlockData *Highlighter::blockData(QTextBlockUserData *userData) { return static_cast(userData); } void Highlighter::pushDynamicContext(const QSharedPointer &baseContext) { // A dynamic context is created from another context which serves as its basis. Then, // its rules are updated according to the captures from the calling regular expression which // triggered the push of the dynamic context. QSharedPointer context(new Context(*baseContext)); context->configureId(m_dynamicContextsCounter); context->updateDynamicRules(m_currentCaptures); m_contexts.push_back(context); ++m_dynamicContextsCounter; } void Highlighter::assignCurrentContext() { if (m_contexts.isEmpty()) { // This is not supposed to happen. However, there are broken files (for example, php.xml) // which will cause this behaviour. In such cases pushing the default context is enough to // keep highlighter working. m_contexts.push_back(m_defaultContext); } m_currentContext = m_contexts.back(); } int Highlighter::extractRegionDepth(const int state) { return state >> 12; } int Highlighter::extractObservableState(const int state) { return state & 0xFFF; } int Highlighter::computeState(const int observableState) const { return m_regionDepth << 12 | observableState; } int Highlighter::firstNonSpace(const QString &text) const { int i = 0; while (i < text.size()) { if (!text.at(i).isSpace()) return i; ++i; } return i; } int Highlighter::tabIndentationColumn(const QString &text) const { return tabColumnAt(text, firstNonSpace(text)); } int Highlighter::tabColumnAt(const QString &text, int position) const { int column = 0; for (int i = 0; i < position; ++i) { if (text.at(i) == QLatin1Char('\t')) column = column - (column % m_tabSize) + m_tabSize; else ++column; } return column; } void Highlighter::setFoldIndent(BlockData *data, int indent, const QTextBlock &block) { if (data->foldingIndent() != indent) { emit foldIndentChanged(block); } data->setFoldingIndent(indent); } void Highlighter::applyRegionBasedFolding() { int folding = 0; BlockData *data = blockData(currentBlockUserData()); BlockData *previousData = blockData(currentBlock().previous().userData()); if (previousData) { folding = extractRegionDepth(previousBlockState()); if (data->m_foldingIndentDelta != 0) { folding += data->m_foldingIndentDelta; if (data->m_foldingIndentDelta > 0) data->setFoldingStartIncluded(true); else previousData->setFoldingEndIncluded(false); data->m_foldingIndentDelta = 0; } } data->setFoldingEndIncluded(true); //data->setFoldingIndent(folding); setFoldIndent(data,folding,currentBlock()); } void Highlighter::applyIndentationBasedFolding(const QString &text) { BlockData *data = blockData(currentBlockUserData()); data->setFoldingEndIncluded(true); // If this line is empty, check its neighbours. They all might be part of the same block. if (text.trimmed().isEmpty()) { //data->setFoldingIndent(0); setFoldIndent(data,0,currentBlock()); const int previousIndent = neighbouringNonEmptyBlockIndent(currentBlock().previous(), true); if (previousIndent > 0) { const int nextIndent = neighbouringNonEmptyBlockIndent(currentBlock().next(), false); if (previousIndent == nextIndent) { //data->setFoldingIndent(previousIndent); setFoldIndent(data,0,currentBlock()); } } } else { //data->setFoldingIndent(m_tabSettings->indentationColumn(text)); setFoldIndent(data,tabIndentationColumn(text),currentBlock()); } } int Highlighter::neighbouringNonEmptyBlockIndent(QTextBlock block, const bool previous) const { while (true) { if (!block.isValid()) return 0; if (block.text().trimmed().isEmpty()) { if (previous) block = block.previous(); else block = block.next(); } else { return tabIndentationColumn(block.text()); } } } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlighter.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef HIGHLIGHTER_H #define HIGHLIGHTER_H #include "../basetextdocumentlayout.h" #include "../syntaxhighlighter.h" #include "context.h" #include #include #include #include #include #include #include namespace TextEditor { class TabSettings; namespace Internal { class Rule; class Context; class HighlightDefinition; class ProgressData; class Highlighter : public TextEditor::SyntaxHighlighter { Q_OBJECT public: Highlighter(QTextDocument *parent = 0); virtual ~Highlighter(); //void setTabSettings(const TabSettings &ts); virtual void setTabSize(int tabSize); void setDefaultContext(const QSharedPointer &defaultContext); protected: virtual void highlightBlock(const QString &text); private: void setupDataForBlock(const QString &text); void setupDefault(); void setupFromWillContinue(); void setupFromContinued(); void setupFromPersistent(); void iterateThroughRules(const QString &text, const int length, ProgressData *progress, const bool childRule, const QList > &rules); void assignCurrentContext(); bool contextChangeRequired(const QString &contextName) const; void handleContextChange(const QString &contextName, const QSharedPointer &definition, const bool setCurrent = true); void changeContext(const QString &contextName, const QSharedPointer &definition, const bool assignCurrent = true); QString currentContextSequence() const; void mapPersistentSequence(const QString &contextSequence); void mapLeadingSequence(const QString &contextSequence); void pushContextSequence(int state); void pushDynamicContext(const QSharedPointer &baseContext); void createWillContinueBlock(); void analyseConsistencyOfWillContinueBlock(const QString &text); void applyFormat(int offset, int count, const QString &itemDataName, const QSharedPointer &definition); void applyRegionBasedFolding(); void applyIndentationBasedFolding(const QString &text); int neighbouringNonEmptyBlockIndent(QTextBlock block, const bool previous) const; // Mapping from Kate format strings to format ids. public: struct BlockData : TextBlockUserData { BlockData(); virtual ~BlockData(); int m_foldingIndentDelta; int m_originalObservableState; QStack m_foldingRegions; QSharedPointer m_contextToContinue; }; protected: void setFoldIndent(BlockData *data, int indent, const QTextBlock &block); BlockData *initializeBlockData(); static BlockData *blockData(QTextBlockUserData *userData); // Block states are composed by the region depth (used for code folding) and what I call // observable states. Observable states occupy the 12 least significant bits. They might have // the following values: // - Default [0]: Nothing special. // - WillContinue [1]: When there is match of the LineContinue rule (backslash as the last // character). // - Continued [2]: Blocks that happen after a WillContinue block and continue from their // context until the next line end. // - Persistent(s) [Anything >= 3]: Correspond to persistent contexts which last until a pop // occurs due to a matching rule. Every sequence of persistent contexts seen so far is // associated with a number (incremented by a unit each time). // Region depths occupy the remaining bits. enum ObservableBlockState { Default = 0, WillContinue, Continued, PersistentsStart }; int computeState(const int observableState) const; int tabIndentationColumn(const QString &text) const; int tabColumnAt(const QString &text, int position) const; int firstNonSpace(const QString &text) const; static int extractRegionDepth(const int state); static int extractObservableState(const int state); int m_regionDepth; int m_lastRegionDepth; int m_lastRegionChanged; bool m_indentationBasedFolding; //const TabSettings *m_tabSettings; int m_tabSize; int m_persistentObservableStatesCounter; int m_dynamicContextsCounter; bool m_isBroken; bool m_stringOrComment; TextFormatId m_currentFormat; QSharedPointer m_defaultContext; QSharedPointer m_currentContext; QVector > m_contexts; // Mapping from context sequences to the observable persistent state they represent. QHash m_persistentObservableStates; // Mapping from context sequences to the non-persistent observable state that led to them. QHash m_leadingObservableStates; // Mapping from observable persistent states to context sequences (the actual "stack"). QHash > > m_persistentContexts; // Captures used in dynamic rules. QStringList m_currentCaptures; }; } // namespace Internal } // namespace TextEditor #endif // HIGHLIGHTER_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlighterexception.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef HIGHLIGHTEREXCEPTION_H #define HIGHLIGHTEREXCEPTION_H namespace TextEditor { namespace Internal { class HighlighterException {}; } // namespace Internal } // namespace TextEditor #endif // HIGHLIGHTEREXCEPTION_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/highlightersettingspage.ui ================================================ HighlighterSettingsPage 0 0 521 332 Form 0 0 <html><head/><body> <p>Highlight definitions are provided by the <a href="http://kate-editor.org/">Kate Text Editor</a>.</p></body></html> Qt::RichText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true true Qt::Vertical QSizePolicy::Fixed 20 3 Syntax Highlight Definition Files Location: 0 Use fallback location Behavior Alert when a highlight definition is not found Ignored file patterns: Qt::Vertical 20 117 Utils::PathChooser QWidget
utils/pathchooser.h
1 editingFinished() browsingFinished()
alertWhenNoDefinition ignoreEdit
================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/includerulesinstruction.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "includerulesinstruction.h" #include "reuse.h" using namespace TextEditor; using namespace Internal; IncludeRulesInstruction::IncludeRulesInstruction(const QString &context, int hint, const QString &replaceItemData) : m_sourceContext(context), m_indexHint(hint), m_replaceItemData(toBool(replaceItemData)) { } const QString &IncludeRulesInstruction::sourceContext() const { return m_sourceContext; } int IncludeRulesInstruction::indexHint() const { return m_indexHint; } bool IncludeRulesInstruction::replaceItemData() const { return m_replaceItemData; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/includerulesinstruction.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef INCLUDERULESINSTRUCTION_H #define INCLUDERULESINSTRUCTION_H #include namespace TextEditor { namespace Internal { class IncludeRulesInstruction { public: IncludeRulesInstruction(const QString &context, int hint, const QString &replaceItemData); const QString &sourceContext() const; int indexHint() const; bool replaceItemData() const; private: QString m_sourceContext; int m_indexHint; bool m_replaceItemData; }; } // namespace Internal } // namespace TextEditor #endif // INCLUDERULESINSTRUCTION_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/itemdata.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "itemdata.h" #include "reuse.h" using namespace TextEditor; using namespace Internal; ItemData::ItemData() : m_italic(false), m_italicSpecified(false), m_bold(false), m_boldSpecified(false), m_underlined(false), m_underlinedSpecified(false), m_strikedOut(false), m_strikeOutSpecified(false), m_spellChecking(true), m_spellCheckingSpecified(false), m_isCustomized(false) {} void ItemData::setStyle(const QString &style) { m_style = style; } const QString &ItemData::style() const { return m_style; } void ItemData::setColor(const QString &color) { if (!color.isEmpty()) { m_color.setNamedColor(color); m_isCustomized = true; } } const QColor &ItemData::color() const { return m_color; } void ItemData::setSelectionColor(const QString &color) { if (!color.isEmpty()) { m_selectionColor.setNamedColor(color); m_isCustomized = true; } } const QColor &ItemData::selectionColor() const { return m_selectionColor; } void ItemData::setItalic(const QString &italic) { if (!italic.isEmpty()) { m_italic = toBool(italic); m_italicSpecified = true; m_isCustomized = true; } } bool ItemData::isItalic() const { return m_italic; } bool ItemData::isItalicSpecified() const { return m_italicSpecified; } void ItemData::setBold(const QString &bold) { if (!bold.isEmpty()) { m_bold = toBool(bold); m_boldSpecified = true; m_isCustomized = true; } } bool ItemData::isBold() const { return m_bold; } bool ItemData::isBoldSpecified() const { return m_boldSpecified; } void ItemData::setUnderlined(const QString &underlined) { if (!underlined.isEmpty()) { m_underlined = toBool(underlined); m_underlinedSpecified = true; m_isCustomized = true; } } bool ItemData::isUnderlined() const { return m_underlined; } bool ItemData::isUnderlinedSpecified() const { return m_underlinedSpecified; } void ItemData::setStrikeOut(const QString &strike) { if (!strike.isEmpty()) { m_strikedOut = toBool(strike); m_strikeOutSpecified = true; m_isCustomized = true; } } bool ItemData::isStrikeOut() const { return m_strikedOut; } bool ItemData::isStrikeOutSpecified() const { return m_strikeOutSpecified; } void ItemData::setSpellChecking(const QString &checking) { if (!checking.isEmpty()) { m_spellChecking = toBool(checking); m_spellCheckingSpecified = true; m_isCustomized = true; } } bool ItemData::isSpellChecking() const { return m_spellChecking; } bool ItemData::isSpellCheckingSpecified() const { return m_spellCheckingSpecified; } bool ItemData::isCustomized() const { return m_isCustomized; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/itemdata.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef ITEMDATA_H #define ITEMDATA_H #include #include namespace TextEditor { namespace Internal { class ItemData { public: ItemData(); void setStyle(const QString &style); const QString &style() const; void setColor(const QString &color); const QColor &color() const; void setSelectionColor(const QString &color); const QColor &selectionColor() const; void setItalic(const QString &italic); bool isItalic() const; bool isItalicSpecified() const; void setBold(const QString &bold); bool isBold() const; bool isBoldSpecified() const; void setUnderlined(const QString &underlined); bool isUnderlined() const; bool isUnderlinedSpecified() const; void setStrikeOut(const QString &strike); bool isStrikeOut() const; bool isStrikeOutSpecified() const; void setSpellChecking(const QString &checking); bool isSpellChecking() const; bool isSpellCheckingSpecified() const; bool isCustomized() const; private: bool m_italic; bool m_italicSpecified; bool m_bold; bool m_boldSpecified; bool m_underlined; bool m_underlinedSpecified; bool m_strikedOut; bool m_strikeOutSpecified; bool m_spellChecking; bool m_spellCheckingSpecified; bool m_isCustomized; QString m_style; QColor m_color; QColor m_selectionColor; }; } // namespace Internal } // namespace TextEditor #endif // ITEMDATA_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/keywordlist.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "keywordlist.h" using namespace TextEditor; using namespace Internal; void KeywordList::addKeyword(const QString &keyword) { if (keyword.isEmpty()) return; m_keywords.insert(keyword); } bool KeywordList::isKeyword(const QString &keyword, Qt::CaseSensitivity sensitivity) const { if (keyword.isEmpty()) return false; // Case sensitivity could be implemented, for example, by converting all keywords to lower // if the global sensitivity attribute is insensitive, then always checking for containment // (with a conversion to lower in the necessary cases). But the code below is one alternative // to support the existence of local sensitivity attributes (which override the global one - // currently not documented). if (sensitivity == Qt::CaseSensitive) { return m_keywords.contains(keyword); } else { foreach (const QString &s, m_keywords) if (keyword.compare(s, Qt::CaseInsensitive) == 0) return true; return false; } } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/keywordlist.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef KEYWORDLIST_H #define KEYWORDLIST_H #include #include namespace TextEditor { namespace Internal { class KeywordList { public: void addKeyword(const QString &keyword); bool isKeyword(const QString &keyword, Qt::CaseSensitivity sensitivity) const; private: QSet m_keywords; }; } // namespace Internal } // namespace TextEditor #endif // KEYWORDLIST_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/managedefinitionsdialog.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "managedefinitionsdialog.h" #include "manager.h" #include #include #include #include #include #include #include #include #include #include #include using namespace TextEditor; using namespace Internal; ManageDefinitionsDialog::ManageDefinitionsDialog( const QList &metaDataList, const QString &path, QWidget *parent) : QDialog(parent), m_definitionsMetaData(metaDataList), m_path(path) { ui.setupUi(this); ui.definitionsTable->setHorizontalHeaderLabels( QStringList() << tr("Name") << tr("Installed") << tr("Available")); ui.definitionsTable->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); setWindowTitle(tr("Download Definitions")); populateDefinitionsWidget(); connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadDefinitions())); connect(ui.allButton, SIGNAL(clicked()), this, SLOT(selectAll())); connect(ui.clearButton, SIGNAL(clicked()), this, SLOT(clearSelection())); connect(ui.invertButton, SIGNAL(clicked()), this, SLOT(invertSelection())); } void ManageDefinitionsDialog::populateDefinitionsWidget() { const int size = m_definitionsMetaData.size(); ui.definitionsTable->setRowCount(size); for (int i = 0; i < size; ++i) { const HighlightDefinitionMetaData &downloadData = m_definitionsMetaData.at(i); // Look for this definition in the current path specified by the user, not the one // stored in the settings. So the manager should not be queried for this information. QString dirVersion; QFileInfo fi(m_path + downloadData.fileName()); QFile definitionFile(fi.absoluteFilePath()); if (definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) { const QSharedPointer &data = Manager::parseMetadata(fi); if (!data.isNull()) dirVersion = data->version(); } for (int j = 0; j < 3; ++j) { QTableWidgetItem *item = new QTableWidgetItem; if (j == 0) item->setText(downloadData.name()); else if (j == 1) { item->setText(dirVersion); item->setTextAlignment(Qt::AlignCenter); } else if (j == 2) { item->setText(downloadData.version()); item->setTextAlignment(Qt::AlignCenter); } ui.definitionsTable->setItem(i, j, item); } } } void ManageDefinitionsDialog::downloadDefinitions() { if (Manager::instance()->isDownloadingDefinitions()) { QMessageBox::information( this, tr("Download Information"), tr("There is already one download in progress. Please wait until it is finished.")); return; } QList urls; foreach (const QModelIndex &index, ui.definitionsTable->selectionModel()->selectedRows()) urls.append(m_definitionsMetaData.at(index.row()).url()); Manager::instance()->downloadDefinitions(urls, m_path); accept(); } void ManageDefinitionsDialog::selectAll() { ui.definitionsTable->selectAll(); ui.definitionsTable->setFocus(); } void ManageDefinitionsDialog::clearSelection() { ui.definitionsTable->clearSelection(); } void ManageDefinitionsDialog::invertSelection() { const QModelIndex &topLeft = ui.definitionsTable->model()->index(0, 0); const QModelIndex &bottomRight = ui.definitionsTable->model()->index(ui.definitionsTable->rowCount() - 1, ui.definitionsTable->columnCount() - 1); QItemSelection itemSelection(topLeft, bottomRight); ui.definitionsTable->selectionModel()->select(itemSelection, QItemSelectionModel::Toggle); ui.definitionsTable->setFocus(); } void ManageDefinitionsDialog::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui.retranslateUi(this); break; default: break; } } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/managedefinitionsdialog.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef MANAGEDEFINITIONSDIALOG_H #define MANAGEDEFINITIONSDIALOG_H #include "ui_managedefinitionsdialog.h" #include "highlightdefinitionmetadata.h" #include namespace TextEditor { namespace Internal { class ManageDefinitionsDialog : public QDialog { Q_OBJECT public: explicit ManageDefinitionsDialog(const QList &metaDataList, const QString &path, QWidget *parent = 0); protected: void changeEvent(QEvent *e); private slots: void downloadDefinitions(); void selectAll(); void clearSelection(); void invertSelection(); private: void populateDefinitionsWidget(); QList m_definitionsMetaData; QString m_path; Ui::ManageDefinitionsDialog ui; }; } // namespace Internal } // namespace TextEditor #endif // MANAGEDEFINITIONSDIALOG_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/managedefinitionsdialog.ui ================================================ ManageDefinitionsDialog 0 0 586 280 Dialog Definitions QAbstractItemView::NoEditTriggers false QAbstractItemView::ExtendedSelection QAbstractItemView::SelectRows false Qt::NoPen 3 false false 20 false Select All Clear Selection Invert Selection Qt::Vertical 20 244 Download Selected Definitions Qt::Horizontal 188 20 QDialogButtonBox::Close buttonBox rejected() ManageDefinitionsDialog close() 385 420 223 222 ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/manager.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "manager.h" #include "highlightdefinition.h" #include "highlightdefinitionhandler.h" #include "highlighterexception.h" //#include "definitiondownloader.h" //#include "highlightersettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace TextEditor; using namespace Internal; Manager::Manager() : m_downloadingDefinitions(false), m_registeringMimeTypes(false), m_queuedMimeTypeRegistrations(0) { //connect(&m_mimeTypeWatcher, SIGNAL(resultReadyAt(int)), this, SLOT(registerMimeType(int))); //connect(&m_mimeTypeWatcher, SIGNAL(finished()), this, SLOT(registerMimeTypesFinished())); connect(&m_downloadWatcher, SIGNAL(finished()), this, SLOT(downloadDefinitionsFinished())); } Manager::~Manager() {} Manager *Manager::instance() { static Manager manager; return &manager; } QString Manager::definitionIdByName(const QString &name) const { return m_idByName.value(name); } QString Manager::definitionIdByMimeType(const QString &mimeType) const { return m_idByMimeType.value(mimeType); } QString Manager::definitionIdByAnyMimeType(const QStringList &mimeTypes) const { QString definitionId; foreach (const QString &mimeType, mimeTypes) { definitionId = definitionIdByMimeType(mimeType); if (!definitionId.isEmpty()) break; } return definitionId; } QSharedPointer Manager::definition(const QString &id) { if (!id.isEmpty() && !m_definitions.contains(id)) { QFile definitionFile(id); if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) return QSharedPointer(); QSharedPointer definition(new HighlightDefinition); HighlightDefinitionHandler handler(definition); QXmlInputSource source(&definitionFile); QXmlSimpleReader reader; reader.setContentHandler(&handler); m_isBuilding.insert(id); try { reader.parse(source); } catch (HighlighterException &) { definition.clear(); } m_isBuilding.remove(id); definitionFile.close(); m_definitions.insert(id, definition); } return m_definitions.value(id); } QSharedPointer Manager::definitionMetaData(const QString &id) const { return m_definitionsMetaData.value(id); } bool Manager::isBuildingDefinition(const QString &id) const { return m_isBuilding.contains(id); } void Manager::loadFromPath(const QStringList & definitionsPaths) { foreach (const QString &path, definitionsPaths) { if (path.isEmpty()) continue; QDir definitionsDir(path); QStringList filter(QLatin1String("*.xml")); definitionsDir.setNameFilters(filter); QList > allMetaData; const QFileInfoList &filesInfo = definitionsDir.entryInfoList(); foreach (const QFileInfo &fileInfo, filesInfo) { const QSharedPointer &metaData = parseMetadata(fileInfo); if (!metaData.isNull()) allMetaData.append(metaData); } // Consider definitions with higher priority first. qSort(allMetaData.begin(), allMetaData.end(), PriorityComp()); foreach (const QSharedPointer &metaData, allMetaData) { if (m_idByName.contains(metaData->name())) // Name already exists... This is a fallback item, do not consider it. continue; const QString &id = metaData->id(); m_idByName.insert(metaData->name(), id); m_definitionsMetaData.insert(id, metaData); qDebug() << metaData->mimeTypes(); foreach (const QString &type, metaData->mimeTypes()) { if (m_idByMimeType.contains(type)) continue; m_idByMimeType.insert(type, id); } // static const QStringList textPlain(QLatin1String("text/plain")); // // A definition can specify multiple MIME types and file extensions/patterns. // // However, each thing is done with a single string. There is no direct way to // // tell which patterns belong to which MIME types nor whether a MIME type is just // // an alias for the other. Currently, I associate all patterns with all MIME // // types from a definition. // QList globPatterns; // foreach (const QString &type, metaData->mimeTypes()) { // if (m_idByMimeType.contains(type)) // continue; // m_idByMimeType.insert(type, id); // Core::MimeType mimeType = mimeDatabase->findByType(type); // if (mimeType.isNull()) { // mimeType.setType(type); // mimeType.setSubClassesOf(textPlain); // mimeType.setComment(metaData->name()); // // If there's a user modification for this mime type, we want to use the // // modified patterns and rule-based matchers. If not, just consider what // // is specified in the definition file. // QHash::const_iterator it = // userModified.find(mimeType.type()); // if (it == userModified.end()) { // if (globPatterns.isEmpty()) { // foreach (const QString &pattern, metaData->patterns()) { // static const QLatin1String mark("*."); // if (pattern.startsWith(mark)) { // const QString &suffix = pattern.right(pattern.length() - 2); // if (!knownSuffixes.contains(suffix)) // knownSuffixes.insert(suffix); // else // continue; // } // QRegExp regExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard); // globPatterns.append(Core::MimeGlobPattern(regExp, 50)); // } // } // mimeType.setGlobPatterns(globPatterns); // } else { // mimeType.setGlobPatterns(it.value().globPatterns()); // mimeType.setMagicRuleMatchers(it.value().magicRuleMatchers()); // } // mimeDatabase->addMimeType(mimeType); // future.reportResult(mimeType); // } // } } } } void Manager::registerMimeTypes() { // if (!m_registeringMimeTypes) { // m_registeringMimeTypes = true; // clear(); // QFuture future = // QtConcurrent::run(&Manager::gatherDefinitionsMimeTypes, this); // m_mimeTypeWatcher.setFuture(future); // Core::ICore::instance()->progressManager()->addTask(future, // tr("Registering definitions"), // Constants::TASK_REGISTER_DEFINITIONS); // } else { // // QFutures returned from QConcurrent::run cannot be cancelled. So the queue. // ++m_queuedMimeTypeRegistrations; // } } //void Manager::gatherDefinitionsMimeTypes(QFutureInterface &future) //{ // // Please be aware of the following limitation in the current implementation. // // The generic highlighter only register its types after all other plugins // // have populated Creator's MIME database (so it does not override anything). // // When the generic highlighter settings change only its internal data is cleaned-up // // and rebuilt. Creator's MIME database is not touched. So depending on how the // // user plays around with the generic highlighter file definitions (changing // // duplicated patterns, for example), some changes might not be reflected. // // A definitive implementation would require some kind of re-load or update // // (considering hierarchies, aliases, etc) of the MIME database whenever there // // is a change in the generic highlighter settings. // QStringList definitionsPaths; // const HighlighterSettings &settings = TextEditorSettings::instance()->highlighterSettings(); // definitionsPaths.append(settings.definitionFilesPath()); // if (settings.useFallbackLocation()) // definitionsPaths.append(settings.fallbackDefinitionFilesPath()); // Core::MimeDatabase *mimeDatabase = Core::ICore::instance()->mimeDatabase(); // QSet knownSuffixes = QSet::fromList(mimeDatabase->suffixes()); // QHash userModified; // const QList &userMimeTypes = mimeDatabase->readUserModifiedMimeTypes(); // foreach (const Core::MimeType &userMimeType, userMimeTypes) // userModified.insert(userMimeType.type(), userMimeType); // foreach (const QString &path, definitionsPaths) { // if (path.isEmpty()) // continue; // QDir definitionsDir(path); // QStringList filter(QLatin1String("*.xml")); // definitionsDir.setNameFilters(filter); // QList > allMetaData; // const QFileInfoList &filesInfo = definitionsDir.entryInfoList(); // foreach (const QFileInfo &fileInfo, filesInfo) { // const QSharedPointer &metaData = parseMetadata(fileInfo); // if (!metaData.isNull()) // allMetaData.append(metaData); // } // // Consider definitions with higher priority first. // qSort(allMetaData.begin(), allMetaData.end(), PriorityComp()); // foreach (const QSharedPointer &metaData, allMetaData) { // if (m_idByName.contains(metaData->name())) // // Name already exists... This is a fallback item, do not consider it. // continue; // const QString &id = metaData->id(); // m_idByName.insert(metaData->name(), id); // m_definitionsMetaData.insert(id, metaData); // static const QStringList textPlain(QLatin1String("text/plain")); // // A definition can specify multiple MIME types and file extensions/patterns. // // However, each thing is done with a single string. There is no direct way to // // tell which patterns belong to which MIME types nor whether a MIME type is just // // an alias for the other. Currently, I associate all patterns with all MIME // // types from a definition. // QList globPatterns; // foreach (const QString &type, metaData->mimeTypes()) { // if (m_idByMimeType.contains(type)) // continue; // m_idByMimeType.insert(type, id); // Core::MimeType mimeType = mimeDatabase->findByType(type); // if (mimeType.isNull()) { // mimeType.setType(type); // mimeType.setSubClassesOf(textPlain); // mimeType.setComment(metaData->name()); // // If there's a user modification for this mime type, we want to use the // // modified patterns and rule-based matchers. If not, just consider what // // is specified in the definition file. // QHash::const_iterator it = // userModified.find(mimeType.type()); // if (it == userModified.end()) { // if (globPatterns.isEmpty()) { // foreach (const QString &pattern, metaData->patterns()) { // static const QLatin1String mark("*."); // if (pattern.startsWith(mark)) { // const QString &suffix = pattern.right(pattern.length() - 2); // if (!knownSuffixes.contains(suffix)) // knownSuffixes.insert(suffix); // else // continue; // } // QRegExp regExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard); // globPatterns.append(Core::MimeGlobPattern(regExp, 50)); // } // } // mimeType.setGlobPatterns(globPatterns); // } else { // mimeType.setGlobPatterns(it.value().globPatterns()); // mimeType.setMagicRuleMatchers(it.value().magicRuleMatchers()); // } // mimeDatabase->addMimeType(mimeType); // future.reportResult(mimeType); // } // } // } // } //} void Manager::registerMimeType(int index) const { //const Core::MimeType &mimeType = m_mimeTypeWatcher.resultAt(index); //TextEditorPlugin::instance()->editorFactory()->addMimeType(mimeType.type()); } void Manager::registerMimeTypesFinished() { m_registeringMimeTypes = false; if (m_queuedMimeTypeRegistrations > 0) { --m_queuedMimeTypeRegistrations; registerMimeTypes(); } else { emit mimeTypesRegistered(); } } QSharedPointer Manager::parseMetadata(const QFileInfo &fileInfo) { static const QLatin1Char kSemiColon(';'); static const QLatin1Char kSpace(' '); static const QLatin1Char kDash('-'); static const QLatin1String kLanguage("language"); static const QLatin1String kArtificial("text/x-artificial-"); QFile definitionFile(fileInfo.absoluteFilePath()); if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) return QSharedPointer(); QSharedPointer metaData(new HighlightDefinitionMetaData); QXmlStreamReader reader(&definitionFile); while (!reader.atEnd() && !reader.hasError()) { if (reader.readNext() == QXmlStreamReader::StartElement && reader.name() == kLanguage) { const QXmlStreamAttributes &atts = reader.attributes(); metaData->setFileName(fileInfo.fileName()); metaData->setId(fileInfo.absoluteFilePath()); metaData->setName(atts.value(HighlightDefinitionMetaData::kName).toString()); metaData->setVersion(atts.value(HighlightDefinitionMetaData::kVersion).toString()); metaData->setPriority(atts.value(HighlightDefinitionMetaData::kPriority).toString() .toInt()); metaData->setPatterns(atts.value(HighlightDefinitionMetaData::kExtensions) .toString().split(kSemiColon, QString::SkipEmptyParts)); QStringList mimeTypes = atts.value(HighlightDefinitionMetaData::kMimeType). toString().split(kSemiColon, QString::SkipEmptyParts); if (mimeTypes.isEmpty()) { // There are definitions which do not specify a MIME type, but specify file // patterns. Creating an artificial MIME type is a workaround. QString artificialType(kArtificial); artificialType.append(metaData->name().trimmed().replace(kSpace, kDash)); mimeTypes.append(artificialType); } metaData->setMimeTypes(mimeTypes); break; } } reader.clear(); definitionFile.close(); return metaData; } QList Manager::parseAvailableDefinitionsList(QIODevice *device) const { static const QLatin1Char kSlash('/'); static const QLatin1String kDefinition("Definition"); QList metaDataList; QXmlStreamReader reader(device); while (!reader.atEnd() && !reader.hasError()) { if (reader.readNext() == QXmlStreamReader::StartElement && reader.name() == kDefinition) { const QXmlStreamAttributes &atts = reader.attributes(); HighlightDefinitionMetaData metaData; metaData.setName(atts.value(HighlightDefinitionMetaData::kName).toString()); metaData.setVersion(atts.value(HighlightDefinitionMetaData::kVersion).toString()); QString url(atts.value(HighlightDefinitionMetaData::kUrl).toString()); metaData.setUrl(QUrl(url)); const int slash = url.lastIndexOf(kSlash); if (slash != -1) metaData.setFileName(url.right(url.length() - slash - 1)); metaDataList.append(metaData); } } reader.clear(); return metaDataList; } void Manager::downloadAvailableDefinitionsMetaData() { // QUrl url(QLatin1String("http://www.kate-editor.org/syntax/update-3.2.xml")); // QNetworkRequest request(url); // Currently this takes a couple of seconds on Windows 7: QTBUG-10106. // QNetworkReply *reply = m_networkManager.get(request); // connect(reply, SIGNAL(finished()), this, SLOT(downloadAvailableDefinitionsListFinished())); } void Manager::downloadAvailableDefinitionsListFinished() { // if (QNetworkReply *reply = qobject_cast(sender())) { // if (reply->error() == QNetworkReply::NoError) // emit definitionsMetaDataReady(parseAvailableDefinitionsList(reply)); // else // emit errorDownloadingDefinitionsMetaData(); // reply->deleteLater(); // } } void Manager::downloadDefinitions(const QList &urls, const QString &savePath) { // m_downloaders.clear(); // foreach (const QUrl &url, urls) // m_downloaders.append(new DefinitionDownloader(url, savePath)); // m_downloadingDefinitions = true; // QFuture future = QtConcurrent::map(m_downloaders, DownloaderStarter()); // m_downloadWatcher.setFuture(future); // Core::ICore::instance()->progressManager()->addTask(future, // tr("Downloading definitions"), // Constants::TASK_DOWNLOAD_DEFINITIONS); } void Manager::downloadDefinitionsFinished() { // int errors = 0; // bool writeError = false; // foreach (DefinitionDownloader *downloader, m_downloaders) { // DefinitionDownloader::Status status = downloader->status(); // if (status != DefinitionDownloader::Ok) { // ++errors; // if (status == DefinitionDownloader::WriteError && !writeError) // writeError = true; // } // delete downloader; // } // if (errors > 0) { // QString text; // if (errors == m_downloaders.size()) // text = tr("Error downloading selected definition(s)."); // else // text = tr("Error downloading one or more definitions."); // if (writeError) // text.append(tr("\nPlease check the directory's access rights.")); // QMessageBox::critical(0, tr("Download Error"), text); // } // m_downloadingDefinitions = false; } bool Manager::isDownloadingDefinitions() const { return m_downloadingDefinitions; } void Manager::clear() { m_idByName.clear(); m_idByMimeType.clear(); m_definitions.clear(); m_definitionsMetaData.clear(); } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/manager.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef MANAGER_H #define MANAGER_H #include "highlightdefinitionmetadata.h" #include #include #include #include #include #include #include //#include QT_BEGIN_NAMESPACE class QFileInfo; class QStringList; class QIODevice; template class QFutureInterface; template class QSharedPointer; QT_END_NAMESPACE namespace TextEditor { namespace Internal { class HighlightDefinition; class DefinitionDownloader; // This is the generic highlighter manager. It is not thread-safe. class Manager : public QObject { Q_OBJECT public: virtual ~Manager(); static Manager *instance(); QString definitionIdByName(const QString &name) const; QString definitionIdByMimeType(const QString &mimeType) const; QString definitionIdByAnyMimeType(const QStringList &mimeTypes) const; bool isBuildingDefinition(const QString &id) const; QSharedPointer definition(const QString &id); QSharedPointer definitionMetaData(const QString &id) const; void downloadAvailableDefinitionsMetaData(); void downloadDefinitions(const QList &urls, const QString &savePath); bool isDownloadingDefinitions() const; static QSharedPointer parseMetadata(const QFileInfo &fileInfo); void loadFromPath(const QStringList & definitionsPaths); public slots: void registerMimeTypes(); private slots: void registerMimeType(int index) const; void registerMimeTypesFinished(); void downloadAvailableDefinitionsListFinished(); void downloadDefinitionsFinished(); signals: void mimeTypesRegistered(); private: Manager(); Q_DISABLE_COPY(Manager) // void gatherDefinitionsMimeTypes(QFutureInterface &future); QList parseAvailableDefinitionsList(QIODevice *device) const; void clear(); bool m_downloadingDefinitions; bool m_registeringMimeTypes; int m_queuedMimeTypeRegistrations; QHash m_idByName; QHash m_idByMimeType; QHash > m_definitions; QHash > m_definitionsMetaData; QSet m_isBuilding; //QList m_downloaders; //QNetworkAccessManager m_networkManager; QFutureWatcher m_downloadWatcher; //QFutureWatcher m_mimeTypeWatcher; struct PriorityComp { bool operator()(const QSharedPointer &a, const QSharedPointer &b) { return a->priority() > b->priority(); } }; signals: void definitionsMetaDataReady(const QList&); void errorDownloadingDefinitionsMetaData(); }; } // namespace Internal } // namespace TextEditor #endif // MANAGER_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/manager2.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "manager2.h" #include "highlighter.h" #include "highlightdefinition.h" #include "highlightdefinitionhandler.h" #include "highlighterexception.h" #include "highlightdefinitionmetadata.h" #include #include #include using namespace TextEditor::Internal; Manager2 *Manager2::instance() { static Manager2 manager; return &manager; } QSharedPointer Manager2::parseMetadata(const QFileInfo &fileInfo) { static const QLatin1Char kSemiColon(';'); static const QLatin1Char kSpace(' '); static const QLatin1Char kDash('-'); static const QLatin1String kLanguage("language"); static const QLatin1String kArtificial("text/x-artificial-"); QFile definitionFile(fileInfo.absoluteFilePath()); if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) return QSharedPointer(); QSharedPointer metaData(new HighlightDefinitionMetaData); QXmlStreamReader reader(&definitionFile); while (!reader.atEnd() && !reader.hasError()) { if (reader.readNext() == QXmlStreamReader::StartElement && reader.name() == kLanguage) { const QXmlStreamAttributes &atts = reader.attributes(); metaData->setFileName(fileInfo.fileName()); metaData->setId(fileInfo.absoluteFilePath()); metaData->setName(atts.value(HighlightDefinitionMetaData::kName).toString()); metaData->setVersion(atts.value(HighlightDefinitionMetaData::kVersion).toString()); metaData->setPriority(atts.value(HighlightDefinitionMetaData::kPriority).toString() .toInt()); metaData->setPatterns(atts.value(HighlightDefinitionMetaData::kExtensions) .toString().split(kSemiColon, qtSkipEmptyParts)); QStringList mimeTypes = atts.value(HighlightDefinitionMetaData::kMimeType). toString().split(kSemiColon, qtSkipEmptyParts); if (mimeTypes.isEmpty()) { // There are definitions which do not specify a MIME type, but specify file // patterns. Creating an artificial MIME type is a workaround. QString artificialType(kArtificial); artificialType.append(metaData->name().trimmed().replace(kSpace, kDash)); mimeTypes.append(artificialType); } metaData->setMimeTypes(mimeTypes); break; } } reader.clear(); definitionFile.close(); return metaData; } struct PriorityComp { bool operator()(const QSharedPointer &a, const QSharedPointer &b) { return a->priority() > b->priority(); } }; void Manager2::loadPath(const QStringList &definitionsPaths) { foreach (const QString &path, definitionsPaths) { if (path.isEmpty()) continue; QDir definitionsDir(path); QStringList filter(QLatin1String("*.xml")); definitionsDir.setNameFilters(filter); QList > allMetaData; const QFileInfoList &filesInfo = definitionsDir.entryInfoList(); foreach (const QFileInfo &fileInfo, filesInfo) { const QSharedPointer &metaData = parseMetadata(fileInfo); if (!metaData.isNull()) allMetaData.append(metaData); } // Consider definitions with higher priority first. qSort(allMetaData.begin(), allMetaData.end(), PriorityComp()); foreach (const QSharedPointer &metaData, allMetaData) { if (m_idByName.contains(metaData->name())) // Name already exists... This is a fallback item, do not consider it. continue; const QString &id = metaData->id(); m_idByName.insert(metaData->name(), id); m_definitionsMetaData.insert(id, metaData); foreach (const QString &type, metaData->mimeTypes()) { if (m_idByMimeType.contains(type)) continue; m_idByMimeType.insert(type, id); } // static const QStringList textPlain(QLatin1String("text/plain")); // // A definition can specify multiple MIME types and file extensions/patterns. // // However, each thing is done with a single string. There is no direct way to // // tell which patterns belong to which MIME types nor whether a MIME type is just // // an alias for the other. Currently, I associate all patterns with all MIME // // types from a definition. // QList globPatterns; // foreach (const QString &type, metaData->mimeTypes()) { // if (m_idByMimeType.contains(type)) // continue; // m_idByMimeType.insert(type, id); // Core::MimeType mimeType = mimeDatabase->findByType(type); // if (mimeType.isNull()) { // mimeType.setType(type); // mimeType.setSubClassesOf(textPlain); // mimeType.setComment(metaData->name()); // // If there's a user modification for this mime type, we want to use the // // modified patterns and rule-based matchers. If not, just consider what // // is specified in the definition file. // QHash::const_iterator it = // userModified.find(mimeType.type()); // if (it == userModified.end()) { // if (globPatterns.isEmpty()) { // foreach (const QString &pattern, metaData->patterns()) { // static const QLatin1String mark("*."); // if (pattern.startsWith(mark)) { // const QString &suffix = pattern.right(pattern.length() - 2); // if (!knownSuffixes.contains(suffix)) // knownSuffixes.insert(suffix); // else // continue; // } // QRegExp regExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard); // globPatterns.append(Core::MimeGlobPattern(regExp, 50)); // } // } // mimeType.setGlobPatterns(globPatterns); // } else { // mimeType.setGlobPatterns(it.value().globPatterns()); // mimeType.setMagicRuleMatchers(it.value().magicRuleMatchers()); // } // mimeDatabase->addMimeType(mimeType); // future.reportResult(mimeType); // } // } } } } QString Manager2::definitionIdByName(const QString &name) const { return m_idByName.value(name); } QString Manager2::definitionIdByMimeType(const QString &mimeType) const { return m_idByMimeType.value(mimeType); } QStringList Manager2::mimeTypes() const { return m_idByMimeType.keys(); } QString Manager2::definitionIdByAnyMimeType(const QStringList &mimeTypes) const { QString definitionId; foreach (const QString &mimeType, mimeTypes) { definitionId = definitionIdByMimeType(mimeType); if (!definitionId.isEmpty()) break; } return definitionId; } QSharedPointer Manager2::definition(const QString &id) { if (!id.isEmpty() && !m_definitions.contains(id)) { QFile definitionFile(id); if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) return QSharedPointer(); QSharedPointer definition(new HighlightDefinition); HighlightDefinitionHandler handler(definition); QXmlInputSource source(&definitionFile); QXmlSimpleReader reader; reader.setContentHandler(&handler); m_isBuilding.insert(id); try { reader.parse(source); } catch (HighlighterException &) { definition.clear(); } m_isBuilding.remove(id); definitionFile.close(); m_definitions.insert(id, definition); } return m_definitions.value(id); } QSharedPointer Manager2::definitionMetaData(const QString &id) const { return m_definitionsMetaData.value(id); } bool Manager2::isBuildingDefinition(const QString &id) const { return m_isBuilding.contains(id); } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/manager2.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef MANAGER2_H #define MANAGER2_H #include "highlightdefinitionmetadata.h" #include "highlightdefinition.h" #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QFileInfo; class QStringList; class QIODevice; template class QFutureInterface; template class QSharedPointer; QT_END_NAMESPACE namespace TextEditor { namespace Internal { // This is the generic highlighter manager. It is not thread-safe. class Manager2 : public QObject { Q_OBJECT public: static Manager2 *instance(); void loadPath(const QStringList &definitionsPaths); public: QSharedPointer parseMetadata(const QFileInfo &fileInfo); QString definitionIdByName(const QString &name) const; QString definitionIdByMimeType(const QString &mimeType) const; QString definitionIdByAnyMimeType(const QStringList &mimeTypes) const; QSharedPointer definition(const QString &id); QSharedPointer definitionMetaData(const QString &id) const; bool isBuildingDefinition(const QString &id) const; public: QStringList mimeTypes() const; protected: QHash m_idByName; QHash m_idByMimeType; QHash > m_definitions; QHash > m_definitionsMetaData; QSet m_isBuilding; }; } // namespace Internal } // namespace TextEditor #endif // MANAGER2_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/progressdata.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "progressdata.h" #include "rule.h" #include using namespace TextEditor; using namespace Internal; ProgressData::ProgressData() : m_offset(0), m_savedOffset(-1), m_onlySpacesSoFar(true), m_openingBraceMatchAtFirstNonSpace(false), m_closingBraceMatchAtNonEnd(false), m_willContinueLine(false) {} ProgressData::~ProgressData() { foreach (Rule *rule, m_trackedRules) rule->progressFinished(); } void ProgressData::setOffset(const int offset) { m_offset = offset; } int ProgressData::offset() const { return m_offset; } void ProgressData::incrementOffset() { ++m_offset; } void ProgressData::incrementOffset(const int increment) { m_offset += increment; } void ProgressData::saveOffset() { m_savedOffset = m_offset; } void ProgressData::restoreOffset() { Q_ASSERT(m_savedOffset != -1); m_offset = m_savedOffset; m_savedOffset = -1; } void ProgressData::setOnlySpacesSoFar(const bool onlySpaces) { m_onlySpacesSoFar = onlySpaces; } bool ProgressData::isOnlySpacesSoFar() const { return m_onlySpacesSoFar; } void ProgressData::setOpeningBraceMatchAtFirstNonSpace(const bool match) { m_openingBraceMatchAtFirstNonSpace = match; } bool ProgressData::isOpeningBraceMatchAtFirstNonSpace() const { return m_openingBraceMatchAtFirstNonSpace; } void ProgressData::setClosingBraceMatchAtNonEnd(const bool match) { m_closingBraceMatchAtNonEnd = match; } bool ProgressData::isClosingBraceMatchAtNonEnd() const { return m_closingBraceMatchAtNonEnd; } void ProgressData::clearBracesMatches() { if (m_openingBraceMatchAtFirstNonSpace) m_openingBraceMatchAtFirstNonSpace = false; if (m_closingBraceMatchAtNonEnd) m_closingBraceMatchAtNonEnd = false; } void ProgressData::setWillContinueLine(const bool willContinue) { m_willContinueLine = willContinue; } bool ProgressData::isWillContinueLine() const { return m_willContinueLine; } void ProgressData::setCaptures(const QStringList &captures) { m_captures = captures; } const QStringList &ProgressData::captures() const { return m_captures; } void ProgressData::trackRule(Rule *rule) { m_trackedRules.append(rule); } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/progressdata.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef PROGRESSDATA_H #define PROGRESSDATA_H #include namespace TextEditor { namespace Internal { class Rule; class ProgressData { public: ProgressData(); ~ProgressData(); void setOffset(const int offset); int offset() const; void incrementOffset(); void incrementOffset(const int increment); void saveOffset(); void restoreOffset(); void setOnlySpacesSoFar(const bool onlySpaces); bool isOnlySpacesSoFar() const; void setOpeningBraceMatchAtFirstNonSpace(const bool match); bool isOpeningBraceMatchAtFirstNonSpace() const; void setClosingBraceMatchAtNonEnd(const bool match); bool isClosingBraceMatchAtNonEnd() const; void clearBracesMatches(); void setWillContinueLine(const bool willContinue); bool isWillContinueLine() const; void setCaptures(const QStringList &captures); const QStringList &captures() const; void trackRule(Rule *rule); private: int m_offset; int m_savedOffset; bool m_onlySpacesSoFar; bool m_openingBraceMatchAtFirstNonSpace; bool m_closingBraceMatchAtNonEnd; bool m_willContinueLine; QStringList m_captures; QList m_trackedRules; }; } // namespace Internal } // namespace TextEditor #endif // PROGRESSDATA_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/reuse.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef REUSE_H #define REUSE_H #include #include #include #include #include namespace TextEditor { namespace Internal { inline bool toBool(const QString &s) { static const QLatin1String kTrue("true"); static const QLatin1String k1("1"); if (s.toLower() == kTrue || s == k1) return true; return false; } inline Qt::CaseSensitivity toCaseSensitivity(const bool sensitive) { if (sensitive) return Qt::CaseSensitive; return Qt::CaseInsensitive; } inline QFont::Weight toFontWeight(const bool bold) { if (bold) return QFont::Bold; else return QFont::Normal; } inline bool isOctalDigit(const QChar &c) { static const QLatin1Char k0('0'); static const QLatin1Char k7('7'); return c >= k0 && c <= k7; } inline bool isHexDigit(const QChar &c) { static const QLatin1Char k0('0'); static const QLatin1Char k9('9'); static const QLatin1Char kA('A'); static const QLatin1Char kF('F'); static const QLatin1Char ka('a'); static const QLatin1Char kf('f'); if ((c >= k0 && c <= k9) || (c >= kA && c <= kF) || (c >= ka && c <= kf)) return true; return false; } inline void setStartCharacter(QChar *c, const QString &character) { if (!character.isEmpty()) *c = character.at(0); } } // namespace Internal } // namespace TextEditor #endif // REUSE_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/rule.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "rule.h" #include "highlighterexception.h" #include "progressdata.h" #include "highlightdefinition.h" #include "reuse.h" #include #include using namespace TextEditor; using namespace Internal; const QLatin1Char Rule::kBackSlash('\\'); const QLatin1Char Rule::kUnderscore('_'); const QLatin1Char Rule::kDot('.'); const QLatin1Char Rule::kPlus('+'); const QLatin1Char Rule::kMinus('-'); const QLatin1Char Rule::kZero('0'); const QLatin1Char Rule::kQuote('\"'); const QLatin1Char Rule::kSingleQuote('\''); const QLatin1Char Rule::kQuestion('?'); const QLatin1Char Rule::kX('x'); const QLatin1Char Rule::kA('a'); const QLatin1Char Rule::kB('b'); const QLatin1Char Rule::kE('e'); const QLatin1Char Rule::kF('f'); const QLatin1Char Rule::kN('n'); const QLatin1Char Rule::kR('r'); const QLatin1Char Rule::kT('t'); const QLatin1Char Rule::kV('v'); const QLatin1Char Rule::kOpeningBrace('{'); const QLatin1Char Rule::kClosingBrace('}'); Rule::Rule(bool consumesNonSpace) : m_lookAhead(false), m_firstNonSpace(false), m_column(-1), m_consumesNonSpace(consumesNonSpace) {} Rule::~Rule() {} void Rule::setContext(const QString &context) { m_context = context; } const QString &Rule::context() const { return m_context; } void Rule::setItemData(const QString &itemData) { m_itemData = itemData; } const QString &Rule::itemData() const { return m_itemData; } void Rule::setBeginRegion(const QString &begin) { m_beginRegion = begin; } const QString &Rule::beginRegion() const { return m_beginRegion; } void Rule::setEndRegion(const QString &end) { m_endRegion = end; } const QString &Rule::endRegion() const { return m_endRegion; } void Rule::setLookAhead(const QString &lookAhead) { m_lookAhead = toBool(lookAhead); } bool Rule::isLookAhead() const { return m_lookAhead; } void Rule::setFirstNonSpace(const QString &firstNonSpace) { m_firstNonSpace = toBool(firstNonSpace); } bool Rule::isFirstNonSpace() const { return m_firstNonSpace; } void Rule::setColumn(const QString &column) { bool ok; m_column = column.toInt(&ok); if (!ok) m_column = -1; } int Rule::column() const { return m_column; } void Rule::addChild(const QSharedPointer &rule) { m_children.append(rule); } bool Rule::hasChildren() const { return !m_children.isEmpty(); } const QList > &Rule::children() const { return m_children; } void Rule::setDefinition(const QSharedPointer &definition) { m_definition = definition; } const QSharedPointer &Rule::definition() const { return m_definition; } template bool Rule::predicateMatchSucceed(const QString &text, const int length, ProgressData *progress, const predicate_t &p) const { int original = progress->offset(); while (progress->offset() < length && p(text.at(progress->offset()))) progress->incrementOffset(); if (original != progress->offset()) return true; return false; } bool Rule::charPredicateMatchSucceed(const QString &text, const int length, ProgressData *progress, bool (QChar::* predicate)() const) const { return predicateMatchSucceed(text, length, progress, std::mem_fun_ref(predicate)); } bool Rule::charPredicateMatchSucceed(const QString &text, const int length, ProgressData *progress, bool (*predicate)(const QChar &)) const { return predicateMatchSucceed(text, length, progress, std::ptr_fun(predicate)); } bool Rule::matchSucceed(const QString &text, const int length, ProgressData *progress) { if (m_firstNonSpace && !progress->isOnlySpacesSoFar()) return false; if (m_column != -1 && m_column != progress->offset()) return false; int original = progress->offset(); if (doMatchSucceed(text, length, progress)) { if (progress->isOnlySpacesSoFar() && !m_lookAhead && m_consumesNonSpace) progress->setOnlySpacesSoFar(false); if (m_lookAhead) progress->setOffset(original); return true; } return false; } Rule *Rule::clone() const { return doClone(); } void Rule::progressFinished() { doProgressFinished(); } bool Rule::matchCharacter(const QString &text, const int length, ProgressData *progress, const QChar &c, bool saveRestoreOffset) const { Q_UNUSED(length) Q_ASSERT(progress->offset() < length); if (text.at(progress->offset()) == c) { if (saveRestoreOffset) progress->saveOffset(); progress->incrementOffset(); return true; } return false; } bool Rule::matchEscapeSequence(const QString &text, const int length, ProgressData *progress, bool saveRestoreOffset) const { if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) { if (progress->offset() < length) { const QChar &c = text.at(progress->offset()); if (c == kA || c == kB || c == kE || c == kF || c == kN || c == kR || c == kT || c == kV || c == kQuestion || c == kSingleQuote || c == kQuote || c == kBackSlash) { progress->incrementOffset(); return true; } else if (saveRestoreOffset) { progress->restoreOffset(); } } else if (saveRestoreOffset) { progress->restoreOffset(); } } return false; } bool Rule::matchOctalSequence(const QString &text, const int length, ProgressData *progress, bool saveRestoreOffset) const { // An octal sequence is identified as in the C++ Standard. // octal-escape-sequence: // \ octal-digit // \ octal-digit octal-digit // \ octal-digit octal-digit octal-digit if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) { int count = 0; while (progress->offset() < length && count < 3 && isOctalDigit(text.at(progress->offset()))) { ++count; progress->incrementOffset(); } if (count > 0) return true; else if (saveRestoreOffset) progress->restoreOffset(); } return false; } bool Rule::matchHexSequence(const QString &text, const int length, ProgressData *progress, bool saveRestoreOffset) const { // An hex sequence is identified as in the C++ Standard. // hexadecimal-escape-sequence: // \x hexadecimal-digit // hexadecimal-escape-sequence hexadecimal-digit if (matchCharacter(text, length, progress, kBackSlash, saveRestoreOffset)) { if (progress->offset() < length && matchCharacter(text, length, progress, kX, false)) { bool found = false; while (progress->offset() < length && isHexDigit(text.at(progress->offset()))) { if (!found) found = true; progress->incrementOffset(); } if (found) return true; else if (saveRestoreOffset) progress->restoreOffset(); } else if (saveRestoreOffset) { progress->restoreOffset(); } } return false; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/rule.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef RULE_H #define RULE_H #include #include #include namespace TextEditor { namespace Internal { class ProgressData; class HighlightDefinition; class Rule { public: Rule(bool consumesNonSpace = true); virtual ~Rule(); void setContext(const QString &context); const QString &context() const; void setItemData(const QString &itemData); const QString &itemData() const; void setBeginRegion(const QString &begin); const QString &beginRegion() const; void setEndRegion(const QString &end); const QString &endRegion() const; void setLookAhead(const QString &lookAhead); bool isLookAhead() const; void setFirstNonSpace(const QString &firstNonSpace); bool isFirstNonSpace() const; void setColumn(const QString &column); int column() const; void addChild(const QSharedPointer &rule); const QList > &children() const; bool hasChildren() const; void setDefinition(const QSharedPointer &definition); const QSharedPointer &definition() const; bool matchSucceed(const QString &text, const int length, ProgressData *progress); Rule *clone() const; void progressFinished(); protected: bool charPredicateMatchSucceed(const QString &text, const int length, ProgressData *progress, bool (QChar::* predicate)() const) const; bool charPredicateMatchSucceed(const QString &text, const int length, ProgressData *progress, bool (*predicate)(const QChar &)) const; bool matchCharacter(const QString &text, const int length, ProgressData *progress, const QChar &c, bool saveRestoreOffset = true) const; bool matchEscapeSequence(const QString &text, const int length, ProgressData *progress, bool saveRestoreOffset = true) const; bool matchOctalSequence(const QString &text, const int length, ProgressData *progress, bool saveRestoreOffset = true) const; bool matchHexSequence(const QString &text, const int length, ProgressData *progress, bool saveRestoreOffset = true) const; static const QLatin1Char kBackSlash; static const QLatin1Char kUnderscore; static const QLatin1Char kDot; static const QLatin1Char kPlus; static const QLatin1Char kMinus; static const QLatin1Char kZero; static const QLatin1Char kQuote; static const QLatin1Char kSingleQuote; static const QLatin1Char kQuestion; static const QLatin1Char kX; static const QLatin1Char kA; static const QLatin1Char kB; static const QLatin1Char kE; static const QLatin1Char kF; static const QLatin1Char kN; static const QLatin1Char kR; static const QLatin1Char kT; static const QLatin1Char kV; static const QLatin1Char kOpeningBrace; static const QLatin1Char kClosingBrace; private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress) = 0; virtual Rule *doClone() const = 0; virtual void doProgressFinished() {} template bool predicateMatchSucceed(const QString &text, const int length, ProgressData *progress, const predicate_t &p) const; QString m_context; QString m_itemData; QString m_beginRegion; QString m_endRegion; bool m_lookAhead; bool m_firstNonSpace; int m_column; bool m_consumesNonSpace; QList > m_children; // Rules are represented within contexts. However, they have their own definition because // of externally included rules. QSharedPointer m_definition; }; } // namespace Internal } // namespace TextEditor #endif // RULE_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/specificrules.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "specificrules.h" #include "highlightdefinition.h" #include "keywordlist.h" #include "progressdata.h" #include "reuse.h" #include #include using namespace TextEditor; using namespace Internal; namespace { void replaceByCaptures(QChar *c, const QStringList &captures) { int index = c->digitValue(); if (index > 0) { const QString &capture = captures.at(index); if (!capture.isEmpty()) *c = capture.at(0); } } void replaceByCaptures(QString *s, const QStringList &captures) { static const QLatin1Char kPercent('%'); int index; int from = 0; while ((index = s->indexOf(kPercent, from)) != -1) { from = index + 1; QString accumulator; while (from < s->length() && s->at(from).isDigit()) { accumulator.append(s->at(from)); ++from; } bool ok; int number = accumulator.toInt(&ok); Q_ASSERT(ok); s->replace(index, accumulator.length() + 1, captures.at(number)); } } } // DetectChar void DetectCharRule::setChar(const QString &character) { setStartCharacter(&m_char, character); } void DetectCharRule::doReplaceExpressions(const QStringList &captures) { replaceByCaptures(&m_char, captures); } bool DetectCharRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (matchCharacter(text, length, progress, m_char)) { return true; } return false; // if (matchCharacter(text, length, progress, m_char)) { // return true; // // This is to make code folding have a control flow style look in the case of braces. // // Naturally, this assumes that language definitions use braces with this meaning. // if (m_char == kOpeningBrace && progress->isOnlySpacesSoFar() && !isLookAhead()) { // progress->setOpeningBraceMatchAtFirstNonSpace(true); // } else if (m_char == kClosingBrace && // !text.right(length - progress->offset()).trimmed().isEmpty()) { // progress->setClosingBraceMatchAtNonEnd(true); // } // return true; // } // return false; // if (matchCharacter(text, length, progress, m_char)) { // qDebug() << m_char << text; // if (text.trimmed() == "} else {" && m_char == '}') { // //qDebug() << "error"; // progress->setClosingBraceMatchAtNonEnd(true); // } // return true; // // This is to make code folding have a control flow style look in the case of braces. // // Naturally, this assumes that language definitions use braces with this meaning. // if ( (m_char == '{' || m_char == '(' || m_char == '[') // && progress->isOnlySpacesSoFar() && !isLookAhead()) { // progress->setOpeningBraceMatchAtFirstNonSpace(true); // } else if ( (m_char == '}' || m_char == ')' || m_char == ']') && // !text.right(length - progress->offset()).trimmed().isEmpty()) { // progress->setClosingBraceMatchAtNonEnd(true); // } // if (m_char == kOpeningBrace && progress->isOnlySpacesSoFar() && !isLookAhead()) { // progress->setOpeningBraceMatchAtFirstNonSpace(true); // } else if (m_char == kClosingBrace && // !text.right(length - progress->offset()).trimmed().isEmpty()) { // progress->setClosingBraceMatchAtNonEnd(true); // } // return true; // } // return false; } // Detect2Chars void Detect2CharsRule::setChar(const QString &character) { setStartCharacter(&m_char, character); } void Detect2CharsRule::setChar1(const QString &character) { setStartCharacter(&m_char1, character); } void Detect2CharsRule::doReplaceExpressions(const QStringList &captures) { replaceByCaptures(&m_char, captures); replaceByCaptures(&m_char1, captures); } bool Detect2CharsRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (matchCharacter(text, length, progress, m_char)) { if (progress->offset() < length && matchCharacter(text, length, progress, m_char1, false)) return true; else progress->restoreOffset(); } return false; } // AnyChar void AnyCharRule::setCharacterSet(const QString &s) { m_characterSet = s; } bool AnyCharRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { Q_UNUSED(length) if (m_characterSet.contains(text.at(progress->offset()))) { progress->incrementOffset(); return true; } return false; } // StringDetect void StringDetectRule::setString(const QString &s) { m_string = s; m_length = m_string.length(); } void StringDetectRule::setInsensitive(const QString &insensitive) { m_caseSensitivity = toCaseSensitivity(!toBool(insensitive)); } void StringDetectRule::doReplaceExpressions(const QStringList &captures) { replaceByCaptures(&m_string, captures); m_length = m_string.length(); } bool StringDetectRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (length - progress->offset() >= m_length) { QString candidate = text.fromRawData(text.unicode() + progress->offset(), m_length); if (candidate.compare(m_string, m_caseSensitivity) == 0) { progress->incrementOffset(m_length); return true; } } return false; } // RegExpr void RegExprRule::setPattern(const QString &pattern) { if (pattern.startsWith(QLatin1Char('^'))) m_onlyBegin = true; m_expression.setPattern(pattern); } void RegExprRule::setInsensitive(const QString &insensitive) { m_expression.setCaseSensitivity(toCaseSensitivity(!toBool(insensitive))); } void RegExprRule::setMinimal(const QString &minimal) { m_expression.setMinimal(toBool(minimal)); } void RegExprRule::doReplaceExpressions(const QStringList &captures) { QString s = m_expression.pattern(); replaceByCaptures(&s, captures); m_expression.setPattern(s); } void RegExprRule::doProgressFinished() { m_isCached = false; } bool RegExprRule::isExactMatch(ProgressData *progress) { if (progress->offset() == m_offset && m_length > 0) { progress->incrementOffset(m_length); progress->setCaptures(m_captures); return true; } return false; } bool RegExprRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { Q_UNUSED(length) // A regular expression match is considered valid if it happens at the current position // and if the match length is not zero. const int offset = progress->offset(); if (offset > 0 && m_onlyBegin) return false; if (m_isCached) { if (offset < m_offset || m_offset == -1 || m_length == 0) return false; if (isExactMatch(progress)) return true; } m_offset = m_expression.indexIn(text, offset, QRegExp::CaretAtOffset); m_length = m_expression.matchedLength(); m_captures = m_expression.capturedTexts(); if (isExactMatch(progress)) return true; m_isCached = true; progress->trackRule(this); return false; } // Keyword KeywordRule::KeywordRule(const QSharedPointer &definition) : m_overrideGlobal(false), m_localCaseSensitivity(Qt::CaseSensitive) { setDefinition(definition); } KeywordRule::~KeywordRule() {} void KeywordRule::setInsensitive(const QString &insensitive) { if (!insensitive.isEmpty()) { m_overrideGlobal = true; m_localCaseSensitivity = toCaseSensitivity(!toBool(insensitive)); } } void KeywordRule::setList(const QString &listName) { m_list = definition()->keywordList(listName); } bool KeywordRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { int current = progress->offset(); if (current > 0 && !definition()->isDelimiter(text.at(current - 1))) return false; if (definition()->isDelimiter(text.at(current))) return false; while (current < length && !definition()->isDelimiter(text.at(current))) ++current; QString candidate = QString::fromRawData(text.unicode() + progress->offset(), current - progress->offset()); if ((m_overrideGlobal && m_list->isKeyword(candidate, m_localCaseSensitivity)) || (!m_overrideGlobal && m_list->isKeyword(candidate, definition()->keywordsSensitive()))) { progress->setOffset(current); return true; } return false; } // Int bool IntRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { const int offset = progress->offset(); // This is necessary to correctly highlight an invalid octal like 09, for example. if (offset > 0 && text.at(offset - 1).isDigit()) return false; if (text.at(offset).isDigit() && text.at(offset) != kZero) { progress->incrementOffset(); charPredicateMatchSucceed(text, length, progress, &QChar::isDigit); return true; } return false; } // Float bool FloatRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { progress->saveOffset(); bool integralPart = charPredicateMatchSucceed(text, length, progress, &QChar::isDigit); bool decimalPoint = false; if (progress->offset() < length && text.at(progress->offset()) == kDot) { progress->incrementOffset(); decimalPoint = true; } bool fractionalPart = charPredicateMatchSucceed(text, length, progress, &QChar::isDigit); bool exponentialPart = false; int offset = progress->offset(); if (offset < length && (text.at(offset) == kE || text.at(offset).toLower() == kE)) { progress->incrementOffset(); offset = progress->offset(); if (offset < length && (text.at(offset) == kPlus || text.at(offset) == kMinus)) progress->incrementOffset(); if (charPredicateMatchSucceed(text, length, progress, &QChar::isDigit)) { exponentialPart = true; } else { progress->restoreOffset(); return false; } } if ((integralPart || fractionalPart) && (decimalPoint || exponentialPart)) return true; progress->restoreOffset(); return false; } // COctal bool HlCOctRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (matchCharacter(text, length, progress, kZero)) { // In the definition files the number matching rules which are more restrictive should // appear before the rules which are least resctritive. Although this happens in general // there is at least one case where this is not strictly followed for existent definition // files (specifically, HlCHex comes before HlCOct). So the condition below. const int offset = progress->offset(); if (offset < length && (text.at(offset) == kX || text.at(offset).toLower() == kX)) { progress->restoreOffset(); return false; } charPredicateMatchSucceed(text, length, progress, &isOctalDigit); return true; } return false; } // CHex bool HlCHexRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (matchCharacter(text, length, progress, kZero)) { const int offset = progress->offset(); if (offset < length && text.at(offset) != kX && text.at(offset).toLower() != kX) { progress->restoreOffset(); return false; } progress->incrementOffset(); if (charPredicateMatchSucceed(text, length, progress, &isHexDigit)) return true; else progress->restoreOffset(); } return false; } // CString bool HlCStringCharRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (matchEscapeSequence(text, length, progress)) return true; if (matchOctalSequence(text, length, progress)) return true; if (matchHexSequence(text, length, progress)) return true; return false; } // CChar bool HlCCharRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (matchCharacter(text, length, progress, kSingleQuote)) { if (progress->offset() < length) { if (text.at(progress->offset()) != kBackSlash && text.at(progress->offset()) != kSingleQuote) { progress->incrementOffset(); } else if (!matchEscapeSequence(text, length, progress, false)) { progress->restoreOffset(); return false; } if (progress->offset() < length && matchCharacter(text, length, progress, kSingleQuote, false)) { return true; } else { progress->restoreOffset(); } } else { progress->restoreOffset(); } } return false; } // RangeDetect void RangeDetectRule::setChar(const QString &character) { setStartCharacter(&m_char, character); } void RangeDetectRule::setChar1(const QString &character) { setStartCharacter(&m_char1, character); } bool RangeDetectRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (matchCharacter(text, length, progress, m_char)) { while (progress->offset() < length) { if (matchCharacter(text, length, progress, m_char1, false)) return true; progress->incrementOffset(); } progress->restoreOffset(); } return false; } // LineContinue bool LineContinueRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { if (progress->offset() != length - 1) return false; if (text.at(progress->offset()) == kBackSlash) { progress->incrementOffset(); progress->setWillContinueLine(true); return true; } return false; } // DetectSpaces DetectSpacesRule::DetectSpacesRule() : Rule(false) {} bool DetectSpacesRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { return charPredicateMatchSucceed(text, length, progress, &QChar::isSpace); } // DetectIdentifier bool DetectIdentifierRule::doMatchSucceed(const QString &text, const int length, ProgressData *progress) { // Identifiers are characterized by a letter or underscore as the first character and then // zero or more word characters (\w*). if (text.at(progress->offset()).isLetter() || text.at(progress->offset()) == kUnderscore) { progress->incrementOffset(); while (progress->offset() < length) { const QChar ¤t = text.at(progress->offset()); if (current.isLetterOrNumber() || current.isMark() || current == kUnderscore) progress->incrementOffset(); else break; } return true; } return false; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/generichighlighter/specificrules.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef SPECIFICRULES_H #define SPECIFICRULES_H #include "rule.h" #include "dynamicrule.h" #include #include #include #include namespace TextEditor { namespace Internal { class KeywordList; class HighlightDefinition; class DetectCharRule : public DynamicRule { public: virtual ~DetectCharRule() {} void setChar(const QString &character); private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual DetectCharRule *doClone() const { return new DetectCharRule(*this); } virtual void doReplaceExpressions(const QStringList &captures); QChar m_char; }; class Detect2CharsRule : public DynamicRule { public: virtual ~Detect2CharsRule() {} void setChar(const QString &character); void setChar1(const QString &character); private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual Detect2CharsRule *doClone() const { return new Detect2CharsRule(*this); } virtual void doReplaceExpressions(const QStringList &captures); QChar m_char; QChar m_char1; }; class AnyCharRule : public Rule { public: virtual ~AnyCharRule() {} void setCharacterSet(const QString &s); private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual AnyCharRule *doClone() const { return new AnyCharRule(*this); } QString m_characterSet; }; class StringDetectRule : public DynamicRule { public: virtual ~StringDetectRule() {} void setString(const QString &s); void setInsensitive(const QString &insensitive); private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual StringDetectRule *doClone() const { return new StringDetectRule(*this); } virtual void doReplaceExpressions(const QStringList &captures); QString m_string; int m_length; Qt::CaseSensitivity m_caseSensitivity; }; class RegExprRule : public DynamicRule { public: RegExprRule() : m_onlyBegin(false), m_isCached(false) {} virtual ~RegExprRule() {} void setPattern(const QString &pattern); void setInsensitive(const QString &insensitive); void setMinimal(const QString &minimal); private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual RegExprRule *doClone() const { return new RegExprRule(*this); } virtual void doReplaceExpressions(const QStringList &captures); virtual void doProgressFinished(); bool isExactMatch(ProgressData *progress); bool m_onlyBegin; bool m_isCached; int m_offset; int m_length; QStringList m_captures; QRegExp m_expression; }; class KeywordRule : public Rule { public: KeywordRule(const QSharedPointer &definition); virtual ~KeywordRule(); void setInsensitive(const QString &insensitive); void setList(const QString &listName); private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual KeywordRule *doClone() const { return new KeywordRule(*this); } bool m_overrideGlobal; Qt::CaseSensitivity m_localCaseSensitivity; QSharedPointer m_list; }; class IntRule : public Rule { public: virtual ~IntRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual IntRule *doClone() const { return new IntRule(*this); } }; class FloatRule : public Rule { public: virtual ~FloatRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual FloatRule *doClone() const { return new FloatRule(*this); } }; class HlCOctRule : public Rule { public: virtual ~HlCOctRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual HlCOctRule *doClone() const { return new HlCOctRule(*this); } }; class HlCHexRule : public Rule { public: virtual ~HlCHexRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual HlCHexRule *doClone() const { return new HlCHexRule(*this); } }; class HlCStringCharRule : public Rule { public: virtual ~HlCStringCharRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual HlCStringCharRule *doClone() const { return new HlCStringCharRule(*this); } }; class HlCCharRule : public Rule { public: virtual ~HlCCharRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual HlCCharRule *doClone() const { return new HlCCharRule(*this); } }; class RangeDetectRule : public Rule { public: virtual ~RangeDetectRule() {} void setChar(const QString &character); void setChar1(const QString &character); private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual RangeDetectRule *doClone() const { return new RangeDetectRule(*this); } QChar m_char; QChar m_char1; }; class LineContinueRule : public Rule { public: virtual ~LineContinueRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual LineContinueRule *doClone() const { return new LineContinueRule(*this); } }; class DetectSpacesRule : public Rule { public: DetectSpacesRule(); virtual ~DetectSpacesRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual DetectSpacesRule *doClone() const { return new DetectSpacesRule(*this); } }; class DetectIdentifierRule : public Rule { public: virtual ~DetectIdentifierRule() {} private: virtual bool doMatchSucceed(const QString &text, const int length, ProgressData *progress); virtual DetectIdentifierRule *doClone() const { return new DetectIdentifierRule(*this); } }; } // namespace Internal } // namespace TextEditor #endif // SPECIFICRULES_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/itexteditor.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "itexteditor.h" //#include #include #include using namespace TextEditor; void ITextMark::paint(QPainter *painter, const QRect &rect) const { m_icon.paint(painter, rect, Qt::AlignCenter); } int ITextMark::blockNumber() const { return m_blockNumber; } void ITextMark::updateBlockNumber(int lineNumber) { m_blockNumber = lineNumber; } void ITextMark::updateBlock(const QTextBlock &) {} void ITextMark::removedFromEditor() {} void ITextMark::documentClosing() {} void ITextMark::setIcon(const QIcon &icon) { m_icon = icon; } int ITextMark::type() const { return m_type; } int ITextMark::indexOfType() const { return m_indexOfType; } double ITextMark::widthFactor() const { return 1.0; } QTextBlock ITextMark::block() const { return QTextBlock(); } QMap ITextEditor::openedTextEditorsContents() { QMap workingCopy; // foreach (Core::IEditor *editor, Core::EditorManager::instance()->openedEditors()) { // ITextEditor *textEditor = qobject_cast(editor); // if (!textEditor) // continue; // QString fileName = textEditor->file()->fileName(); // workingCopy[fileName] = textEditor->contents(); // } return workingCopy; } QMap TextEditor::ITextEditor::openedTextEditorsEncodings() { QMap workingCopy; // foreach (Core::IEditor *editor, Core::EditorManager::instance()->openedEditors()) { // ITextEditor *textEditor = qobject_cast(editor); // if (!textEditor) // continue; // QString fileName = textEditor->file()->fileName(); // workingCopy[fileName] = textEditor->textCodec(); // } return workingCopy; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/itexteditor.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef ITEXTEDITOR_H #define ITEXTEDITOR_H #include "texteditor_global.h" #include "liteeditorapi/liteeditorapi.h" //#include #include #include #include #include QT_BEGIN_NAMESPACE class QIcon; class QMenu; class QPainter; class QPoint; class QRect; class QTextBlock; QT_END_NAMESPACE namespace TextEditor { class ITextEditor; class TEXTEDITOR_EXPORT ITextMark : public LiteApi::IEditorMarkNode { Q_OBJECT public: ITextMark(QObject *parent = 0) : LiteApi::IEditorMarkNode(parent), m_blockNumber(-1), m_type(-1), m_indexOfType(0) {} virtual ~ITextMark() {} // determine order on markers on the same line. virtual void paint(QPainter *painter, const QRect &rect) const; virtual int blockNumber() const; virtual void updateBlockNumber(int blockNumber); virtual void updateBlock(const QTextBlock &block); virtual void removedFromEditor(); virtual void documentClosing(); virtual void setIcon(const QIcon &icon); virtual int type() const; virtual int indexOfType() const; virtual double widthFactor() const; virtual QTextBlock block() const; protected: QIcon m_icon; int m_blockNumber; int m_type; int m_indexOfType; }; typedef QList TextMarks; class TEXTEDITOR_EXPORT ITextMarkable : public QObject { Q_OBJECT public: ITextMarkable(QObject *parent = 0) : QObject(parent) {} virtual ~ITextMarkable() {} virtual bool addMark(ITextMark *mark, int line) = 0; virtual TextMarks marksAt(int line) const = 0; virtual void removeMark(ITextMark *mark) = 0; virtual bool hasMark(ITextMark *mark) const = 0; virtual void updateMark(ITextMark *mark) = 0; }; class TEXTEDITOR_EXPORT ITextEditor : public QObject//Core::IEditor { Q_OBJECT public: enum PositionOperation { Current = 1, EndOfLine = 2, StartOfLine = 3, Anchor = 4, EndOfDoc = 5 }; ITextEditor() {} virtual ~ITextEditor() {} virtual int find(const QString &string) const = 0; virtual int position(PositionOperation posOp = Current, int at = -1) const = 0; virtual void convertPosition(int pos, int *line, int *column) const = 0; virtual QRect cursorRect(int pos = -1) const = 0; virtual int columnCount() const = 0; virtual int rowCount() const = 0; virtual QString contents() const = 0; virtual QString selectedText() const = 0; virtual QString textAt(int pos, int length) const = 0; virtual QChar characterAt(int pos) const = 0; /*! Removes \a length characters to the right of the cursor. */ virtual void remove(int length) = 0; /*! Inserts the given string to the right of the cursor. */ virtual void insert(const QString &string) = 0; /*! Replaces \a length characters to the right of the cursor with the given string. */ virtual void replace(int length, const QString &string) = 0; /*! Sets current cursor position to \a pos. */ virtual void setCursorPosition(int pos) = 0; /*! Selects text between current cursor position and \a toPos. */ virtual void select(int toPos) = 0; virtual ITextMarkable *markableInterface() = 0; virtual void setContextHelpId(const QString &) = 0; enum TextCodecReason { TextCodecOtherReason, TextCodecFromSystemSetting, TextCodecFromProjectSetting }; virtual void setTextCodec(QTextCodec *, TextCodecReason reason = TextCodecOtherReason) = 0; virtual QTextCodec *textCodec() const = 0; static QMap openedTextEditorsContents(); static QMap openedTextEditorsEncodings(); signals: void contentsChanged(); void contentsChangedBecauseOfUndo(); void markRequested(TextEditor::ITextEditor *editor, int line); void markContextMenuRequested(TextEditor::ITextEditor *editor, int line, QMenu *menu); void tooltipOverrideRequested(TextEditor::ITextEditor *editor, const QPoint &globalPos, int position, bool *handled); void tooltipRequested(TextEditor::ITextEditor *editor, const QPoint &globalPos, int position); void contextHelpIdRequested(TextEditor::ITextEditor *editor, int position); }; } // namespace TextEditor #endif // ITEXTEDITOR_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/katehighlighter.cpp ================================================ #include "katehighlighter.h" #include "generichighlighter/highlighter.h" #include "generichighlighter/highlightdefinition.h" #include "generichighlighter/highlightdefinitionhandler.h" #include "generichighlighter/highlighterexception.h" #include "generichighlighter/highlightdefinitionmetadata.h" #include "generichighlighter/manager2.h" #include "texteditorconstants.h" #include #include #include #include "colorstyle/colorstyle.h" using namespace TextEditor::Internal; using namespace TextEditor::Constants; using namespace TextEditor; KateHighlighter::KateHighlighter(QObject *parent) : QObject(parent) { } void KateHighlighter::loadPath(const QString &definitionsPaths) { Manager2::instance()->loadPath(QStringList(definitionsPaths)); } QStringList KateHighlighter::mimeTypes() const { return Manager2::instance()->mimeTypes(); } QString KateHighlighter::mimeTypeName(const QString &mimeType) const { QString id = Manager2::instance()->definitionIdByMimeType(mimeType); QSharedPointer data = Manager2::instance()->definitionMetaData(id); if (data) { return data->name(); } return QString(); } QStringList KateHighlighter::mimeTypePatterns(const QString &mimeType) const { QString id = Manager2::instance()->definitionIdByMimeType(mimeType); QSharedPointer data = Manager2::instance()->definitionMetaData(id); if (data) { return data->patterns(); } return QStringList(); } TextEditor::SyntaxHighlighter *KateHighlighter::create(QTextDocument *doc, const QString &mimeType) { Highlighter *h = new Highlighter(doc); //reset(h); QString id = Manager2::instance()->definitionIdByMimeType(mimeType); QSharedPointer def = Manager2::instance()->definition(id); if (def) { SyntaxComment comment; comment.singleLineComment = def->singleLineComment(); comment.multiLineCommentStart = def->multiLineCommentStart(); comment.multiLineCommentEnd = def->multiLineCommentEnd(); comment.isCommentAfterWhiteSpaces = def->isCommentAfterWhiteSpaces(); if (comment.isCommentAfterWhiteSpaces) { comment.isCommentAfterWhiteSpacesAddSpace = true; } h->setupComment(comment); h->setDefaultContext(def->initialContext()); } return h; } ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/katehighlighter.h ================================================ #ifndef KATEHIGHLIGHTER_H #define KATEHIGHLIGHTER_H #include "texteditor_global.h" #include #include #include #include #include "syntaxhighlighter.h" #include "colorscheme.h" class ColorStyleScheme; class TEXTEDITOR_EXPORT KateHighlighter : public QObject { Q_OBJECT public: explicit KateHighlighter(QObject *parent = 0); public: void loadPath(const QString &definitionsPaths); QStringList mimeTypes() const; QStringList mimeTypePatterns(const QString &mimeType) const; QString mimeTypeName(const QString &mimeType) const; TextEditor::SyntaxHighlighter *create(QTextDocument *doc, const QString &mimeType); QTextCharFormat toTextCharFormat(const QString &name); }; #endif // KATEHIGHLIGHTER_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/qtc_texteditor.pri ================================================ LIBS *= -l$$qtLibraryName(qtctexteditor) ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/qtc_texteditor.pro ================================================ TARGET = qtctexteditor TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) include(../../utils/colorstyle/colorstyle.pri) DEFINES += TEXTEDITOR_LIBRARY INCLUDEPATH += . HEADERS += \ texteditor_global.h \ tabsettings.h \ syntaxhighlighter.h \ itexteditor.h \ basetextdocumentlayout.h \ generichighlighter/specificrules.h \ generichighlighter/rule.h \ generichighlighter/reuse.h \ generichighlighter/progressdata.h \ generichighlighter/keywordlist.h \ generichighlighter/itemdata.h \ generichighlighter/includerulesinstruction.h \ generichighlighter/highlighterexception.h \ generichighlighter/highlighter.h \ generichighlighter/highlightdefinitionmetadata.h \ generichighlighter/highlightdefinitionhandler.h \ generichighlighter/highlightdefinition.h \ generichighlighter/dynamicrule.h \ generichighlighter/context.h \ katehighlighter.h \ generichighlighter/manager2.h \ colorscheme.h \ autocompleter.h \ basetextblockselection.h SOURCES += \ tabsettings.cpp \ syntaxhighlighter.cpp \ itexteditor.cpp \ basetextdocumentlayout.cpp \ generichighlighter/specificrules.cpp \ generichighlighter/rule.cpp \ generichighlighter/progressdata.cpp \ generichighlighter/keywordlist.cpp \ generichighlighter/itemdata.cpp \ generichighlighter/includerulesinstruction.cpp \ generichighlighter/highlighter.cpp \ generichighlighter/highlightdefinitionmetadata.cpp \ generichighlighter/highlightdefinitionhandler.cpp \ generichighlighter/highlightdefinition.cpp \ generichighlighter/dynamicrule.cpp \ generichighlighter/context.cpp \ katehighlighter.cpp \ generichighlighter/manager2.cpp \ colorscheme.cpp \ autocompleter.cpp \ basetextblockselection.cpp ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/syntaxhighlighter.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "syntaxhighlighter.h" #include "basetextdocumentlayout.h" #include #include #include #include #include #include #include #include using namespace TextEditor; class TextEditor::SyntaxHighlighterPrivate { SyntaxHighlighter *q_ptr; Q_DECLARE_PUBLIC(SyntaxHighlighter) public: inline SyntaxHighlighterPrivate() : q_ptr(0), rehighlightPending(false), inReformatBlocks(false) {} QPointer doc; void _q_reformatBlocks(int from, int charsRemoved, int charsAdded); void reformatBlocks(int from, int charsRemoved, int charsAdded); void reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded); inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) { inReformatBlocks = true; cursor.beginEditBlock(); int from = cursor.position(); cursor.movePosition(operation); reformatBlocks(from, 0, cursor.position() - from); cursor.endEditBlock(); inReformatBlocks = false; } inline void _q_delayedRehighlight() { if (!rehighlightPending) return; rehighlightPending = false; q_func()->rehighlight(); } void applyFormatChanges(int from, int charsRemoved, int charsAdded); QVector formatChanges; QTextBlock currentBlock; QList tokens; SyntaxComment comment; bool rehighlightPending; bool inReformatBlocks; }; static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsRemoved, int charsAdded) { if (range.start >= from) { range.start += charsAdded - charsRemoved; return true; } else if (range.start + range.length > from) { range.length += charsAdded - charsRemoved; return true; } return false; } void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, int charsAdded) { bool formatsChanged = false; QTextLayout *layout = currentBlock.layout(); QList ranges = layout->additionalFormats(); bool doAdjustRange = currentBlock.contains(from); QList old_ranges; if (!ranges.isEmpty()) { QList::Iterator it = ranges.begin(); while (it != ranges.end()) { if (it->format.property(QTextFormat::UserProperty).toBool()) { if (doAdjustRange) formatsChanged = adjustRange(*it, from - currentBlock.position(), charsRemoved, charsAdded) || formatsChanged; ++it; } else { old_ranges.append(*it); it = ranges.erase(it); } } } QTextCharFormat emptyFormat; QTextLayout::FormatRange r; r.start = -1; QList new_ranges; int i = 0; while (i < formatChanges.count()) { while (i < formatChanges.count() && formatChanges.at(i) == emptyFormat) ++i; if (i >= formatChanges.count()) break; r.start = i; r.format = formatChanges.at(i); while (i < formatChanges.count() && formatChanges.at(i) == r.format) ++i; if (i >= formatChanges.count()) break; r.length = i - r.start; new_ranges << r; r.start = -1; } if (r.start != -1) { r.length = formatChanges.count() - r.start; new_ranges << r; } formatsChanged = formatsChanged || (new_ranges.size() != old_ranges.size()); for (int i = 0; !formatsChanged && i < new_ranges.size(); ++i) { const QTextLayout::FormatRange &o = old_ranges.at(i); const QTextLayout::FormatRange &n = new_ranges.at(i); formatsChanged = (o.start != n.start || o.length != n.length || o.format != n.format); } if (formatsChanged) { ranges.append(new_ranges); layout->setAdditionalFormats(ranges); doc->markContentsDirty(currentBlock.position(), currentBlock.length()); } } void SyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, int charsAdded) { if (!inReformatBlocks) reformatBlocks(from, charsRemoved, charsAdded); } void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded) { rehighlightPending = false; QTextBlock block = doc->findBlock(from); if (!block.isValid()) return; int endPosition; QTextBlock lastBlock = doc->findBlock(from + charsAdded + (charsRemoved > 0 ? 1 : 0)); if (lastBlock.isValid()) endPosition = lastBlock.position() + lastBlock.length(); else endPosition = doc->lastBlock().position() + doc->lastBlock().length(); //doc->docHandle()->length(); bool forceHighlightOfNextBlock = false; while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) { const int stateBeforeHighlight = block.userState(); reformatBlock(block, from, charsRemoved, charsAdded); forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight); block = block.next(); } formatChanges.clear(); } void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded) { Q_Q(SyntaxHighlighter); Q_ASSERT_X(!currentBlock.isValid(), "SyntaxHighlighter::reformatBlock()", "reFormatBlock() called recursively"); currentBlock = block; tokens.clear(); formatChanges.fill(QTextCharFormat(), block.length() - 1); q->highlightBlock(block.text()); BaseTextDocumentLayout::userData(block)->setTokens(tokens); BaseTextDocumentLayout::setLexerState(block,q->currentBlockState()); applyFormatChanges(from, charsRemoved, charsAdded); currentBlock = QTextBlock(); } const SyntaxHighlighter::KateFormatMap SyntaxHighlighter::m_kateFormats; SyntaxHighlighter::KateFormatMap::KateFormatMap() { m_ids.insert(QLatin1String("dsNormal"), SyntaxHighlighter::Normal); m_ids.insert(QLatin1String("dsKeyword"), SyntaxHighlighter::Keyword); m_ids.insert(QLatin1String("dsDataType"), SyntaxHighlighter::DataType); m_ids.insert(QLatin1String("dsDecVal"), SyntaxHighlighter::Decimal); m_ids.insert(QLatin1String("dsBaseN"), SyntaxHighlighter::BaseN); m_ids.insert(QLatin1String("dsFloat"), SyntaxHighlighter::Float); m_ids.insert(QLatin1String("dsChar"), SyntaxHighlighter::Char); m_ids.insert(QLatin1String("dsString"), SyntaxHighlighter::String); m_ids.insert(QLatin1String("dsComment"), SyntaxHighlighter::Comment); m_ids.insert(QLatin1String("dsOthers"), SyntaxHighlighter::Others); m_ids.insert(QLatin1String("dsAlert"), SyntaxHighlighter::Alert); m_ids.insert(QLatin1String("dsFunction"), SyntaxHighlighter::Function); m_ids.insert(QLatin1String("dsRegionMarker"), SyntaxHighlighter::RegionMarker); m_ids.insert(QLatin1String("dsError"), SyntaxHighlighter::Error); m_ids.insert(QLatin1String("dsSymbol"),SyntaxHighlighter::Symbol); m_ids.insert(QLatin1String("dsBuiltinFunc"), SyntaxHighlighter::BuiltinFunc); m_ids.insert(QLatin1String("dsPredeclared"), SyntaxHighlighter::Predeclared); m_ids.insert(QLatin1String("dsFuncDecl"), SyntaxHighlighter::FuncDecl); m_ids.insert(QLatin1String("dsPlaceholder"), SyntaxHighlighter::Placeholder); m_ids.insert(QLatin1String("dsToDo"), SyntaxHighlighter::ToDo); m_ids.insert(QLatin1String("dsPreprocessorFormat"),SyntaxHighlighter::PreprocessorFormat); } void SyntaxHighlighter::configureFormat(TextFormatId id, const QTextCharFormat &format) { m_creatorFormats[id] = format; } void SyntaxHighlighter::setTabSize(int /*tabSize*/) { } SyntaxComment SyntaxHighlighter::comment() const { Q_D(const SyntaxHighlighter); return d->comment; } void SyntaxHighlighter::setupComment(const SyntaxComment &comment) { Q_D(SyntaxHighlighter); d->comment = comment; } /*! \class SyntaxHighlighter \reentrant \brief The SyntaxHighlighter class allows you to define syntax highlighting rules, and in addition you can use the class to query a document's current formatting or user data. \since 4.1 \ingroup richtext-processing The SyntaxHighlighter class is a base class for implementing QTextEdit syntax highlighters. A syntax highligher automatically highlights parts of the text in a QTextEdit, or more generally in a QTextDocument. Syntax highlighters are often used when the user is entering text in a specific format (for example source code) and help the user to read the text and identify syntax errors. To provide your own syntax highlighting, you must subclass SyntaxHighlighter and reimplement highlightBlock(). When you create an instance of your SyntaxHighlighter subclass, pass it the QTextEdit or QTextDocument that you want the syntax highlighting to be applied to. For example: \snippet doc/src/snippets/code/src_gui_text_SyntaxHighlighter.cpp 0 After this your highlightBlock() function will be called automatically whenever necessary. Use your highlightBlock() function to apply formatting (e.g. setting the font and color) to the text that is passed to it. SyntaxHighlighter provides the setFormat() function which applies a given QTextCharFormat on the current text block. For example: \snippet doc/src/snippets/code/src_gui_text_SyntaxHighlighter.cpp 1 Some syntaxes can have constructs that span several text blocks. For example, a C++ syntax highlighter should be able to cope with \c{/}\c{*...*}\c{/} multiline comments. To deal with these cases it is necessary to know the end state of the previous text block (e.g. "in comment"). Inside your highlightBlock() implementation you can query the end state of the previous text block using the previousBlockState() function. After parsing the block you can save the last state using setCurrentBlockState(). The currentBlockState() and previousBlockState() functions return an int value. If no state is set, the returned value is -1. You can designate any other value to identify any given state using the setCurrentBlockState() function. Once the state is set the QTextBlock keeps that value until it is set set again or until the corresponding paragraph of text is deleted. For example, if you're writing a simple C++ syntax highlighter, you might designate 1 to signify "in comment": \snippet doc/src/snippets/code/src_gui_text_SyntaxHighlighter.cpp 2 In the example above, we first set the current block state to 0. Then, if the previous block ended within a comment, we higlight from the beginning of the current block (\c {startIndex = 0}). Otherwise, we search for the given start expression. If the specified end expression cannot be found in the text block, we change the current block state by calling setCurrentBlockState(), and make sure that the rest of the block is higlighted. In addition you can query the current formatting and user data using the format() and currentBlockUserData() functions respectively. You can also attach user data to the current text block using the setCurrentBlockUserData() function. QTextBlockUserData can be used to store custom settings. In the case of syntax highlighting, it is in particular interesting as cache storage for information that you may figure out while parsing the paragraph's text. For an example, see the setCurrentBlockUserData() documentation. \sa QTextEdit, {Syntax Highlighter Example} */ /*! Constructs a SyntaxHighlighter with the given \a parent. */ SyntaxHighlighter::SyntaxHighlighter(QObject *parent) : QObject(parent), d_ptr(new SyntaxHighlighterPrivate) { d_ptr->q_ptr = this; } /*! Constructs a SyntaxHighlighter and installs it on \a parent. The specified QTextDocument also becomes the owner of the SyntaxHighlighter. */ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) : QObject(parent), d_ptr(new SyntaxHighlighterPrivate) { d_ptr->q_ptr = this; setDocument(parent); } /*! Constructs a SyntaxHighlighter and installs it on \a parent 's QTextDocument. The specified QTextEdit also becomes the owner of the SyntaxHighlighter. */ SyntaxHighlighter::SyntaxHighlighter(QTextEdit *parent) : QObject(parent), d_ptr(new SyntaxHighlighterPrivate) { d_ptr->q_ptr = this; setDocument(parent->document()); } /*! Destructor. Uninstalls this syntax highlighter from the text document. */ SyntaxHighlighter::~SyntaxHighlighter() { setDocument(0); } /*! Installs the syntax highlighter on the given QTextDocument \a doc. A SyntaxHighlighter can only be used with one document at a time. */ void SyntaxHighlighter::setDocument(QTextDocument *doc) { Q_D(SyntaxHighlighter); if (d->doc) { disconnect(d->doc, SIGNAL(contentsChange(int,int,int)), this, SLOT(_q_reformatBlocks(int,int,int))); QTextCursor cursor(d->doc); cursor.beginEditBlock(); for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next()) blk.layout()->clearAdditionalFormats(); cursor.endEditBlock(); } d->doc = doc; if (d->doc) { connect(d->doc, SIGNAL(contentsChange(int,int,int)), this, SLOT(_q_reformatBlocks(int,int,int))); d->rehighlightPending = true; QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight())); } } /*! Returns the QTextDocument on which this syntax highlighter is installed. */ QTextDocument *SyntaxHighlighter::document() const { Q_D(const SyntaxHighlighter); return d->doc; } /*! \since 4.2 Reapplies the highlighting to the whole document. \sa rehighlightBlock() */ void SyntaxHighlighter::rehighlight() { Q_D(SyntaxHighlighter); if (!d->doc) return; QTextCursor cursor(d->doc); d->rehighlight(cursor, QTextCursor::End); } /*! \since 4.6 Reapplies the highlighting to the given QTextBlock \a block. \sa rehighlight() */ void SyntaxHighlighter::rehighlightBlock(const QTextBlock &block) { Q_D(SyntaxHighlighter); if (!d->doc || !block.isValid() || block.document() != d->doc) return; const bool rehighlightPending = d->rehighlightPending; QTextCursor cursor(block); d->rehighlight(cursor, QTextCursor::EndOfBlock); if (rehighlightPending) d->rehighlightPending = rehighlightPending; } /*! \fn void SyntaxHighlighter::highlightBlock(const QString &text) Highlights the given text block. This function is called when necessary by the rich text engine, i.e. on text blocks which have changed. To provide your own syntax highlighting, you must subclass SyntaxHighlighter and reimplement highlightBlock(). In your reimplementation you should parse the block's \a text and call setFormat() as often as necessary to apply any font and color changes that you require. For example: \snippet doc/src/snippets/code/src_gui_text_SyntaxHighlighter.cpp 3 Some syntaxes can have constructs that span several text blocks. For example, a C++ syntax highlighter should be able to cope with \c{/}\c{*...*}\c{/} multiline comments. To deal with these cases it is necessary to know the end state of the previous text block (e.g. "in comment"). Inside your highlightBlock() implementation you can query the end state of the previous text block using the previousBlockState() function. After parsing the block you can save the last state using setCurrentBlockState(). The currentBlockState() and previousBlockState() functions return an int value. If no state is set, the returned value is -1. You can designate any other value to identify any given state using the setCurrentBlockState() function. Once the state is set the QTextBlock keeps that value until it is set set again or until the corresponding paragraph of text gets deleted. For example, if you're writing a simple C++ syntax highlighter, you might designate 1 to signify "in comment". For a text block that ended in the middle of a comment you'd set 1 using setCurrentBlockState, and for other paragraphs you'd set 0. In your parsing code if the return value of previousBlockState() is 1, you would highlight the text as a C++ comment until you reached the closing \c{*}\c{/}. \sa previousBlockState(), setFormat(), setCurrentBlockState() */ /*! This function is applied to the syntax highlighter's current text block (i.e. the text that is passed to the highlightBlock() function). The specified \a format is applied to the text from the \a start position for a length of \a count characters (if \a count is 0, nothing is done). The formatting properties set in \a format are merged at display time with the formatting information stored directly in the document, for example as previously set with QTextCursor's functions. Note that the document itself remains unmodified by the format set through this function. \sa format(), highlightBlock() */ void SyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format, int id) { Q_D(SyntaxHighlighter); if (start < 0 || start >= d->formatChanges.count()) return; const int end = qMin(start + count, d->formatChanges.count()); for (int i = start; i < end; ++i) d->formatChanges[i] = format; if (id >= Normal) { int offset = start; int count = end-start; if (!d->tokens.empty()) { SyntaxToken &last = d->tokens.last(); if ((last.id == id) && (last.offset+last.count == offset)) { last.count += count; return; } } SyntaxToken token; token.offset = offset; token.count = count; token.id = id; d->tokens.append(token); } } /*! \overload The specified \a color is applied to the current text block from the \a start position for a length of \a count characters. The other attributes of the current text block, e.g. the font and background color, are reset to default values. \sa format(), highlightBlock() */ //void SyntaxHighlighter::setFormat(int start, int count, const QColor &color) //{ // QTextCharFormat format; // format.setForeground(color); // setFormat(start, count, format); //} /*! \overload The specified \a font is applied to the current text block from the \a start position for a length of \a count characters. The other attributes of the current text block, e.g. the font and background color, are reset to default values. \sa format(), highlightBlock() */ //void SyntaxHighlighter::setFormat(int start, int count, const QFont &font) //{ // QTextCharFormat format; // format.setFont(font); // setFormat(start, count, format); //} void SyntaxHighlighter::applyFormatToSpaces(const QString &text, const QTextCharFormat &format) { int offset = 0; const int length = text.length(); while (offset < length) { if (text.at(offset).isSpace()) { int start = offset++; while (offset < length && text.at(offset).isSpace()) ++offset; setFormat(start, offset - start, format); } else { ++offset; } } } /*! \fn QTextCharFormat SyntaxHighlighter::format(int position) const Returns the format at \a position inside the syntax highlighter's current text block. */ QTextCharFormat SyntaxHighlighter::format(int pos) const { Q_D(const SyntaxHighlighter); if (pos < 0 || pos >= d->formatChanges.count()) return QTextCharFormat(); return d->formatChanges.at(pos); } /*! Returns the end state of the text block previous to the syntax highlighter's current block. If no value was previously set, the returned value is -1. \sa highlightBlock(), setCurrentBlockState() */ int SyntaxHighlighter::previousBlockState() const { Q_D(const SyntaxHighlighter); if (!d->currentBlock.isValid()) return -1; const QTextBlock previous = d->currentBlock.previous(); if (!previous.isValid()) return -1; return previous.userState(); } /*! Returns the state of the current text block. If no value is set, the returned value is -1. */ int SyntaxHighlighter::currentBlockState() const { Q_D(const SyntaxHighlighter); if (!d->currentBlock.isValid()) return -1; return d->currentBlock.userState(); } /*! Sets the state of the current text block to \a newState. \sa highlightBlock() */ void SyntaxHighlighter::setCurrentBlockState(int newState) { Q_D(SyntaxHighlighter); if (!d->currentBlock.isValid()) return; d->currentBlock.setUserState(newState); } /*! Attaches the given \a data to the current text block. The ownership is passed to the underlying text document, i.e. the provided QTextBlockUserData object will be deleted if the corresponding text block gets deleted. QTextBlockUserData can be used to store custom settings. In the case of syntax highlighting, it is in particular interesting as cache storage for information that you may figure out while parsing the paragraph's text. For example while parsing the text, you can keep track of parenthesis characters that you encounter ('{[(' and the like), and store their relative position and the actual QChar in a simple class derived from QTextBlockUserData: \snippet doc/src/snippets/code/src_gui_text_SyntaxHighlighter.cpp 4 During cursor navigation in the associated editor, you can ask the current QTextBlock (retrieved using the QTextCursor::block() function) if it has a user data object set and cast it to your \c BlockData object. Then you can check if the current cursor position matches with a previously recorded parenthesis position, and, depending on the type of parenthesis (opening or closing), find the next opening or closing parenthesis on the same level. In this way you can do a visual parenthesis matching and highlight from the current cursor position to the matching parenthesis. That makes it easier to spot a missing parenthesis in your code and to find where a corresponding opening/closing parenthesis is when editing parenthesis intensive code. \sa QTextBlock::setUserData() */ void SyntaxHighlighter::setCurrentBlockUserData(QTextBlockUserData *data) { Q_D(SyntaxHighlighter); if (!d->currentBlock.isValid()) return; d->currentBlock.setUserData(data); } /*! Returns the QTextBlockUserData object previously attached to the current text block. \sa QTextBlock::userData(), setCurrentBlockUserData() */ QTextBlockUserData *SyntaxHighlighter::currentBlockUserData() const { Q_D(const SyntaxHighlighter); if (!d->currentBlock.isValid()) return 0; return d->currentBlock.userData(); } /*! \since 4.4 Returns the current text block. */ QTextBlock SyntaxHighlighter::currentBlock() const { Q_D(const SyntaxHighlighter); return d->currentBlock; } static bool byStartOfRange(const QTextLayout::FormatRange &range, const QTextLayout::FormatRange &other) { return range.start < other.start; } void SyntaxHighlighter::setExtraAdditionalFormats(const QTextBlock& block, const QList &fmts) { // qDebug() << "setAdditionalFormats() on block" << block.blockNumber(); // for (int i = 0; i < overrides.count(); ++i) // qDebug() << " from " << overrides.at(i).start << "length" // << overrides.at(i).length // << "color:" << overrides.at(i).format.foreground().color(); Q_D(SyntaxHighlighter); if (block.layout() == 0) return; QList formats; formats.reserve(fmts.size()); foreach (QTextLayout::FormatRange r, fmts) { r.format.setProperty(QTextFormat::UserProperty, true); formats.append(r); } qSort(formats.begin(), formats.end(), byStartOfRange); QList previousSemanticFormats; QList formatsToApply; const QList all = block.layout()->additionalFormats(); foreach (const QTextLayout::FormatRange &r, all) { if (r.format.hasProperty(QTextFormat::UserProperty)) previousSemanticFormats.append(r); else formatsToApply.append(r); } if (formats.size() == previousSemanticFormats.size()) { qSort(previousSemanticFormats.begin(), previousSemanticFormats.end(), byStartOfRange); int index = 0; for (; index != formats.size(); ++index) { const QTextLayout::FormatRange &range = formats.at(index); const QTextLayout::FormatRange &previousRange = previousSemanticFormats.at(index); if (range.start != previousRange.start || range.length != previousRange.length || range.format != previousRange.format) break; } if (index == formats.size()) return; } formatsToApply += formats; bool wasInReformatBlocks = d->inReformatBlocks; d->inReformatBlocks = true; block.layout()->setAdditionalFormats(formatsToApply); document()->markContentsDirty(block.position(), block.length()-1); d->inReformatBlocks = wasInReformatBlocks; } #include "moc_syntaxhighlighter.cpp" ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/syntaxhighlighter.h ================================================ /**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TEXTEDITOR_SYNTAXHIGHLIGHTER_H #define TEXTEDITOR_SYNTAXHIGHLIGHTER_H #include "texteditor_global.h" #include #include QT_BEGIN_NAMESPACE class QTextDocument; class QSyntaxHighlighterPrivate; class QTextCharFormat; class QFont; class QColor; class QTextBlockUserData; class QTextEdit; QT_END_NAMESPACE namespace TextEditor { class SyntaxHighlighterPrivate; struct SyntaxComment { SyntaxComment() : isCommentAfterWhiteSpaces(true), isCommentAfterWhiteSpacesAddSpace (true) {} bool isEmpty() const { return singleLineComment.isEmpty() && multiLineCommentStart.isEmpty() && multiLineCommentEnd.isEmpty(); } QString singleLineComment; QString multiLineCommentStart; QString multiLineCommentEnd; bool isCommentAfterWhiteSpaces; bool isCommentAfterWhiteSpacesAddSpace; }; class TEXTEDITOR_EXPORT SyntaxHighlighter : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(SyntaxHighlighter) public: enum TextFormatId { Normal = 1, VisualWhitespace, Keyword, DataType, Decimal, BaseN, Float, Char, String, Comment, Alert, Error, Function, RegionMarker, Others, Symbol, BuiltinFunc, Predeclared, FuncDecl, Placeholder, ToDo, PreprocessorFormat, TextFormatId_MAX }; public: SyntaxHighlighter(QObject *parent); SyntaxHighlighter(QTextDocument *parent); SyntaxHighlighter(QTextEdit *parent); virtual ~SyntaxHighlighter(); void setDocument(QTextDocument *doc); QTextDocument *document() const; void setContextData(const QString &id, const QString &value) { m_contextMap[id] = value; } QString contextData(const QString &id) { return m_contextMap[id]; } void setExtraAdditionalFormats(const QTextBlock& block, const QList &formats); void configureFormat(TextFormatId id, const QTextCharFormat &format); virtual void setTabSize(int tabSize); public: SyntaxComment comment() const; void setupComment(const SyntaxComment &comment); signals: void foldIndentChanged(QTextBlock block); public Q_SLOTS: void rehighlight(); void rehighlightBlock(const QTextBlock &block); protected: virtual void highlightBlock(const QString &text) = 0; void setFormat(int start, int count, const QTextCharFormat &format, int id = 0); //void setFormat(int start, int count, const QColor &color); //void setFormat(int start, int count, const QFont &font); QTextCharFormat format(int pos) const; void applyFormatToSpaces(const QString &text, const QTextCharFormat &format); int previousBlockState() const; int currentBlockState() const; void setCurrentBlockState(int newState); void setCurrentBlockUserData(QTextBlockUserData *data); QTextBlockUserData *currentBlockUserData() const; QTextBlock currentBlock() const; QMap m_contextMap; protected: struct KateFormatMap { KateFormatMap(); QHash m_ids; }; static const KateFormatMap m_kateFormats; QTextCharFormat m_creatorFormats[TextFormatId_MAX]; private: Q_DISABLE_COPY(SyntaxHighlighter) Q_PRIVATE_SLOT(d_ptr, void _q_reformatBlocks(int from, int charsRemoved, int charsAdded)) Q_PRIVATE_SLOT(d_ptr, void _q_delayedRehighlight()) QScopedPointer d_ptr; }; } // namespace TextEditor #endif // TEXTEDITOR_SYNTAXHIGHLIGHTER_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/tabsettings.cpp ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "tabsettings.h" #include #include #include #include #include #include static const char *spacesForTabsKey = "SpacesForTabs"; static const char *autoSpacesForTabsKey = "AutoSpacesForTabs"; static const char *smartBackspaceKey = "SmartBackspace"; static const char *autoIndentKey = "AutoIndent"; static const char *tabSizeKey = "TabSize"; static const char *indentSizeKey = "IndentSize"; static const char *indentBracesKey = "IndentBraces"; static const char *doubleIndentBlocksKey = "DoubleIndentBlocks"; static const char *tabKeyBehaviorKey = "TabKeyBehavior"; static const char *groupPostfix = "TabSettings"; static const char *paddingModeKey = "PaddingMode"; namespace TextEditor { TabSettings::TabSettings() : m_spacesForTabs(true), m_autoSpacesForTabs(false), m_autoIndent(true), m_smartBackspace(false), m_tabSize(4), m_indentSize(4), m_indentBraces(false), m_doubleIndentBlocks(false), m_tabKeyBehavior(TabNeverIndents), m_continuationAlignBehavior(ContinuationAlignWithSpaces) { } void TabSettings::toSettings(const QString &category, QSettings *s) const { Utils::toSettings(QLatin1String(groupPostfix), category, s, this); } void TabSettings::fromSettings(const QString &category, const QSettings *s) { *this = TabSettings(); // Assign defaults Utils::fromSettings(QLatin1String(groupPostfix), category, s, this); } void TabSettings::toMap(const QString &prefix, QVariantMap *map) const { map->insert(prefix + QLatin1String(spacesForTabsKey), m_spacesForTabs); map->insert(prefix + QLatin1String(autoSpacesForTabsKey), m_autoSpacesForTabs); map->insert(prefix + QLatin1String(autoIndentKey), m_autoIndent); map->insert(prefix + QLatin1String(smartBackspaceKey), m_smartBackspace); map->insert(prefix + QLatin1String(tabSizeKey), m_tabSize); map->insert(prefix + QLatin1String(indentSizeKey), m_indentSize); map->insert(prefix + QLatin1String(indentBracesKey), m_indentBraces); map->insert(prefix + QLatin1String(doubleIndentBlocksKey), m_doubleIndentBlocks); map->insert(prefix + QLatin1String(tabKeyBehaviorKey), m_tabKeyBehavior); map->insert(prefix + QLatin1String(paddingModeKey), m_continuationAlignBehavior); } void TabSettings::fromMap(const QString &prefix, const QVariantMap &map) { m_spacesForTabs = map.value(prefix + QLatin1String(spacesForTabsKey), m_spacesForTabs).toBool(); m_autoSpacesForTabs = map.value(prefix + QLatin1String(autoSpacesForTabsKey), m_autoSpacesForTabs).toBool(); m_autoIndent = map.value(prefix + QLatin1String(autoIndentKey), m_autoIndent).toBool(); m_smartBackspace = map.value(prefix + QLatin1String(smartBackspaceKey), m_smartBackspace).toBool(); m_tabSize = map.value(prefix + QLatin1String(tabSizeKey), m_tabSize).toInt(); m_indentSize = map.value(prefix + QLatin1String(indentSizeKey), m_indentSize).toInt(); m_indentBraces = map.value(prefix + QLatin1String(indentBracesKey), m_indentBraces).toBool(); m_doubleIndentBlocks = map.value(prefix + QLatin1String(doubleIndentBlocksKey), m_doubleIndentBlocks).toBool(); m_tabKeyBehavior = (TabKeyBehavior) map.value(prefix + QLatin1String(tabKeyBehaviorKey), m_tabKeyBehavior).toInt(); m_continuationAlignBehavior = (ContinuationAlignBehavior) map.value(prefix + QLatin1String(paddingModeKey), m_continuationAlignBehavior).toInt(); } bool TabSettings::cursorIsAtBeginningOfLine(const QTextCursor &cursor) const { QString text = cursor.block().text(); int fns = firstNonSpace(text); return (cursor.position() - cursor.block().position() <= fns); } int TabSettings::lineIndentPosition(const QString &text) const { int i = 0; while (i < text.size()) { if (!text.at(i).isSpace()) break; ++i; } int column = columnAt(text, i); return i - (column % m_indentSize); } int TabSettings::firstNonSpace(const QString &text) const { int i = 0; while (i < text.size()) { if (!text.at(i).isSpace()) return i; ++i; } return i; } QString TabSettings::indentationString(const QString &text) const { return text.left(firstNonSpace(text)); } int TabSettings::indentationColumn(const QString &text) const { return columnAt(text, firstNonSpace(text)); } int TabSettings::maximumPadding(const QString &text) const { int fns = firstNonSpace(text); int i = fns; while (i > 0) { if (text.at(i-1) != QLatin1Char(' ')) break; --i; } return fns - i; } int TabSettings::trailingWhitespaces(const QString &text) const { int i = 0; while (i < text.size()) { if (!text.at(text.size()-1-i).isSpace()) return i; ++i; } return i; } bool TabSettings::isIndentationClean(const QTextBlock &block) const { int i = 0; int spaceCount = 0; QString text = block.text(); bool spacesForTabs = guessSpacesForTabs(block); while (i < text.size()) { QChar c = text.at(i); if (!c.isSpace()) return true; if (c == QLatin1Char(' ')) { ++spaceCount; if (!spacesForTabs && spaceCount == m_tabSize) return false; } else if (c == QLatin1Char('\t')) { if (spacesForTabs || spaceCount != m_indentSize) return false; spaceCount = 0; } ++i; } return true; } bool TabSettings::tabShouldIndent(const QTextDocument *document, QTextCursor cursor, int *suggestedPosition) const { if (m_tabKeyBehavior == TabNeverIndents) return false; QTextCursor tc = cursor; if (suggestedPosition) *suggestedPosition = tc.position(); // At least suggest original position tc.movePosition(QTextCursor::StartOfLine); if (tc.atBlockEnd()) // cursor was on a blank line return true; if (document->characterAt(tc.position()).isSpace()) { tc.movePosition(QTextCursor::WordRight); if (tc.positionInBlock() >= cursor.positionInBlock()) { if (suggestedPosition) *suggestedPosition = tc.position(); // Suggest position after whitespace if (m_tabKeyBehavior == TabLeadingWhitespaceIndents) return true; } } return (m_tabKeyBehavior == TabAlwaysIndents); } int TabSettings::columnAt(const QString &text, int position) const { int column = 0; for (int i = 0; i < position; ++i) { if (text.at(i) == QLatin1Char('\t')) column = column - (column % m_tabSize) + m_tabSize; else ++column; } return column; } int TabSettings::positionAtColumn(const QString &text, int column, int *offset) const { int col = 0; int i = 0; while (i < text.size() && col < column) { if (text.at(i) == QLatin1Char('\t')) col = col - (col % m_tabSize) + m_tabSize; else ++col; ++i; } if (offset) *offset = column - col; return i; } int TabSettings::spacesLeftFromPosition(const QString &text, int position) const { int i = position; while (i > 0) { if (!text.at(i-1).isSpace()) break; --i; } return position - i; } int TabSettings::indentedColumn(int column, bool doIndent) const { int aligned = (column / m_indentSize) * m_indentSize; if (doIndent) return aligned + m_indentSize; if (aligned < column) return aligned; return qMax(0, aligned - m_indentSize); } bool TabSettings::guessSpacesForTabs(const QTextBlock &_block) const { if (m_spacesForTabs && m_autoSpacesForTabs && _block.isValid()) { const QTextDocument *doc = _block.document(); QVector currentBlocks(2, _block); // [0] looks back; [1] looks forward int maxLookAround = 100; while (maxLookAround-- > 0) { if (currentBlocks.at(0).isValid()) currentBlocks[0] = currentBlocks.at(0).previous(); if (currentBlocks.at(1).isValid()) currentBlocks[1] = currentBlocks.at(1).next(); bool done = true; foreach (const QTextBlock &block, currentBlocks) { if (block.isValid()) done = false; if (!block.isValid() || block.length() == 0) continue; const QChar firstChar = doc->characterAt(block.position()); if (firstChar == QLatin1Char(' ')) { return true; } else if (firstChar == QLatin1Char('\t')) { return false; } } if (done) break; } } return m_spacesForTabs; } QString TabSettings::indentationString(int startColumn, int targetColumn, const QTextBlock &block) const { targetColumn = qMax(startColumn, targetColumn); if (guessSpacesForTabs(block)) return QString(targetColumn - startColumn, QLatin1Char(' ')); QString s; int alignedStart = startColumn - (startColumn % m_tabSize) + m_tabSize; if (alignedStart > startColumn && alignedStart <= targetColumn) { s += QLatin1Char('\t'); startColumn = alignedStart; } if (int columns = targetColumn - startColumn) { int tabs = columns / m_tabSize; s += QString(tabs, QLatin1Char('\t')); s += QString(columns - tabs * m_tabSize, QLatin1Char(' ')); } return s; } void TabSettings::indentLine(QTextBlock block, int newIndent, int padding) const { const QString text = block.text(); const int oldBlockLength = text.size(); if (m_continuationAlignBehavior == NoContinuationAlign) { newIndent -= padding; padding = 0; } else if (m_continuationAlignBehavior == ContinuationAlignWithIndent) { padding = 0; } // Quickly check whether indenting is required. if (indentationColumn(text) == newIndent) return; QString indentString; if (!m_spacesForTabs) { // user likes tabs for spaces and uses tabs for indentation, preserve padding indentString = indentationString(0, newIndent - padding, block); indentString += QString(padding, QLatin1Char(' ')); } else { indentString = indentationString(0, newIndent, block); } if (oldBlockLength == indentString.length() && text == indentString) return; QTextCursor cursor(block); cursor.beginEditBlock(); cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace(text)); cursor.removeSelectedText(); cursor.insertText(indentString); cursor.endEditBlock(); } void TabSettings::reindentLine(QTextBlock block, int delta) const { const QString text = block.text(); const int oldBlockLength = text.size(); int oldIndent = indentationColumn(text); int newIndent = qMax(oldIndent + delta, 0); if (oldIndent == newIndent) return; QString indentString; if (!m_spacesForTabs && m_tabSize == m_indentSize) { // user likes tabs for spaces and uses tabs for indentation, preserve padding int padding = qMin(maximumPadding(text), newIndent); indentString = indentationString(0, newIndent - padding, block); indentString += QString(padding, QLatin1Char(' ')); } else { indentString = indentationString(0, newIndent, block); } if (oldBlockLength == indentString.length() && text == indentString) return; QTextCursor cursor(block); cursor.beginEditBlock(); cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace(text)); cursor.removeSelectedText(); cursor.insertText(indentString); cursor.endEditBlock(); } bool TabSettings::equals(const TabSettings &ts) const { return m_spacesForTabs == ts.m_spacesForTabs && m_autoSpacesForTabs == ts.m_autoSpacesForTabs && m_autoIndent == ts.m_autoIndent && m_smartBackspace == ts.m_smartBackspace && m_tabSize == ts.m_tabSize && m_indentSize == ts.m_indentSize && m_indentBraces == ts.m_indentBraces && m_doubleIndentBlocks == ts.m_doubleIndentBlocks && m_tabKeyBehavior == ts.m_tabKeyBehavior && m_continuationAlignBehavior == ts.m_continuationAlignBehavior; } } // namespace TextEditor ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/tabsettings.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef TABSETTINGS_H #define TABSETTINGS_H #include "texteditor_global.h" #include #include QT_BEGIN_NAMESPACE class QSettings; QT_END_NAMESPACE namespace TextEditor { // Tab settings: Data type the GeneralSettingsPage acts on // with some convenience functions for formatting. class TEXTEDITOR_EXPORT TabSettings { public: // This enum must match the indexes of tabKeyBehavior widget enum TabKeyBehavior { TabNeverIndents = 0, TabAlwaysIndents = 1, TabLeadingWhitespaceIndents = 2 }; // This enum must match the indexes of continuationAlignBehavior widget enum ContinuationAlignBehavior { NoContinuationAlign = 0, ContinuationAlignWithSpaces = 1, ContinuationAlignWithIndent = 2 }; TabSettings(); void toSettings(const QString &category, QSettings *s) const; void fromSettings(const QString &category, const QSettings *s); void toMap(const QString &prefix, QVariantMap *map) const; void fromMap(const QString &prefix, const QVariantMap &map); int lineIndentPosition(const QString &text) const; int firstNonSpace(const QString &text) const; inline bool onlySpace(const QString &text) const { return firstNonSpace(text) == text.length(); } int columnAt(const QString &text, int position) const; int positionAtColumn(const QString &text, int column, int *offset = 0) const; int spacesLeftFromPosition(const QString &text, int position) const; int indentedColumn(int column, bool doIndent = true) const; QString indentationString(int startColumn, int targetColumn, const QTextBlock ¤tBlock = QTextBlock()) const; QString indentationString(const QString &text) const; int indentationColumn(const QString &text) const; int maximumPadding(const QString &text) const; bool cursorIsAtBeginningOfLine(const QTextCursor &cursor) const; void indentLine(QTextBlock block, int newIndent, int padding = 0) const; void reindentLine(QTextBlock block, int delta) const; int trailingWhitespaces(const QString &text) const; bool isIndentationClean(const QTextBlock &block) const; bool tabShouldIndent(const QTextDocument *document, QTextCursor cursor, int *suggestedPosition = 0) const; bool guessSpacesForTabs(const QTextBlock &block) const; bool m_spacesForTabs; bool m_autoSpacesForTabs; bool m_autoIndent; bool m_smartBackspace; int m_tabSize; int m_indentSize; bool m_indentBraces; bool m_doubleIndentBlocks; TabKeyBehavior m_tabKeyBehavior; ContinuationAlignBehavior m_continuationAlignBehavior; bool equals(const TabSettings &ts) const; }; inline bool operator==(const TabSettings &t1, const TabSettings &t2) { return t1.equals(t2); } inline bool operator!=(const TabSettings &t1, const TabSettings &t2) { return !t1.equals(t2); } } // namespace TextEditor #endif // TABSETTINGS_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/texteditor_global.h ================================================ #ifndef TEXTEDITOR_GLOBAL_H #define TEXTEDITOR_GLOBAL_H #include #define TEXTEDITOR_EXPORT /* #if defined(TEXTEDITOR_LIBRARY) # define TEXTEDITOR_EXPORT Q_DECL_EXPORT #else # define TEXTEDITOR_EXPORT Q_DECL_IMPORT #endif */ #endif // TEXTEDITOR_GLOBAL_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/texteditorconstants.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef TEXTEDITORCONSTANTS_H #define TEXTEDITORCONSTANTS_H #include namespace TextEditor { namespace Constants { const char * const C_TEXTEDITOR = "Text Editor"; const char * const COMPLETE_THIS = "TextEditor.CompleteThis"; const char * const QUICKFIX_THIS = "TextEditor.QuickFix"; const char * const VISUALIZE_WHITESPACE = "TextEditor.VisualizeWhitespace"; const char * const CLEAN_WHITESPACE = "TextEditor.CleanWhitespace"; const char * const TEXT_WRAPPING = "TextEditor.TextWrapping"; const char * const UN_COMMENT_SELECTION = "TextEditor.UnCommentSelection"; const char * const REFORMAT = "TextEditor.Reformat"; const char * const FOLD = "TextEditor.Fold"; const char * const UNFOLD = "TextEditor.Unfold"; const char * const UNFOLD_ALL = "TextEditor.UnFoldAll"; const char * const AUTO_INDENT_SELECTION = "TextEditor.AutoIndentSelection"; const char * const INCREASE_FONT_SIZE = "TextEditor.IncreaseFontSize"; const char * const DECREASE_FONT_SIZE = "TextEditor.DecreaseFontSize"; const char * const RESET_FONT_SIZE = "TextEditor.ResetFontSize"; const char * const GOTO_BLOCK_START = "TextEditor.GotoBlockStart"; const char * const GOTO_BLOCK_START_WITH_SELECTION = "TextEditor.GotoBlockStartWithSelection"; const char * const GOTO_BLOCK_END = "TextEditor.GotoBlockEnd"; const char * const GOTO_BLOCK_END_WITH_SELECTION = "TextEditor.GotoBlockEndWithSelection"; const char * const SELECT_BLOCK_UP = "TextEditor.SelectBlockUp"; const char * const SELECT_BLOCK_DOWN = "TextEditor.SelectBlockDown"; const char * const MOVE_LINE_UP = "TextEditor.MoveLineUp"; const char * const MOVE_LINE_DOWN = "TextEditor.MoveLineDown"; const char * const COPY_LINE_UP = "TextEditor.CopyLineUp"; const char * const COPY_LINE_DOWN = "TextEditor.CopyLineDown"; const char * const JOIN_LINES = "TextEditor.JoinLines"; const char * const INSERT_LINE_ABOVE = "TextEditor.InsertLineAboveCurrentLine"; const char * const INSERT_LINE_BELOW = "TextEditor.InsertLineBelowCurrentLine"; const char * const UPPERCASE_SELECTION = "TextEditor.UppercaseSelection"; const char * const LOWERCASE_SELECTION = "TextEditor.LowercaseSelection"; const char * const CUT_LINE = "TextEditor.CutLine"; const char * const COPY_LINE = "TextEditor.CopyLine"; const char * const DELETE_LINE = "TextEditor.DeleteLine"; const char * const DELETE_WORD = "TextEditor.DeleteWord"; const char * const SELECT_ENCODING = "TextEditor.SelectEncoding"; const char * const REWRAP_PARAGRAPH = "TextEditor.RewrapParagraph"; const char * const GOTO_OPENING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis"; const char * const GOTO_CLOSING_PARENTHESIS = "TextEditor.GotoClosingParenthesis"; const char * const GOTO_LINE_START = "TextEditor.GotoLineStart"; const char * const GOTO_LINE_END = "TextEditor.GotoLineEnd"; const char * const GOTO_NEXT_LINE = "TextEditor.GotoNextLine"; const char * const GOTO_PREVIOUS_LINE = "TextEditor.GotoPreviousLine"; const char * const GOTO_PREVIOUS_CHARACTER = "TextEditor.GotoPreviousCharacter"; const char * const GOTO_NEXT_CHARACTER = "TextEditor.GotoNextCharacter"; const char * const GOTO_PREVIOUS_WORD = "TextEditor.GotoPreviousWord"; const char * const GOTO_NEXT_WORD = "TextEditor.GotoNextWord"; const char * const GOTO_PREVIOUS_WORD_CAMEL_CASE = "TextEditor.GotoPreviousWordCamelCase"; const char * const GOTO_NEXT_WORD_CAMEL_CASE = "TextEditor.GotoNextWordCamelCase"; const char * const GOTO_LINE_START_WITH_SELECTION = "TextEditor.GotoLineStartWithSelection"; const char * const GOTO_LINE_END_WITH_SELECTION = "TextEditor.GotoLineEndWithSelection"; const char * const GOTO_NEXT_LINE_WITH_SELECTION = "TextEditor.GotoNextLineWithSelection"; const char * const GOTO_PREVIOUS_LINE_WITH_SELECTION = "TextEditor.GotoPreviousLineWithSelection"; const char * const GOTO_PREVIOUS_CHARACTER_WITH_SELECTION = "TextEditor.GotoPreviousCharacterWithSelection"; const char * const GOTO_NEXT_CHARACTER_WITH_SELECTION = "TextEditor.GotoNextCharacterWithSelection"; const char * const GOTO_PREVIOUS_WORD_WITH_SELECTION = "TextEditor.GotoPreviousWordWithSelection"; const char * const GOTO_NEXT_WORD_WITH_SELECTION = "TextEditor.GotoNextWordWithSelection"; const char * const GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION = "TextEditor.GotoPreviousWordCamelCaseWithSelection"; const char * const GOTO_NEXT_WORD_CAMEL_CASE_WITH_SELECTION = "TextEditor.GotoNextWordCamelCaseWithSelection"; const char * const C_TEXTEDITOR_MIMETYPE_TEXT = "text/plain"; const char * const INFO_SYNTAX_DEFINITION = "TextEditor.InfoSyntaxDefinition"; const char * const TASK_DOWNLOAD_DEFINITIONS = "TextEditor.Task.Download"; const char * const TASK_REGISTER_DEFINITIONS = "TextEditor.Task.Register"; const char * const TASK_OPEN_FILE = "TextEditor.Task.OpenFile"; // Text color and style categories const char * const C_TEXT = "Text"; const char * const C_LINK = "Link"; const char * const C_SELECTION = "Selection"; const char * const C_LINE_NUMBER = "LineNumber"; const char * const C_SEARCH_RESULT = "SearchResult"; const char * const C_SEARCH_SCOPE = "SearchScope"; const char * const C_PARENTHESES = "Parentheses"; const char * const C_CURRENT_LINE = "CurrentLine"; const char * const C_CURRENT_LINE_NUMBER = "CurrentLineNumber"; const char * const C_OCCURRENCES = "Occurrences"; const char * const C_OCCURRENCES_UNUSED = "Occurrences.Unused"; const char * const C_OCCURRENCES_RENAME = "Occurrences.Rename"; const char * const C_NUMBER = "Number"; const char * const C_STRING = "String"; const char * const C_TYPE = "Type"; const char * const C_LOCAL = "Local"; const char * const C_FIELD = "Field"; const char * const C_STATIC = "Static"; const char * const C_VIRTUAL_METHOD = "VirtualMethod"; const char * const C_KEYWORD = "Keyword"; const char * const C_OPERATOR = "Operator"; const char * const C_PREPROCESSOR = "Preprocessor"; const char * const C_LABEL = "Label"; const char * const C_COMMENT = "Comment"; const char * const C_DOXYGEN_COMMENT = "Doxygen.Comment"; const char * const C_DOXYGEN_TAG = "Doxygen.Tag"; const char * const C_VISUAL_WHITESPACE = "VisualWhitespace"; const char * const C_DISABLED_CODE = "DisabledCode"; const char * const C_ADDED_LINE = "AddedLine"; const char * const C_REMOVED_LINE = "RemovedLine"; const char * const C_DIFF_FILE = "DiffFile"; const char * const C_DIFF_LOCATION = "DiffLocation"; const char * const TEXT_EDITOR_SETTINGS_CATEGORY = "C.TextEditor"; const char * const TEXT_EDITOR_SETTINGS_CATEGORY_ICON = ":/core/images/category_texteditor.png"; const char * const TEXT_EDITOR_SETTINGS_TR_CATEGORY = QT_TRANSLATE_NOOP("TextEditor", "Text Editor"); const char * const TEXT_EDITOR_FONT_SETTINGS = "A.FontSettings"; const char * const TEXT_EDITOR_BEHAVIOR_SETTINGS = "B.BehaviourSettings"; const char * const TEXT_EDITOR_DISPLAY_SETTINGS = "D.DisplaySettings"; const char * const TEXT_EDITOR_HIGHLIGHTER_SETTINGS = "E.HighlighterSettings"; const char * const TEXT_EDITOR_SNIPPETS_SETTINGS = "F.SnippetsSettings"; const char * const SNIPPET_EDITOR_ID = "TextEditor.SnippetEditor"; const char * const TEXT_SNIPPET_GROUP_ID = "Text"; } // namespace Constants } // namespace TextEditor #endif // TEXTEDITORCONSTANTS_H ================================================ FILE: liteidex/src/3rdparty/qtc_texteditor/utils/settingsutils.h ================================================ /************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** No Commercial Usage ** ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #ifndef SETTINGSUTILS_H #define SETTINGSUTILS_H #include #include #include #include namespace Utils { template void fromSettings(const QString &postFix, const QString &category, const QSettings *s, SettingsClassT *obj) { QVariantMap map; const QStringList &keys = s->allKeys(); foreach (const QString &key, keys) map.insert(key, s->value(key)); QString group = postFix; if (!category.isEmpty()) group.insert(0, category); group += QLatin1Char('/'); obj->fromMap(group, map); } template void toSettings(const QString &postFix, const QString &category, QSettings *s, const SettingsClassT *obj) { QString group = postFix; if (!category.isEmpty()) group.insert(0, category); group += QLatin1Char('/'); QVariantMap map; obj->toMap(group, &map); QVariantMap::const_iterator it = map.constBegin(); for (; it != map.constEnd(); ++it) s->setValue(it.key(), it.value()); } } // Utils #endif // SETTINGSUTILS_H ================================================ FILE: liteidex/src/3rdparty/treemodelcompleter/treemodelcompleter.cpp ================================================ /**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ** the names of its contributors may be used to endorse or promote ** products derived from this software without specific prior written ** permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "treemodelcompleter.h" #include #include //! [0] TreeModelCompleter::TreeModelCompleter(QObject *parent) : QCompleter(parent) { } //! [0] //! [1] TreeModelCompleter::TreeModelCompleter(QAbstractItemModel *model, QObject *parent) : QCompleter(model, parent) { } //! [1] void TreeModelCompleter::setSeparator(const QString &separator) { sep = separator; } //! [2] QString TreeModelCompleter::separator() const { return sep; } //! [2] //! [3] QStringList TreeModelCompleter::splitPath(const QString &path) const { if (sep.isNull()) { return QCompleter::splitPath(path); } return path.split(sep); } //! [3] //! [4] QString TreeModelCompleter::pathFromIndex(const QModelIndex &index) const { if (sep.isNull()) { return QCompleter::pathFromIndex(index); } // navigate up and accumulate data QStringList dataList; for (QModelIndex i = index; i.isValid(); i = i.parent()) { dataList.prepend(model()->data(i, completionRole()).toString()); } return dataList.join(sep); } //! [4] ================================================ FILE: liteidex/src/3rdparty/treemodelcompleter/treemodelcompleter.h ================================================ /**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ** the names of its contributors may be used to endorse or promote ** products derived from this software without specific prior written ** permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef TREEMODELCOMPLETER_H #define TREEMODELCOMPLETER_H #include //! [0] class TreeModelCompleter : public QCompleter { Q_OBJECT Q_PROPERTY(QString separator READ separator WRITE setSeparator) public: TreeModelCompleter(QObject *parent = 0); TreeModelCompleter(QAbstractItemModel *model, QObject *parent = 0); QString separator() const; public slots: void setSeparator(const QString &separator); protected: QStringList splitPath(const QString &path) const; QString pathFromIndex(const QModelIndex &index) const; private: QString sep; }; //! [0] #endif // TREEMODELCOMPLETER_H ================================================ FILE: liteidex/src/3rdparty/treemodelcompleter/treemodelcompleter.pri ================================================ LIBS *= -l$$qtLibraryName(treemodelcompleter) ================================================ FILE: liteidex/src/3rdparty/treemodelcompleter/treemodelcompleter.pro ================================================ TARGET = treemodelcompleter TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += treemodelcompleter.h SOURCES += treemodelcompleter.cpp ================================================ FILE: liteidex/src/api/api.pro ================================================ # USE .subdir AND .depends ! # OTHERWISE PLUGINS WILL BUILD IN WRONG ORDER (DIRECTORIES ARE COMPILED IN PARALLEL) TEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ liteapi \ liteenvapi \ litefindapi \ litebuildapi \ liteeditorapi \ litedebugapi \ litettyapi \ docbrowserapi \ golangdocapi \ golangastapi \ quickopenapi \ terminalapi ================================================ FILE: liteidex/src/api/docbrowserapi/docbrowserapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: docbrowserapi.h // Creator: visualfc #ifndef LITEDOCBROWSERAPI_H #define LITEDOCBROWSERAPI_H #include "liteapi/liteapi.h" #include "liteapi/litehtml.h" #include #include #include namespace LiteApi { class IDocumentBrowser : public IBrowserEditor { Q_OBJECT public: IDocumentBrowser(QObject *parent) : IBrowserEditor(parent) {} virtual void setSearchPaths(const QStringList &paths) = 0; virtual void setUrlHtml(const QUrl &url,const QString &html) = 0; virtual void scrollToAnchor(const QString &text) = 0; virtual QToolBar *toolBar() = 0; virtual QComboBox *urlComboBox() = 0; virtual IHtmlWidget *htmlWidget() = 0; signals: void linkHovered(const QUrl &url); void requestUrl(const QUrl &url); void forwardAvailable(bool available); void backwardAvailable(bool available); void documentLoaded(); void anchorChanged(const QString &anchor); public slots: virtual void backward() = 0; virtual void forward() = 0; }; } #endif //LITEDOCBROWSERAPI_H ================================================ FILE: liteidex/src/api/docbrowserapi/docbrowserapi.pri ================================================ LIBS *= -l$$qtLibraryName(docbrowserapi) INCLUDEPATH *= $$PWD ================================================ FILE: liteidex/src/api/docbrowserapi/docbrowserapi.pro ================================================ TARGET = docbrowserapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) DEFINES += DOCBROWSERAPI_LIBRARY HEADERS += docbrowserapi.h ================================================ FILE: liteidex/src/api/golangastapi/golangastapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastapi.h // Creator: visualfc #ifndef GOLANGASTAPI_H #define GOLANGASTAPI_H #include "liteapi/liteapi.h" #include namespace LiteApi { /* const ( tag_package = "p" tag_type = "t" tag_struct = "s" tag_interface = "i" tag_value = "v" tag_const = "c" tag_func = "f" tag_value_folder = "+v" tag_const_folder = "+c" tag_func_folder = "+f" tag_type_method = "tm" tag_type_factor = "tf" tag_type_value = "tv" tag_todo = "b" tag_todo_folder = "+b" ) */ enum ASTTAG_ENUM { TagNone = 0, TagPackage, TagImport, TagImportFolder, TagType, TagStruct, TagInterface, TagValue, TagConst, TagFunc, TagValueFolder, TagConstFolder, TagFuncFolder, TagTypeMethod, TagTypeFactor, TagTypeValue, TagTodo, TagTodoFolder }; class IGolangAst : public QObject { Q_OBJECT public: IGolangAst(QObject *parent = 0): QObject(parent) {} virtual ~IGolangAst() {} virtual QIcon iconFromTag(const QString &tag, bool pub) const = 0; virtual QIcon iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool pub) const = 0; }; } //namespace LiteApi #endif //GOLANGASTAPI_H ================================================ FILE: liteidex/src/api/golangastapi/golangastapi.pri ================================================ LIBS *= -l$$qtLibraryName(golangastapi) ================================================ FILE: liteidex/src/api/golangastapi/golangastapi.pro ================================================ TARGET = golangastapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += golangastapi.h ================================================ FILE: liteidex/src/api/golangdocapi/golangdocapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangdocapi.h // Creator: visualfc #ifndef GOLANGDOCAPI_H #define GOLANGDOCAPI_H #include "liteapi/liteapi.h" /* openUrl(const QUrl &url); url scheme file : open html or plain file list : url path only [pkg|cmd] find : find pkg name pdoc : show pkg doc */ namespace LiteApi { enum PkgApiEnum { NullApi = 0, PkgApi = 0x0001, ConstApi = 0x0002, VarApi = 0x0004, StructApi = 0x0008, InterfaceApi = 0x0010, TypeApi = 0x0020, FuncApi = 0x0040, TypeMethodApi = 0x0080, TypeVarApi = 0x0100, AllTypeApi = StructApi | InterfaceApi | TypeApi, AllGolangApi = PkgApi | ConstApi | VarApi | StructApi | InterfaceApi | TypeApi | FuncApi | TypeMethodApi | TypeVarApi }; class IGolangApi : public QObject { Q_OBJECT public: IGolangApi(QObject *parent) : QObject(parent) {} public: virtual QStringList all(int flag = AllGolangApi) const = 0; virtual PkgApiEnum findExp(const QString &tag, QString &exp) const = 0; virtual QStringList findDocUrl(const QString &tag) const = 0; virtual QString findDocInfo(const QString &tag) const = 0; }; class IGolangDoc : public IObject { Q_OBJECT public: IGolangDoc(QObject *parent) : IObject(parent) {} public slots: virtual void openUrl(const QUrl &url, const QVariant &addin = QVariant()) = 0; virtual void activeBrowser() = 0; }; inline IGolangDoc *getGolangDoc(LiteApi::IApplication *app) { return LiteApi::findExtensionObject(app,"LiteApi.IGolangDoc"); } } #endif //GOLANGDOCAPI_H ================================================ FILE: liteidex/src/api/golangdocapi/golangdocapi.pri ================================================ LIBS *= -l$$qtLibraryName(golangdocapi) ================================================ FILE: liteidex/src/api/golangdocapi/golangdocapi.pro ================================================ TARGET = golangdocapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) DEFINES += DOCBROWSERAPI_LIBRARY HEADERS += golangdocapi.h ================================================ FILE: liteidex/src/api/liteapi/liteapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteapi.h // Creator: visualfc #ifndef LITEAPI_H #define LITEAPI_H #include "liteqt.h" #include "liteobj.h" #include "litehtml.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include class ColorStyle; class ColorStyleScheme; namespace LiteApi { class IApplication; class IManager; class IFile; class IProject; class IEditor; /* valueForKey EDITORPATH EDITORNAME EDITORDIR PROJECTPATH PROJECTNAME PROJECTDIR WORKDIR TARGETPATH TARGETNAME TARGETDIR */ struct TargetInfo1 { QString workDir; QString targetPath; QString targetName; QString targetDir; }; struct ProjectInfo { QString projectPath; QString projectName; QString projectDir; }; struct EditorInfo { QString editorPath; QString editorName; QString editorDir; }; class IManager : public QObject { Q_OBJECT public: IManager(QObject *parent = 0) : QObject(parent) {} virtual ~IManager() {} virtual bool initWithApp(IApplication *app) { m_liteApp = app; return true; } virtual IApplication* application() { return m_liteApp; } protected: IApplication *m_liteApp; }; class IMimeType { public: virtual ~IMimeType() {} virtual QString package() const = 0; virtual QString type() const = 0; virtual QString scheme() const = 0; virtual QString comment() const = 0; virtual QString codec() const = 0; virtual bool tabToSpace() const = 0; virtual int tabWidth() const = 0; virtual QStringList globPatterns() const = 0; virtual QStringList subClassesOf() const = 0; virtual void merge(const IMimeType *mimeType) = 0; virtual void setCustomPatterns(const QStringList &custom) = 0; virtual QStringList customPatterns() const = 0; virtual QStringList allPatterns() const = 0; }; class IMimeTypeManager : public IManager { Q_OBJECT public: IMimeTypeManager(QObject *parent = 0) : IManager(parent) {} virtual bool addMimeType(IMimeType *mimeType) = 0; virtual void removeMimeType(IMimeType *mimeType) = 0; virtual QList mimeTypeList() const= 0; virtual IMimeType *findMimeType(const QString &type) const = 0; virtual QString findPackageByMimeType(const QString &type) const = 0; virtual QString findMimeTypeByFile(const QString &fileName) const = 0; virtual QString findMimeTypeBySuffix(const QString &suffix) const = 0; virtual QString findMimeTypeByScheme(const QString &scheme) const = 0; virtual QStringList findAllFilesByMimeType(const QString &dir, const QString &type, int deep = 0) const = 0; }; inline QString mimeHead(const QString &mimeType) { int find = mimeType.indexOf('/'); if (find == -1) { return mimeType; } return mimeType.left(find); } inline bool mimeIsText(const QString &mimeType) { return mimeHead(mimeType) == "text"; } inline bool mimeIsFolder(const QString &mimeType) { return mimeHead(mimeType) == "folder"; } class IFile : public QObject { Q_OBJECT public: IFile(QObject *parent = 0) : QObject(parent) {} virtual ~IFile() { } virtual bool loadText(const QString &filePath, const QString &mimeType, QString &outText) = 0; virtual bool reloadText(QString &outText) = 0; virtual bool saveText(const QString &filePath, const QString &text) = 0; virtual bool isReadOnly() const = 0; virtual bool isBinary() const = 0; virtual QString filePath() const = 0; virtual QString mimeType() const = 0; }; class IEditorFactory : public QObject { Q_OBJECT public: IEditorFactory(QObject *parent = 0) : QObject(parent) {} virtual QStringList mimeTypes() const = 0; virtual IEditor *open(const QString &fileName, const QString &mimeType) = 0; virtual IEditor *create(const QString &contents, const QString &mimeType) = 0; virtual QString id() const = 0; virtual QString displayName() const = 0; virtual bool testMimeType(const QString &mimeType) = 0; }; class IProjectFactory : public QObject { Q_OBJECT public: IProjectFactory(QObject *parent = 0) : QObject(parent) {} virtual QStringList mimeTypes() const = 0; virtual IProject *open(const QString &fileName, const QString &mimeType) = 0; virtual bool findTargetInfo(const QString &fileName, const QString &mimetype, QMap& targetInfo) const = 0; }; enum FILESYSTEM_CONTEXT_FLAG { FILESYSTEM_ROOT = 0, FILESYSTEM_ROOTFOLDER, FILESYSTEM_FOLDER, FILESYSTEM_FILES }; class IRecent : public QObject { Q_OBJECT public: IRecent(QObject *parent = 0) : QObject(parent) {} virtual QString type() const = 0; virtual QString displyType() const = 0; virtual void addRecent(const QString &name, int maxRecent) = 0; virtual void removeRecent(const QString &name) = 0; virtual QStringList recentNameList() = 0; virtual void clearRecentNameList() = 0; virtual void openRecent(const QString &name) = 0; }; class ISettingRecent : public IRecent { Q_OBJECT public: ISettingRecent(QSettings *setting, QObject *parent) : IRecent(parent), m_settings(setting) { } virtual void addRecent(const QString &name, int maxRecent) { QString key = recentKey(); QStringList files = m_settings->value(key).toStringList(); files.removeAll(name); files.prepend(name); while (files.size() > maxRecent) { files.removeLast(); } m_settings->setValue(key, files); } virtual void removeRecent(const QString &name) { QString key = recentKey(); QStringList values = m_settings->value(key).toStringList(); values.removeAll(name); m_settings->setValue(key, values); } virtual QStringList recentNameList() { QString key = recentKey(); return m_settings->value(key).toStringList(); } virtual void clearRecentNameList() { QString key = recentKey(); m_settings->remove(key); } protected: virtual QString recentKey() const { return QString("Recent1/%1").arg(type()); } protected: QSettings *m_settings; }; class IRecentManager : public IManager { Q_OBJECT public: IRecentManager(QObject *parent = 0) : IManager(parent) {} virtual void registerRecent(IRecent *recent) = 0; virtual QList recentList() const = 0; virtual IRecent *findRecent(const QString &type) const = 0; virtual QStringList recentTypeList() const = 0; virtual void addRecent(const QString &name, const QString &type) = 0; virtual void removeRecent(const QString &name, const QString &type) = 0; virtual QStringList recentNameList(const QString &type) = 0; virtual void clearRecentNameList(const QString &type) = 0; virtual void openRecent(const QString &name, const QString &type) = 0; virtual void updateRecentMenu(const QString &type) = 0; signals: void recentNameListChanged(const QString &type); }; class IFileManager : public IManager { Q_OBJECT public: IFileManager(QObject *parent = 0) : IManager(parent) {} virtual void execFileWizard(const QString &projPath, const QString &filePath, const QString &gopath = QString()) = 0; virtual bool openFile(const QString &fileName) = 0; virtual IEditor *openEditor(const QString &fileName, bool bActive = true, bool ignoreNavigationHistory = false) = 0; virtual IEditor *openEditorByFactory(const QString &fileName, const QString &factoryId, bool bActive = true, bool ignoreNavigationHistory = false) = 0; virtual IEditor *createEditor(const QString &contents, const QString &_mimeType) = 0; virtual IEditor *createEditor(const QString &fileName) = 0; virtual IProject *openProject(const QString &fileName) = 0; virtual IProject *openProjectScheme(const QString &fileName, const QString &scheme) = 0; virtual bool findProjectTargetInfo(const QString &fileName, QMap& targetInfo) const = 0; //virtual IApplication* openFolderEx(const QString &folder) = 0; virtual QStringList folderList() const = 0; virtual void setFolderList(const QStringList &folders) = 0; virtual void addFolderList(const QString &folders) = 0; virtual IApplication* openFolderInNewWindow(const QString &folder) = 0; virtual void emitAboutToShowFolderContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info, const QString &context) = 0; signals: void fileListChanged(); void fileWizardFinished(const QString &type, const QString &scheme, const QString &location); void aboutToShowFolderContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info,const QString &context); public slots: virtual void newFile() = 0; virtual void openFiles() = 0; virtual void openFolder() = 0; virtual void openEditors() = 0; virtual void openProjects() = 0; }; class IEditContext : public QObject { Q_OBJECT public: IEditContext(QObject *parent) : QObject(parent) {} virtual QWidget *focusWidget() const = 0; virtual QMenu *focusMenu() const = 0; virtual QToolBar *focusToolBar() const = 0; }; class IView : public IObject { Q_OBJECT public: IView(QObject *parent = 0) : IObject(parent) {} virtual QWidget *widget() = 0; virtual QString name() const = 0; virtual QIcon icon() const { return QIcon(); } }; class IEditor : public IView { Q_OBJECT public: IEditor(QObject *parent = 0) : IView(parent) {} virtual bool open(const QString &filePath,const QString &mimeType) = 0; virtual bool reload() = 0; virtual bool save() = 0; virtual bool saveAs(const QString &filePath) = 0; virtual void setReadOnly(bool b) = 0; virtual bool isReadOnly() const = 0; virtual bool isModified() const = 0; virtual QString filePath() const = 0; virtual QString mimeType() const = 0; virtual QByteArray saveState() const = 0; virtual bool restoreState(const QByteArray &array) = 0; virtual void onActive() = 0; signals: void modificationChanged(bool); void contentsChanged(); void reloaded(); }; struct FindOption { QString findText; bool useRegexp; bool matchWord; bool matchCase; bool wrapAround; bool backWard; }; class ITextEditor : public IEditor { Q_OBJECT public: enum PositionOperation { Current = 1, EndOfLine = 2, StartOfLine = 3, Anchor = 4, EndOfDoc = 5 }; ITextEditor(QObject *parent = 0) : IEditor(parent) {} virtual int line() const = 0; virtual int column() const = 0; virtual int utf8Position(bool realFile = false, int pos = -1) const = 0; virtual QByteArray utf8Data() const = 0; virtual void setLineWrap(bool wrap) = 0; virtual bool isLineWrap() const = 0; virtual void gotoLine(int blockNumber, int column, bool center = false, int selection = 0) = 0; virtual void setFindOption(FindOption *opt) = 0; virtual int position(PositionOperation posOp = Current, int at = -1) const = 0; virtual QString textAt(int pos, int length) const = 0; virtual QRect cursorRect(int pos = -1) const = 0; virtual QTextCursor textCursor() const = 0; virtual QTextDocument *document() const = 0; }; inline ITextEditor *getTextEditor(IEditor *editor) { if (editor && editor->extension()) { return findExtensionObject(editor->extension(),"LiteApi.ITextEditor"); } return 0; } inline QMenu *getMenu(IObject *obj, const QString &id) { if (obj && obj->extension()) { return findExtensionObject(obj->extension(),QString("LiteApi.Menu.%1").arg(id)); } return 0; } inline IEditContext *getEditContext(IObject *obj) { if (obj && obj->extension()) { return findExtensionObject(obj->extension(),"LiteApi.IEditContext"); } return 0; } inline QMenu *getEditMenu(IObject *obj) { return getMenu(obj,"Edit"); } inline QMenu *getContextMenu(IObject *obj) { if (obj && obj->extension()) { return findExtensionObject(obj->extension(),"LiteApi.ContextMenu"); } return 0; } inline QPlainTextEdit *getPlainTextEdit(IEditor *editor) { if (editor && editor->extension()) { return findExtensionObject(editor->extension(),"LiteApi.QPlainTextEdit"); } return 0; } inline QToolBar *getEditToolBar(IEditor *editor) { if (editor && editor->extension()) { return findExtensionObject(editor->extension(),"LiteApi.QToolBar.Edit"); } return 0; } inline QToolBar *getBuildToolBar(IEditor *editor) { if (editor && editor->extension()) { return findExtensionObject(editor->extension(),"LiteApi.QToolBar.Build"); } return 0; } class IEditorManager : public IManager { Q_OBJECT public: IEditorManager(QObject *parent = 0) : IManager(parent) {} virtual IEditor *openEditor(const QString &fileName, const QString &mimeType) = 0; virtual IEditor *openEditorByFactory(const QString &fileName, const QString &mimeType, const QString &factoryId) = 0; virtual void addFactory(IEditorFactory *factory) = 0; virtual void removeFactory(IEditorFactory *factory) = 0; virtual QList factoryList() const = 0; virtual QStringList mimeTypeList() const = 0; virtual QWidget *widget() = 0; virtual IEditor *currentEditor() const = 0; virtual void setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory = false) = 0; virtual IEditor *findEditor(const QString &fileName, bool canonical) const = 0; virtual QList editorList() const = 0; virtual QAction *registerBrowser(IEditor *editor) = 0; virtual void activeBrowser(IEditor *editor) = 0; virtual void addNavigationHistory(IEditor *editor = 0,const QByteArray &saveState = QByteArray()) = 0; virtual void cutForwardNavigationHistory() = 0; virtual void loadColorStyleScheme(const QString &fileName) = 0; virtual const ColorStyleScheme *colorStyleScheme() const = 0; virtual void addEditContext(IEditContext *context) = 0; virtual void removeEditContext(IEditContext *context) = 0; virtual void updateEditInfo(const QString &info) = 0; public slots: virtual bool saveEditor(IEditor *editor = 0, bool emitAboutSave = true) = 0; virtual bool saveEditorAs(IEditor *editor = 0) = 0; virtual bool saveAllEditors(bool emitAboutSave = true) = 0; virtual bool closeEditor(IEditor *editor = 0) = 0; virtual bool closeAllEditors() = 0; signals: void currentEditorChanged(LiteApi::IEditor *editor); void editorCreated(LiteApi::IEditor *editor); void editorAboutToClose(LiteApi::IEditor *editor); void editorAboutToSave(LiteApi::IEditor *editor); void editorSaved(LiteApi::IEditor *editor); void editorModifyChanged(LiteApi::IEditor *editor, bool b); void colorStyleSchemeChanged(); }; class IBrowserEditor : public IEditor { Q_OBJECT public: IBrowserEditor(QObject *parent = 0) : IEditor(parent) {} virtual bool open(const QString &/*fileName*/,const QString &/*mimeType*/) { return false; } virtual bool reload() { return false; } virtual bool save() { return false; } virtual bool saveAs(const QString &/*fileName*/){ return false; } virtual void setReadOnly(bool /*b*/) {} virtual bool isReadOnly() const { return true; } virtual bool isModified() const { return false; } virtual QString filePath() const { return QString(); } virtual QMap editorInfo() const { return QMap(); } virtual QMap targetInfo() const { return QMap(); } virtual QByteArray saveState() const {return QByteArray(); } virtual bool restoreState(const QByteArray &) { return false; } virtual void onActive(){} }; class IWebKitBrowser : public IBrowserEditor { Q_OBJECT public: IWebKitBrowser(QObject *parent = 0) : IBrowserEditor(parent) {} virtual void openUrl(const QUrl &url) = 0; signals: void loadFinished(bool); }; class IProject : public IView { Q_OBJECT public: virtual QString filePath() const = 0; virtual QString mimeType() const = 0; virtual QStringList folderList() const = 0; virtual QStringList fileNameList() const = 0; virtual QStringList filePathList() const = 0; virtual QString fileNameToFullPath(const QString &filePath) = 0; virtual QMap targetInfo() const = 0; virtual void load() = 0; signals: void reloaded(); }; class IFileProject : public IProject { Q_OBJECT public: virtual bool isFolder() const { return false; } }; class IFolderProject : public IProject { Q_OBJECT public: virtual bool isFolder() const { return true; } virtual QStringList folderList() const = 0; }; class IOption : public IView { Q_OBJECT public: IOption(QObject *parent = 0) : IView(parent) {} virtual QString mimeType() const = 0; virtual void save() = 0; virtual void load() = 0; }; class IOptionFactory : public QObject { Q_OBJECT public: IOptionFactory(QObject *parent = 0) : QObject(parent) {} virtual QStringList mimeTypes() const = 0; virtual IOption *create(const QString &mimeType) = 0; }; class IOptionManager : public IManager { Q_OBJECT public: IOptionManager(QObject *parent = 0) : IManager(parent) {} virtual void addFactory(IOptionFactory *factory) = 0; virtual void removeFactory(IOptionFactory *factory) = 0; virtual QList factoryList() const = 0; virtual void emitApplyOption(const QString &mimetype) = 0; public slots: virtual void exec(const QString &mimeType) = 0; signals: void applyOption(QString); }; class IProjectManager : public IManager { Q_OBJECT public: IProjectManager(QObject *parent = 0) : IManager(parent) {} virtual IFolderProject *openFolder(const QString &folderPath) = 0; virtual IProject *openProject(const QString &fileName, const QString &mimeType) = 0; virtual void addFactory(IProjectFactory *factory) = 0; virtual void removeFactory(IProjectFactory *factory) = 0; virtual QList factoryList() const = 0; virtual QStringList mimeTypeList() const = 0; virtual void setCurrentProject(IProject *project) = 0; virtual IProject *currentProject() const = 0; virtual QList editorList(IProject *project) const = 0; virtual void addImportAction(QAction *act) = 0; virtual QWidget *widget() = 0; public slots: virtual void saveProject(IProject *project = 0) = 0; virtual void closeProject(IProject *project = 0) = 0; virtual void openSchemeDialog(const QString &scheme) = 0; signals: void currentProjectChanged(LiteApi::IProject *project); void projectAboutToClose(LiteApi::IProject *project); }; class IToolWindowManager : public IManager { Q_OBJECT public: IToolWindowManager(QObject *parent = 0) : IManager(parent) {} virtual QAction *addToolWindow(Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split, QList widgetActions = QList(), QList widgetList = QList() ) = 0; virtual void moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to,QAction *action, bool split) = 0; virtual QAction *findToolWindow(QWidget *widget) = 0; virtual void removeToolWindow(QAction *action) = 0; virtual void removeToolWindow(QWidget *widget) = 0; }; class IDockManager : public IManager { Q_OBJECT public: IDockManager(QObject *parent = 0) : IManager(parent) {} virtual QWidget *widget() = 0; virtual QDockWidget *addDock(QWidget *widget, const QString &title, Qt::DockWidgetArea ares = Qt::LeftDockWidgetArea, Qt::DockWidgetAreas alowedAreas = Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea, QDockWidget::DockWidgetFeatures features = QDockWidget::AllDockWidgetFeatures) = 0; virtual void removeDock(QWidget *widget) = 0; virtual void showDock(QWidget *widget) = 0; virtual void hideDock(QWidget *widget) = 0; virtual QDockWidget *dockWidget(QWidget *widget) = 0; }; enum VIEWMENU_ACTION_POS { ViewMenuToolBarPos = 1, ViewMenuToolWindowPos, ViewMenuBrowserPos, ViewMenuLastPos }; struct ActionInfo { QString label; QString defks; QString ks; bool standard; QList keys; QAction *action; }; class IActionContext { public: virtual ~IActionContext() {} virtual QString contextName() const = 0; virtual void regAction(QAction *act, const QString &id, const QString &defks, bool standard = false) = 0; virtual void regAction(QAction *act, const QString &id, const QKeySequence::StandardKey &def) = 0; virtual QStringList actionKeys() const = 0; virtual ActionInfo *actionInfo(const QString &id) const = 0; virtual void setActionShortcuts(const QString &id, const QString &shortcuts) = 0; }; class IActionManager : public IManager { Q_OBJECT public: IActionManager(QObject *parent = 0) : IManager(parent) {} virtual QMenu *insertMenu(const QString &id, const QString &title, const QString &idBefore = QString()) = 0; virtual QMenu *loadMenu(const QString &id) = 0; virtual void removeMenu(QMenu *menu) = 0; virtual QList menuList() const = 0; virtual QToolBar *insertToolBar(const QString &id, const QString &title, const QString &before = QString()) = 0; virtual void insertToolBar(QToolBar *toolBar,const QString &before = QString()) = 0; virtual QToolBar *loadToolBar(const QString &id) = 0; virtual void removeToolBar(QToolBar* toolBar) = 0; virtual QList toolBarList() const = 0; virtual void insertViewMenu(VIEWMENU_ACTION_POS pos, QAction *act) = 0; virtual void setViewMenuSeparator(const QString &sepid, bool group = false) = 0; virtual void insertViewMenuAction(QAction *act, const QString &sepid) = 0; virtual bool insertMenuActions(const QString &idMenu, const QString &idBeforeSep, bool newGroup, QList &actions) = 0; virtual IActionContext *getActionContext(QObject *obj, const QString &name) = 0; virtual QStringList actionKeys() const = 0; virtual ActionInfo *actionInfo(const QString &id) const = 0; virtual void setActionShourtcuts(const QString &id, const QString &shortcuts) = 0; virtual QStringList actionContextNameList() const = 0; virtual IActionContext *actionContextForName(const QString &name) = 0; }; class IGoProxy : public QObject { Q_OBJECT public: IGoProxy(QObject *parent) : QObject(parent) {} virtual bool isValid() const = 0; virtual bool isRunning() const = 0; virtual QByteArray commandId() const = 0; virtual void writeStdin(const QByteArray &data) = 0; signals: void started(); void stdoutput(const QByteArray &data); void stderror(const QByteArray &data); void finished(int code, const QByteArray &msg); public slots: virtual void call(const QByteArray &id, const QByteArray &args = QByteArray()) = 0; }; class IPlugin; class IApplication : public IObject { Q_OBJECT public: virtual ~IApplication() {} virtual IApplication *newInstance(const QString &session) = 0; virtual QList instanceList() const = 0; virtual bool hasGoProxy() const = 0; virtual IGoProxy *createGoProxy(QObject *parent) = 0; virtual IProjectManager *projectManager() = 0; virtual IEditorManager *editorManager() = 0; virtual IFileManager *fileManager() = 0; virtual IActionManager *actionManager() = 0; virtual IMimeTypeManager *mimeTypeManager() = 0; virtual IOptionManager *optionManager() = 0; virtual IToolWindowManager *toolWindowManager() = 0; virtual IHtmlWidgetManager *htmlWidgetManager() = 0; virtual IRecentManager *recentManager() = 0; virtual QMainWindow *mainWindow() const = 0; virtual QSettings *settings() = 0; virtual QMap &globalCookie() = 0; //global cookie virtual QString rootPath() const = 0; virtual QString applicationPath() const = 0; virtual QString toolPath() const = 0; virtual QString resourcePath() const = 0; virtual QString pluginPath() const = 0; virtual QString storagePath() const = 0; virtual QString ideVersion() const = 0; virtual QString ideFullName() const = 0; virtual QString ideName() const = 0; virtual QString ideCopyright() const = 0; virtual QList pluginList() const = 0; virtual void loadSession(const QString &sessioin) = 0; virtual void saveSession(const QString &sessioin) = 0; virtual QStringList sessionList() const = 0; virtual QString currentSession() const = 0; virtual void loadState() = 0; virtual void saveState() = 0; virtual void appendLog(const QString &model, const QString &log, bool error = false) = 0; virtual void sendBroadcast(const QString &module, const QString &id, const QVariant ¶m = QVariant()) = 0; signals: void loaded(); void aboutToQuit(); void key_escape(); void broadcast(QString,QString,QVariant); void sessionListChanged(); }; class PluginInfo { public: PluginInfo() : m_mustLoad(false) {} virtual ~PluginInfo() {} QString author() const { return m_author; } QString info() const { return m_info; } QString id() const { return m_id; } QString name() const { return m_name; } QString ver() const { return m_ver; } QStringList dependList() const { return m_dependList; } QString filePath() const { return m_filePath; } bool isMustLoad() const { return m_mustLoad; } void setAuthor(const QString &author) { m_author = author; } void setInfo(const QString &info) { m_info = info; } void setId(const QString &id) { m_id = id.toLower(); } void setName(const QString &name) { m_name = name; } void setVer(const QString &ver) { m_ver = ver; } void setFilePath(const QString &path) { m_filePath = path; } void setDependList(const QStringList &dependList) { m_dependList = dependList; } void appendDepend(const QString &depend) { m_dependList.append(depend); } void setMustLoad(bool b) { m_mustLoad = b; } protected: bool m_mustLoad; QString m_author; QString m_info; QString m_id; QString m_name; QString m_filePath; QString m_ver; QStringList m_dependList; }; class IPlugin : public IObject { Q_OBJECT public: virtual bool load(LiteApi::IApplication *app) = 0; }; class IPluginFactory : public QObject { Q_OBJECT public: virtual ~IPluginFactory() {} virtual QString id() const = 0; virtual PluginInfo *info() const = 0; virtual QStringList dependPluginList() const = 0; virtual void setFilePath(const QString &path) = 0; virtual QString filePath() const = 0; virtual IPlugin *createPlugin() = 0; }; class IPluginFactoryImpl : public IPluginFactory { Q_OBJECT public: IPluginFactoryImpl() : m_info(new PluginInfo) { } virtual ~IPluginFactoryImpl() { delete m_info; } virtual QString id() const { return m_info->id(); } virtual PluginInfo *info() const { return m_info; } virtual QStringList dependPluginList() const{ return m_info->dependList(); } virtual void setFilePath(const QString &path) { m_info->setFilePath(path); } virtual QString filePath() const { return m_info->filePath(); } protected: PluginInfo *m_info; }; template class PluginFactoryT : public IPluginFactoryImpl { public: virtual IPlugin *createPlugin() { return new T; } }; class IAppIdleTimer : public QObject { Q_OBJECT signals: void appIdle(int sec); public: virtual void resetTimer() = 0; }; inline IAppIdleTimer *GetAppIdleTimer(LiteApi::IApplication *app) { return static_cast(app->extension()->findObject("LiteApi.IAppIdleTimer")); } inline bool gotoLine(IApplication *app, const QString &fileName, int line, int col, bool forceCenter, bool saveHistory) { if (saveHistory) { app->editorManager()->addNavigationHistory(); } IEditor *cur = app->editorManager()->currentEditor(); IEditor *edit = app->fileManager()->openEditor(fileName); ITextEditor *textEdit = getTextEditor(edit); if (textEdit) { if (cur == edit) { textEdit->gotoLine(line,col,forceCenter); } else { textEdit->gotoLine(line,col,true); } return true; } return false; } inline QSize getToolBarIconSize(LiteApi::IApplication *app) { int v = app->settings()->value("General/ToolBarIconSize",0).toInt(); switch (v) { case 0: return QSize(16,16); case 1: return QSize(18,18); case 2: return QSize(20,20); case 3: return QSize(22,22); case 4: return QSize(24,24); } return QSize(16,16); } inline IWebKitBrowser *getWebKitBrowser(LiteApi::IApplication *app) { return static_cast(app->extension()->findObject("LiteApp.IWebKitBrowser")); } inline QString getGotools(LiteApi::IApplication *app) { #ifdef Q_OS_WIN return app->toolPath()+"/gotools.exe"; #else return app->toolPath()+"/gotools"; #endif } inline QString findPackageByMimeType(LiteApi::IApplication *app, const QString mimeType) { return app->mimeTypeManager()->findPackageByMimeType(mimeType); } } //namespace LiteApi Q_DECLARE_INTERFACE(LiteApi::IPluginFactory,"LiteApi.IPluginFactory.X37") #endif //LITEAPI_H ================================================ FILE: liteidex/src/api/liteapi/liteapi.pri ================================================ LIBS *= -l$$qtLibraryName(liteapi) ================================================ FILE: liteidex/src/api/liteapi/liteapi.pro ================================================ TARGET = liteapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) DEFINES += LITEAPI_LIBRARY HEADERS += liteobj.h \ liteapi.h \ litehtml.h \ liteqt.h \ liteutil.h \ liteids.h ================================================ FILE: liteidex/src/api/liteapi/litehtml.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: litehtml.h // Creator: visualfc #ifndef LITEHTML_H #define LITEHTML_H #include #include #include #ifndef QT_NO_PRINTER #include #endif namespace LiteApi { class IHtmlWidget : public QObject { Q_OBJECT public: IHtmlWidget(QObject *parent) :QObject(parent){} virtual ~IHtmlWidget() {} public: virtual QWidget *widget() const = 0; virtual QString className() const = 0; virtual void setSearchPaths(const QStringList &paths) = 0; virtual void setHtml(const QString &html, const QUrl &url) = 0; virtual QUrl url() const = 0; virtual void clear() = 0; virtual void scrollToAnchor(const QString &anchor) = 0; virtual void setScrollBarValue(Qt::Orientation orientation, int value) = 0; virtual int scrollBarValue(Qt::Orientation orientation) const = 0; virtual int scrollBarMinimum(Qt::Orientation orientation) const = 0; virtual int scrollBarMaximum(Qt::Orientation orientation) const = 0; virtual QString selectedText() const = 0; virtual bool findText(const QString & exp, QTextDocument::FindFlags options) = 0; public slots: #ifndef QT_NO_PRINTER virtual void print(QPrinter *printer) = 0; #endif signals: void contentsSizeChanged(); void loadFinished(bool); void anchorChanged(const QString & anchor); void linkClicked(const QUrl & url); void linkHovered(const QUrl & url); }; //html document util class IHtmlDocument : public QObject { Q_OBJECT public: IHtmlDocument(QObject *parent) : QObject(parent){} virtual ~IHtmlDocument() {} public: virtual void setHtml(const QString &html, const QUrl &url) = 0; public slots: #ifndef QT_NO_PRINTER virtual void print(QPrinter *printer) = 0; #endif virtual QString toHtml () const = 0; virtual QString toPlainText () const = 0; signals: void loadFinished(bool); }; class IHtmlWidgetFactory : public QObject { Q_OBJECT public: IHtmlWidgetFactory(QObject *parent = 0) : QObject(parent) {} virtual QString className() const = 0; virtual IHtmlWidget *create(QObject *parent) = 0; virtual IHtmlDocument *createDocument(QObject *parent) = 0; }; // QTextBrowser and QWebView class IHtmlWidgetManager : public QObject { Q_OBJECT public: IHtmlWidgetManager(QObject *parent = 0) : QObject(parent) {} virtual QStringList classNameList() const = 0; virtual void addFactory(IHtmlWidgetFactory *factory) = 0; virtual QList factoryList() const = 0; virtual bool setDefaultClassName(const QString &className) = 0; virtual QString defaultClassName() const = 0; virtual IHtmlWidget *create(QObject *parent) = 0; virtual IHtmlWidget *createByName(QObject *parent, const QString &className) = 0; virtual IHtmlDocument *createDocument(QObject *parent) = 0; virtual IHtmlDocument *createDocumentByName(QObject *parent, const QString &className) = 0; }; } //namespace LiteApi #endif // LITEHTML_H ================================================ FILE: liteidex/src/api/liteapi/liteids.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteids.h // Creator: visualfc #ifndef LITEIDS_H #define LITEIDS_H #define ID_MENU_FILE "menu/file" #define ID_MENU_RECENT "menu/recent" #define ID_MENU_VIEW "menu/view" #define ID_MENU_EDIT "menu/edit" #define ID_MENU_FIND "menu/find" #define ID_MENU_TOOLS "menu/tools" #define ID_MENU_BUILD "menu/build" #define ID_MENU_DEBUG "menu/debug" #define ID_MENU_HELP "menu/help" #define ID_TOOLBAR_STD "toolbar/std" #define ID_TOOLBAR_ENV "toolbar/env" #define ID_TOOLBAR_BUILD "toolbar/build" #endif // LITEIDS_H ================================================ FILE: liteidex/src/api/liteapi/liteobj.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteobj.h // Creator: visualfc #ifndef LITEOBJ_H #define LITEOBJ_H #include #include #include namespace LiteApi { #ifdef Q_OS_MAC enum { UseMacShortcuts = 1 }; #else enum { UseMacShortcuts = 0 }; #endif class IObject; class IExtension { public: virtual ~IExtension() {} virtual void addObject(const QString &meta, QObject *obj) = 0; virtual void removeObject(const QString &meta) = 0; virtual QObject *findObject(const QString &meta) const = 0; virtual QStringList objectMetaList() const = 0; }; class IObject : public QObject { public: IObject(QObject *parent = 0) : QObject(parent) {} virtual ~IObject() {} virtual IExtension *extension() { return 0; } }; template inline T findExtensionObject(IObject *obj, const QString & meta) { IExtension *ext = obj->extension(); if (!ext) { return 0; } QObject *t = ext->findObject(meta); if (!t) { return 0; } return static_cast(t); } template inline T findExtensionObject(IExtension *ext, const QString & meta) { QObject *t = ext->findObject(meta); if (!t) { return 0; } return static_cast(t); } } //LiteApi #endif // LITEOBJ_H ================================================ FILE: liteidex/src/api/liteapi/liteqt.h ================================================ #ifndef LITEQT_H #define LITEQT_H #include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) #define qtKeepEmptyParts Qt::KeepEmptyParts #define qtSkipEmptyParts Qt::SkipEmptyParts #else #define qtKeepEmptyParts QString::KeepEmptyParts #define qtSkipEmptyParts QString::SkipEmptyParts #endif #endif // LITEQT_H ================================================ FILE: liteidex/src/api/liteapi/liteutil.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteutil.h // Creator: visualfc #ifndef LITEUTIL_H #define LITEUTIL_H #include "liteapi.h" namespace LiteApi { inline void updateSetting(QSettings *setting, const QString &key, const QVariant &value, const QVariant &def) { if (value == def) { setting->remove(key); } else { setting->setValue(key,value); } } inline void updateAppSetting(LiteApi::IApplication *app, const QString &key, const QVariant &value, const QVariant &def) { updateSetting(app->settings(),key,value,def); } } #endif // LITEUTIL_H ================================================ FILE: liteidex/src/api/litebuildapi/litebuildapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: litebuildapi.h // Creator: visualfc #ifndef LITEBUILDAPI_H #define LITEBUILDAPI_H #include "liteapi/liteapi.h" #include namespace LiteApi { class BuildAction { public: BuildAction(): m_debug(false), m_output(false), m_readline(false), m_separator(false), m_killold(false), m_navigate(false), m_folder(false), m_takeall(false) {} void setId(const QString &id) { m_id = id; } void setOs(const QString &os) { m_os = os; } void setMenu(const QString &menu) { m_menu = menu; } void setKey(const QString &key) { m_key = key; } void setFunc(const QString &func) { m_func = func; } void setCmd(const QString &cmd) { m_cmd = cmd; } void setArgs(const QString &args) { m_args = args; } void setSave(const QString &save) { m_save = save; } void setDebug(const QString &text) { m_debug = QVariant(text).toBool(); } void setOutput(const QString &text) { m_output = QVariant(text).toBool(); } void setReadline(const QString &text) { m_readline = QVariant(text).toBool(); } void setSeparator(const QString &text) { m_separator = QVariant(text).toBool(); } void setKillold(const QString &text) { m_killold = QVariant(text).toBool(); } void setNavigate(const QString &text) { m_navigate = QVariant(text).toBool(); } void setFolder(const QString &text) { m_folder = QVariant(text).toBool(); } void setTakeall(const QString &text) { m_takeall = QVariant(text).toBool(); } void setWork(const QString &work) { m_work = work; } void setCodec(const QString &codec) { m_codec = codec; } void setRegex(const QString ®ex) { m_regex = regex; } void setImg(const QString &img) {m_img = img; } void setTask(const QStringList &task) { m_task = task; } QString work() const { return m_work; } QString id() const { return m_id; } QString os() const { return m_os; } QString menu() const { return m_menu; } QString key() const { return m_key; } QString cmd() const { return m_cmd; } QString func() const { return m_func; } QString args() const { return m_args; } QString save() const { return m_save; } bool isDebug() const { return m_debug; } bool isOutput() const { return m_output; } bool isReadline() const {return m_readline; } bool isSeparator() const { return m_separator; } bool isFolder() const { return m_folder; } bool isKillOld() const { return m_killold; } bool isNavigate() const { return m_navigate; } bool isTakeall() const { return m_takeall; } QString codec() const { return m_codec; } QString regex() const { return m_regex; } QString img() const { return m_img; } QStringList task() const { return m_task; } void clear() { m_id.clear(); m_cmd.clear(); m_key.clear(); m_args.clear(); m_codec.clear(); m_regex.clear(); m_img.clear(); m_save.clear(); m_task.clear(); m_debug = false; m_output = false; m_readline = false; m_separator = false; m_killold = false; m_folder = false; m_takeall = false; } bool isEmpty() { return m_id.isEmpty(); } bool isHidden() { return m_id.isEmpty() || m_id[0].isLower(); } protected: QString m_id; QString m_os; QString m_key; QString m_cmd; QString m_func; QString m_args; QString m_codec; QString m_regex; QString m_save; QString m_img; QString m_work; QString m_menu; QStringList m_task; bool m_debug; bool m_output; bool m_readline; bool m_separator; bool m_killold; bool m_navigate; bool m_folder; bool m_takeall; }; class BuildLookup { public: BuildLookup() : m_top(1) { } void setMimeType(const QString &type) {m_type=type;} void setFile(const QString &file) {m_file=file;} void setTop(const QString &top) { if (top.isEmpty()) { return; } bool ok = false; int value = top.toInt(&ok); if (ok) { m_top=value; } } QString mimeType() const {return m_type;} QString file() const {return m_file;} int top() const {return m_top;} protected: QString m_type; QString m_file; int m_top; }; class BuildConfig { public: BuildConfig() { } void setId(const QString &id) { m_id = id; } void setName(const QString &name) { m_name = name; } void setValue(const QString &value) { m_value = value; } QString id() const { return m_id; } QString name() const { return m_name; } QString value() const { return m_value; } protected: QString m_id; QString m_name; QString m_value; }; class BuildCustom { public: BuildCustom() : m_hasShared(false), m_isReadOnly(false), m_isEscaped(false) { } void setId(const QString &id) { m_id = id; } void setName(const QString &name) { m_name = name; } void setValue(const QString &value) { m_value = value; } void setSharedValue(const QString &value) { m_hasShared = true; m_sharedValue = value; } void setReadOnly(const QString &value) { m_isReadOnly = QVariant(value).toBool(); } void setEscaped(const QString &value) { m_isEscaped = QVariant(value).toBool(); } QString id() const { return m_id; } QString name() const { return m_name; } QString value() const { return m_value; } bool hasShared() const { return m_hasShared; } QString sharedValue() const { return m_sharedValue; } bool isReadOnly() const { return m_isReadOnly; } bool isEscaped() const { return m_isEscaped; } protected: QString m_id; QString m_name; QString m_value; QString m_sharedValue; bool m_hasShared; bool m_isReadOnly; bool m_isEscaped; }; class BuildTarget { public: BuildTarget() { } void setId(const QString &id) { m_id = id; } void setCmd(const QString &cmd) { m_cmd = cmd; } void setDebug(const QString &debug) { m_debug = debug; } void setArgs(const QString &args) { m_args = args; } void setWork(const QString &work) { m_work = work; } void setBuildArgs(const QString &args) { m_buildArgs = args; } QString id() const { return m_id; } QString cmd() const { return m_cmd; } QString debug() const { return m_debug; } QString args() const { return m_args; } QString work() const { return m_work; } QString buildArgs() const { return m_buildArgs; } bool isEmpty() { return m_id.isEmpty(); } protected: QString m_id; QString m_cmd; QString m_debug; QString m_buildArgs; QString m_args; QString m_work; }; class IBuild : public QObject { Q_OBJECT public: IBuild(QObject *parent = 0): QObject(parent) {} virtual ~IBuild() {} virtual QString mimeType() const = 0; virtual QString id() const = 0; virtual QString work() const = 0; virtual QString lock() const = 0; virtual QList actionList() const = 0; virtual QList lookupList() const = 0; virtual QList configList() const = 0; virtual QList customList() const = 0; virtual QList targetList() const = 0; virtual BuildAction *findAction(const QString &name) = 0; virtual QList actions() = 0; signals: void buildAction(LiteApi::IBuild *build, LiteApi::BuildAction *act); }; class IBuildManager : public IManager { Q_OBJECT public: IBuildManager(QObject *parent = 0) : IManager(parent) {} virtual void addBuild(IBuild *build) = 0; virtual void removeBuild(IBuild *build) = 0; virtual IBuild *findBuild(const QString &mimeType) = 0; virtual QList buildList() const = 0; virtual void setCurrentBuild(IBuild *build) = 0; virtual IBuild *currentBuild() const = 0; signals: void buildChanged(LiteApi::IBuild*); }; struct TargetInfo { QString buildRootPath; QString targetName; QString debugName; QString buildArgs; QString targetArgs; QString targetWorkDir; }; class ILiteBuild : public IObject { Q_OBJECT public: ILiteBuild(QObject *parent) : IObject(parent) { } public: virtual QString buildTag() const = 0; virtual QMap buildEnvMap() const = 0; virtual TargetInfo getTargetInfo() = 0; virtual IBuildManager *buildManager() const = 0; virtual QString envValue(LiteApi::IBuild *build, const QString &value) = 0; virtual QString buildPathEnvValue(LiteApi::IBuild *build, const QString &buildFilePath, const QString &value) = 0; virtual void appendOutput(const QString &str, const QBrush &brush, bool active, bool updateExistsTextColor = true) = 0; virtual void execCommand(const QString &cmd, const QString &args, const QString &workDir, bool updateExistsTextColor = true, bool activateOutputCheck = true, bool navigate = true, bool command = true) = 0; virtual bool execGoCommand(const QStringList &args, const QString &work, bool waitFinish = true) = 0; public slots: virtual void execBuildAction(LiteApi::IBuild*,LiteApi::BuildAction*) = 0; }; inline QString sourceBuildFilePath(const QString &filePath) { QFileInfo info(filePath); if (info.isDir()) { return info.filePath(); } return info.path(); } inline QString editorBuildFilePath(IEditor *editor) { QString buildFilePath; if (editor) { QString filePath = editor->filePath(); if (!filePath.isEmpty()) { buildFilePath = QFileInfo(filePath).path(); } } return buildFilePath; } inline ILiteBuild *getLiteBuild(LiteApi::IApplication* app) { return LiteApi::findExtensionObject(app,"LiteApi.ILiteBuild"); } inline IBuild *getGoBuild(LiteApi::IApplication *app) { ILiteBuild *build = getLiteBuild(app); if (!build) { return 0; } return build->buildManager()->findBuild("text/x-gosrc"); } inline QString parserArgumentValue(const QString &opt, const QString &text) { int pos = text.indexOf(opt); if (pos == -1) { return QString(); } QString value = text.mid(pos+opt.length()); if (value.startsWith('=')) { value = value.mid(1); } else if (value.startsWith(' ')) { value = value.trimmed(); } if (value.isEmpty()) { return QString(); } if (value.startsWith('\'')) { int pos = value.indexOf('\'',1); if (pos != -1) { return value.left(pos+1); } } else if (value.startsWith('\"')) { int pos = value.indexOf('\"',1); if (pos != -1) { return value.left(pos+1); } } else { int pos = value.indexOf(' '); if (pos != -1) { return value.left(pos); } return value; } return QString(); } inline QString getGoBuildFlagsArgument(LiteApi::IApplication *app, const QString &buildFilePath, const QString &opt) { ILiteBuild *liteBuild = getLiteBuild(app); LiteApi::IBuild *build = getGoBuild(app); if (!liteBuild || !build ) { return QString(); } QString value = liteBuild->buildPathEnvValue(build,buildFilePath,"$(BUILDFLAGS)"); QString tags = parserArgumentValue(opt,value); if (tags.isEmpty()) { value = liteBuild->buildPathEnvValue(build,buildFilePath,"$(BUILDARGS)"); tags = parserArgumentValue(opt,value); } return tags; } inline QString getGoBuildFlagsArgument(LiteApi::IApplication *app, LiteApi::IEditor *editor, const QString &opt) { ILiteBuild *liteBuild = getLiteBuild(app); if (!liteBuild) { return QString(); } QString buildFilePath = editorBuildFilePath(editor); return getGoBuildFlagsArgument(app,buildFilePath,opt); } } //namespace LiteApi #endif //LITEBUILDAPI_H ================================================ FILE: liteidex/src/api/litebuildapi/litebuildapi.pri ================================================ LIBS *= -l$$qtLibraryName(litebuildapi) ================================================ FILE: liteidex/src/api/litebuildapi/litebuildapi.pro ================================================ TARGET = litebuildapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += litebuildapi.h ================================================ FILE: liteidex/src/api/litedebugapi/litedebugapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: litedebugapi.h // Creator: visualfc #ifndef LITEDEBUGAPI_H #define LITEDEBUGAPI_H #include "liteapi/liteapi.h" #include namespace LiteApi { enum DEBUG_MODEL_TYPE{ ASYNC_MODEL = 1, VARS_MODEL, WATCHES_MODEL, FRAMES_MODEL, BREAKPOINTS_MODEL, THREADS_MODEL, LIBRARY_MODEL, GOROUTINES_MODEL, REGS_MODEL, ASM_MODEL }; enum DEBUG_LOG_TYPE { DebugConsoleLog = 1, DebugApplationLog, DebugRuntimeLog, DebugErrorLog }; enum DEBUG_EDITOR_MARKTYPE { BreakPointMarkType = 2000, CurrentLineMarkType = 3000 }; class IDebugger : public QObject { Q_OBJECT public: IDebugger(QObject *parent = 0): QObject(parent) {} virtual ~IDebugger() {} public: virtual QString mimeType() const = 0; virtual QAbstractItemModel *debugModel(DEBUG_MODEL_TYPE type) = 0; virtual void setWorkingDirectory(const QString &dir) = 0; virtual void setEnvironment (const QStringList &environment) = 0; virtual bool start(const QString &cmd, const QString &arguments) = 0; virtual void stop() = 0; virtual bool isRunning() = 0; virtual void stepOver() = 0; virtual void stepInto() = 0; virtual void stepOut() = 0; virtual void continueRun() = 0; virtual void runToLine(const QString &fileName, int line) = 0; virtual void command(const QByteArray &cmd) = 0; virtual void enterAppText(const QString &text) = 0; virtual void enterDebugText(const QString &text) = 0; virtual void expandItem(QModelIndex index, DEBUG_MODEL_TYPE type) = 0; virtual void setInitBreakTable(const QMultiMap &bks) = 0; virtual void setInitWatchList(const QStringList &names) = 0; virtual void insertBreakPoint(const QString &fileName, int line) = 0; virtual void removeBreakPoint(const QString &fileName, int line) = 0; virtual void createWatch(const QString &var) = 0; virtual void removeWatch(const QString &var) = 0; virtual void removeAllWatch() = 0; virtual void dbclickItem(QModelIndex index, DEBUG_MODEL_TYPE type) = 0; signals: void debugStarted(); void debugStoped(); void debugLoaded(); void debugLog(LiteApi::DEBUG_LOG_TYPE type, const QString &log); void setExpand(LiteApi::DEBUG_MODEL_TYPE type, const QModelIndex &index, bool expanded); void setCurrentLine(const QString &fileName, int line); void gotoLine(const QString &fileName, int line); void watchCreated(const QString &watch,const QString &name); void watchRemoved(const QString &watch); void beginUpdateModel(LiteApi::DEBUG_MODEL_TYPE type); void endUpdateModel(LiteApi::DEBUG_MODEL_TYPE type); void scrollTo(LiteApi::DEBUG_MODEL_TYPE type, const QModelIndex &index); }; class IDebuggerManager : public IManager { Q_OBJECT public: IDebuggerManager(QObject *parent = 0) : IManager(parent) {} virtual void addDebugger(IDebugger *debug) = 0; virtual void removeDebugger(IDebugger *debug) = 0; virtual IDebugger *findDebugger(const QString &mimeType) = 0; virtual QList debuggerList() const = 0; virtual void setCurrentDebugger(IDebugger *debug) = 0; virtual IDebugger *currentDebugger() = 0; signals: void currentDebuggerChanged(LiteApi::IDebugger*); }; inline IDebuggerManager *getDebugManager(LiteApi::IApplication *app) { return LiteApi::findExtensionObject(app,"LiteApi.IDebuggerManager"); } class ILiteDebug : public IObject { Q_OBJECT public: ILiteDebug(QObject *parent) : IObject(parent) { } public: virtual IDebuggerManager *debugManager() const = 0; virtual void startDebug(const QString &cmd, const QString &args, const QString &work) = 0; virtual bool isRunning() const = 0; public slots: virtual void continueRun() = 0; virtual void runToLine() = 0; virtual void stopDebug() = 0; virtual void stepOver() = 0; virtual void stepInto() = 0; virtual void stepOut() = 0; virtual void showLine() = 0; virtual void toggleBreakPoint() = 0; virtual void removeAllBreakPoints() = 0; signals: void debugBefore(); void debugEnd(); }; inline ILiteDebug *getLiteDebug(LiteApi::IApplication *app) { return LiteApi::findExtensionObject(app,"LiteApi.ILiteDebug"); } } //namespace LiteApi #endif //LITEDEBUGAPI_H ================================================ FILE: liteidex/src/api/litedebugapi/litedebugapi.pri ================================================ LIBS *= -l$$qtLibraryName(litedebugapi) ================================================ FILE: liteidex/src/api/litedebugapi/litedebugapi.pro ================================================ TARGET = litedebugapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += litedebugapi.h ================================================ FILE: liteidex/src/api/liteeditorapi/liteeditorapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteeditorapi.h // Creator: visualfc #ifndef LITEEDITORAPI_H #define LITEEDITORAPI_H #include "liteapi/liteapi.h" #include #include #include #include namespace TextEditor { class SyntaxHighlighter; } namespace LiteApi { class ILiteEditor; class IWordApi { public: virtual ~IWordApi() {} virtual QString package() const = 0; virtual QStringList apiFiles() const = 0; virtual bool loadApi() = 0; virtual QStringList wordList() const = 0; virtual QStringList expList() const = 0; virtual void appendExp(const QStringList &list) = 0; }; struct Snippet { QString Name; QString Info; QString Text; }; class ISnippetApi { public: virtual ~ISnippetApi() {} virtual QString package() const = 0; virtual QStringList apiFiles() const = 0; virtual bool loadApi() = 0; virtual QList snippetList() const = 0; }; class IEditorApiManager : public IManager { Q_OBJECT public: IEditorApiManager(QObject *parent = 0) : IManager(parent) {} virtual void addWordApi(IWordApi *api) = 0; virtual void removeWordApi(IWordApi *api) = 0; virtual IWordApi *findWordApi(const QString &mimeType) = 0; virtual QList wordApiList() const = 0; virtual void addSnippetApi(ISnippetApi *api) = 0; virtual void removeSnippetApi(ISnippetApi *api) = 0; virtual ISnippetApi *findSnippetApi(const QString &mimeType) = 0; virtual QList snippetApiList() const = 0; }; enum CompletionContext { CompleterCodeContext = 0, CompleterImportContext, }; class ICompleter : public QObject { Q_OBJECT public: ICompleter(QObject *parent): QObject(parent) {} virtual void setEditor(QPlainTextEdit *editor) = 0; virtual QStandardItem *findRoot(const QString &name) = 0; virtual void clearChildItem(QStandardItem *root) = 0; virtual void appendChildItem(QStandardItem *root,QString name,const QString &kind, const QString &info,const QIcon &icon, bool temp) = 0; virtual bool appendItem(const QString &name,const QIcon &icon, bool temp) = 0; virtual bool appendItemEx(const QString &name,const QString &kind, const QString &info,const QIcon &icon, bool temp) = 0; virtual void appendItems(QStringList items, const QString &kind, const QString &info,const QIcon &icon, bool temp) = 0; virtual void appendSnippetItem(const QString &name, const QString &info, const QString &content) = 0; virtual void clearItemChilds(const QString &name) = 0; virtual void clearTemp() = 0; virtual void clear() = 0; virtual void setSearchSeparator(bool b) = 0; virtual bool searchSeparator() const = 0; virtual void setExternalMode(bool b) = 0; virtual bool externalMode() const = 0; virtual void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) = 0; virtual void setFuzzy(bool fuzzy) = 0; virtual void setCompletionPrefix(const QString &prefix) = 0; virtual QString completionPrefix() const = 0; virtual void setCompletionContext(CompletionContext ctx) = 0; virtual CompletionContext completionContext() const = 0; virtual void setSeparator(const QString &sep) = 0; virtual QString separator() const = 0; virtual void showPopup() = 0; virtual void hidePopup() = 0; virtual QAbstractItemView *popup() const = 0; virtual QModelIndex currentIndex() const = 0; virtual QString currentCompletion() const = 0; virtual QAbstractItemModel *completionModel() const = 0; virtual bool startCompleter(const QString &completionPrefix) = 0; virtual void updateCompleterModel() = 0; virtual void updateCompleteInfo(QModelIndex index) = 0; virtual void setImportList(const QStringList &importList) = 0; virtual void setPrefixMin(int min) = 0; virtual int prefixMin() const = 0; signals: void prefixChanged(QTextCursor,QString,bool force); void wordCompleted(const QString &func, const QString &kind, const QString &info); }; class IEditorMark : public QObject { Q_OBJECT public: IEditorMark(QObject *parent) : QObject(parent) {} virtual void addMark(int line, int type) = 0; virtual void addMarkList(const QList &lines, int type) = 0; virtual void removeMark(int line, int type) = 0; virtual void removeMarkList(const QList &lines, int type) = 0; virtual QList markLinesByType(int type) const = 0; virtual QList markBlocksByType(int type) const = 0; virtual QList markTypesByLine(int line) const = 0; virtual ILiteEditor *editor() const = 0; virtual QString filePath() const = 0; signals: void markListChanged(int type); }; class IEditorMarkNode : public QObject { Q_OBJECT public: IEditorMarkNode(QObject *parent = 0) : QObject(parent) {} virtual ~IEditorMarkNode() {} virtual int blockNumber() const = 0; virtual int type() const = 0; virtual QTextBlock block() const = 0; }; class IEditorMarkManager : public IManager { Q_OBJECT public: IEditorMarkManager(QObject *parent = 0) : IManager(parent) {} virtual void registerMark(int type, const QIcon &icon) = 0; virtual QList markTypeList() const = 0; virtual QIcon iconForType(int type) const = 0; virtual int indexOfType(int type) const = 0; virtual QList editorMarkList() const = 0; signals: void editorMarkCreated(LiteApi::IEditorMark *mark); void editorMarkRemoved(LiteApi::IEditorMark *mark); void editorMarkListChanged(LiteApi::IEditorMark *mark, int type); void editorMarkNodeCreated(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node); void editorMarkNodeRemoved(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node); void editorMarkNodeChanged(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node); }; enum EditorNaviagteType{ EditorNavigateNormal = 1, EditorNavigateWarning = 2, EditorNavigateError = 4, EditorNavigateReload = 8, EditorNavigateFind = 16, EditorNavigateSelection = 32, EditorNavigateBad = EditorNavigateWarning|EditorNavigateError }; enum ExtraSelectionKind { CurrentLineSelection, ParenthesesMatchingSelection, LinkSelection, }; struct Link { Link(): linkTextStart(-1) , linkTextEnd(-1) , targetLine(-1) , targetColumn(-1) , showTip(false) , showNav(false) {} void clear() { linkTextStart = -1; linkTextEnd = -1; targetOpenDir.clear(); targetOpenDirInfo.clear(); targetFileName.clear(); targetInfo.clear(); sourceInfo.clear(); targetLine = 0; targetColumn = 0; showTip = false; showNav = false; text.clear(); } bool hasValidTarget() const { return !targetFileName.isEmpty(); } bool hasValidLinkText() const { return linkTextStart != linkTextEnd; } bool operator==(const Link &other) const { return linkTextStart == other.linkTextStart && linkTextEnd == other.linkTextEnd; } int linkTextStart; int linkTextEnd; int targetLine; int targetColumn; bool showTip; bool showNav; QString targetOpenDir; QString targetOpenDirInfo; QString targetFileName; QString targetInfo; QString sourceInfo; QPoint cursorPos; QString text; }; class ITextLexer : public QObject { public: ITextLexer(QObject *parent = 0) : QObject(parent) {} virtual ~ITextLexer() {} virtual bool isLangSupport() const = 0; virtual bool isInComment(const QTextCursor &cursor) const = 0; virtual bool isInString(const QTextCursor &cursor) const = 0; virtual bool isInEmptyString(const QTextCursor &cursor) const = 0; virtual bool isEndOfString(const QTextCursor &cursor) const = 0; virtual bool isInStringOrComment(const QTextCursor &cursor) const = 0; virtual bool isCanAutoCompleter(const QTextCursor &cursor) const = 0; virtual bool isInImport(const QTextCursor &cursor) const = 0; virtual int startOfFunctionCall(const QTextCursor &cursor) const = 0; virtual QString fetchFunctionTip(const QString &func, const QString &kind, const QString &info) = 0; virtual bool fetchFunctionArgs(const QString &str, int &argnr, int &parcount) = 0; virtual QString stringQuoteList() const = 0; virtual bool hasStringBackslash() const = 0; }; class ILiteEditor : public ITextEditor { Q_OBJECT public: ILiteEditor(QObject *parent = 0) : ITextEditor(parent) {} virtual QTextDocument* document() const = 0; virtual void setCompleter(ICompleter *complter) = 0; virtual void setEditorMark(IEditorMark *mark) = 0; virtual void setTextLexer(ITextLexer *lexer) = 0; virtual void setSpellCheckZoneDontComplete(bool b) = 0; virtual void insertNavigateMark(int line, EditorNaviagteType type, const QString &msg, const QString &tag = "", int offset = 0, int selection = 0) = 0; virtual void clearNavigateMarak(int line) = 0; virtual void clearAllNavigateMarks() = 0; virtual void clearAllNavigateMark(EditorNaviagteType types, const QString &tag = "") = 0; virtual void setNavigateHead(EditorNaviagteType type, const QString &msg) = 0; virtual void showLink(const Link &link) = 0; virtual void clearLink() = 0; virtual void setTabOption(int tabSize, bool tabToSpace) = 0; virtual void setEnableAutoIndentAction(bool b) = 0; virtual bool isLineEndUnix() const = 0; virtual void setLineEndUnix(bool b) = 0; virtual void showToolTipInfo(const QPoint & pos, const QString & text) = 0; virtual void loadDiff(const QString &diff) = 0; virtual void loadTextUseDiff(const QString &text) = 0; signals: void updateLink(const QTextCursor &cursor, const QPoint &pos, bool nav); }; inline ILiteEditor *getLiteEditor(IEditor *editor) { if (editor && editor->extension()) { return findExtensionObject(editor->extension(),"LiteApi.ILiteEditor"); } return 0; } inline ITextLexer *getTextLexer(IEditor *editor) { if (editor && editor->extension()) { return findExtensionObject(editor->extension(),"LiteApi.ITextLexer"); } return 0; } inline IEditorMark *getEditorMark(IEditor *editor) { if (editor && editor->extension()) { return findExtensionObject(editor->extension(),"LiteApi.IEditorMark"); } return 0; } inline IEditorMarkManager *getEditorMarkManager(IApplication *app) { if (app && app->extension()) { return findExtensionObject(app->extension(),"LiteApi.IEditorMarkManager"); } return 0; } class IHighlighterFactory : public QObject { Q_OBJECT public: IHighlighterFactory(QObject *parent) : QObject(parent) {} virtual QStringList mimeTypes() const = 0; virtual TextEditor::SyntaxHighlighter* create(ITextEditor *editor, QTextDocument *doc, const QString &mimeType) = 0; }; class IHighlighterManager :public IManager { Q_OBJECT public: IHighlighterManager(QObject *parent) : IManager(parent) {} virtual void addFactory(IHighlighterFactory *factroy) = 0; virtual void removeFactory(IHighlighterFactory *factory) = 0; virtual QList factoryList() const = 0; virtual QStringList mimeTypeList() const = 0; virtual IHighlighterFactory *findFactory(const QString &mimeType) const = 0; }; inline IHighlighterManager *getHighlighterManager(LiteApi::IApplication *app) { return static_cast(app->extension()->findObject("LiteApi.IHighlighterManager")); } inline QString wordUnderCursor(QTextCursor tc, bool *moveLeft = 0, int *selectStart = 0) { QString text = tc.block().text(); int pos = tc.positionInBlock(); if (pos > 0 && pos < text.length()) { QChar ch = text.at(pos-1); if (ch.isLetterOrNumber() || ch == '_') { tc.movePosition(QTextCursor::Left); if (moveLeft) { *moveLeft = true; } } } tc.select(QTextCursor::WordUnderCursor); if (selectStart) { *selectStart = tc.selectionStart(); } return tc.selectedText(); } inline void selectWordUnderCursor(QTextCursor &tc, bool *moveLeft = 0) { QString text = tc.block().text(); int pos = tc.positionInBlock(); if (pos > 0 && pos < text.length()) { QChar ch = text.at(pos-1); if (ch.isLetterOrNumber() || ch == '_') { tc.movePosition(QTextCursor::Left); if (moveLeft) { *moveLeft = true; } } } tc.select(QTextCursor::WordUnderCursor); } } //namespace LiteApi #endif //LITEEDITORAPI_H ================================================ FILE: liteidex/src/api/liteeditorapi/liteeditorapi.pri ================================================ LIBS *= -l$$qtLibraryName(liteeditorapi) ================================================ FILE: liteidex/src/api/liteeditorapi/liteeditorapi.pro ================================================ TARGET = liteeditorapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += liteeditorapi.h ================================================ FILE: liteidex/src/api/liteenvapi/liteenvapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteenvapi.h // Creator: visualfc #ifndef LITEENVAPI_H #define LITEENVAPI_H #include "liteapi/liteapi.h" #include #include #include namespace LiteApi { class IEnv : public QObject { Q_OBJECT public: IEnv(QObject *parent = 0): QObject(parent) {} virtual ~IEnv() {} virtual QString id() const = 0; virtual QString filePath() const = 0; virtual QStringList orgEnvLines() const = 0; virtual QMap goEnvMap() const = 0; virtual QProcessEnvironment& environment() = 0; virtual void reload() = 0; signals: void goenvError(QString,QString); void goenvChanged(QString); }; class IEnvManager : public IManager { Q_OBJECT public: IEnvManager(QObject *parent = 0) : IManager(parent) {} virtual QList envList() const = 0; virtual IEnv *findEnv(const QString &id, const QString &backup = "system") const = 0; virtual void setCurrentEnvId(const QString &id) = 0; virtual IEnv *currentEnv() const = 0; virtual QProcessEnvironment currentEnvironment() const = 0; virtual void reloadCurrentEnv() = 0; signals: void currentEnvChanged(LiteApi::IEnv*); }; class IGoEnvManger: public IManager { Q_OBJECT public: IGoEnvManger(QObject *parent = 0) : IManager(parent) {} virtual QString gocmd() const = 0; virtual QString gotools() const = 0; virtual QString GOROOT() const = 0; virtual QStringList GOPATH() const = 0; virtual QProcessEnvironment environment() const = 0; virtual QProcessEnvironment customEnvironment(const QString &buildFilePath, QString *pCustomBuildPath = 0) const = 0; virtual QStringList customGOPATH(const QString &buildPath, QString *pCustomBuildPath = 0) const = 0; virtual QString findRealCustomBuildPath(const QString &buildPath) const = 0; virtual bool hasCustomGOPATH(const QString &buildPath) const = 0; virtual void updateGoEnv() = 0; virtual void updateCustomGOPATH(const QString &buildPath) = 0; signals: void globalGOPATHChanged(); void customGOPATHChanged(const QString &buildPath); }; inline IEnvManager *getEnvManager(LiteApi::IApplication* app) { return LiteApi::findExtensionObject(app,"LiteApi.IEnvManager"); } inline IGoEnvManger *getGoEnvManager(LiteApi::IApplication *app) { return LiteApi::findExtensionObject(app,"LiteApi.IGoEnvManger"); } inline QProcessEnvironment getCurrentEnvironment(LiteApi::IApplication *app) { QProcessEnvironment e; IEnvManager *env = getEnvManager(app); if (env) { e = env->currentEnvironment(); } else { e = QProcessEnvironment::systemEnvironment(); } #ifdef Q_OS_WIN QString sep = ";"; #else QString sep = ":"; #endif QStringList pathList; foreach (QString path, e.value("PATH").split(sep,qtSkipEmptyParts)) { pathList.append(QDir::toNativeSeparators(path)); } pathList.append(app->applicationPath()); pathList.removeDuplicates(); e.insert("PATH",pathList.join(sep)); return e; } inline QString getDefaultGOOS() { const char* goos = ""; #ifdef Q_OS_WIN goos = "windows"; #endif #ifdef Q_OS_LINUX goos = "linux"; #endif #ifdef Q_OS_DARWIN goos = "darwin"; #endif #ifdef Q_OS_FREEBSD goos = "freebsd"; #endif #ifdef Q_OS_OPENBSD goos = "openbsd"; #endif return goos; } inline QString getDefaultGOROOT() { #ifdef Q_OS_WIN return "c:\\go"; #else return "/usr/local/go"; #endif } inline bool hasGoEnv(const QProcessEnvironment &env) { return env.contains("GOROOT") && env.contains("GOARCH"); } inline QProcessEnvironment getSysEnvironment(LiteApi::IApplication *app) { QProcessEnvironment env = getCurrentEnvironment(app); #ifdef Q_OS_WIN QString sep = ";"; #else QString sep = ":"; #endif IEnvManager *mgr = LiteApi::getEnvManager(app); if (mgr) { LiteApi::IEnv *ce = mgr->currentEnv(); if (ce) { QMapIterator i(ce->goEnvMap()); while(i.hasNext()) { i.next(); env.insert(i.key(),i.value()); } } } QString goos = env.value("GOOS"); if (goos.isEmpty()) { goos = getDefaultGOOS(); } QString goroot = env.value("GOROOT"); if (goroot.isEmpty()) { goroot = getDefaultGOROOT(); } return env; } inline QProcessEnvironment getGoEnvironment(LiteApi::IApplication *app) { QProcessEnvironment env = getCurrentEnvironment(app); #ifdef Q_OS_WIN QString sep = ";"; #else QString sep = ":"; #endif IEnvManager *mgr = LiteApi::getEnvManager(app); if (mgr) { LiteApi::IEnv *ce = mgr->currentEnv(); if (ce) { QMapIterator i(ce->goEnvMap()); while(i.hasNext()) { i.next(); env.insert(i.key(),i.value()); } } } QString goos = env.value("GOOS"); if (goos.isEmpty()) { goos = getDefaultGOOS(); } if (!env.contains("GOEXE")) { QString goexe; if (goos == "windows") { goexe = ".exe"; } env.insert("GOEXE",goexe); } QString goarch = env.value("GOARCH"); QString goroot = env.value("GOROOT"); if (goroot.isEmpty()) { goroot = getDefaultGOROOT(); } if (app->settings()->value("liteide/use111gomodule",false).toBool()) { env.insert("GO111MODULE",app->settings()->value("liteide/go111module").toString()); } if (app->settings()->value("liteide/usegoproxy",false).toBool()) { env.insert("GOPROXY",app->settings()->value("liteide/goproxy").toString()); } if (app->settings()->value("liteide/usegoprivate",false).toBool()) { env.insert("GOPRIVATE",app->settings()->value("liteide/goprivate").toString()); } if (app->settings()->value("liteide/usegonoproxy",false).toBool()) { env.insert("GONOPROXY",app->settings()->value("liteide/gonoproxy").toString()); } if (app->settings()->value("liteide/usegonosumdb",false).toBool()) { env.insert("GONOSUMDB",app->settings()->value("liteide/gonosumdb").toString()); } QStringList pathList; if (app->settings()->value("liteide/usesysgopath",true).toBool()) { foreach (QString path, env.value("GOPATH").split(sep,qtSkipEmptyParts)) { pathList.append(QDir::toNativeSeparators(path)); } } if (app->settings()->value("liteide/uselitegopath",true).toBool()) { foreach (QString path, app->settings()->value("liteide/gopath").toStringList()) { pathList.append(QDir::toNativeSeparators(path)); } } pathList.removeDuplicates(); env.insert("GOPATH",pathList.join(sep)); if (!goroot.isEmpty()) { pathList.prepend(goroot); } QStringList binList; QString gobin = env.value("GOBIN"); if (!gobin.isEmpty()) { binList.append(gobin); } foreach (QString path, pathList) { binList.append(QFileInfo(path,"bin").filePath()); binList.append(QFileInfo(path,"bin/"+goos+"_"+goarch).filePath()); } env.insert("PATH",env.value("PATH")+sep+binList.join(sep)+sep); return env; } inline QStringList getGOPATH(LiteApi::IApplication *app, bool includeGoroot) { QProcessEnvironment env = getGoEnvironment(app); #ifdef Q_OS_WIN QString sep = ";"; #else QString sep = ":"; #endif QStringList pathList; QString goroot = QDir::toNativeSeparators(env.value("GOROOT")); if (includeGoroot) { pathList.append(goroot); } foreach (QString path, env.value("GOPATH").split(sep,qtSkipEmptyParts)) { pathList.append(QDir::toNativeSeparators(path)); } if (!includeGoroot) { pathList.removeAll(goroot); } pathList.removeDuplicates(); return pathList; } inline QString getGOROOT(LiteApi::IApplication *app) { return getGoEnvironment(app).value("GOROOT"); } inline QString lookupSrcRoot(const QString &buildFilePath) { int index = buildFilePath.indexOf("/src/"); if (index < 0) { return QString(); } return buildFilePath.left(index+4); } inline QString lookupParentHasCustom(LiteApi::IApplication *app, const QString &buildFilePath, const QString &srcRoot, QString *pCustomParent = 0) { QFileInfo info(buildFilePath); QString parent = info.path(); if (parent == srcRoot || info.dir().isRoot()) { return QString(); } QString customKey = "litebuild-custom/"+parent; bool use_custom_gopath = app->settings()->value(customKey+"#use_custom_gopath",false).toBool(); if (use_custom_gopath) { if (pCustomParent) { *pCustomParent = parent; } return customKey; } return lookupParentHasCustom(app,parent,srcRoot); } inline QProcessEnvironment getCustomGoEnvironment(LiteApi::IApplication *app, const QString &buildFilePath, QString *pCustomBuildPath = 0) { if (buildFilePath.isEmpty()) { return getGoEnvironment(app); } QString customKey = "litebuild-custom/"+buildFilePath; QString customBuildPath = buildFilePath; bool use_custom_gopath = app->settings()->value(customKey+"#use_custom_gopath",false).toBool(); if (!use_custom_gopath) { QString srcRoot = lookupSrcRoot(buildFilePath); if (!srcRoot.isEmpty()) { customKey = lookupParentHasCustom(app,buildFilePath,srcRoot, &customBuildPath); if (!customKey.isEmpty()) { use_custom_gopath = true; } } } if (!use_custom_gopath) { return getGoEnvironment(app); } if (pCustomBuildPath) { *pCustomBuildPath = customBuildPath; } QProcessEnvironment env = getCurrentEnvironment(app); #ifdef Q_OS_WIN QString sep = ";"; #else QString sep = ":"; #endif IEnvManager *mgr = LiteApi::getEnvManager(app); if (mgr) { LiteApi::IEnv *ce = mgr->currentEnv(); if (ce) { QMapIterator i(ce->goEnvMap()); while(i.hasNext()) { i.next(); env.insert(i.key(),i.value()); } } } QString goos = env.value("GOOS"); if (goos.isEmpty()) { goos = getDefaultGOOS(); } if (!env.contains("GOEXE")) { QString goexe; if (goos == "windows") { goexe = ".exe"; } env.insert("GOEXE",goexe); } QString goarch = env.value("GOARCH"); QString goroot = env.value("GOROOT"); if (goroot.isEmpty()) { goroot = getDefaultGOROOT(); } QStringList pathList; bool inherit_sys_gopath = app->settings()->value(customKey+"#inherit_sys_gopath",true).toBool(); bool inherit_lite_gopath = app->settings()->value(customKey+"#inherit_lite_gopath",true).toBool(); bool custom_gopath = app->settings()->value(customKey+"#custom_gopath",false).toBool(); if (inherit_sys_gopath) { foreach (QString path, env.value("GOPATH").split(sep,qtSkipEmptyParts)) { pathList.append(QDir::toNativeSeparators(path)); } } if (inherit_lite_gopath) { foreach (QString path, app->settings()->value("liteide/gopath").toStringList()) { pathList.append(QDir::toNativeSeparators(path)); } } if (custom_gopath) { foreach (QString path, app->settings()->value(customKey+"#gopath").toStringList()) { pathList.append(QDir::toNativeSeparators(path)); } } pathList.removeDuplicates(); env.insert("GOPATH",pathList.join(sep)); if (!goroot.isEmpty()) { pathList.prepend(goroot); } QStringList binList; QString gobin = env.value("GOBIN"); if (!gobin.isEmpty()) { binList.append(gobin); } foreach (QString path, pathList) { binList.append(QFileInfo(path,"bin").filePath()); binList.append(QFileInfo(path,"bin/"+goos+"_"+goarch).filePath()); } env.insert("PATH",env.value("PATH")+sep+binList.join(sep)+sep); return env; } inline QProcessEnvironment getCustomGoEnvironment(LiteApi::IApplication *app, LiteApi::IEditor *editor) { QString buildFilePath; if (editor) { QString filePath = editor->filePath(); if (!filePath.isEmpty()) { buildFilePath = QFileInfo(filePath).path(); } } return getCustomGoEnvironment(app,buildFilePath); } } //namespace LiteApi #endif //LITEENVAPI_H ================================================ FILE: liteidex/src/api/liteenvapi/liteenvapi.pri ================================================ LIBS *= -l$$qtLibraryName(liteenvapi) ================================================ FILE: liteidex/src/api/liteenvapi/liteenvapi.pro ================================================ TARGET = liteenvapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += liteenvapi.h ================================================ FILE: liteidex/src/api/litefindapi/litefindapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: litefindapi.h // Creator: visualfc #ifndef LITEFINDAPI_H #define LITEFINDAPI_H #include "liteapi/liteapi.h" namespace LiteApi { class FileSearchResult { public: FileSearchResult() : line(0), col(0), len(0) {} FileSearchResult(const QString &path, const QString &lineText, int line, int col, int len) : path(path), lineText(lineText), line(line), col(col), len(len) {} public: QString path; QString lineText; int line; int col; int len; }; class IFileSearch : public QObject { Q_OBJECT public: IFileSearch(QObject *parent) : QObject(parent) {} virtual QString mimeType() const = 0; virtual QString displayName() const = 0; virtual QWidget* widget() const = 0; virtual void start() = 0; virtual void cancel() = 0; virtual void activate() = 0; virtual QString searchText() const = 0; virtual bool replaceMode() const = 0; virtual bool readOnly() const = 0; virtual bool canCancel() const = 0; virtual void setSearchInfo(const QString &text, const QString &filter, const QString &path) = 0; signals: void searchTextChanged(const QString &text); void findStarted(); void findFinished(bool b = true); void findResult(const LiteApi::FileSearchResult &result); void findError(const QString &error); }; class IFileSearchManager : public IManager { Q_OBJECT public: IFileSearchManager(QObject *parent = 0) : IManager(parent) {} virtual void addFileSearch(IFileSearch* search) = 0; virtual IFileSearch *findFileSearch(const QString &mime) = 0; virtual QList fileSearchList() const = 0; virtual void setCurrentSearch(LiteApi::IFileSearch *search) = 0; virtual void showFileSearch(const QString &text, const QString &filter, const QString &path) = 0; public slots: virtual void newSearch() = 0; }; inline IFileSearchManager* getFileSearchManager(LiteApi::IApplication *app) { return LiteApi::findExtensionObject(app,"LiteApi.IFileSearchManager"); } } //namespace LiteApi #endif //LITEFINDAPI_H ================================================ FILE: liteidex/src/api/litefindapi/litefindapi.pri ================================================ LIBS *= -l$$qtLibraryName(litefindapi) ================================================ FILE: liteidex/src/api/litefindapi/litefindapi.pro ================================================ TARGET = litefindapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += litefindapi.h ================================================ FILE: liteidex/src/api/litettyapi/litettyapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: litettyapi.h // Creator: visualfc #ifndef LITETTYAPI_H #define LITETTYAPI_H #include "liteapi/liteapi.h" #include #include namespace LiteApi { class ITty : public QObject { Q_OBJECT public: ITty(QObject *parent = 0): QObject(parent) {} virtual QString serverName() const = 0; virtual QString errorString() const = 0; virtual bool listen() = 0; virtual void shutdown() = 0; virtual void write(const QByteArray &data) = 0; signals: void byteDelivery(const QByteArray &data); }; class ILiteTty : public QObject { public: ILiteTty(QObject *parent) : QObject(parent) { } virtual ITty* createTty(QObject *parent) const = 0; }; inline ILiteTty *getLiteTty(LiteApi::IApplication* app) { return LiteApi::findExtensionObject(app,"LiteApi.ILiteTty"); } inline ITty *createTty(LiteApi::IApplication *app,QObject *parent) { ILiteTty *liteTty = getLiteTty(app); if (liteTty) { return liteTty->createTty(parent); } return 0; } } //namespace LiteApi #endif //LITETTYAPI_H ================================================ FILE: liteidex/src/api/litettyapi/litettyapi.pri ================================================ LIBS *= -l$$qtLibraryName(litettyapi) ================================================ FILE: liteidex/src/api/litettyapi/litettyapi.pro ================================================ TARGET = litettyapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += litettyapi.h ================================================ FILE: liteidex/src/api/quickopenapi/quickopenapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: quickopenapi.h // Creator: visualfc #ifndef QUICKOPENAPI_H #define QUICKOPENAPI_H #include "liteapi/liteapi.h" class QTreeView; class QLineEdit; namespace LiteApi { class IQuickOpen : public QObject { Q_OBJECT public: IQuickOpen(QObject *parent = 0) : QObject(parent) {} virtual QString id() const = 0; virtual QString info() const = 0; virtual QString placeholderText() const = 0; virtual void activate() = 0; virtual QAbstractItemModel *model() const = 0; virtual QModelIndex rootIndex() const = 0; virtual void updateModel() = 0; virtual QModelIndex filterChanged(const QString &text) = 0; virtual void indexChanged(const QModelIndex &index) = 0; virtual bool selected(const QString &text, const QModelIndex &index) = 0; virtual void cancel() = 0; }; class IQuickOpenFolder : public IQuickOpen { Q_OBJECT public: IQuickOpenFolder(QObject *parent = 0) : IQuickOpen(parent) {} virtual void setFolder(const QString &folder) = 0; virtual void setPlaceholderText(const QString &text) = 0; }; class IQuickOpenFileSystem : public IQuickOpen { public: IQuickOpenFileSystem(QObject *parent = 0) : IQuickOpen(parent) {} virtual void setRootPath(const QString &root) = 0; virtual void setPlaceholderText(const QString &text) = 0; virtual QModelIndex indexForPath(const QString &indexForPath) const = 0; virtual QString pathForIndex(const QModelIndex &index) const = 0; }; class IQuickOpenAdapter : public QObject { Q_OBJECT public: IQuickOpenAdapter(QObject *parent = 0) : QObject(parent) {} virtual QStringList mimeTypes() const = 0; virtual IQuickOpen *load(const QString &mimeType) = 0; }; class IQuickOpenMimeType : public LiteApi::IQuickOpen { public: IQuickOpenMimeType(QObject *parent) : LiteApi::IQuickOpen(parent) {} virtual void addAdapter(LiteApi::IQuickOpenAdapter *factory) = 0; virtual void setId(const QString &id) = 0; virtual void setInfo(const QString &info) = 0; virtual void setNoFoundMessage(const QString &message) = 0; }; class IQuickOpenManager : public IManager { Q_OBJECT public: IQuickOpenManager(QObject *parent = 0) : IManager(parent) {} virtual void addFilter(const QString &sym, IQuickOpen *filter) = 0; virtual void removeFilter(IQuickOpen *filter) = 0; virtual QList filterList() const = 0; virtual QMap symFilterMap() const = 0; virtual void setCurrentFilter(IQuickOpen *filter) = 0; virtual IQuickOpen *currentFilter() const = 0; virtual QModelIndex currentIndex() const = 0; virtual void showById(const QString &id) = 0; virtual void showBySymbol(const QString &sym) = 0; virtual IQuickOpen *findById(const QString &id) = 0; virtual IQuickOpen *findBySymbol(const QString &sym) = 0; virtual QWidget *widget() const = 0; virtual QTreeView *modelView() const = 0; virtual QLineEdit *lineEdit() const = 0; virtual void setTempToolBar(QToolBar *tooBar) = 0; public: virtual void showPopup(QPoint *pos = 0) = 0; virtual void hidePopup() = 0; public: virtual IQuickOpenMimeType *registerQuickOpenMimeType(const QString &sym) = 0; signals: void currentFilterChanged(IQuickOpen *filter); }; inline IQuickOpenManager *getQuickOpenManager(LiteApi::IApplication* app) { return LiteApi::findExtensionObject(app,"LiteApi.IQuickOpenManager"); } inline IQuickOpenFolder *getQuickOpenFolder(LiteApi::IQuickOpenManager *mgr) { return (IQuickOpenFolder*)mgr->findById("quickopen/folder"); } inline IQuickOpenFileSystem *getQuickOpenFileSystem(LiteApi::IQuickOpenManager *mgr) { return (IQuickOpenFileSystem*)mgr->findById("quickopen/filesystem"); } } //namespace LiteApi #endif //QUICKOPENAPI_H ================================================ FILE: liteidex/src/api/quickopenapi/quickopenapi.pri ================================================ LIBS *= -l$$qtLibraryName(quickopenapi) ================================================ FILE: liteidex/src/api/quickopenapi/quickopenapi.pro ================================================ TARGET = quickopenapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += quickopenapi.h ================================================ FILE: liteidex/src/api/terminalapi/terminalapi.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2020 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: terminalapi.h // Creator: visualfc #ifndef TERMINALAPI_H #define TERMINALAPI_H #include "liteapi/liteapi.h" class QTreeView; class QLineEdit; namespace LiteApi { class ITerminal : public QObject { Q_OBJECT public: ITerminal(QObject *parent = 0) : QObject(parent) {} virtual void openDefaultTerminal(const QString &workDir) = 0; }; inline ITerminal* getTerminalManager(LiteApi::IApplication *app) { return LiteApi::findExtensionObject(app,"LiteApi.ITerminal"); } } //namespace LiteApi #endif //TERMINALAPI_H ================================================ FILE: liteidex/src/api/terminalapi/terminalapi.pri ================================================ LIBS *= -l$$qtLibraryName(terminalapi) ================================================ FILE: liteidex/src/api/terminalapi/terminalapi.pro ================================================ TARGET = terminalapi TEMPLATE = lib CONFIG += staticlib include (../../liteideapi.pri) include (../liteapi/liteapi.pri) HEADERS += terminalapi.h ================================================ FILE: liteidex/src/libgopher/libgopher.go ================================================ package main /* //flag: 1 stdout, 2 stderr, 0 finished typedef struct {char *data; int size;} TString; typedef int (*CB)(void *ctx, int flag, char *data, int size); static int WriteContext(void *ctx, void *cb, int flag, char *data, int size) { return ((CB)cb)(ctx,flag,data,size); } #include */ import "C" import ( "bytes" "io" "os" "strings" "unsafe" "github.com/visualfc/gotools/astview" "github.com/visualfc/gotools/buildctx" "github.com/visualfc/gotools/command" "github.com/visualfc/gotools/docview" "github.com/visualfc/gotools/finddoc" "github.com/visualfc/gotools/gofmt" "github.com/visualfc/gotools/gopresent" "github.com/visualfc/gotools/jsonfmt" "github.com/visualfc/gotools/pkgs" "github.com/visualfc/gotools/runcmd" "github.com/visualfc/gotools/types" ) type Context struct { ctx unsafe.Pointer cb unsafe.Pointer flag C.int } func (c *Context) Write(data []byte) (n int, err error) { cdata := C.CBytes(data) defer C.free(unsafe.Pointer(cdata)) return int(C.WriteContext(c.ctx, c.cb, c.flag, (*C.char)(cdata), C.int(len(data)))), nil } func (c *Context) Finished(err error) { if err == nil { C.WriteContext(c.ctx, c.cb, 0, nil, 0) return } s := err.Error() if s == "" { s = "unknown error" } cdata := C.CString(s) defer C.free(unsafe.Pointer(cdata)) C.WriteContext(c.ctx, c.cb, 0, cdata, C.int(len(s))) } var ( buildEnv = make(map[string]string) ) //export Setenv func Setenv(ck *C.TString, cv *C.TString) { os.Setenv(C.GoStringN(ck.data, ck.size), C.GoStringN(ck.data, ck.size)) } //export SetBuildEnv func SetBuildEnv(ck *C.TString, cv *C.TString) { key := C.GoStringN(ck.data, ck.size) value := C.GoStringN(cv.data, cv.size) buildEnv[key] = value } //export ClearBuildEnv func ClearBuildEnv() { buildEnv = make(map[string]string) } func init() { buildctx.SetLookupEnv(func(key string) (string, bool) { r, ok := buildEnv[key] return r, ok }) } //export InvokeAsync func InvokeAsync(cid *C.TString, cargs *C.TString, csep *C.TString, csin *C.TString, ctx unsafe.Pointer, cb unsafe.Pointer) { id := C.GoStringN(cid.data, cid.size) args := C.GoStringN(cargs.data, cargs.size) sep := C.GoStringN(csep.data, csep.size) sin := C.GoStringN(csin.data, csin.size) go func(id string, args string, sep string, sin string) { stdout := &Context{ctx, cb, 1} stderr := &Context{ctx, cb, 2} err := InvokeHelper(id, args, sep, bytes.NewBufferString(sin), stdout, stderr) stdout.Finished(err) }(id, args, sep, sin) } //export Invoke func Invoke(id string, args string, sep string, sin string, sout *string, serr *string) int32 { var err error var stdout bytes.Buffer var stderr bytes.Buffer err = InvokeHelper(id, args, sep, bytes.NewBufferString(sin), &stdout, &stderr) *sout = stdout.String() *serr = stderr.String() if err != nil { *serr = err.Error() return -1 } return 0 } func InvokeCommand(id string, args string, sep string, stdin string) (sout string, serr string, err error) { var stdout bytes.Buffer var stderr bytes.Buffer err = InvokeHelper(id, args, sep, bytes.NewBufferString(stdin), &stdout, &stderr) sout = stdout.String() serr = stderr.String() return } func InvokeHelper(id string, args string, sep string, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { for _, cmd := range command.CommandList() { if cmd == string(id) { var arguments []string arguments = append(arguments, id) if len(args) > 0 { if sep == "" { sep = " " } for _, opt := range strings.Split(args, sep) { if len(opt) > 0 { arguments = append(arguments, opt) } } } err := command.RunArgs(arguments, stdin, stdout, stderr, ) return err } } return os.ErrInvalid } func init() { command.Register(types.Command) command.Register(jsonfmt.Command) command.Register(finddoc.Command) command.Register(runcmd.Command) command.Register(docview.Command) command.Register(astview.Command) command.Register(gofmt.Command) command.Register(gopresent.Command) command.Register(pkgs.Command) } func main() {} ================================================ FILE: liteidex/src/license_update.lua ================================================ local tmp = "/tmp" local sep = "/" local upper = ".." require"lfs" print ("license update") local license = [[ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2020 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ ]] local info = [[ // Module: $FILENAME // Creator: $ANCHOR $EMAIL ]] function update_head(file,name) local f = io.open(file,"r") if f == nil then return end local data = f:read("*all") f:close() local i0 = string.find(data,"Module:") local i1 = string.find(data,"Creator:") if i0 ~= nil and i1 ~= nil then print("skip",file) return end local i = string.find(data,"#") if i == nil then i = 1 end f = io.open(file,"w") if f == nil then return end local w_info = string.gsub(info,"$FILENAME",name) w_info = string.gsub(w_info,"$ANCHOR","visualfc") w_info = string.gsub(w_info,"$EMAIL","") f:write(license..w_info..string.sub(data,i,#data)) f:close() print(file) end function process_file(file,name) local ext = string.match(file,"%.%w+$") if ext == ".h" or ext == ".cpp" then update_head(file,name) end end function attrdir (path) for file in lfs.dir(path) do if file ~= "." and file ~= ".." then local f = path..sep..file local attr = lfs.attributes (f) assert (type(attr) == "table") if attr.mode == "directory" then attrdir (f) else process_file(f,file) end end end end attrdir("./liteapp") attrdir("./plugins") attrdir("./utils") attrdir("./api") ================================================ FILE: liteidex/src/liteapp/Info.plist ================================================ NSPrincipalClass NSApplication NSHighResolutionCapable True NSHumanReadableCopyright Copyright © 2011-2025 visualfc. All rights reserved. CFBundleIconFile liteide.icns CFBundlePackageType APPL CFBundleSignature ???? CFBundleExecutable LiteIDE CFBundleIdentifier com.visualfc.liteide CFBundleVersion X38 CFBundleShortVersionString 38.4 CFBundleDocumentTypes CFBundleTypeExtensions h CFBundleTypeIconFile c.icns CFBundleTypeName C header file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions c CFBundleTypeIconFile c.icns CFBundleTypeName C source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions gitattributes gitconfig gitignore CFBundleTypeIconFile config.icns CFBundleTypeName Git configuration file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions asp aspx cshtml jshtm jsp phtml shtml CFBundleTypeIconFile html.icns CFBundleTypeName HTML template document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions bat cmd CFBundleTypeIconFile bat.icns CFBundleTypeName Windows command script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions bowerrc CFBundleTypeIconFile Bower.icns CFBundleTypeName Bower document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions config editorconfig ini cfg CFBundleTypeIconFile config.icns CFBundleTypeName Configuration file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions hh hpp hxx h++ CFBundleTypeIconFile cpp.icns CFBundleTypeName C++ header file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions cc cpp cxx c++ CFBundleTypeIconFile cpp.icns CFBundleTypeName C++ source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions m CFBundleTypeIconFile default.icns CFBundleTypeName Objective-C source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions mm CFBundleTypeIconFile cpp.icns CFBundleTypeName Objective-C++ source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions cs csx CFBundleTypeIconFile csharp.icns CFBundleTypeName C# source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions css CFBundleTypeIconFile css.icns CFBundleTypeName CSS CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions go CFBundleTypeIconFile go.icns CFBundleTypeName Go source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions htm html xhtml CFBundleTypeIconFile HTML.icns CFBundleTypeName HTML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions jade CFBundleTypeIconFile Jade.icns CFBundleTypeName Jade document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions jav java CFBundleTypeIconFile Java.icns CFBundleTypeName Java document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions js jscsrc jshintrc mjs cjs CFBundleTypeIconFile Javascript.icns CFBundleTypeName Javascript file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions json CFBundleTypeIconFile JSON.icns CFBundleTypeName JSON document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions less CFBundleTypeIconFile Less.icns CFBundleTypeName Less document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions markdown md mdoc mdown mdtext mdtxt mdwn mkd mkdn CFBundleTypeIconFile Markdown.icns CFBundleTypeName Markdown document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions php CFBundleTypeIconFile PHP.icns CFBundleTypeName PHP source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ps1 psd1 psm1 CFBundleTypeIconFile Powershell.icns CFBundleTypeName Powershell script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions py pyi CFBundleTypeIconFile Python.icns CFBundleTypeName Python script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions gemspec rb erb CFBundleTypeIconFile Ruby.icns CFBundleTypeName Ruby source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions scss sass CFBundleTypeIconFile SASS.icns CFBundleTypeName SASS file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions sql CFBundleTypeIconFile SQL.icns CFBundleTypeName SQL script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ts CFBundleTypeIconFile TypeScript.icns CFBundleTypeName TypeScript file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions tsx jsx CFBundleTypeIconFile React.icns CFBundleTypeName React source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions vue CFBundleTypeIconFile Vue.icns CFBundleTypeName Vue source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ascx csproj dtd plist wxi wxl wxs xml xaml CFBundleTypeIconFile XML.icns CFBundleTypeName XML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions eyaml eyml yaml yml CFBundleTypeIconFile YAML.icns CFBundleTypeName YAML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions bash bash_login bash_logout bash_profile bashrc profile rhistory rprofile sh zlogin zlogout zprofile zsh zshenv zshrc CFBundleTypeIconFile Shell.icns CFBundleTypeName Shell script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions clj cljs cljx clojure CFBundleTypeIconFile default.icns CFBundleTypeName Clojure source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions code-workspace CFBundleTypeIconFile default.icns CFBundleTypeName VS Code workspace file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions coffee CFBundleTypeIconFile default.icns CFBundleTypeName CoffeeScript source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions csv CFBundleTypeIconFile default.icns CFBundleTypeName Comma Separated Values CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions cmake CFBundleTypeIconFile default.icns CFBundleTypeName CMake script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions dart CFBundleTypeIconFile default.icns CFBundleTypeName Dart script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions diff CFBundleTypeIconFile default.icns CFBundleTypeName Diff file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions dockerfile CFBundleTypeIconFile default.icns CFBundleTypeName Dockerfile CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions gradle CFBundleTypeIconFile default.icns CFBundleTypeName Gradle file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions groovy CFBundleTypeIconFile default.icns CFBundleTypeName Groovy script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions makefile mk CFBundleTypeIconFile default.icns CFBundleTypeName Makefile CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions lua CFBundleTypeIconFile default.icns CFBundleTypeName Lua script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions pug CFBundleTypeIconFile default.icns CFBundleTypeName Pug document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ipynb CFBundleTypeIconFile default.icns CFBundleTypeName Jupyter CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions lock CFBundleTypeIconFile default.icns CFBundleTypeName Lockfile CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions log CFBundleTypeIconFile default.icns CFBundleTypeName Log file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions txt CFBundleTypeIconFile default.icns CFBundleTypeName Plain Text File CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions xcodeproj CFBundleTypeIconFile default.icns CFBundleTypeName Xcode project file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions xcworkspace CFBundleTypeIconFile default.icns CFBundleTypeName Xcode workspace file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions vb CFBundleTypeIconFile default.icns CFBundleTypeName Visual Basic script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions r CFBundleTypeIconFile default.icns CFBundleTypeName R source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions rs CFBundleTypeIconFile default.icns CFBundleTypeName Rust source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions rst CFBundleTypeIconFile default.icns CFBundleTypeName Restructured Text document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions tex cls CFBundleTypeIconFile default.icns CFBundleTypeName LaTeX document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions fs CFBundleTypeIconFile default.icns CFBundleTypeName F# source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions fsi CFBundleTypeIconFile default.icns CFBundleTypeName F# signature file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions fsx fsscript CFBundleTypeIconFile default.icns CFBundleTypeName F# script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions svg svgz CFBundleTypeIconFile default.icns CFBundleTypeName SVG document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions toml CFBundleTypeIconFile default.icns CFBundleTypeName TOML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions swift CFBundleTypeIconFile default.icns CFBundleTypeName Swift source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions containerfile ctp dot edn handlebars hbs ml mli pl pl6 pm pm6 pod pp properties psgi rt t CFBundleTypeIconFile default.icns CFBundleTypeName Visual Studio Code document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions CFBundleTypeIconFile default.icns CFBundleTypeName Folder CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor LSItemContentTypes public.folder ================================================ FILE: liteidex/src/liteapp/aboutdialog.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: aboutdialog.cpp // Creator: visualfc #include "aboutdialog.h" #include "ui_aboutdialog.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end AboutDialog::AboutDialog(LiteApi::IApplication *app,QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog) { ui->setupUi(this); ui->verLabel->setText(app->ideVersion()); ui->qtVerLabel->setText(QString(tr("Based on Qt %1 (%2 bit)")).arg(QLatin1String(qVersion())). arg(QString::number(QSysInfo::WordSize))); } AboutDialog::~AboutDialog() { delete ui; } ================================================ FILE: liteidex/src/liteapp/aboutdialog.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: aboutdialog.h // Creator: visualfc #ifndef ABOUTDIALOG_H #define ABOUTDIALOG_H #include #include "liteapi/liteapi.h" namespace Ui { class AboutDialog; } class AboutDialog : public QDialog { Q_OBJECT public: explicit AboutDialog(LiteApi::IApplication *app, QWidget *parent = 0); ~AboutDialog(); private: Ui::AboutDialog *ui; }; #endif // ABOUTDIALOG_H ================================================ FILE: liteidex/src/liteapp/aboutdialog.ui ================================================ AboutDialog 0 0 552 468 0 0 About LiteIDE 0 :/images/liteide-logo64.png Qt::AlignCenter <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:24pt; font-weight:600; font-style:italic;">LiteIDE X</span></p></body></html> Qt::AlignCenter Simple Cross Platform Open Source IDE Qt::AlignCenter <html><head/><body><p>2011-2023 (c) visualfc &lt;visualfc@gmail.com&gt;</p></body></html> Qt::AlignCenter 0 QLayout::SetMinimumSize 0 0 :/images/logo/space.png :/images/logo/li.png Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop :/images/logo/dui.png Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft :/images/logo/space.png 0 0 0 Information Welcome: Welcome to LiteIDE X! LiteIDE is a simple, open source, cross-platform IDE. Project: LiteIDE X Author: <html><head/><body><p><a href="https://github.com/visualfc/liteide"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/visualfc/liteide</span></a></p></body></html> true Name: Based on Qt Version: visualfc@gmail.com Qt::AutoText false Build: Source Code: X64 Support LiteIDE: <html><head/><body><p><a href="http://visualfc.github.com/support"><span style=" text-decoration: underline; color:#0000ff;">https://visualfc.github.com/support</span></a></p></body></html> true Qt::Vertical 20 40 Developers LiteIDE X Developer visualfc <visualfc@gmail.com> LiteIDE 0.1.2-0.2.1 visualfc <visualfc@gmail.com> Developer LiteIDE 0.1 Developer visualfc <visualfc@gmail.com> Developer xushiwei <xushiweizh@gmail.com> Qt::Vertical 20 40 Translations LiteIDE X Chinese visualfc <visualfc@gmail.com> Japanese mattn <mattn.jp@gmail.com> Russian Lockals <lockalsash@gmail.com> French TomBoss <tomboss@gmx.com> Traditional Chinese Timothy Lin <zh9102@gmail.com> German Helge Plaschke <github.com/HelgePlaschke> Qt::AutoText Michael <github.com/michael-k> Roman Shmelev <rshmelev@gmail.com> Ukrainian Vladislav Glinsky <cl0ne@mithril.org.ua> Qt::Vertical 20 40 Thanks to... <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } hr { height: 1px; border-width: 0; } li.unchecked::marker { content: "\2610"; } li.checked::marker { content: "\2612"; } </style></head><body style=" font-family:'.SF NS Text'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All contributors that provided patches.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Go Project &lt;http://golang.org&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Qt Project &lt;https://qt-project.org&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The QtCreator Project &lt;https://qt-project.org&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Kate Project &lt;http://kate-editor.org&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GNU Software Foundation &lt;https://www.gnu.org&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The CommonMark cmark library &lt;https://github.com/commonmark/cmark&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Sundown project &lt;https://github.com/vmg/sundown&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Markdown CSS files from Mou &lt;http://mouapp.com&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Gocode tool &lt;https://github.com/nsf/gocode&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The libvterm project &lt;https://github.com/neovim/libvterm&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The ptyqt project &lt;https://github.com/kafeg/ptyqt&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The LiteIDE logo designed by BESD &lt;http://www.besdlab.cn&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Last, but not least, the open-source community.</p></body></html> License <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } hr { height: 1px; border-width: 0; } li.unchecked::marker { content: "\2610"; } li.checked::marker { content: "\2612"; } </style></head><body style=" font-family:'.SF NS Text'; font-size:13pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright (c) 2011-2022 LiteIDE. All rights reserved.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This library 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 Lesser General Public License for more details.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">In addition, as a special exception, that plugins developed for LiteIDE, are allowed to remain closed sourced and can be distributed under any license .These rights are included in the file LGPL_EXCEPTION.txt in this package.</p></body></html> Qt::Horizontal 40 20 Close closeButton clicked() AboutDialog accept() 406 268 232 147 ================================================ FILE: liteidex/src/liteapp/actionmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: actionmanager.cpp // Creator: visualfc #include "actionmanager.h" #include "liteapp_global.h" #include "liteapi/liteids.h" #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ActionManager::ActionManager(QObject *parent) : IActionManager(parent), m_viewMenu(0), m_baseToolBarAct(0), m_baseBrowserAct(0) { } ActionManager::~ActionManager() { QMapIterator it(m_objContextMap); while(it.hasNext()) { it.next(); delete it.value(); } } bool ActionManager::initWithApp(IApplication *app) { if (!IActionManager::initWithApp(app)) { return false; } insertMenu(ID_MENU_FILE,tr("&File")); insertMenu(ID_MENU_RECENT,tr("&Recent")); insertMenu(ID_MENU_EDIT,tr("&Edit")); insertMenu(ID_MENU_FIND,tr("F&ind")); m_viewMenu = insertMenu(ID_MENU_VIEW,tr("&View")); m_viewMenu->addSeparator(); m_baseToolBarAct = m_viewMenu->addSeparator(); m_baseBrowserAct = m_viewMenu->addSeparator(); m_viewMenu->addSeparator(); insertMenu(ID_MENU_TOOLS,tr("&Tools")); insertMenu(ID_MENU_BUILD,tr("&Build")); insertMenu(ID_MENU_DEBUG,tr("&Debug")); insertMenu(ID_MENU_HELP,tr("&Help")); QToolBar *stdToolBar = insertToolBar(ID_TOOLBAR_STD,tr("Standard Toolbar")); insertViewMenu(LiteApi::ViewMenuToolBarPos,stdToolBar->toggleViewAction()); return true; } QMenu *ActionManager::insertMenu(const QString &id, const QString &title, const QString &idBefore) { QMenu *menu = m_idMenuMap.value(id); if (menu) { return menu; } menu = new QMenu(title,m_liteApp->mainWindow()); menu->setObjectName(id); QMenu *m = 0; if (!idBefore.isEmpty()) { m = m_idMenuMap.value(idBefore); } if (m) { m_liteApp->mainWindow()->menuBar()->insertMenu(m->menuAction(),menu); } else { m_liteApp->mainWindow()->menuBar()->addAction(menu->menuAction()); } m_idMenuMap.insert(id,menu); return menu; } void ActionManager::removeMenu(QMenu *menu) { if (!menu) { return; } QString id = m_idMenuMap.key(menu); if (!id.isEmpty()) { m_idMenuMap.remove(id); } m_liteApp->mainWindow()->menuBar()->removeAction(menu->menuAction()); } QList ActionManager::menuList() const { return m_idMenuMap.keys(); } QMenu *ActionManager::loadMenu(const QString &id) { return m_idMenuMap.value(id); } QToolBar *ActionManager::insertToolBar(const QString &id, const QString &title, const QString &idBefore) { QToolBar *toolBar = m_idToolBarMap.value(id); if (toolBar) { return toolBar; } toolBar = new QToolBar(title, m_liteApp->mainWindow()); toolBar->setObjectName(id); toolBar->setIconSize(LiteApi::getToolBarIconSize(m_liteApp)); QToolBar *m = 0; if (!idBefore.isEmpty()) { m = m_idToolBarMap.value(idBefore); } if (m) { m_liteApp->mainWindow()->insertToolBar(m,toolBar); } else { m_liteApp->mainWindow()->addToolBar(toolBar); } m_idToolBarMap.insert(id,toolBar); return toolBar; } void ActionManager::insertToolBar(QToolBar *toolBar, const QString &idBefore) { QString id = toolBar->objectName(); toolBar->setIconSize(LiteApi::getToolBarIconSize(m_liteApp)); QToolBar *m = 0; if (!idBefore.isEmpty()) { m = m_idToolBarMap.value(idBefore); } if (m) { m_liteApp->mainWindow()->insertToolBar(m,toolBar); } else { m_liteApp->mainWindow()->addToolBar(toolBar); } m_idToolBarMap.insert(id,toolBar); } QToolBar *ActionManager::loadToolBar(const QString &id) { return m_idToolBarMap.value(id); } QList ActionManager::toolBarList() const { return m_idToolBarMap.keys(); } void ActionManager::removeToolBar(QToolBar* toolBar) { if (!toolBar) { return; } QString id = m_idToolBarMap.key(toolBar); if (!id.isEmpty()) { m_idToolBarMap.remove(id); } m_liteApp->mainWindow()->removeToolBar(toolBar); } void ActionManager::insertViewMenu(VIEWMENU_ACTION_POS pos, QAction *act) { if (pos == ViewMenuToolBarPos) { m_viewMenu->insertAction(m_baseToolBarAct,act); } else if(pos == ViewMenuBrowserPos){ m_viewMenu->insertAction(m_baseBrowserAct,act); } else { m_viewMenu->addAction(act); } } void ActionManager::setViewMenuSeparator(const QString &sepid, bool group) { if (sepid.isEmpty()) { return; } if (m_idSeperatorMap.contains(sepid)) { return; } if (group) { m_viewMenu->addSeparator(); } QAction *sep = m_viewMenu->addSeparator(); m_idSeperatorMap.insert(sepid,sep); } bool ActionManager::insertMenuActions(const QString &idMenu, const QString &idBeforeSep, bool newGroup, QList &actions) { if (idMenu.isEmpty()) { return false; } QMenu *menu = loadMenu(idMenu); if (!menu) { return false; } if (newGroup) { QMenu *realMenu = menu->menuAction()->menu(); if (realMenu) { if (!realMenu->actions().isEmpty() && !realMenu->actions().last()->isSeparator()) { menu->addSeparator(); } } else { menu->addSeparator(); } } QAction *sep = 0; if (!idBeforeSep.isEmpty()) { sep = m_idMenuSepMap[idMenu][idBeforeSep]; if (!sep) { sep = menu->addSeparator(); m_idMenuSepMap[idMenu].insert(idBeforeSep,sep); } } foreach (QAction *act, actions) { menu->insertAction(sep,act); } return true; } void ActionManager::insertViewMenuAction(QAction *act, const QString &sepid) { QAction *sep = m_idSeperatorMap[sepid]; m_viewMenu->insertAction(sep,act); } IActionContext *ActionManager::getActionContext(QObject *obj, const QString &name) { IActionContext *context = m_objContextMap.value(obj); if (!context) { context = new ActionContext(m_liteApp,name); connect(obj,SIGNAL(destroyed(QObject*)),this,SLOT(removeActionContext(QObject*))); m_objContextMap.insert(obj,context); } return context; } QStringList ActionManager::actionKeys() const { QStringList keys; QMapIterator it(m_objContextMap); while(it.hasNext()) { it.next(); keys.append(it.value()->actionKeys()); } keys.removeDuplicates(); return keys; } ActionInfo *ActionManager::actionInfo(const QString &id) const { QMapIterator it(m_objContextMap); while (it.hasNext()) { it.next(); ActionInfo *info = it.value()->actionInfo(id); if (info) { return info; } } return 0; } QList ActionManager::toShortcuts(const QString &ks) { QString keyseq = ks; QString part; int p = 0, diff = 0; QList keys; while (keyseq.length()) { // We MUST use something to separate each sequence, and space // does not cut it, since some of the key names have space // in them.. (Let's hope no one translate with a comma in it:) p = keyseq.indexOf(QLatin1Char(';')); if (-1 != p) { if (p == keyseq.count() - 1) { // Last comma 'Ctrl+;' p = -1; } else { if (QLatin1Char(';') == keyseq.at(p+1)) // e.g. 'Ctrl+;; Shift+;;' p++; if (QLatin1Char(' ') == keyseq.at(p+1)) { // Space after comma diff = 1; p++; } else { diff = 0; } } } part = keyseq.left(-1 == p ? keyseq.length() : p - diff); keyseq = keyseq.right(-1 == p ? 0 : keyseq.length() - (p + 1)); QKeySequence key(part); if (!key.isEmpty()) { keys.append(key); } } return keys; } QString ActionManager::formatShortcutsString(const QString &ks) { QStringList ksList; foreach(QKeySequence k, toShortcuts(ks)) { ksList.append(k.toString()); } return ksList.join("; "); } QString ActionManager::formatShortcutsNativeString(const QString &ks) { QStringList ksList; foreach(QKeySequence k, toShortcuts(ks)) { ksList.append(k.toString(QKeySequence::NativeText)); } return ksList.join("; "); } void ActionManager::setActionShourtcuts(const QString &id, const QString &shortcuts) { QMapIterator it(m_objContextMap); while(it.hasNext()) { it.next(); it.value()->setActionShortcuts(id,shortcuts); } } QStringList ActionManager::actionContextNameList() const { QStringList nameList; QMapIterator it(m_objContextMap); while(it.hasNext()) { it.next(); nameList.append(it.value()->contextName()); } nameList.removeDuplicates(); return nameList; } IActionContext *ActionManager::actionContextForName(const QString &name) { QMapIterator it(m_objContextMap); while(it.hasNext()) { it.next(); if (it.value()->contextName().compare(name,Qt::CaseInsensitive) == 0) { return it.value(); } } return 0; } void ActionManager::removeActionContext(QObject *obj) { QMutableMapIterator it(m_objContextMap); while (it.hasNext()) { it.next(); if (it.key() == obj) { delete it.value(); it.remove(); break; } } } ActionContext::ActionContext(IApplication *app, const QString &name) : m_liteApp(app), m_name(name) { } QString ActionContext::contextName() const { return m_name; } ActionContext::~ActionContext() { QMapIterator it(m_actionInfoMap); while(it.hasNext()) { it.next(); ActionInfo* info = it.value(); delete info; } m_actionInfoMap.clear(); } void ActionContext::regAction(QAction *act, const QString &id, const QString &defks, bool standard) { ActionInfo *info = m_actionInfoMap.value(id); if (info == 0) { info = new ActionInfo; m_actionInfoMap.insert(id,info); } info->standard = standard; info->defks = ActionManager::formatShortcutsString(defks); info->ks = m_liteApp->settings()->value(LITEAPP_SHORTCUTS+id,info->defks).toString(); info->ks = ActionManager::formatShortcutsString(info->ks); info->keys = ActionManager::toShortcuts(info->ks); if (act) { info->label = act->text(); act->setShortcuts(info->keys); act->setData(id); if (!info->ks.isEmpty()) { act->setToolTip(QString("%1 (%2)").arg(act->text()).arg(ActionManager::formatShortcutsNativeString(info->ks))); } info->action = act; } else { info->action = 0; } } void ActionContext::regAction(QAction *act, const QString &id, const QKeySequence::StandardKey &def) { regAction(act,id,QKeySequence(def).toString(),true); } QStringList ActionContext::actionKeys() const { return m_actionInfoMap.keys(); } ActionInfo *ActionContext::actionInfo(const QString &id) const { return m_actionInfoMap.value(id); } void ActionContext::setActionShortcuts(const QString &id, const QString &shortcuts) { ActionInfo *info = m_actionInfoMap.value(id); if (!info) { return; } info->ks = ActionManager::formatShortcutsString(shortcuts); info->keys = ActionManager::toShortcuts(info->ks); if (info->action) { info->action->setShortcuts(info->keys); if (!info->ks.isEmpty()) { info->action->setToolTip(QString("%1 (%2)").arg(info->action->text()).arg(ActionManager::formatShortcutsNativeString(info->ks))); } } if (info->ks != info->defks) { m_liteApp->settings()->setValue(LITEAPP_SHORTCUTS+id,info->ks); } else { m_liteApp->settings()->remove(LITEAPP_SHORTCUTS+id); } } ================================================ FILE: liteidex/src/liteapp/actionmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: actionmanager.h // Creator: visualfc #ifndef ACTIONMANAGER_H #define ACTIONMANAGER_H #include "liteapi/liteapi.h" using namespace LiteApi; class ActionContext : public IActionContext { public: ActionContext(LiteApi::IApplication *app, const QString &name); virtual ~ActionContext(); virtual QString contextName() const; virtual void regAction(QAction *act, const QString &id, const QString &defks, bool standard = false); virtual void regAction(QAction *act, const QString &id, const QKeySequence::StandardKey &def); virtual QStringList actionKeys() const; virtual ActionInfo *actionInfo(const QString &id) const; virtual void setActionShortcuts(const QString &id, const QString &shortcuts); protected: LiteApi::IApplication *m_liteApp; QString m_name; QMap m_actionInfoMap; }; class ActionManager : public IActionManager { Q_OBJECT public: ActionManager(QObject *parent = 0); virtual ~ActionManager(); virtual bool initWithApp(IApplication *app); virtual QMenu *insertMenu(const QString &id, const QString &title, const QString &idBefore = QString()); virtual QMenu *loadMenu(const QString &id); virtual void removeMenu(QMenu *menu); virtual QList menuList() const; virtual QToolBar *insertToolBar(const QString &id, const QString &title, const QString &before = QString()); virtual void insertToolBar(QToolBar *toolBar,const QString &before = QString()); virtual QToolBar *loadToolBar(const QString &id); virtual void removeToolBar(QToolBar* toolBar); virtual QList toolBarList() const; virtual void insertViewMenu(VIEWMENU_ACTION_POS pos, QAction *act); virtual void setViewMenuSeparator(const QString &sepid, bool group); virtual void insertViewMenuAction(QAction *act, const QString &sepid); virtual bool insertMenuActions(const QString &idMenu, const QString &idBeforeSep, bool newGroup, QList &actions); virtual IActionContext *getActionContext(QObject *obj, const QString &name); virtual QStringList actionKeys() const; virtual ActionInfo *actionInfo(const QString &id) const; virtual void setActionShourtcuts(const QString &id, const QString &shortcuts); virtual QStringList actionContextNameList() const; virtual IActionContext *actionContextForName(const QString &name); protected slots: void removeActionContext(QObject *obj); public: static QList toShortcuts(const QString &ks); static QString formatShortcutsString(const QString &ks); static QString formatShortcutsNativeString(const QString &ks); protected: QMap m_idMenuMap; QMap m_idToolBarMap; QMap m_idSeperatorMap; QMap > m_idMenuSepMap; QMenu *m_viewMenu; QAction *m_baseToolBarAct; QAction *m_baseBrowserAct; QMap m_objContextMap; }; #endif // ACTIONMANAGER_H ================================================ FILE: liteidex/src/liteapp/cdrv.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: cdrv.h // Creator: visualfc #ifndef CDRV_H #define CDRV_H #include "liteapp_global.h" typedef void (*DRV_CALLBACK)(char *id, int id_size, char *reply, int len, int err, void *ctx); typedef int (*GODRV_CALL)(char* id,int id_size, char* args, int args_size, DRV_CALLBACK cb, void *ctx); extern "C" int LITEIDESHARED_EXPORT cdrv_main(int argc, char **argv); extern "C" void LITEIDESHARED_EXPORT cdrv_init(void *fn); extern "C" void LITEIDESHARED_EXPORT cdrv_cb(DRV_CALLBACK cb, char *id, char *reply, int size, int err, void* ctx); #endif // CDRV_H ================================================ FILE: liteidex/src/liteapp/editormanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: editormanager.cpp // Creator: visualfc #include "editormanager.h" #include "liteapp_global.h" #include "liteapi/liteids.h" #include "liteenvapi/liteenvapi.h" #include "terminalapi/terminalapi.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fileutil/fileutil.h" #include "liteapp.h" #include "openeditorswidget.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end EditorManager::~EditorManager() { delete m_tabContextFileMenu; delete m_tabContextNofileMenu; delete m_editorTabWidget; delete m_listMenu; delete m_openEditorWidget; m_browserActionMap.clear(); if (!m_nullMenu->parent()) { delete m_nullMenu; } } bool EditorManager::initWithApp(IApplication *app) { if (!IEditorManager::initWithApp(app)) { return false; } m_updateMenuInFocus = false; m_mouseExtNavigate = true; m_nullMenu = new QMenu; m_nullMenu->setEnabled(false); m_currentNavigationHistoryPosition = 0; m_colorStyleScheme = new ColorStyleScheme(this); m_maxEditorCount = m_liteApp->settings()->value(LITEAPP_MAXEDITORCOUNT,64).toInt(); m_widget = new QWidget; //create editor tab widget m_editorTabWidget = new LiteTabWidget(LiteApi::getToolBarIconSize(m_liteApp)); //create list menu m_listMenu = new QMenu; m_listGroup = new QActionGroup(this); m_editorTabWidget->setListMenu(m_listMenu); connect(m_listMenu,SIGNAL(aboutToShow()),this,SLOT(aboutToShowListMenu())); connect(m_listGroup,SIGNAL(triggered(QAction*)),this,SLOT(triggeredListAction(QAction*))); //create editor model m_editorModel = new QStandardItemModel(this); //create opne editor for model m_openEditorWidget = new OpenEditorsWidget(app); m_openEditorWidget->setEditorModel(m_editorModel); m_liteApp->toolWindowManager()->addToolWindow(Qt::LeftDockWidgetArea,m_openEditorWidget,"OpenEditor",tr("Open Editor"),true); m_editorTabWidget->tabBar()->setTabsClosable(m_liteApp->settings()->value(LITEAPP_EDITTABSCLOSABLE,true).toBool()); m_editorTabWidget->tabBar()->setEnableWheel(m_liteApp->settings()->value(LITEAPP_EDITTABSENABLEWHELL,true).toBool()); //m_editorTabWidget->tabBar()->setIconSize(LiteApi::getToolBarIconSize()); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->setMargin(0); mainLayout->setSpacing(0); // QToolBar *toolBar = m_editorTabWidget->headerToolBar(); // toolBar->setObjectName("toolbar/tabs"); // m_liteApp->actionManager()->insertToolBar(toolBar); // m_editorTabWidget->headerToolBar()->setAllowedAreas(Qt::TopToolBarArea|Qt::BottomToolBarArea); mainLayout->addWidget(m_editorTabWidget->tabBarWidget()); mainLayout->addWidget(m_editorTabWidget->stackedWidget()); m_widget->setLayout(mainLayout); connect(m_editorTabWidget,SIGNAL(currentChanged(int)),this,SLOT(editorTabChanged(int))); connect(m_editorTabWidget,SIGNAL(tabCloseRequested(int)),this,SLOT(editorTabCloseRequested(int))); connect(m_editorTabWidget,SIGNAL(tabAddRequest()),this,SIGNAL(tabAddRequest())); m_editorTabWidget->stackedWidget()->installEventFilter(this); m_editorTabWidget->tabBar()->installEventFilter(this); m_tabContextFileMenu = new QMenu; m_tabContextNofileMenu = new QMenu; m_tabContextIndex = -1; QAction *closeAct = new QAction(tr("Close"),this); closeAct->setShortcut(QKeySequence("Ctrl+W")); QAction *closeOthersAct = new QAction(tr("Close Others"),this); QAction *closeAllAct = new QAction(tr("Close All"),this); QAction *closeLeftAct = new QAction(tr("Close Left Tabs"),this); QAction *closeRightAct = new QAction(tr("Close Right Tabs"),this); QAction *closeSameFolderFiles = new QAction(tr("Close Files in Same Folder"),this); QAction *closeOtherFolderFiles = new QAction(tr("Close Files in Other Folders"),this); QAction *copyPathToClipboard = new QAction(tr("Copy Full Path to Clipboard"),this); #if defined(Q_OS_WIN) QAction *showInExplorer = new QAction(tr("Show in Explorer"),this); #elif defined(Q_OS_MAC) QAction *showInExplorer = new QAction(tr("Show in Finder"),this); #else QAction *showInExplorer = new QAction(tr("Show Containing Folder"),this); #endif #ifdef Q_OS_WIN QAction *openInShell = new QAction(tr("Open Command Prompt Here"),this); #else QAction *openInShell = new QAction(tr("Open Terminal Here"),this); #endif QAction *openTerminal = new QAction(tr("Open in Integrated Terminal"),this); QAction *moveToAct = new QAction(tr("Move to New Window"),this); m_tabContextFileMenu->addAction(closeAct); m_tabContextFileMenu->addAction(closeOthersAct); m_tabContextFileMenu->addAction(closeLeftAct); m_tabContextFileMenu->addAction(closeRightAct); m_tabContextFileMenu->addAction(closeAllAct); m_tabContextFileMenu->addSeparator(); m_tabContextFileMenu->addAction(closeSameFolderFiles); m_tabContextFileMenu->addAction(closeOtherFolderFiles); m_tabContextFileMenu->addSeparator(); m_tabContextFileMenu->addAction(copyPathToClipboard); m_tabContextFileMenu->addAction(showInExplorer); m_tabContextFileMenu->addAction(openInShell); m_tabContextFileMenu->addAction(openTerminal); m_tabContextFileMenu->addSeparator(); m_tabContextFileMenu->addAction(moveToAct); m_tabContextNofileMenu->addAction(closeAct); m_tabContextNofileMenu->addAction(closeOthersAct); m_tabContextNofileMenu->addAction(closeLeftAct); m_tabContextNofileMenu->addAction(closeRightAct); m_tabContextNofileMenu->addAction(closeAllAct); connect(closeAct,SIGNAL(triggered()),this,SLOT(tabContextClose())); connect(closeOthersAct,SIGNAL(triggered()),this,SLOT(tabContextCloseOthers())); connect(closeLeftAct,SIGNAL(triggered()),this,SLOT(tabContextCloseLefts())); connect(closeRightAct,SIGNAL(triggered()),this,SLOT(tabContextCloseRights())); connect(closeAllAct,SIGNAL(triggered()),this,SLOT(tabContextCloseAll())); connect(closeSameFolderFiles,SIGNAL(triggered()),this,SLOT(tabContextCloseSameFolderFiles())); connect(closeOtherFolderFiles,SIGNAL(triggered()),this,SLOT(tabContextCloseOtherFolderFiles())); connect(copyPathToClipboard,SIGNAL(triggered()),this,SLOT(tabContextCopyPathToClipboard())); connect(showInExplorer,SIGNAL(triggered()),this,SLOT(tabContextShowInExplorer())); connect(openInShell,SIGNAL(triggered()),this,SLOT(tabContextOpenInShell())); connect(openTerminal,SIGNAL(triggered()),this,SLOT(tabContextOpenInTerminal())); connect(moveToAct,SIGNAL(triggered()),this,SLOT(moveToNewWindow())); connect(qApp,SIGNAL(focusChanged(QWidget*,QWidget*)),this,SLOT(focusChanged(QWidget*,QWidget*))); QStatusBar *bar = m_liteApp->mainWindow()->statusBar(); m_lineInfo = new QLabel("000:000"); bar->addPermanentWidget(m_lineInfo); LiteApi::IAppIdleTimer *idleTimer = LiteApi::GetAppIdleTimer(m_liteApp); if (idleTimer) { connect(idleTimer,SIGNAL(appIdle(int)),this,SLOT(appIdle(int))); } m_editorTabWidget->tabBar()->setElideMode(Qt::ElideNone); applyOption(OPTION_LITEAPP); return true; } void EditorManager::createActions() { m_editMenu = m_liteApp->actionManager()->loadMenu(ID_MENU_EDIT); QToolBar *toolBar = m_liteApp->actionManager()->loadToolBar(ID_TOOLBAR_STD); m_goBackAct = new QAction(tr("Navigate Backward"),this); m_goBackAct->setIcon(QIcon("icon:images/backward.png")); m_goForwardAct = new QAction(tr("Navigate Forward"),this); m_goForwardAct->setIcon(QIcon("icon:images/forward.png")); m_gotoNextTab = new QAction(tr("Go to next tab"),this); m_gotoPrevTab = new QAction(tr("Go to previous tab"),this); IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(m_liteApp,"App"); #ifdef Q_OS_MAC actionContext->regAction(m_goBackAct,"Backward","Ctrl+Alt+Left"); actionContext->regAction(m_goForwardAct,"Forward","Ctrl+Alt+Right"); actionContext->regAction(m_gotoNextTab,"GotoNextTab","Alt+Tab"); actionContext->regAction(m_gotoPrevTab,"GotoPreviusTab","Alt+Shift+Tab"); #else actionContext->regAction(m_goBackAct,"Backward","Alt+Left"); actionContext->regAction(m_goForwardAct,"Forward","Alt+Right"); actionContext->regAction(m_gotoNextTab,"GotoNextTab","Ctrl+Tab"); actionContext->regAction(m_gotoPrevTab,"GotoPreviusTab","Ctrl+Shift+Tab"); #endif m_liteApp->actionManager()->setViewMenuSeparator("sep/nav",true); m_liteApp->actionManager()->insertViewMenuAction(m_goBackAct,"sep/nav"); m_liteApp->actionManager()->insertViewMenuAction(m_goForwardAct,"sep/nav"); updateNavigatorActions(); toolBar->addSeparator(); toolBar->addAction(m_goBackAct); toolBar->addAction(m_goForwardAct); m_widget->addAction(m_gotoNextTab); m_widget->addAction(m_gotoPrevTab); connect(m_goBackAct,SIGNAL(triggered()),this,SLOT(goBack())); connect(m_goForwardAct,SIGNAL(triggered()),this,SLOT(goForward())); connect(m_gotoNextTab,SIGNAL(triggered()),this,SLOT(gotoNextTab())); connect(m_gotoPrevTab,SIGNAL(triggered()),this,SLOT(gotoPrevTab())); } QWidget *EditorManager::widget() { return m_widget; } void EditorManager::editorTabChanged(int /*index*/) { QWidget *w = m_editorTabWidget->currentWidget(); if (w == 0) { this->setCurrentEditor(0); } else { IEditor *ed = m_widgetEditorMap.value(w,0); this->setCurrentEditor(ed); } } void EditorManager::editorTabCloseRequested(int index) { QWidget *w = m_editorTabWidget->widget(index); IEditor *ed = m_widgetEditorMap.value(w,0); closeEditor(ed); } QList EditorManager::sortedEditorList() const { QList editorList; foreach (QWidget *w,m_editorTabWidget->widgetList()) { IEditor *ed = m_widgetEditorMap.value(w); if (ed) { editorList << ed; } } return editorList; } class EditorItem : public QStandardItem { public: LiteApi::IEditor *editor; }; void EditorManager::addEditor(IEditor *editor) { QWidget *w = m_widgetEditorMap.key(editor,0); if (w == 0) { w = editor->widget(); if (w == 0) { return; } m_editorTabWidget->addTab(w,QIcon(),editor->name(),editor->filePath()); m_widgetEditorMap.insert(w,editor); emit editorCreated(editor); connect(editor,SIGNAL(modificationChanged(bool)),this,SLOT(modificationChanged(bool))); LiteApi::IEditContext *context = LiteApi::getEditContext(editor); if (context) { this->addEditContext(context); } if (!editor->filePath().isEmpty()) { QStandardItem *item = new QStandardItem(editor->name()); item->setToolTip(editor->filePath()); m_editorModel->appendRow(QList() << item); } } } void EditorManager::gotoNextTab() { int index = m_editorTabWidget->tabBar()->currentIndex(); index++; if (index >= m_editorTabWidget->tabBar()->count()) { index = 0; } m_editorTabWidget->setCurrentIndex(index); // qDebug() << "Changing to next tab:" << index; } void EditorManager::gotoPrevTab() { int index = m_editorTabWidget->tabBar()->currentIndex(); index--; if (index < 0) { index = m_editorTabWidget->tabBar()->count()-1; } m_editorTabWidget->setCurrentIndex(index); // qDebug() << "Changing to previous tab:" << index; } bool EditorManager::eventFilter(QObject *target, QEvent *event) { if (event->type() == QEvent::MouseButtonDblClick && target == m_editorTabWidget->tabBar()) { QMouseEvent *ev = (QMouseEvent*)event; if (ev->button() == Qt::LeftButton) { emit doubleClickedTab(); } } else if (event->type() == QEvent::MouseButtonPress) { QMouseEvent *ev = (QMouseEvent*)event; if (m_mouseExtNavigate) { if ( ev->button() == 0x00000008/*Qt::BackButton*/) { this->goBack(); } else if (ev->button() == 0x00000010/*Qt::ForwardButton*/) { this->goForward(); } } if (target == m_editorTabWidget->tabBar()) { if (ev->button() == Qt::RightButton) { m_tabContextIndex = m_editorTabWidget->tabBar()->tabAt(ev->pos()); if (m_tabContextIndex >= 0) { QString filePath = tabContextFilePath(); if (filePath.isEmpty()) { m_tabContextNofileMenu->popup(ev->globalPos()); } else { m_tabContextFileMenu->popup(ev->globalPos()); } } } else if (ev->button() == Qt::MiddleButton) { int index = m_editorTabWidget->tabBar()->tabAt(ev->pos()); if (index >= 0) { editorTabCloseRequested(index); } } } } return IEditorManager::eventFilter(target,event); } QString EditorManager::tabContextFilePath() const { if (m_tabContextIndex < 0) { return QString(); } QWidget *w = m_editorTabWidget->widget(m_tabContextIndex); IEditor *ed = m_widgetEditorMap.value(w,0); if (!ed) { return QString(); } return ed->filePath(); } QAction *EditorManager::registerBrowser(IEditor *editor) { QAction *act = new QAction(editor->name(),this); act->setCheckable(true); act->setChecked(false); connect(act,SIGNAL(toggled(bool)),this,SLOT(toggleBrowserAction(bool))); m_browserActionMap.insert(editor,act); return act; } void EditorManager::activeBrowser(IEditor *editor) { QAction *act = m_browserActionMap.value(editor); if (!act) { return; } if (!act->isChecked()) { act->toggle(); } setCurrentEditor(editor); } bool EditorManager::closeEditor(IEditor *editor) { if (!editor) { editor = m_currentEditor; } if (editor == 0) { return false; } if (editor->isModified() && !editor->isReadOnly()) { QString text = QString(tr("Save changes to %1?")).arg(editor->filePath()); int ret = QMessageBox::question(m_widget,tr("Unsaved Modifications"),text,QMessageBox::Save | QMessageBox::No | QMessageBox::Cancel); if (ret == QMessageBox::Cancel) { return false; } else if (ret == QMessageBox::Save) { //cur->save(); saveEditor(editor); } } if (!editor->filePath().isEmpty()) { m_liteApp->settings()->setValue(QString("state_%1").arg(editor->filePath()),editor->saveState()); } int index = m_editorTabWidget->indexOf(editor->widget()); if (index < 0) { return false; } emit editorAboutToClose(editor); m_editorTabWidget->removeTab(index); m_widgetEditorMap.remove(editor->widget()); QString filePath = editor->filePath(); if (!filePath.isEmpty()) { for (int i = 0; i < m_editorModel->rowCount(); i++) { QStandardItem *item = m_editorModel->item(i,0); if (item->toolTip() == filePath) { m_editorModel->removeRow(i); break; } } } QMapIterator i(m_browserActionMap); while (i.hasNext()) { i.next(); if (i.key() == editor) { i.value()->blockSignals(true); i.value()->setChecked(false); i.value()->blockSignals(false); return true; } } LiteApi::IEditContext *context = LiteApi::getEditContext(editor); if (context) { this->removeEditContext(context); } editor->deleteLater(); return true; } bool EditorManager::saveEditor(IEditor *editor, bool emitAboutSave) { IEditor *cur = 0; if (editor) { cur = editor; } else { cur = m_currentEditor; } if (cur && cur->isModified()) { if (emitAboutSave) { emit editorAboutToSave(cur); } if (cur->save()) { emit editorSaved(cur); } else if (cur->isReadOnly()){ m_liteApp->appendLog("Editor",QString("File is read only %1").arg(cur->filePath()),false); } else { m_liteApp->appendLog("Editor",QString("Failed to save %1").arg(cur->filePath()),true); } return true; } return false; } bool EditorManager::saveEditorAs(IEditor *editor) { IEditor *cur = 0; if (editor) { cur = editor; } else { cur = m_currentEditor; } if (cur == 0) { return false; } QString fileName = cur->filePath(); if (fileName.isEmpty()) { return false; } QFileInfo info(fileName); QStringList filter; QString ext = info.suffix(); if (!ext.isEmpty()) { filter.append(QString("%1 (*.%1)").arg(ext).arg(ext)); } filter.append(tr("All Files (*)")); QString path = info.absolutePath(); QString saveFileName = QFileDialog::getSaveFileName(m_liteApp->mainWindow(),tr("Save As"),path,filter.join(";;")); if (FileUtil::compareFile(fileName,saveFileName,false)) { return false; } if (!cur->saveAs(saveFileName)) { return false; } QWidget *w = m_widgetEditorMap.key(cur,0); if(w) { int index = m_editorTabWidget->indexOf(w); m_editorTabWidget->setTabText(index,cur->name()); } emit currentEditorChanged(cur); return true; } bool EditorManager::saveAllEditors(bool emitAboutSave) { QList editorList = m_widgetEditorMap.values(); foreach (IEditor *editor, editorList) { saveEditor(editor,emitAboutSave); } return true; } bool EditorManager::closeAllEditors() { bool bCloseAll = true; QMapIterator i (m_widgetEditorMap); while (i.hasNext()) { i.next(); if (!closeEditor(i.value())) { bCloseAll = false; break; } } return bCloseAll; } IEditor *EditorManager::currentEditor() const { return m_currentEditor; } void EditorManager::updateEditorMenu(IEditContext *context) { if (context && context->focusMenu()) { #if defined(Q_OS_OSX) // dirty trick to show the correct edit menu at the first time on Mac OS X m_editMenu->setEnabled(false); #endif m_editMenu->menuAction()->setMenu(context->focusMenu()); m_editMenu->setEnabled(true); } else { m_editMenu->menuAction()->setMenu(m_nullMenu); m_editMenu->setEnabled(false); } if (context && context->focusToolBar()) { context->focusToolBar()->setEnabled(true); } } void EditorManager::setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory) { if (m_currentEditor == editor) { return; } if (editor && !ignoreNavigationHistory) { this->addNavigationHistory(); } m_currentEditor = editor; this->updateEditInfo(""); if (editor != 0) { m_editorTabWidget->setCurrentWidget(editor->widget()); editor->onActive(); } if (!m_updateMenuInFocus) { IEditContext *context = LiteApi::getEditContext(editor); updateEditorMenu(context); } emit currentEditorChanged(editor); } IEditor *EditorManager::findEditor(const QString &fileName, bool canonical) const { QMapIterator i(m_widgetEditorMap); while (i.hasNext()) { i.next(); if (FileUtil::compareFile(i.value()->filePath(),fileName,canonical)) { return i.value(); } } return 0; } QList EditorManager::editorList() const { return m_widgetEditorMap.values(); } void EditorManager::addFactory(IEditorFactory *factory) { m_factoryList.append(factory); } void EditorManager::removeFactory(IEditorFactory *factory) { m_factoryList.removeOne(factory); } QList EditorManager::factoryList() const { return m_factoryList; } QStringList EditorManager::mimeTypeList() const { QStringList types; foreach(IEditorFactory *factory, m_factoryList) { types.append(factory->mimeTypes()); } return types; } IEditor *EditorManager::openEditor(const QString &fileName, const QString &mimeType) { IEditor *editor = findEditor(fileName,true); if (editor) { return editor; } bool matchFactory = false; foreach (IEditorFactory *factory, m_factoryList) { if (factory->mimeTypes().contains(mimeType)) { matchFactory = true; try { editor = factory->open(fileName,mimeType); } catch(std::bad_alloc &ba) { m_liteApp->appendLog("EditorManager",QString("exception %1! can not load file %2").arg(ba.what()).arg(fileName),true); return 0; } if (editor) { break; } } } if (editor == 0 && !matchFactory) { QString type = "liteide/default.editor"; foreach (IEditorFactory *factory, m_factoryList) { if (factory->mimeTypes().contains(type)) { try { editor = factory->open(fileName,type); } catch(std::bad_alloc &ba) { m_liteApp->appendLog("EditorManager",QString("exception %1! can not load file %2").arg(ba.what()).arg(fileName),true); return 0; } if (editor) { break; } } } } if (editor) { addEditor(editor); ITextEditor *textEditor = getTextEditor(editor); if (textEditor) { textEditor->restoreState(m_liteApp->settings()->value(QString("state_%1").arg(editor->filePath())).toByteArray()); } while (m_editorTabWidget->tabBar()->count() > m_maxEditorCount) { this->closeEditorForTab(0); } } return editor; } IEditor *EditorManager::openEditorByFactory(const QString &fileName, const QString &mimeType, const QString &factoryId) { IEditor *editor1 = findEditor(fileName,true); IEditor *editor = 0; foreach (IEditorFactory *factory, m_factoryList) { if (factory->id() == factoryId) { if (factory->testMimeType(mimeType)) { try { editor = factory->open(fileName,mimeType); } catch(std::bad_alloc &ba) { m_liteApp->appendLog("EditorManager",QString("exception %1! can not load file %2").arg(ba.what()).arg(fileName),true); return 0; } if (editor) { break; } } break; } } if (editor1) { if (editor) { this->closeEditor(editor1); } else { return editor1; } } if (editor) { addEditor(editor); ITextEditor *textEditor = getTextEditor(editor); if (textEditor) { textEditor->restoreState(m_liteApp->settings()->value(QString("state_%1").arg(editor->filePath())).toByteArray()); } while (m_editorTabWidget->tabBar()->count() > m_maxEditorCount) { this->closeEditorForTab(0); } } return editor; } void EditorManager::toggleBrowserAction(bool b) { QAction *act = (QAction*)sender(); if (act) { IEditor *editor = m_browserActionMap.key(act,0); if (editor) { if (b) { addEditor(editor); setCurrentEditor(editor); } else { closeEditor(editor); } } } } void EditorManager::modificationChanged(bool b) { IEditor *editor = static_cast(sender()); if (editor) { QString text = editor->name(); QString filePath = editor->filePath(); if (b) { text += " *"; } int index = m_editorTabWidget->indexOf(editor->widget()); if (index >= 0) { m_editorTabWidget->setTabText(index,text); } for (int i = 0; i < m_editorModel->rowCount(); i++) { QStandardItem *item = m_editorModel->item(i,0); if (item->toolTip() == filePath) { item->setText(text); break; } } emit editorModifyChanged(editor,b); } } void EditorManager::addNavigationHistory(IEditor *editor,const QByteArray &saveState) { if (editor && editor != currentEditor()) { return; // we only save editor sate for the current editor, when the user interacts } if (!editor) editor = currentEditor(); if (!editor) return; QString filePath = editor->filePath(); if (filePath.isEmpty()) { return; } QByteArray state; if (saveState.isNull()) { state = editor->saveState(); } else { state = saveState; } m_currentNavigationHistoryPosition = qMin(m_currentNavigationHistoryPosition, m_navigationHistory.size()); // paranoia if (m_currentNavigationHistoryPosition > 0 && m_currentNavigationHistoryPosition <= m_navigationHistory.size()) { EditLocation &prev = m_navigationHistory[m_currentNavigationHistoryPosition-1]; if (prev.filePath == filePath && prev.state == state) { return; } } EditLocation location; location.filePath = filePath; location.state = state; m_navigationHistory.insert(m_currentNavigationHistoryPosition, location); ++m_currentNavigationHistoryPosition; while (m_navigationHistory.size() >= 100) { if (m_currentNavigationHistoryPosition > 50) { m_navigationHistory.removeFirst(); --m_currentNavigationHistoryPosition; } else { m_navigationHistory.removeLast(); } } updateNavigatorActions(); } void EditorManager::goBack() { updateCurrentPositionInNavigationHistory(); if (m_currentNavigationHistoryPosition > 0) { --m_currentNavigationHistoryPosition; EditLocation location = m_navigationHistory.at(m_currentNavigationHistoryPosition); IEditor *editor = m_liteApp->fileManager()->openEditor(location.filePath,true,true); if (editor) { editor->restoreState(location.state); } else { m_navigationHistory.removeAt(m_currentNavigationHistoryPosition); } } updateNavigatorActions(); } void EditorManager::goForward() { updateCurrentPositionInNavigationHistory(); if (m_currentNavigationHistoryPosition >= m_navigationHistory.size()-1) return; ++m_currentNavigationHistoryPosition; EditLocation location = m_navigationHistory.at(m_currentNavigationHistoryPosition); IEditor *editor = m_liteApp->fileManager()->openEditor(location.filePath,true,true); if (!editor) { return; } editor->restoreState(location.state); updateNavigatorActions(); } void EditorManager::updateNavigatorActions() { m_goBackAct->setEnabled(m_currentNavigationHistoryPosition > 0); m_goForwardAct->setEnabled(m_currentNavigationHistoryPosition < m_navigationHistory.size()-1); } void EditorManager::cutForwardNavigationHistory() { while (m_currentNavigationHistoryPosition < m_navigationHistory.size() - 1) m_navigationHistory.removeLast(); } void EditorManager::loadColorStyleScheme(const QString &fileName) { if (m_colorStyleScheme->load(fileName)) { emit colorStyleSchemeChanged(); } } const ColorStyleScheme *EditorManager::colorStyleScheme() const { return m_colorStyleScheme; } void EditorManager::addEditContext(IEditContext *context) { m_editContextMap.insert(context->focusWidget(),context); } void EditorManager::removeEditContext(IEditContext *context) { m_editContextMap.remove(context->focusWidget()); } void EditorManager::updateEditInfo(const QString &info) { m_lineInfo->setText(info); } void EditorManager::updateCurrentPositionInNavigationHistory() { IEditor *editor = currentEditor(); if (!editor) return; QString filePath = editor->filePath(); if(filePath.isEmpty()) { return; } EditLocation *location; if (m_currentNavigationHistoryPosition < m_navigationHistory.size()) { location = &m_navigationHistory[m_currentNavigationHistoryPosition]; } else { m_navigationHistory.append(EditLocation()); location = &m_navigationHistory[m_navigationHistory.size()-1]; } location->filePath = filePath; location->state = editor->saveState(); } void EditorManager::tabContextClose() { if (m_tabContextIndex < 0) { return; } editorTabCloseRequested(m_tabContextIndex); } void EditorManager::tabContextCloseOthers() { if (m_tabContextIndex < 0) { return; } QList closeList; for (int i = 0; i < m_editorTabWidget->tabBar()->count(); i++) { if (i != m_tabContextIndex) { QWidget *w = m_editorTabWidget->widget(i); IEditor *ed = m_widgetEditorMap.value(w,0); closeList << ed; } } foreach(IEditor *ed, closeList ) { closeEditor(ed); } } void EditorManager::tabContextCloseLefts() { if (m_tabContextIndex < 0) { return; } QList closeList; for (int i = 0; i < m_tabContextIndex; i++) { QWidget *w = m_editorTabWidget->widget(i); IEditor *ed = m_widgetEditorMap.value(w,0); closeList << ed; } foreach(IEditor *ed, closeList ) { closeEditor(ed); } } void EditorManager::tabContextCloseRights() { if (m_tabContextIndex < 0) { return; } QList closeList; for (int i = m_tabContextIndex+1; i < m_editorTabWidget->tabBar()->count(); i++) { QWidget *w = m_editorTabWidget->widget(i); IEditor *ed = m_widgetEditorMap.value(w,0); closeList << ed; } foreach(IEditor *ed, closeList ) { closeEditor(ed); } } void EditorManager::tabContextCloseAll() { closeAllEditors(); } void EditorManager::tabContextCopyPathToClipboard() { QString filePath = tabContextFilePath(); if (filePath.isEmpty()) { return; } qApp->clipboard()->setText(QDir::toNativeSeparators(filePath)); } void EditorManager::tabContextShowInExplorer() { QString filePath = tabContextFilePath(); if (filePath.isEmpty()) { return; } FileUtil::openInExplorer(filePath); } void EditorManager::tabContextOpenInShell() { QString filePath = tabContextFilePath(); if (filePath.isEmpty()) { return; } QProcessEnvironment env = LiteApi::getCurrentEnvironment(m_liteApp); FileUtil::openInShell(env,filePath); } void EditorManager::tabContextOpenInTerminal() { QString filePath = tabContextFilePath(); if (filePath.isEmpty()) { return; } QFileInfo info(filePath); LiteApi::ITerminal *terminal = LiteApi::getTerminalManager(m_liteApp); if (terminal) { terminal->openDefaultTerminal(info.path()); } } void EditorManager::tabContextCloseOtherFolderFiles() { QString filePath = tabContextFilePath(); if (filePath.isEmpty()) { return; } QFileInfo info(filePath); QString path = info.path(); QList closeList; for (int i = 0; i < m_editorTabWidget->tabBar()->count(); i++) { if (i != m_tabContextIndex) { QWidget *w = m_editorTabWidget->widget(i); IEditor *ed = m_widgetEditorMap.value(w,0); QString filePath = ed->filePath(); if (filePath.isEmpty()) { continue; } QFileInfo info(filePath); if (info.path() != path) { closeList << ed; } } } foreach(IEditor *ed, closeList ) { closeEditor(ed); } } void EditorManager::tabContextCloseSameFolderFiles() { if (m_tabContextIndex < 0) { return; } QWidget *w = m_editorTabWidget->widget(m_tabContextIndex); IEditor *ed = m_widgetEditorMap.value(w,0); if (!ed) { return; } QString filePath = ed->filePath(); if (filePath.isEmpty()) { return; } QFileInfo info(filePath); QString path = info.path(); QList closeList; closeList << ed; for (int i = 0; i < m_editorTabWidget->tabBar()->count(); i++) { if (i != m_tabContextIndex) { QWidget *w = m_editorTabWidget->widget(i); IEditor *ed = m_widgetEditorMap.value(w,0); QString filePath = ed->filePath(); if (filePath.isEmpty()) { continue; } QFileInfo info(filePath); if (info.path() == path) { closeList << ed; } } } foreach(IEditor *ed, closeList ) { closeEditor(ed); } } void EditorManager::moveToNewWindow() { if (m_tabContextIndex < 0) { return; } QWidget *w = m_editorTabWidget->widget(m_tabContextIndex); IEditor *ed = m_widgetEditorMap.value(w,0); if (!ed) { return; } QString filePath = ed->filePath(); if (filePath.isEmpty()) { return; } QString sessionName = "dir:"+QFileInfo(filePath).dir().dirName(); IApplication *app = m_liteApp->newInstance(sessionName); QFileInfo info(filePath); if (app->fileManager()->openEditor(filePath)) { this->closeEditor(ed); app->fileManager()->addFolderList(info.path()); } } void EditorManager::focusChanged(QWidget *old, QWidget *now) { if (!m_updateMenuInFocus) { return; } IEditContext *context = m_editContextMap.value(now); updateEditorMenu(context); context = m_editContextMap.value(old); if (context && context->focusToolBar()) { context->focusToolBar()->setEnabled(false); } } void EditorManager::aboutToShowListMenu() { m_listMenu->clear(); QList actions = m_listGroup->actions(); qDeleteAll(actions); foreach (QWidget *widget, m_editorTabWidget->widgetList()) { LiteApi::IEditor *editor = m_widgetEditorMap.value(widget); if (!editor) { continue; } QAction *act = new QAction(editor->name()+"\t"+editor->filePath(),m_listGroup); act->setCheckable(true); act->setToolTip(editor->filePath()); m_listGroup->addAction(act); if (m_currentEditor == editor) { act->setChecked(true); } } m_listMenu->addActions(m_listGroup->actions()); } void EditorManager::triggeredListAction(QAction *act) { int index = m_listGroup->actions().indexOf(act); if (index < 0) { return; } m_editorTabWidget->setCurrentIndex(index); } void EditorManager::applyOption(QString id) { if (id != OPTION_LITEAPP) { return; } m_isAutoIdleSaveDocuments = m_liteApp->settings()->value(LITEAPP_AUTOIDLESAVEDOCUMENTS,false).toBool(); m_autoIdleSaveDocumentsTime = m_liteApp->settings()->value(LITEAPP_AUTOIDLESAVEDOCUMENTS_TIME,3).toInt(); if (m_autoIdleSaveDocumentsTime < 1) { m_autoIdleSaveDocumentsTime = 1; } m_maxEditorCount = m_liteApp->settings()->value(LITEAPP_MAXEDITORCOUNT,64).toInt(); m_editorTabWidget->tabBar()->setTabsClosable(m_liteApp->settings()->value(LITEAPP_EDITTABSCLOSABLE,true).toBool()); m_editorTabWidget->tabBar()->setEnableWheel(m_liteApp->settings()->value(LITEAPP_EDITTABSENABLEWHELL,true).toBool()); m_mouseExtNavigate = m_liteApp->settings()->value(LITEAPP_EDITORMOUSEEXTNAVIGATE,true).toBool(); #ifdef Q_OS_MAC #if QT_VERSION >= 0x050900 QString qss = m_liteApp->settings()->value(LITEAPP_QSS,"default.qss").toString(); if (qss == "default.qss") { m_editorTabWidget->tabBar()->setStyleSheet( "QTabBar::tab {" "border: 1px solid #C4C4C3;" "border-bottom-color: #C2C7CB; /* same as the pane color */" "min-width: 8ex;" "padding: 4px 2px 4px 2px;" "}" "QTabBar::close-button:hover,QTabBar::close-button:selected {" "margin: 0px;" "image: url(:/images/close.png);" "subcontrol-position: left;" "padding: 1px;" "}" "QTabBar::tab:selected, QTabBar::tab:hover {" "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," "stop: 0 #fafafa, stop: 0.4 #f4f4f4," "stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);" "}" "QTabBar::tab:selected {" "border-color: #9B9B9B;" "border-bottom-color: #C2C7CB; /* same as pane color */" "}" "QTabBar::tab:!selected {" "margin-top: 2px; /* make non-selected tabs look smaller */" "}"); } else { m_editorTabWidget->tabBar()->setStyleSheet("QTabBar::close-button:hover,QTabBar::close-button:selected {margin: 0px; image: url(:/images/close.png); subcontrol-position: left; }"); } #endif #endif } void EditorManager::appIdle(int sec) { if (m_isAutoIdleSaveDocuments) { if (sec == m_autoIdleSaveDocumentsTime) { this->saveAllEditors(false); } } } void EditorManager::closeEditorForTab(int index) { QWidget *w = m_editorTabWidget->widget(index); IEditor *ed = m_widgetEditorMap.value(w,0); closeEditor(ed); } ================================================ FILE: liteidex/src/liteapp/editormanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: editormanager.h // Creator: visualfc #ifndef EDITORMANAGER_H #define EDITORMANAGER_H #include "liteapi/liteapi.h" #include "colorstyle/colorstyle.h" #include "tabwidget/litetabwidget.h" #include using namespace LiteApi; class LiteTabWidget; class QStackedWidget; class QToolButton; class QLabel; class QStandardItemModel; class OpenEditorsWidget; class QTreeView; struct EditLocation { QString filePath; QByteArray state; }; class EditorManager : public IEditorManager { Q_OBJECT public: ~EditorManager(); virtual bool initWithApp(IApplication *app); void createActions(); public: virtual IEditor *openEditor(const QString &fileName, const QString &mimeType); virtual IEditor *openEditorByFactory(const QString &fileName, const QString &mimeType, const QString &factoryId); virtual void addFactory(IEditorFactory *factory); virtual void removeFactory(IEditorFactory *factory); virtual QList factoryList() const; virtual QStringList mimeTypeList() const; public: virtual QWidget *widget(); virtual IEditor *currentEditor() const; virtual void setCurrentEditor(IEditor *editor, bool ignoreNavigationHistory = false); virtual IEditor *findEditor(const QString &fileName, bool canonical) const; virtual QList editorList() const; virtual QAction *registerBrowser(IEditor *editor); virtual void activeBrowser(IEditor *editor); virtual void addNavigationHistory(IEditor *editor = 0,const QByteArray &saveState = QByteArray()); virtual void cutForwardNavigationHistory(); virtual void loadColorStyleScheme(const QString &file); virtual const ColorStyleScheme *colorStyleScheme() const; virtual void addEditContext(IEditContext *context); virtual void removeEditContext(IEditContext *context); virtual void updateEditInfo(const QString &info); protected: void addEditor(IEditor *editor); bool eventFilter(QObject *target, QEvent *event); QString tabContextFilePath() const; public: QList sortedEditorList() const; public slots: virtual bool saveEditor(IEditor *editor = 0, bool emitAboutSave = true); virtual bool saveEditorAs(IEditor *editor = 0); virtual bool saveAllEditors(bool emitAboutSave = true); virtual bool closeEditor(IEditor *editor = 0); virtual bool closeAllEditors(); void tabContextClose(); void tabContextCloseOthers(); void tabContextCloseLefts(); void tabContextCloseRights(); void tabContextCloseAll(); void tabContextCloseOtherFolderFiles(); void tabContextCloseSameFolderFiles(); void tabContextCopyPathToClipboard(); void tabContextShowInExplorer(); void tabContextOpenInShell(); void tabContextOpenInTerminal(); void goBack(); void goForward(); void updateNavigatorActions(); void updateCurrentPositionInNavigationHistory(); void moveToNewWindow(); void focusChanged(QWidget *old,QWidget *now); void aboutToShowListMenu(); void triggeredListAction(QAction *act); void applyOption(QString); void appIdle(int sec); void closeEditorForTab(int index); void updateEditorMenu(IEditContext *context); signals: void tabAddRequest(); void doubleClickedTab(); protected slots: void editorTabChanged(int); void editorTabCloseRequested(int); void modificationChanged(bool); void toggleBrowserAction(bool); void gotoNextTab(); void gotoPrevTab(); protected: QMenu *m_nullMenu; QList m_navigationHistory; int m_currentNavigationHistoryPosition; QWidget *m_widget; LiteTabWidget *m_editorTabWidget; QMap m_widgetEditorMap; QStandardItemModel *m_editorModel; OpenEditorsWidget *m_openEditorWidget; QPointer m_currentEditor; QList m_factoryList; QMap m_browserActionMap; QMap m_editContextMap; QAction *m_goBackAct; QAction *m_goForwardAct; QAction *m_gotoNextTab; QAction *m_gotoPrevTab; QMenu *m_listMenu; QActionGroup *m_listGroup; QMenu *m_editMenu; QMenu *m_tabContextFileMenu; QMenu *m_tabContextNofileMenu; ColorStyleScheme *m_colorStyleScheme; int m_tabContextIndex; int m_maxEditorCount; QLabel *m_lineInfo; bool m_isAutoIdleSaveDocuments; bool m_updateMenuInFocus; bool m_mouseExtNavigate; int m_autoIdleSaveDocumentsTime; }; #endif // EDITORMANAGER_H ================================================ FILE: liteidex/src/liteapp/filemanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filemanager.cpp // Creator: visualfc #include "filemanager.h" #include "newfiledialog.h" #include "fileutil/fileutil.h" #include "liteenvapi/liteenvapi.h" #include "folderview/folderlistview.h" #include "folderview/multifolderview.h" #include "liteapp_global.h" #include "multifolderwindow.h" #include "splitfolderwindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end bool FileManager::initWithApp(IApplication *app) { if (!IFileManager::initWithApp(app)) { return false; } // m_folderWindow = new MultiFolderWindow(app); m_fileWatcher = new QFileSystemWatcher(this); connect(m_fileWatcher,SIGNAL(fileChanged(QString)),this,SLOT(fileChanged(QString))); m_newFileDialog = 0; m_initPath = m_liteApp->settings()->value("FileManager/initpath",QDir::homePath()).toString(); m_fileWatcherAutoReload = m_liteApp->settings()->value(LITEAPP_FILEWATCHERAUTORELOAD,false).toBool(); m_showHideFilesAct = new QAction(tr("Show Hidden Files"),this); m_showHideFilesAct->setCheckable(true); m_showDetailsAct = new QAction(tr("Show Details"),this); m_showDetailsAct->setCheckable(true); m_syncEditorAct = new QAction(QIcon("icon:images/sync.png"),tr("Synchronize with editor"),this); m_syncEditorAct->setCheckable(true); m_splitModeAct = new QAction(tr("Split Mode"),this); m_splitModeAct->setCheckable(true); bool bSplitMode = m_liteApp->settings()->value(LITEAPP_FOLDERSPLITMODE,false).toBool(); if (bSplitMode) { m_folderWindow = new SplitFolderWindow(app); } else { m_folderWindow = new MultiFolderWindow(app); } m_splitModeAct->setChecked(bSplitMode); bool bShowHiddenFiles = m_liteApp->settings()->value(LITEAPP_FOLDERSHOWHIDENFILES,false).toBool(); m_showHideFilesAct->setChecked(bShowHiddenFiles); m_folderWindow->setShowHideFiles(bShowHiddenFiles); bool bShowDetails = m_liteApp->settings()->value(LITEAPP_FOLDERSHOWDETAILS,false).toBool(); m_showDetailsAct->setChecked(bShowDetails); m_folderWindow->setShowDetails(bShowDetails); bool bSyncEditor = m_liteApp->settings()->value(LITEAPP_FOLDERSSYNCEDITOR,false).toBool(); m_syncEditorAct->setChecked(bSyncEditor); m_folderWindow->setSyncEditor(bSyncEditor); connect(m_showHideFilesAct,SIGNAL(triggered(bool)),this,SLOT(setShowHideFiles(bool))); connect(m_showDetailsAct,SIGNAL(triggered(bool)),this,SLOT(setShowDetails(bool))); connect(m_syncEditorAct,SIGNAL(triggered(bool)),this,SLOT(setSyncEditor(bool))); connect(m_splitModeAct,SIGNAL(triggered(bool)),this,SLOT(setSplitMode(bool))); QList actions; m_filterMenu = new QMenu(tr("Filter")); m_filterMenu->setIcon(QIcon("icon:images/filter.png")); m_filterMenu->addAction(m_showHideFilesAct); m_filterMenu->addAction(m_showDetailsAct); m_filterMenu->addSeparator(); m_filterMenu->addAction(m_splitModeAct); actions << m_filterMenu->menuAction() << m_syncEditorAct; m_folderWidget = new QWidget; m_layout = new QVBoxLayout; m_layout->setMargin(0); m_folderWidget->setLayout(m_layout); m_layout->addWidget(m_folderWindow->widget()); m_toolWindowAct = m_liteApp->toolWindowManager()->addToolWindow(Qt::LeftDockWidgetArea,m_folderWidget,"Folders",tr("Folders"),false,actions); return true; } FileManager::FileManager() : m_newFileDialog(0), m_folderWindow(0), m_checkBlockActivated(false), m_checkOnFocusChange(false) { connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(onApplicationFocusChange())); } FileManager::~FileManager() { m_liteApp->settings()->setValue(LITEAPP_FOLDERSSYNCEDITOR,m_syncEditorAct->isChecked()); m_liteApp->settings()->setValue(LITEAPP_FOLDERSHOWHIDENFILES,m_showHideFilesAct->isChecked()); m_liteApp->settings()->setValue(LITEAPP_FOLDERSHOWDETAILS,m_showDetailsAct->isChecked()); m_liteApp->settings()->setValue(LITEAPP_FOLDERSPLITMODE,m_splitModeAct->isChecked()); delete m_filterMenu; delete m_fileWatcher; m_liteApp->settings()->setValue("FileManager/initpath",m_initPath); if (m_newFileDialog) { delete m_newFileDialog; } delete m_folderWindow; } bool FileManager::findProjectTargetInfo(const QString &fileName, QMap& targetInfo) const { QString mimeType = m_liteApp->mimeTypeManager()->findMimeTypeByFile(fileName); if (m_liteApp->projectManager()->mimeTypeList().contains(mimeType)) { QList factoryList = m_liteApp->projectManager()->factoryList(); foreach(LiteApi::IProjectFactory *factory, factoryList) { if (factory->mimeTypes().contains(mimeType)) { bool ret = factory->findTargetInfo(fileName,mimeType,targetInfo); if (ret) { return true; } } } } return false; } QString FileManager::openAllTypeFilter() const { QStringList types; QStringList filter; foreach (IMimeType *mimeType, m_liteApp->mimeTypeManager()->mimeTypeList()) { QStringList patterns = mimeType->allPatterns(); types.append(patterns); filter.append(QString("%1 (%2)").arg(mimeType->comment()).arg(patterns.join(" "))); } types.removeDuplicates(); filter.removeDuplicates(); if (!types.isEmpty()) { QString all = QString(tr("All Support Files (%1)")).arg(types.join(" ")); filter.insert(0,all); } filter.append(tr("All Files (*)")); return filter.join(";;"); } QString FileManager::openProjectTypeFilter() const { QStringList types; QStringList filter; QStringList projectMimeTypes = m_liteApp->projectManager()->mimeTypeList(); foreach (IMimeType *mimeType, m_liteApp->mimeTypeManager()->mimeTypeList()) { QStringList patterns = mimeType->allPatterns(); if (projectMimeTypes.contains(mimeType->type())) { types.append(patterns); filter.append(QString("%1 (%2)").arg(mimeType->comment()).arg(patterns.join(" "))); } } types.removeDuplicates(); filter.removeDuplicates(); if (!types.isEmpty()) { QString all = QString(tr("All Support Files (%1)")).arg(types.join(" ")); filter.insert(0,all); } filter.append(tr("All Files (*)")); return filter.join(";;"); } QString FileManager::openEditorTypeFilter() const { QStringList types; QStringList filter; QStringList projectMimeTypes = m_liteApp->editorManager()->mimeTypeList(); foreach (IMimeType *mimeType, m_liteApp->mimeTypeManager()->mimeTypeList()) { if (projectMimeTypes.contains(mimeType->type())) { QStringList patterns = mimeType->allPatterns(); types.append(patterns); filter.append(QString("%1 (%2)").arg(mimeType->comment()).arg(patterns.join(" "))); } } types.removeDuplicates(); filter.removeDuplicates(); if (!types.isEmpty()) { QString all = QString(tr("All Support Files (%1)")).arg(types.join(" ")); filter.insert(0,all); } filter.append(tr("All Files (*)")); return filter.join(";;"); } QStringList FileManager::folderList() const { return m_folderWindow->folderList(); } void FileManager::setFolderList(const QStringList &folders) { m_folderWindow->setFolderList(folders); } void FileManager::addFolderList(const QString &folder) { m_folderWindow->addFolderList(folder); } IApplication* FileManager::openFolderInNewWindow(const QString &folder) { IApplication *app = m_liteApp->newInstance("dir:"+QDir(folder).dirName()); app->fileManager()->setFolderList(QStringList() << folder); return app; } void FileManager::emitAboutToShowFolderContextMenu(QMenu *menu, FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info, const QString &context) { emit aboutToShowFolderContextMenu(menu,flag,info,context); } void FileManager::newFile() { QString projPath; QString filePath; IProject *project = m_liteApp->projectManager()->currentProject(); if (project) { QFileInfo info(project->filePath()); if (info.isDir()) { projPath = info.filePath(); } else { projPath = info.path(); } } IEditor *editor = m_liteApp->editorManager()->currentEditor(); if (editor && !editor->filePath().isEmpty()) { filePath = QFileInfo(editor->filePath()).absolutePath(); } if (filePath.isEmpty()) { #if QT_VERSION >= 0x050000 filePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); #else filePath = QDesktopServices::storageLocation(QDesktopServices::HomeLocation); #endif } if (projPath.isEmpty()) { #if QT_VERSION >= 0x050000 projPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); #else projPath = QDesktopServices::storageLocation(QDesktopServices::HomeLocation); #endif } execFileWizard(projPath,filePath); } void FileManager::openFiles() { QStringList fileNames = QFileDialog::getOpenFileNames(m_liteApp->mainWindow(), tr("Open Project or File"), m_initPath,openAllTypeFilter()); if (fileNames.isEmpty()) return; foreach (QString fileName, fileNames) { if (openFile(fileName)) { m_initPath = QFileInfo(fileName).canonicalPath(); } } } void FileManager::openFolder() { QString folder = QFileDialog::getExistingDirectory(m_liteApp->mainWindow(), tr("Select a folder:"), m_initPath); if (!folder.isEmpty()) { QDir dir(folder); if (dir.cdUp()) { m_initPath = dir.path(); } this->addFolderList(folder); } } void FileManager::newInstance() { m_liteApp->newInstance(""); } void FileManager::openFolderNewWindow() { QString folder = QFileDialog::getExistingDirectory(m_liteApp->mainWindow(), tr("Select a folder:"), m_initPath); if (!folder.isEmpty()) { QDir dir(folder); if (dir.cdUp()) { m_initPath = dir.path(); } this->openFolderInNewWindow(folder); } } void FileManager::closeAllFolders() { m_folderWindow->closeAllFolders(); } void FileManager::openEditors() { QStringList fileNames = QFileDialog::getOpenFileNames(m_liteApp->mainWindow(), tr("Open Files"), m_initPath,openEditorTypeFilter()); if (fileNames.isEmpty()) return; foreach (QString fileName, fileNames) { if (openEditor(fileName)) { m_initPath = QFileInfo(fileName).canonicalPath(); } } } void FileManager::openProjects() { QStringList fileNames = QFileDialog::getOpenFileNames(m_liteApp->mainWindow(), tr("Open Project"), m_initPath,openProjectTypeFilter()); if (fileNames.isEmpty()) return; foreach (QString fileName, fileNames) { if (openProject(fileName)) { m_initPath = QFileInfo(fileName).canonicalPath(); } } } void FileManager::execFileWizard(const QString &projPath, const QString &filePath, const QString &gopath) { if (!m_newFileDialog) { m_newFileDialog = new NewFileDialog(m_liteApp->mainWindow()); m_newFileDialog->loadTemplate(m_liteApp->resourcePath()+"/liteapp/template"); } QStringList pathList = LiteApi::getGOPATH(m_liteApp,false); //pathList.append(LiteApi::getGOROOT(m_liteApp)); pathList.removeDuplicates(); m_newFileDialog->setPathList(pathList); if (!gopath.isEmpty()) { m_newFileDialog->setGopath(gopath); } m_newFileDialog->setFileLocation(filePath); m_newFileDialog->setProjectLocation(projPath); m_newFileDialog->updateLocation(); if (pathList.isEmpty() && gopath.isEmpty()) { m_newFileDialog->setGopath(projPath); } if (m_newFileDialog->exec() == QDialog::Accepted) { //emit fileWizardFinished(m_newFileDialog->openPath(),m_newFileDialog->f) emit fileWizardFinished(m_newFileDialog->type(),m_newFileDialog->scheme(),m_newFileDialog->openPath()); QMessageBox::StandardButton ret; ret = QMessageBox::question(m_liteApp->mainWindow(), tr("LiteIDE"), tr("Project '%1' has been created.\n" "Do you want to open it now?") .arg(m_newFileDialog->openFiles().join(" ")), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes); if (ret == QMessageBox::Yes) { QString scheme = m_newFileDialog->scheme(); if (scheme == "folder") { this->addFolderList(m_newFileDialog->openPath()); } foreach(QString file, m_newFileDialog->openFiles()) { this->openFile(file); } } } } bool FileManager::openFile(const QString &fileName) { QString mimeType = m_liteApp->mimeTypeManager()->findMimeTypeByFile(fileName); if (m_liteApp->projectManager()->mimeTypeList().contains(mimeType)) { return openProject(fileName) != 0; } else { return openEditor(fileName) != 0; } return false; } IEditor *FileManager::createEditor(const QString &contents, const QString &mimeType) { foreach(LiteApi::IEditorFactory *factory, m_liteApp->editorManager()->factoryList()) { if (factory->mimeTypes().contains(mimeType)) { LiteApi::IEditor *editor = factory->create(contents,mimeType); if (editor) { return editor; } } } return NULL; } IEditor *FileManager::createEditor(const QString &_fileName) { QString fileName = QDir::fromNativeSeparators(_fileName); QString mimeType = m_liteApp->mimeTypeManager()->findMimeTypeByFile(fileName); foreach(LiteApi::IEditorFactory *factory, m_liteApp->editorManager()->factoryList()) { if (factory->mimeTypes().contains(mimeType)) { LiteApi::IEditor *editor = factory->open(fileName,mimeType); if (editor) { return editor; } } } return NULL; } IEditor *FileManager::openEditor(const QString &_fileName, bool bActive, bool ignoreNavigationHistory) { QString fileName = QDir::fromNativeSeparators(QDir::cleanPath(_fileName)); QString mimeType = m_liteApp->mimeTypeManager()->findMimeTypeByFile(fileName); IEditor *editor = m_liteApp->editorManager()->openEditor(fileName,mimeType); if (editor && bActive) { m_liteApp->editorManager()->setCurrentEditor(editor,ignoreNavigationHistory); } if (editor) { m_liteApp->recentManager()->addRecent(fileName,"file"); } else { m_liteApp->recentManager()->removeRecent(fileName,"file"); } return editor; } IEditor *FileManager::openEditorByFactory(const QString &_fileName, const QString &factoryId, bool bActive, bool ignoreNavigationHistory) { QString fileName = QDir::fromNativeSeparators(QDir::cleanPath(_fileName)); QString mimeType = m_liteApp->mimeTypeManager()->findMimeTypeByFile(fileName); IEditor *editor = m_liteApp->editorManager()->openEditorByFactory(fileName,mimeType,factoryId); if (editor && bActive) { m_liteApp->editorManager()->setCurrentEditor(editor,ignoreNavigationHistory); } if (editor) { m_liteApp->recentManager()->addRecent(fileName,"file"); } else { m_liteApp->recentManager()->removeRecent(fileName,"file"); } return editor; } IProject *FileManager::openProject(const QString &_fileName) { QString fileName = QDir::fromNativeSeparators(_fileName); QString mimeType = m_liteApp->mimeTypeManager()->findMimeTypeByFile(fileName); IProject *proj = m_liteApp->projectManager()->openProject(fileName,mimeType); if (proj) { m_liteApp->recentManager()->addRecent(fileName,"proj"); } else { m_liteApp->recentManager()->removeRecent(fileName,"proj"); } return proj; } //IApplication* FileManager::openFolderEx(const QString &folder) //{ // QDir dir(folder); // if (!dir.exists()) { // return m_liteApp; // } // if (m_folderWidget->rootPathList().isEmpty()) { // m_folderWidget->setRootPath(folder); // } else { // if (m_liteApp->settings()->value(LITEAPP_OPTNFOLDERINNEWWINDOW,true).toBool()) { // return this->openFolderInNewWindow(folder); // } else { // m_folderWidget->setRootPath(folder); // } // } // m_toolWindowAct->setChecked(true); // addRecentFile(folder,"folder"); // return m_liteApp; //} IProject *FileManager::openProjectScheme(const QString &_fileName, const QString &scheme) { QString fileName = QDir::fromNativeSeparators(_fileName); QString mimeType = m_liteApp->mimeTypeManager()->findMimeTypeByScheme(scheme); if (mimeType.isEmpty()) { return 0; } IProject *proj = m_liteApp->projectManager()->openProject(QDir::fromNativeSeparators(fileName),mimeType); if (proj) { m_liteApp->recentManager()->addRecent(fileName,scheme); } else { m_liteApp->recentManager()->removeRecent(fileName,scheme); } return proj; } void FileManager::applyOption(QString id) { if (id != OPTION_LITEAPP) { return; } m_fileWatcherAutoReload = m_liteApp->settings()->value(LITEAPP_FILEWATCHERAUTORELOAD,false).toBool(); } void FileManager::updateFileState(const QString &fileName) { if (fileName.isEmpty()) { return; } m_fileStateMap.insert(fileName,QFileInfo(fileName).lastModified()); if (!m_fileWatcher->files().contains(fileName)) { m_fileWatcher->addPath(fileName);; } } void FileManager::editorCreated(LiteApi::IEditor *editor) { if (!editor) { return; } QString fileName = editor->filePath(); if (!fileName.isEmpty()) { updateFileState(fileName); } } void FileManager::editorAboutToClose(LiteApi::IEditor *editor) { if (!editor) { return; } QString fileName = editor->filePath(); if (!fileName.isEmpty()) { m_fileStateMap.remove(fileName); m_changedFiles.remove(fileName); m_fileWatcher->removePath(fileName); } } void FileManager::editorSaved(LiteApi::IEditor *editor) { if (!editor) { return; } updateFileState(editor->filePath()); } void FileManager::fileChanged(QString fileName) { const bool wasempty = m_changedFiles.isEmpty(); if (m_fileStateMap.contains(fileName)) { m_changedFiles.insert(fileName); } if (wasempty && !m_changedFiles.isEmpty()) { QTimer::singleShot(200, this, SLOT(checkForReload())); } } void FileManager::onApplicationFocusChange() { if (!m_checkOnFocusChange) return; m_checkOnFocusChange = false; checkForReload(); } void FileManager::setShowHideFiles(bool b) { m_folderWindow->setShowHideFiles(b); } void FileManager::setShowDetails(bool b) { m_folderWindow->setShowDetails(b); } void FileManager::setSyncEditor(bool b) { m_folderWindow->setSyncEditor(b); } void FileManager::setSplitMode(bool b) { QStringList folderList = m_folderWindow->folderList(); delete m_folderWindow; if (b) { m_folderWindow = new SplitFolderWindow(m_liteApp); } else { m_folderWindow = new MultiFolderWindow(m_liteApp); } m_layout->addWidget(m_folderWindow->widget()); m_folderWindow->setFolderList(folderList); m_folderWindow->setShowHideFiles(m_showHideFilesAct->isChecked()); m_folderWindow->setShowDetails(m_showDetailsAct->isChecked()); m_folderWindow->setSyncEditor(m_syncEditorAct->isChecked()); } void FileManager::checkForReload() { if (m_changedFiles.isEmpty()) { return; } if (this->m_checkBlockActivated) return; if (QApplication::activeModalWidget()) { // We do not want to prompt for modified file if we currently have some modal dialog open. // There is no really sensible way to get notified globally if a window closed, // so just check on every focus change. m_checkOnFocusChange = true; return; } this->m_checkBlockActivated = true; int lastReloadRet = QMessageBox::Yes; int lastCloseRet = QMessageBox::Yes; QStringList files = m_changedFiles.toList(); m_changedFiles.clear(); foreach (QString fileName, files) { if (!QFile::exists(fileName)) { //remove if (m_fileStateMap.contains(fileName)) { if (!fileName.isEmpty()) { LiteApi::IEditor *editor = m_liteApp->editorManager()->findEditor(fileName,false); if (editor) { // The file has been deleted. // If the buffer is modified, ask the user what he wants to do. // Otherwise, apply the default action : close the editor. int ret = QMessageBox::Yes; if (lastCloseRet != QMessageBox::YesToAll) { if (m_fileWatcherAutoReload) { if (editor->isModified() ) { QString text = QString(tr("%1\nThis file has been deleted from the drive,\n" "but you have unsaved modifications in your LiteIDE editor.\n" "\nDo you want to close the editor?" "\nAnswering \"Yes\" will discard your unsaved changes.")).arg(fileName); ret = QMessageBox::question(m_liteApp->mainWindow(),tr("LiteIDE X"),text,QMessageBox::YesToAll|QMessageBox::Yes|QMessageBox::No,QMessageBox::No); } } else { QString text = QString(tr("%1\nThis file has been deleted from the drive.\n" "\nDo you want to close the editor?")).arg(fileName); ret = QMessageBox::question(m_liteApp->mainWindow(),tr("LiteIDE X"),text,QMessageBox::YesToAll|QMessageBox::Yes|QMessageBox::No,QMessageBox::No); } } if (ret == QMessageBox::Yes || ret == QMessageBox::YesToAll) { m_liteApp->editorManager()->closeEditor(editor); m_liteApp->appendLog("EditorManager",fileName+" remove",false); } if (ret == QMessageBox::YesToAll) { lastCloseRet = QMessageBox::YesToAll; } } } } } else { if (m_fileStateMap.contains(fileName)) { LiteApi::IEditor *editor = m_liteApp->editorManager()->findEditor(fileName,true); if (editor) { // The file has been modified. // If the buffer is modified, ask the user what he wants to do. // Otherwise, apply the default action : reload the new content in the editor. QDateTime lastModified = QFileInfo(fileName).lastModified(); QDateTime modified = m_fileStateMap.value(fileName); if (!m_fileWatcher->files().contains(fileName)) { m_fileWatcher->addPath(fileName);; } if (lastModified > modified) { int ret = QMessageBox::Yes; if (lastReloadRet != QMessageBox::YesToAll) { if (m_fileWatcherAutoReload) { if (editor->isModified()) { QString text = QString(tr("%1\nThis file has been modified on the drive,\n" "but you have unsaved modifications in your LiteIDE editor.\n" "\nDo you want to reload the file from disk?" "\nAnswering \"Yes\" will discard your unsaved changes.")).arg(fileName); ret = QMessageBox::question(m_liteApp->mainWindow(),tr("LiteIDE X"),text,QMessageBox::YesToAll|QMessageBox::Yes|QMessageBox::No,QMessageBox::YesToAll); } } else { QString text = QString(tr("%1\nThis file has been modified on the drive.\n" "\nDo you want to reload the file from disk?")).arg(fileName); ret = QMessageBox::question(m_liteApp->mainWindow(),tr("LiteIDE X"),text,QMessageBox::YesToAll|QMessageBox::Yes|QMessageBox::No,QMessageBox::YesToAll); } } if (ret == QMessageBox::YesToAll || ret == QMessageBox::Yes) { // If the file modification is the result of an internal Ctrl+S, do not reload QDateTime lastModified = QFileInfo(fileName).lastModified(); QDateTime modified = m_fileStateMap.value(fileName); if (lastModified != modified) { editor->reload(); m_fileStateMap.insert(fileName,lastModified); m_liteApp->appendLog("EditorManager",fileName+" reload",false); } } if (ret == QMessageBox::YesToAll) { lastReloadRet = QMessageBox::YesToAll; } } } } } } m_checkBlockActivated = false; QTimer::singleShot(200, this, SLOT(checkForReload())); } ================================================ FILE: liteidex/src/liteapp/filemanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filemanager.h // Creator: visualfc #ifndef FILEMANAGER_H #define FILEMANAGER_H #include "liteapi/liteapi.h" #include using namespace LiteApi; class QFileSystemWatcher; class NewFileDialog; class FolderListView; class MultiFolderView; class QVBoxLayout; class IFolderWindow : public QObject { public: IFolderWindow(QObject *parent) : QObject(parent) { } virtual QString id() const = 0; virtual QWidget *widget() const = 0; virtual QStringList folderList() const = 0; virtual void setFolderList(const QStringList &folders) = 0; virtual void addFolderList(const QString &folder) = 0; virtual void closeAllFolders() = 0; virtual void setShowHideFiles(bool b) = 0; virtual void setShowDetails(bool b) = 0; virtual void setSyncEditor(bool b) = 0; }; class FileManager : public IFileManager { Q_OBJECT public: FileManager(); virtual bool initWithApp(IApplication *app); virtual ~FileManager(); public: virtual void execFileWizard(const QString &projPath, const QString &filePath, const QString &gopath = QString()); virtual bool openFile(const QString &fileName); virtual IEditor *openEditor(const QString &fileName, bool bActive = true, bool ignoreNavigationHistory = false); virtual IEditor *openEditorByFactory(const QString &fileName, const QString &factoryId, bool bActive = true, bool ignoreNavigationHistory = false); virtual IEditor *createEditor(const QString &contents, const QString &mimeType); virtual IEditor *createEditor(const QString &fileName); virtual IProject *openProject(const QString &fileName); virtual IProject *openProjectScheme(const QString &fileName, const QString &scheme); virtual bool findProjectTargetInfo(const QString &fileName, QMap& targetInfo) const; //virtual IApplication* openFolderEx(const QString &folder); virtual QStringList folderList() const; virtual void setFolderList(const QStringList &folders); virtual void addFolderList(const QString &folder); virtual IApplication* openFolderInNewWindow(const QString &folder); virtual void emitAboutToShowFolderContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info, const QString &context); public: QString openAllTypeFilter() const; QString openProjectTypeFilter() const; QString openEditorTypeFilter() const; protected: void updateFileState(const QString &fileName); public slots: void newFile(); void openFiles(); void openFolder(); void openFolderNewWindow(); void closeAllFolders(); void newInstance(); void openEditors(); void openProjects(); void fileChanged(QString); void editorSaved(LiteApi::IEditor*); void editorCreated(LiteApi::IEditor*); void editorAboutToClose(LiteApi::IEditor*); void checkForReload(); void applyOption(QString); void onApplicationFocusChange(); void setShowHideFiles(bool b); void setShowDetails(bool b); void setSyncEditor(bool b); void setSplitMode(bool b); protected: NewFileDialog *m_newFileDialog; IFolderWindow *m_folderWindow; QFileSystemWatcher *m_fileWatcher; QMap m_fileStateMap; QSet m_changedFiles; bool m_checkBlockActivated; bool m_checkOnFocusChange; bool m_fileWatcherAutoReload; QString m_initPath; QWidget *m_folderWidget; QVBoxLayout *m_layout; QMenu* m_filterMenu; QAction* m_showHideFilesAct; QAction* m_showDetailsAct; QAction* m_syncEditorAct; QAction* m_splitModeAct; QAction* m_toolWindowAct; }; #endif // FILEMANAGER_H ================================================ FILE: liteidex/src/liteapp/folderproject.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: folderproject.cpp // Creator: visualfc #include "folderproject.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FolderProject::FolderProject(IApplication *app) : m_liteApp(app), m_folderView(0) { #ifdef Q_OS_MAC m_folderView = new FolderListView(true,m_liteApp); #else m_folderView = new FolderListView(false,m_liteApp); #endif // m_folderView = new FolderListView(false,m_liteApp); m_folderView->setDragEnabled(true); m_folderView->setDragDropMode(QAbstractItemView::InternalMove); } FolderProject::~FolderProject() { if (m_folderView) { delete m_folderView; } } QWidget *FolderProject::widget() { return m_folderView; } QString FolderProject::name() const { return "FolderProject"; } QString FolderProject::filePath() const { QStringList paths = m_folderView->rootPathList(); if (!paths.isEmpty()) { return paths[0]; } return QString(); } QString FolderProject::mimeType() const { return "folder/x-path"; } void FolderProject::openFolder(const QString &folder) { m_folderView->setRootPathList(QStringList() << folder); } void FolderProject::appendFolder(const QString &folder) { m_folderView->addRootPath(folder); } void FolderProject::clear() { m_folderView->clear(); } QStringList FolderProject::folderList() const { return m_folderView->rootPathList(); } QStringList FolderProject::fileNameList() const { return QStringList(); } QStringList FolderProject::filePathList() const { return QStringList(); } QString FolderProject::fileNameToFullPath(const QString &filePath) { return filePath; } QMap FolderProject::targetInfo() const { return QMap(); } void FolderProject::load() { } ================================================ FILE: liteidex/src/liteapp/folderproject.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: folderproject.h // Creator: visualfc #ifndef FOLDERPROJECT_H #define FOLDERPROJECT_H #include "liteapi/liteapi.h" #include "folderview/folderlistview.h" using namespace LiteApi; class FolderProject : public IFolderProject { Q_OBJECT public: FolderProject(IApplication *app); virtual ~FolderProject(); virtual QWidget *widget(); virtual QString name() const; virtual QIcon icon() const { return QIcon(); } virtual QString filePath() const; virtual QString mimeType() const; virtual void openFolder(const QString &folder); virtual void appendFolder(const QString &folder); virtual void clear(); virtual QStringList folderList() const; virtual QStringList fileNameList() const; virtual QStringList filePathList() const; virtual QString fileNameToFullPath(const QString &filePath); virtual QMap targetInfo() const; virtual void load(); protected: IApplication *m_liteApp; FolderListView *m_folderView; }; #endif // FOLDERPROJECT_H ================================================ FILE: liteidex/src/liteapp/folderprojectfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: folderprojectfactory.cpp // Creator: visualfc #include "folderprojectfactory.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FolderProjectFactory::FolderProjectFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IProjectFactory(parent), m_liteApp(app) { m_mimeTypes.append("folder/x-path"); } QStringList FolderProjectFactory::mimeTypes() const { return m_mimeTypes; } LiteApi::IProject *FolderProjectFactory::open(const QString &fileName, const QString &mimeType) { if (!m_mimeTypes.contains(mimeType)) { return 0; } return m_liteApp->projectManager()->openFolder(fileName); } bool FolderProjectFactory::findTargetInfo(const QString&, const QString&, QMap&) const { return false; } ================================================ FILE: liteidex/src/liteapp/folderprojectfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: folderprojectfactory.h // Creator: visualfc #ifndef FOLDERPROJECTFACTORY_H #define FOLDERPROJECTFACTORY_H #include "liteapi/liteapi.h" class FolderProjectFactory : public LiteApi::IProjectFactory { public: FolderProjectFactory(LiteApi::IApplication *app, QObject *parnet); virtual QStringList mimeTypes() const; virtual LiteApi::IProject *open(const QString &fileName, const QString &mimeType); virtual bool findTargetInfo(const QString &fileName, const QString &mimetype, QMap& targetInfo) const; public: LiteApi::IApplication *m_liteApp; QStringList m_mimeTypes; }; #endif // FOLDERPROJECTFACTORY_H ================================================ FILE: liteidex/src/liteapp/goproxy.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: goproxy.cpp // Creator: visualfc #include "goproxy.h" #include "cdrv.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static GODRV_CALL godrv_call_fn = 0; static int godrv_call(const QByteArray &id, const QByteArray &args, DRV_CALLBACK cb, void *ctx) { if (godrv_call_fn == 0) { return -1; } return godrv_call_fn((char*)id.constData(),id.length(),(char*)args.constData(),args.length(),cb,ctx); } static void cdrv_callback(char *id, int id_size, char *reply, int len, int err, void *ctx) { ((GoProxy*)(ctx))->callback(id,id_size,reply,len,err); } GoProxy::GoProxy(QObject *parent) : LiteApi::IGoProxy(parent) { m_isRuning = false; } bool GoProxy::isValid() const { return godrv_call_fn != 0; } bool GoProxy::hasProxy() { return godrv_call_fn != 0; } bool GoProxy::isRunning() const { return m_isRuning; } QByteArray GoProxy::commandId() const { return m_id; } void GoProxy::writeStdin(const QByteArray &data) { godrv_call("stdin",data,&cdrv_callback,this); } void GoProxy::call(const QByteArray &id, const QByteArray &args) { m_id = id; m_isRuning = false; godrv_call(id,args,&cdrv_callback,this); } void GoProxy::callback(char *id, int id_size, char *reply, int reply_size, int flag) { if (m_id != QByteArray(id,id_size)) { return; } if (flag == 0) { m_isRuning = true; emit started(); } else if(flag == 1) { emit stdoutput(QByteArray(reply,reply_size)); } else if (flag == 2) { emit stderror(QByteArray(reply,reply_size)); } else if (flag == 3) { m_isRuning = false; emit finished(0,""); } else if (flag == 4) { m_isRuning = false; emit finished(2,QByteArray(reply,reply_size)); } } void cdrv_init(void *fn) { godrv_call_fn = (GODRV_CALL)fn; } void cdrv_cb(DRV_CALLBACK cb, char *id, int id_size, char *reply, int size, int err, void* ctx) { cb(id,id_size,reply,size,err,ctx); } ================================================ FILE: liteidex/src/liteapp/goproxy.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: goproxy.h // Creator: visualfc #ifndef GOPROXY_H #define GOPROXY_H #include "liteapi/liteapi.h" #include class GoProxy : public LiteApi::IGoProxy { Q_OBJECT public: explicit GoProxy(QObject *parent = 0); static bool hasProxy(); virtual bool isValid() const; virtual bool isRunning() const; virtual QByteArray commandId() const; virtual void writeStdin(const QByteArray &data); public slots: virtual void call(const QByteArray &id, const QByteArray &args = QByteArray()); public: void callback(char *id, int id_size, char *reply, int reply_size, int err); protected: bool m_isRuning; QByteArray m_id; }; #endif // GOPROXY_H ================================================ FILE: liteidex/src/liteapp/htmlwidgetmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: htmlwidgetmanager.cpp // Creator: visualfc #include "htmlwidgetmanager.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end HtmlWidgetManager::HtmlWidgetManager(QObject *parent) : IHtmlWidgetManager(parent) { } QStringList HtmlWidgetManager::classNameList() const { QStringList names; foreach(IHtmlWidgetFactory *factory, m_factoryList) { names.append(factory->className()); } return names; } void HtmlWidgetManager::addFactory(IHtmlWidgetFactory *factory) { m_factoryList.append(factory); if (m_factoryList.size() == 1) { m_defaultClassName = factory->className(); } } QList HtmlWidgetManager::factoryList() const { return m_factoryList; } IHtmlWidget *HtmlWidgetManager::create(QObject *parent) { return createByName(parent,m_defaultClassName); } IHtmlWidget *HtmlWidgetManager::createByName(QObject *parent, const QString &className) { foreach(IHtmlWidgetFactory *factory, m_factoryList) { if (factory->className() == className) { return factory->create(parent); } } return 0; } IHtmlDocument *HtmlWidgetManager::createDocument(QObject *parent) { return createDocumentByName(parent,m_defaultClassName); } IHtmlDocument *HtmlWidgetManager::createDocumentByName(QObject *parent, const QString &className) { foreach(IHtmlWidgetFactory *factory, m_factoryList) { if (factory->className() == className) { return factory->createDocument(parent); } } return 0; } bool HtmlWidgetManager::setDefaultClassName(const QString &className) { foreach(IHtmlWidgetFactory *factory, m_factoryList) { if (factory->className() == className) { m_defaultClassName = className; return true; } } return false; } QString HtmlWidgetManager::defaultClassName() const { return m_defaultClassName; } ================================================ FILE: liteidex/src/liteapp/htmlwidgetmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: htmlwidgetmanager.h // Creator: visualfc #ifndef HTMLWIDGETMANAGER_H #define HTMLWIDGETMANAGER_H #include "liteapi/litehtml.h" using namespace LiteApi; class HtmlWidgetManager : public IHtmlWidgetManager { Q_OBJECT public: explicit HtmlWidgetManager(QObject *parent = 0); virtual QStringList classNameList() const; virtual void addFactory(IHtmlWidgetFactory *factory); virtual QList factoryList() const; virtual bool setDefaultClassName(const QString &className); virtual QString defaultClassName() const; virtual IHtmlWidget *create(QObject *parent); virtual IHtmlWidget *createByName(QObject *parent, const QString &className); virtual IHtmlDocument *createDocument(QObject *parent); virtual IHtmlDocument *createDocumentByName(QObject *parent, const QString &className); protected: QList m_factoryList; QString m_defaultClassName; }; #endif // HTMLWIDGETMANAGER_H ================================================ FILE: liteidex/src/liteapp/idletimer.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: idletimer.cpp // Creator: visualfc #include "idletimer.h" #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end AppIdleTimer::AppIdleTimer() { m_timer = new QTimer(this); m_timer->setInterval(1000); connect(m_timer,SIGNAL(timeout()),this,SLOT(timeout())); qApp->installEventFilter(this); m_count = 0; m_timer->start(); } AppIdleTimer::~AppIdleTimer() { m_timer->stop(); } void AppIdleTimer::resetTimer() { m_count = 0; m_timer->stop(); m_timer->start(); } void AppIdleTimer::timeout() { m_count++; emit appIdle(m_count); } bool AppIdleTimer::eventFilter(QObject *obj, QEvent *event) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: resetTimer(); break; default: break; } return QObject::eventFilter(obj,event); } ================================================ FILE: liteidex/src/liteapp/idletimer.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: idletimer.h // Creator: visualfc #ifndef IDLETIMER_H #define IDLETIMER_H #include "liteapi/liteapi.h" class AppIdleTimer : public LiteApi::IAppIdleTimer { Q_OBJECT public: AppIdleTimer(); virtual ~AppIdleTimer(); public: virtual void resetTimer(); protected slots: void timeout(); protected: bool eventFilter(QObject *obj, QEvent *event); protected: QTimer *m_timer; int m_count; }; #endif // IDLETIMER_H ================================================ FILE: liteidex/src/liteapp/liteapp.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteapp.cpp // Creator: visualfc #include "liteapp.h" #include "filemanager.h" #include "editormanager.h" #include "projectmanager.h" #include "pluginmanager.h" #include "actionmanager.h" #include "mimetypemanager.h" #include "optionmanager.h" #include "toolwindowmanager.h" #include "htmlwidgetmanager.h" #include "recentmanager.h" #include "mainwindow.h" #include "liteappoptionfactory.h" #include "folderprojectfactory.h" #include "textbrowserhtmlwidget.h" #include "pluginsdialog.h" #include "liteapp_global.h" #ifdef Q_OS_MAC #include "macsupport.h" #endif #include "splitwindowstyle.h" #include "sidewindowstyle.h" #include "idletimer.h" #include "iconutil/iconutil.h" #include "liteapi/liteutil.h" #include "liteapi/liteids.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end #define LITEIDE_VERSION "X38.4" QString LiteApp::getRootPath() { QDir rootDir = QApplication::applicationDirPath(); rootDir.cdUp(); return rootDir.canonicalPath(); } QString LiteApp::getToolPath() { static QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QString path = env.value("LITEIDE_TOOL_PATH"); if (!path.isEmpty()) { return path; } return QApplication::applicationDirPath(); } QString LiteApp::getPluginPath() { static QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QString path = env.value("LITEIDE_PLUGIN_PATH"); if (!path.isEmpty()) { return path; } QString root = getRootPath(); #ifdef Q_OS_MAC return root+"/PlugIns"; #else return root+"/lib/liteide/plugins"; #endif } QString LiteApp::getResoucePath() { static QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QString path = env.value("LITEIDE_RES_PATH"); if (!path.isEmpty()) { return path; } QString root = getRootPath(); #ifdef Q_OS_MAC return root+"/Resources"; #else return root+"/share/liteide"; #endif } QString LiteApp::getStoragePath() { #if QT_VERSION >= 0x050000 QString root = QStandardPaths::writableLocation(QStandardPaths::DataLocation); #else QString root = QDesktopServices::storageLocation(QDesktopServices::DataLocation); #endif return root+"/liteide"; } IApplication* LiteApp::NewApplication(const QString &sessionName, IApplication *baseApp) { LiteApp *app = new LiteApp; app->load(sessionName,baseApp); return app; } PluginManager *LiteApp::pluginManager() { static PluginManager manager; return &manager; } QList LiteApp::appList() { return s_appList; } QMap LiteApp::s_cookie; QList LiteApp::s_appList; LiteApp::LiteApp() : m_rootPath(LiteApp::getRootPath()), m_applicationPath(QApplication::applicationDirPath()), m_toolPath(LiteApp::getToolPath()), m_pluginPath(LiteApp::getPluginPath()), m_resourcePath(LiteApp::getResoucePath()), m_storagePath(LiteApp::getStoragePath()) { s_appList.append(this); QSettings global(m_resourcePath+"/liteapp/config/global.ini",QSettings::IniFormat); bool storeLocal = global.value(LITEIDE_STORELOCAL,false).toBool(); QString flagLocalSetting = "--local-setting"; QString flagUserSetting = "--user-setting"; if (s_cookie.value(flagUserSetting).toBool()) { storeLocal = false; } else if (s_cookie.value(flagLocalSetting).toBool()) { storeLocal = true; } if (storeLocal) { m_settings = new QSettings(m_resourcePath+"/liteapp/config/liteide.ini", QSettings::IniFormat); } else { m_settings = new QSettings(QSettings::IniFormat,QSettings::UserScope,"liteide","liteide",this); } QStringList searchPathList; if (m_settings->value(LITEIDE_CUSTOMEICON,false).toBool()) { QString iconPath = m_settings->value(LITEIDE_CUSTOMEICONPATH,"default").toString(); if (!iconPath.isEmpty()) { searchPathList << m_resourcePath+"/liteapp/qrc/"+iconPath+"/liteapp"; searchPathList << m_resourcePath+"/liteapp/qrc/"+iconPath; } } searchPathList << ":/"; searchPathList << m_resourcePath+"/liteapp/qrc/default/liteapp"; searchPathList << m_resourcePath+"/liteapp/qrc/default"; QDir::setSearchPaths("icon",searchPathList); m_extension = new Extension; //install idle timer; m_idleTimer = new AppIdleTimer; m_extension->addObject("LiteApi.IAppIdleTimer",m_idleTimer); m_mainwindow = new MainWindow(this); QString style = this->settings()->value(LITEAPP_STYLE,"sidebar").toString(); if (style == "splitter") { SplitWindowStyle *style = new SplitWindowStyle(this,m_mainwindow); m_mainwindow->setWindowStyle(style); } else { SideWindowStyle *style = new SideWindowStyle(this,m_mainwindow); m_mainwindow->setWindowStyle(style); } m_toolWindowManager = new ToolWindowManager; m_htmlWidgetManager = new HtmlWidgetManager; m_actionManager = new ActionManager; m_projectManager = new ProjectManager; m_fileManager = new FileManager; m_editorManager = new EditorManager; m_mimeTypeManager = new MimeTypeManager; m_optionManager = new OptionManager; m_recentManager = new RecentManager; m_goProxy = new GoProxy(this); m_actionManager->initWithApp(this); m_mainwindow->createToolWindowMenu(); m_toolWindowManager->initWithApp(this); m_mimeTypeManager->initWithApp(this); m_recentManager->initWithApp(this); m_projectManager->initWithApp(this); m_fileManager->initWithApp(this); m_editorManager->initWithApp(this); m_optionManager->initWithApp(this); //m_mainwindow->setCentralWidget(m_editorManager->widget()); m_mainwindow->splitter()->addWidget(m_editorManager->widget()); //m_mainwindow->splitter()->addWidget(m_outputManager->widget()); m_mainwindow->splitter()->setStretchFactor(0,50); //m_mainwindow->setStatusBar(m_outputManager->statusBar()); m_htmlWidgetManager->addFactory(new TextBrowserHtmlWidgetFactory(this)); m_extension->addObject("LiteApi.IMimeTypeManager",m_mimeTypeManager); m_extension->addObject("LiteApi.IProjectManager",m_projectManager); m_extension->addObject("LiteApi.IEditManager",m_editorManager); m_extension->addObject("LiteApi.IOptoinManager",m_optionManager); m_extension->addObject("LiteApi.IToolWindowManager",m_toolWindowManager); m_extension->addObject("LiteApi.QMainWindow",m_mainwindow); m_extension->addObject("LiteApi.QMainWindow.QSplitter",m_mainwindow->splitter()); m_extension->addObject("LiteApi.IHtmlWidgetManager",m_htmlWidgetManager); //add actions connect(m_projectManager,SIGNAL(currentProjectChanged(LiteApi::IProject*)),this,SLOT(currentProjectChanged(LiteApi::IProject*))); connect(m_editorManager,SIGNAL(currentEditorChanged(LiteApi::IEditor*)),m_projectManager,SLOT(currentEditorChanged(LiteApi::IEditor*))); connect(m_editorManager,SIGNAL(currentEditorChanged(LiteApi::IEditor*)),m_mainwindow,SLOT(currentEditorChanged(LiteApi::IEditor*))); connect(m_editorManager,SIGNAL(editorModifyChanged(LiteApi::IEditor*,bool)),m_mainwindow,SLOT(editorModifyChanged(LiteApi::IEditor*,bool))); connect(m_editorManager,SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*))); connect(m_editorManager,SIGNAL(tabAddRequest()),m_fileManager,SLOT(openEditors())); connect(m_editorManager,SIGNAL(editorSaved(LiteApi::IEditor*)),m_fileManager,SLOT(editorSaved(LiteApi::IEditor*))); connect(m_editorManager,SIGNAL(editorCreated(LiteApi::IEditor*)),m_fileManager,SLOT(editorCreated(LiteApi::IEditor*))); connect(m_editorManager,SIGNAL(editorAboutToClose(LiteApi::IEditor*)),m_fileManager,SLOT(editorAboutToClose(LiteApi::IEditor*))); connect(m_editorManager,SIGNAL(doubleClickedTab()),m_mainwindow,SLOT(showOrHideToolWindow())); connect(m_optionManager,SIGNAL(applyOption(QString)),m_fileManager,SLOT(applyOption(QString))); connect(m_optionManager,SIGNAL(applyOption(QString)),m_projectManager,SLOT(applyOption(QString))); connect(m_optionManager,SIGNAL(applyOption(QString)),m_editorManager,SLOT(applyOption(QString))); connect(m_optionManager,SIGNAL(applyOption(QString)),this,SLOT(applyOption(QString))); QAction *esc = new QAction(tr("Escape"),this); m_actionManager->getActionContext(this,"App")->regAction(esc,"Escape","ESC"); m_mainwindow->addAction(esc); connect(esc,SIGNAL(triggered()),this,SLOT(escape())); createActions(); createMenus(); createToolBars(); m_editorManager->createActions(); m_logOutput = new TextOutput(this); //m_outputManager->addOutuput(m_logOutput,tr("Console")); m_logAct = m_toolWindowManager->addToolWindow(Qt::BottomDockWidgetArea,m_logOutput,"EventLog",tr("Event Log"),true); connect(m_logOutput,SIGNAL(dbclickEvent(QTextCursor)),this,SLOT(dbclickLogOutput(QTextCursor))); m_optionAct = new QAction(loadIcon("icon:images/options.png"),tr("Options"),this); m_optionAct->setMenuRole(QAction::PreferencesRole); m_actionManager->setViewMenuSeparator("sep/option",true); m_actionManager->insertViewMenuAction(m_optionAct,"sep/option"); m_stdToolBar->addSeparator(); m_stdToolBar->addAction(m_optionAct); connect(m_optionAct,SIGNAL(triggered()),m_optionManager,SLOT(exec())); this->appendLog("LiteApp","Initializing"); this->appendLog("Load Setting",m_settings->fileName()); m_liteAppOptionFactory = new LiteAppOptionFactory(this,this); m_optionManager->addFactory(m_liteAppOptionFactory); connect(m_goProxy,SIGNAL(stdoutput(QByteArray)),this,SLOT(goproxyDone(QByteArray))); //connect(this,SIGNAL(key_escape()),m_mainwindow,SLOT(hideOutputWindow())); connect(m_mainwindow,SIGNAL(fullScreenStateChanged(bool)),m_fullScreent,SLOT(setChecked(bool))); } static QImage makeSplashImage(LiteApi::IApplication *app) { QRect r(0,0,400,280); QImage image(r.size(),QImage::Format_ARGB32_Premultiplied); QPainter painter(&image); painter.setRenderHint(QPainter::Antialiasing,true); QLinearGradient lg(0,0,r.width(),r.height()); lg.setColorAt(0.0,qRgb(0,125,127)); lg.setColorAt(1.0,qRgb(0,88,127)); QBrush bk(lg); painter.fillRect(r,bk); int th = r.height()*2/5; int bh = r.height()-th; painter.fillRect(1,th,r.width()-2,bh-1,Qt::white); QFont font("Timer",32); font.setPointSize(32); font.setItalic(true); painter.setPen(Qt::white); painter.setFont(font); painter.drawText(2,2,r.width()-2,th,Qt::AlignCenter,app->ideFullName()); font.setPointSize(9); font.setItalic(false); font.setBold(true); painter.setPen(Qt::black); painter.setFont(font); painter.drawText(10,th,r.width()-10,bh,Qt::AlignLeft|Qt::AlignVCenter,app->ideCopyright()); painter.drawImage(r.width()-145,r.height()-145,QImage("icon:/images/liteide-logo128.png")); return image; } void LiteApp::load(const QString &sessionName, IApplication *baseApp) { bool bLoadSession = true; if (baseApp == 0) { bLoadSession = m_settings->value(LITEAPP_AUTOLOADLASTSESSION,true).toBool(); } m_currentSession = sessionName; if (!bLoadSession) { m_currentSession = "emtpy"; } QSplashScreen *splash = 0; bool bSplash = m_settings->value(LITEAPP_SPLASHVISIBLE,true).toBool(); if (baseApp) { bSplash = false; } if (bSplash) { splash = new QSplashScreen(QPixmap::fromImage(makeSplashImage(this)),Qt::WindowStaysOnTopHint); } if (bSplash) { splash->show(); } if (bSplash) { splash->showMessage("Scanning plugins...",Qt::AlignLeft|Qt::AlignBottom); } qApp->processEvents(); loadMimeType(); loadPlugins(); if (bSplash) { splash->showMessage("Loading plugins...",Qt::AlignLeft|Qt::AlignBottom); } qApp->processEvents(); initPlugins(); if (bSplash) { splash->showMessage("Loading state...",Qt::AlignLeft|Qt::AlignBottom); } qApp->processEvents(); loadState(); if (baseApp) { if (baseApp->mainWindow()->isMaximized()) { m_mainwindow->resize(800,600); m_mainwindow->show(); } else { QRect rc = baseApp->mainWindow()->geometry(); rc.adjust(20,20,20,20); m_mainwindow->setGeometry(rc); m_mainwindow->show(); } } else { m_mainwindow->show(); } emit loaded(); m_projectManager->setCurrentProject(0); if (bSplash) { splash->showMessage("Loading session...",Qt::AlignLeft|Qt::AlignBottom); } qApp->processEvents(); if (bLoadSession && !sessionName.isEmpty()) { loadSession(sessionName); this->appendLog("Load session",sessionName); } if (bSplash) { m_mainwindow->raise(); splash->finish(m_mainwindow); splash->deleteLater(); } this->appendLog("HtmlWidgetFactory",m_htmlWidgetManager->classNameList().join(" ")); this->appendLog("DefaultHtmlWidgetFactory",m_htmlWidgetManager->defaultClassName()); m_goProxy->call("version"); appendLog("LiteApp","Finished loading"); } LiteApp::~LiteApp() { s_appList.removeAll(this); cleanup(); } IExtension *LiteApp::extension() { return m_extension; } void LiteApp::cleanup() { // emit aboutToQuit(); //delete plugin by reverse depend QListIterator it(m_pluginList); it.toBack(); while(it.hasPrevious()) { IPlugin *p = it.previous(); //qDebug() << "clean plugin" << p; delete p; } m_pluginList.clear(); delete m_idleTimer; delete m_projectManager; delete m_editorManager; delete m_htmlWidgetManager; delete m_liteAppOptionFactory; delete m_fileManager; delete m_mimeTypeManager; delete m_optionManager; delete m_logOutput; delete m_toolWindowManager; delete m_recentManager; delete m_actionManager; delete m_extension; delete m_settings; } void LiteApp::aboutPlugins() { PluginsDialog *dlg = new PluginsDialog(this,m_mainwindow); foreach (LiteApi::IPluginFactory *factory, pluginManager()->factoryList()) { dlg->appendInfo(factory->info()); } dlg->exec(); } void LiteApp::escape() { IEditor *editor = m_editorManager->currentEditor(); if (!editor) { return; } bool bFocus = editor->widget()->isAncestorOf(qApp->focusWidget()); if (!bFocus) { editor->onActive(); } else { emit key_escape(); m_mainwindow->hideOutputWindow(); } } void LiteApp::newWindow() { LiteApp::newInstance("default"); } void LiteApp::closeWindow() { m_mainwindow->close(); } void LiteApp::exit() { qApp->closeAllWindows(); } void LiteApp::applyOption(QString id) { if (id != OPTION_LITEAPP) { return; } //bool b = m_settings->value(LITEAPP_OPTNFOLDERINNEWWINDOW,true).toBool(); //m_openFolderNewWindowAct->setVisible(!b); } bool LiteApp::hasGoProxy() const { return GoProxy::hasProxy(); } IGoProxy *LiteApp::createGoProxy(QObject *parent) { return new GoProxy(parent); } IApplication *LiteApp::newInstance(const QString &sessionName) { return LiteApp::NewApplication(sessionName,this); } QList LiteApp::instanceList() const { return s_appList; } IEditorManager *LiteApp::editorManager() { return m_editorManager; } IFileManager *LiteApp::fileManager() { return m_fileManager; } IProjectManager *LiteApp::projectManager() { return m_projectManager; } IActionManager *LiteApp::actionManager() { return m_actionManager; } IMimeTypeManager *LiteApp::mimeTypeManager() { return m_mimeTypeManager; } IOptionManager *LiteApp::optionManager() { return m_optionManager; } IToolWindowManager *LiteApp::toolWindowManager() { return m_toolWindowManager; } IHtmlWidgetManager *LiteApp::htmlWidgetManager() { return m_htmlWidgetManager; } IRecentManager *LiteApp::recentManager() { return m_recentManager; } QMainWindow *LiteApp::mainWindow() const { return m_mainwindow; } QSettings *LiteApp::settings() { return m_settings; } QMap &LiteApp::globalCookie() { return s_cookie; } QString LiteApp::rootPath() const { return m_rootPath; } QString LiteApp::resourcePath() const { return m_resourcePath; } QString LiteApp::applicationPath() const { return m_applicationPath; } QString LiteApp::toolPath() const { return m_toolPath; } QString LiteApp::pluginPath() const { return m_pluginPath; } QString LiteApp::storagePath() const { return m_storagePath; } QString LiteApp::ideVersion() const { return LITEIDE_VERSION; } QString LiteApp::ideFullName() const { return this->ideName()+" "+this->ideVersion(); } QString LiteApp::ideName() const { return "LiteIDE"; } QString LiteApp::ideCopyright() const { static QString s_info = "2011-2023(c)\n" "visualfc@gmail.com\n" "\n" "https://github.com/visualfc/liteide\n"; return s_info; } void LiteApp::setPluginPath(const QString &path) { m_pluginPath = path; appendLog("LiteApp","Set plugin path to "+path); } void LiteApp::setResourcePath(const QString &path) { m_resourcePath = path; appendLog("LiteApp","Set resource path to "+path); } QList LiteApp::pluginList() const { return m_pluginList; } void LiteApp::appendLog(const QString &model, const QString &log, bool error) { QDateTime dt = QDateTime::currentDateTime(); QString text = dt.toString("hh:mm:ss"); text += QLatin1Char(' '); text += model; text += ": "; text += log; text += QLatin1Char('\n'); m_logOutput->updateExistsTextColor(); if (error) { m_logOutput->append(text,Qt::red); m_logAct->setChecked(true); } else { m_logOutput->append(text); } } void LiteApp::sendBroadcast(const QString &module, const QString &id, const QVariant ¶m) { emit broadcast(module,id,param); } void LiteApp::loadPlugins() { pluginManager()->loadPlugins(m_pluginPath); } void LiteApp::loadMimeType() { QDir dir(m_resourcePath+"/liteapp/mimetype"); if (dir.exists()) { m_mimeTypeManager->loadMimeTypes(dir.absolutePath()); } } void LiteApp::initPlugins() { foreach (IPluginFactory *factory,pluginManager()->factoryList()) { bool load = m_settings->value(QString("liteapp/%1_load").arg(factory->id()),true).toBool(); if (!load) { continue; } LiteApi::IPlugin *plugin = factory->createPlugin(); if (plugin) { bool ret = plugin->load(this); if (ret) { m_pluginList.append(plugin); } appendLog("LiteApp",QString("%1 %2").arg(ret?"Loaded":"ERROR while loading").arg(factory->id()),!ret); } } } void LiteApp::createActions() { IActionContext *actionContext = m_actionManager->getActionContext(this,"App"); m_newAct = new QAction(loadIcon("icon:images/new.png"),tr("New..."),m_mainwindow); actionContext->regAction(m_newAct,"New",QKeySequence::New); m_openFileAct = new QAction(loadIcon("icon:images/openfile.png"),tr("Open File..."),m_mainwindow); actionContext->regAction(m_openFileAct,"OpenFile",QKeySequence::Open); m_openFolderAct = new QAction(loadIcon("icon:images/openfolder.png"),tr("Open Folder..."),m_mainwindow); actionContext->regAction(m_openFolderAct,"OpenFolder",""); m_openFolderNewWindowAct = new QAction(loadIcon("icon:images/openfolder.png"),tr("Open Folder in New Window..."),m_mainwindow); //bool b = m_settings->value(LITEAPP_OPTNFOLDERINNEWWINDOW,true).toBool(); //m_openFolderNewWindowAct->setVisible(!b); actionContext->regAction(m_openFolderNewWindowAct,"OpenFolderNewWindow",""); m_closeAllFolderAct = new QAction(tr("Close All Folders"),m_mainwindow); actionContext->regAction(m_closeAllFolderAct,"CloseAllFolders",""); m_newWindow = new QAction(tr("New Window"),m_mainwindow); actionContext->regAction(m_newWindow,"NewWindow","Ctrl+Shift+N"); m_closeWindow = new QAction(tr("Close Window"),m_mainwindow); actionContext->regAction(m_closeWindow,"CloseWindow","Ctrl+Shift+W"); m_closeAct = new QAction(loadIcon("icon:images/closefile.png"),tr("Close File"),m_mainwindow); actionContext->regAction(m_closeAct,"CloseFile","Ctrl+W"); m_closeAllAct = new QAction(tr("Close All Files"),m_mainwindow); actionContext->regAction(m_closeAllAct,"CloseAllFiles",""); m_openProjectAct = new QAction(loadIcon("icon:images/openproject.png"),tr("Open Project"),m_mainwindow); m_saveProjectAct = new QAction(loadIcon("icon:images/saveproject.png"),tr("Save Project"),m_mainwindow); m_closeProjectAct = new QAction(loadIcon("icon:images/closeproject.png"),tr("Close Project"),m_mainwindow); actionContext->regAction(m_closeProjectAct,"CloseProject",""); m_saveAct = new QAction(loadIcon("icon:images/save.png"),tr("Save File"),m_mainwindow); actionContext->regAction(m_saveAct,"SaveFile",QKeySequence::Save); m_saveAsAct = new QAction(tr("Save File As..."),m_mainwindow); actionContext->regAction(m_saveAsAct,"SaveFileAs",QKeySequence::SaveAs); m_saveAllAct = new QAction(loadIcon("icon:images/saveall.png"),tr("Save All Files"),m_mainwindow); actionContext->regAction(m_saveAllAct,"SaveAllFiles",""); m_exitAct = new QAction(tr("Exit"),m_mainwindow); #ifdef Q_OS_WIN actionContext->regAction(m_exitAct,"Exit","Ctrl+Q"); #else actionContext->regAction(m_exitAct,"Exit",QKeySequence::Quit); #endif m_fullScreent = new QAction(tr("Full Screen"),m_mainwindow); m_fullScreent->setCheckable(true); actionContext->regAction(m_fullScreent,"FullScreen","Ctrl+Shift+F11"); m_aboutAct = new QAction(tr("About LiteIDE"),m_mainwindow); #if defined(Q_OS_OSX) m_aboutAct->setMenuRole(QAction::AboutRole); #endif actionContext->regAction(m_aboutAct,"About",""); m_aboutPluginsAct = new QAction(tr("About Plugins"),m_mainwindow); #if defined(Q_OS_OSX) m_aboutPluginsAct->setMenuRole(QAction::ApplicationSpecificRole); #endif actionContext->regAction(m_aboutPluginsAct,"AboutPlugins",""); connect(m_newAct,SIGNAL(triggered()),m_fileManager,SLOT(newFile())); connect(m_openFileAct,SIGNAL(triggered()),m_fileManager,SLOT(openFiles())); connect(m_openFolderAct,SIGNAL(triggered()),m_fileManager,SLOT(openFolder())); connect(m_openFolderNewWindowAct,SIGNAL(triggered()),m_fileManager,SLOT(openFolderNewWindow())); connect(m_closeAllFolderAct,SIGNAL(triggered()),m_fileManager,SLOT(closeAllFolders())); connect(m_newWindow,SIGNAL(triggered()),this,SLOT(newWindow())); connect(m_closeWindow,SIGNAL(triggered()),this,SLOT(closeWindow())); connect(m_closeAct,SIGNAL(triggered()),m_editorManager,SLOT(closeEditor())); connect(m_closeAllAct,SIGNAL(triggered()),m_editorManager,SLOT(closeAllEditors())); connect(m_openProjectAct,SIGNAL(triggered()),m_fileManager,SLOT(openProjects())); connect(m_saveProjectAct,SIGNAL(triggered()),m_projectManager,SLOT(saveProject())); connect(m_closeProjectAct,SIGNAL(triggered()),m_projectManager,SLOT(closeProject())); connect(m_saveAct,SIGNAL(triggered()),m_editorManager,SLOT(saveEditor())); connect(m_saveAsAct,SIGNAL(triggered()),m_editorManager,SLOT(saveEditorAs())); connect(m_saveAllAct,SIGNAL(triggered()),m_editorManager,SLOT(saveAllEditors())); connect(m_exitAct,SIGNAL(triggered()),this,SLOT(exit())); connect(m_aboutAct,SIGNAL(triggered()),m_mainwindow,SLOT(about())); connect(m_aboutPluginsAct,SIGNAL(triggered()),this,SLOT(aboutPlugins())); connect(m_fullScreent,SIGNAL(toggled(bool)),m_mainwindow,SLOT(setFullScreen(bool))); } void LiteApp::createMenus() { m_fileMenu = m_actionManager->loadMenu(ID_MENU_FILE); m_viewMenu = m_actionManager->loadMenu(ID_MENU_VIEW); m_helpMenu = m_actionManager->loadMenu(ID_MENU_HELP); m_fileMenu->addAction(m_newAct); m_fileMenu->addAction(m_openFileAct); m_fileMenu->addAction(m_openFolderAct); m_fileMenu->addAction(m_openFolderNewWindowAct); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_saveAct); m_fileMenu->addAction(m_saveAsAct); m_fileMenu->addAction(m_saveAllAct); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_newWindow); m_fileMenu->addAction(m_closeWindow); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_closeAct); m_fileMenu->addAction(m_closeAllAct); m_fileMenu->addAction(m_closeAllFolderAct); //m_fileMenu->addAction(m_closeProjectAct); //m_fileMenu->addAction(m_openProjectAct); //m_fileMenu->addAction(m_saveProjectAct); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_exitAct); #ifdef Q_OS_MAC if (MacSupport::isLionOrHigh()) { MacSupport::setFullScreen(m_mainwindow); } else { m_viewMenu->addAction(m_fullScreent); } #else m_viewMenu->addAction(m_fullScreent); #endif m_viewMenu->addSeparator(); m_helpMenu->addAction(m_aboutAct); m_helpMenu->addAction(m_aboutPluginsAct); } void LiteApp::createToolBars() { m_stdToolBar = m_actionManager->loadToolBar(ID_TOOLBAR_STD); m_stdToolBar->addAction(m_newAct); m_stdToolBar->addSeparator(); m_stdToolBar->addAction(m_openFileAct); m_stdToolBar->addAction(m_openFolderAct); m_stdToolBar->addAction(m_saveAct); m_stdToolBar->addAction(m_saveAllAct); //m_stdToolBar->addSeparator(); //m_stdToolBar->addAction(m_openProjectAct); //m_stdToolBar->addAction(m_saveProjectAct); //m_stdToolBar->addAction(m_closeProjectAct); } void LiteApp::projectReloaded() { LiteApi::IProject *project = (LiteApi::IProject*)sender(); if (project) { //m_outputManager->setProjectInfo(project->filePath()); } } void LiteApp::currentProjectChanged(IProject *project) { bool b = (project != 0); m_saveProjectAct->setEnabled(b); m_closeProjectAct->setEnabled(b); if (project) { //m_outputManager->setProjectInfo(project->filePath()); connect(project,SIGNAL(reloaded()),this,SLOT(projectReloaded())); } else { //m_outputManager->setProjectInfo(""); } } void LiteApp::currentEditorChanged(IEditor *editor) { bool b = (editor != 0); if (b) { connect(editor,SIGNAL(modificationChanged(bool)),this,SLOT(editorModifyChanged(bool))); } m_saveAct->setEnabled(b && editor->isModified() && !editor->isReadOnly()); m_saveAsAct->setEnabled(editor && !editor->filePath().isEmpty()); m_saveAllAct->setEnabled(b); m_closeAct->setEnabled(b); m_closeAllAct->setEnabled(b); } void LiteApp::editorModifyChanged(bool /*b*/) { IEditor *editor = (IEditor*)sender(); if (editor && editor->isModified() && !editor->isReadOnly()) { m_saveAct->setEnabled(true); } else { m_saveAct->setEnabled(false); } } void LiteApp::loadState() { QByteArray geometry = m_settings->value("liteapp/geometry").toByteArray(); if (!geometry.isEmpty()) { m_mainwindow->restoreGeometry(geometry); } else { m_mainwindow->resize(800,600); } m_mainwindow->updateConer(); //fix Qt 5.9.6 QDockWidget bug #if QT_VERSION == 0x050906 QList docks = m_mainwindow->findChildren(); QList horz; QList vert; QList ds; foreach (QDockWidget *dock, docks) { bool b = m_settings->value("dock_visible/"+dock->objectName()).toBool(); if (!b) { continue; } dock->setVisible(b); QSize sz = m_settings->value("dock_size/"+dock->objectName()).toSize(); horz << sz.width(); vert << sz.height(); ds << dock; } m_mainwindow->resizeDocks(ds,horz,Qt::Horizontal); m_mainwindow->resizeDocks(ds,vert,Qt::Vertical); foreach (QString id, m_actionManager->toolBarList()) { QToolBar *tbar = m_actionManager->loadToolBar(id); bool b = m_settings->value("toolbar_visible/"+tbar->objectName(),true).toBool(); tbar->setVisible(b); } #else m_mainwindow->restoreState(m_settings->value("liteapp/state").toByteArray()); #endif } void LiteApp::saveState() { m_settings->setValue("liteapp/geometry",m_mainwindow->saveGeometry()); m_settings->setValue("liteapp/state",m_mainwindow->saveState()); //fix Qt 5.9.6 QDockWidget bug #if QT_VERSION == 0x050906 QList docks = m_mainwindow->findChildren(); foreach (QDockWidget *dock, docks) { m_settings->setValue("dock_size/"+dock->objectName(),dock->size()); m_settings->setValue("dock_visible/"+dock->objectName(),dock->isVisible()); } foreach (QString id, m_actionManager->toolBarList()) { QToolBar *tbar = m_actionManager->loadToolBar(id); m_settings->setValue("toolbar_visible/"+tbar->objectName(),tbar->isVisible()); } #endif } void LiteApp::loadSession(const QString &session) { if (session.isEmpty()) { return; } m_recentManager->addRecent(session,"session"); QString sessionKey = "session/"+session; QString projectName = m_settings->value(sessionKey+"_project").toString(); QString scheme = m_settings->value(sessionKey+"_scheme").toString(); QString editorName = m_settings->value(sessionKey+"_cureditor").toString(); QStringList fileList = m_settings->value(sessionKey+"_alleditor").toStringList(); QStringList folderList = m_settings->value(sessionKey+"_folderList").toStringList(); m_fileManager->setFolderList(folderList); if (!projectName.isEmpty()) { if (scheme.isEmpty()) { m_fileManager->openProject(projectName); } else { m_fileManager->openProjectScheme(projectName,scheme); } } else { m_projectManager->closeProject(); } if (m_settings->value(LITEAPP_STARTUPRELOADFILES,true).toBool()) { foreach(QString fileName, fileList) { m_fileManager->openEditor(fileName,false); } if (!editorName.isEmpty()) { m_fileManager->openEditor(editorName,true); } else if (!fileList.isEmpty()){ m_fileManager->openEditor(fileList.last(),true); } } emit sessionListChanged(); } void LiteApp::saveSession(const QString &session) { if (session.isEmpty() || session == "empty") { return; } QString projectName; QString editorName; QString scheme; IProject *project = m_projectManager->currentProject(); if (project) { projectName = project->filePath(); IMimeType *type = m_mimeTypeManager->findMimeType(project->mimeType()); if (type) { scheme = type->scheme(); } } QStringList fileList; foreach (IEditor* ed,m_editorManager->sortedEditorList()) { if (ed->filePath().isEmpty()) { continue; } if (ed == m_editorManager->currentEditor()) { editorName = ed->filePath(); } else { fileList.append(ed->filePath()); } } QString sessionKey = "session/"+session; LiteApi::updateSetting(m_settings,sessionKey+"_project",projectName,""); LiteApi::updateSetting(m_settings,sessionKey+"_scheme",scheme,""); LiteApi::updateSetting(m_settings,sessionKey+"_cureditor",editorName,""); LiteApi::updateSetting(m_settings,sessionKey+"_alleditor",fileList,QStringList()); LiteApi::updateSetting(m_settings,sessionKey+"_folderList",m_fileManager->folderList(),QStringList()); } QStringList LiteApp::sessionList() const { return m_recentManager->recentNameList("session"); } QString LiteApp::currentSession() const { return m_currentSession; } void LiteApp::dbclickLogOutput(QTextCursor cur) { //QRegExp rep("(\\w?:?[\\w\\d_@\\-\\\\/\\.]+):(\\d+):"); QString text = cur.block().text().trimmed(); //skip time 08:38:49 if (text.length() < 9) { return; } QRegExp rep("(\\w?\\:?[\\w\\d\\_\\-\\\\/\\.]+):(\\d+):"); int index = rep.indexIn(text.mid(8)); if (index < 0) return; QStringList capList = rep.capturedTexts(); if (capList.count() < 3) return; QString fileName = capList[1]; QString fileLine = capList[2]; bool ok = false; int line = fileLine.toInt(&ok); if (!ok) return; LiteApi::IEditor *editor = m_fileManager->openEditor(fileName); if (editor) { LiteApi::ITextEditor *textEditor = LiteApi::getTextEditor(editor); if (textEditor) { textEditor->gotoLine(line-1,0,true); } } } void LiteApp::goproxyDone(const QByteArray &reply) { this->appendLog("GoProxy",QString("%1 = %2").arg(QString::fromUtf8(m_goProxy->commandId())).arg(QString::fromUtf8(reply).trimmed())); } ================================================ FILE: liteidex/src/liteapp/liteapp.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteapp.h // Creator: visualfc #ifndef LITEAPP_H #define LITEAPP_H #include "liteapi/liteapi.h" #include "textoutput/textoutput.h" #include "extension/extension.h" #include "goproxy.h" using namespace LiteApi; class MainWindow; class PluginManager; class EditorManager; class FileManager; class ProjectManager; class ActionManager; class MimeTypeManager; class OptionManager; class ToolWindowManager; class HtmlWidgetManager; class QuickOpenManager; class RecentManager; class QSettings; class QSplitter; class QComboBox; class LiteAppOptionFactory; class AppIdleTimer; class LiteApp : public IApplication { Q_OBJECT public: static QString getRootPath(); static QString getToolPath(); static QString getPluginPath(); static QString getResoucePath(); static QString getStoragePath(); static IApplication* NewApplication(const QString &sessionName, IApplication *base = 0); static PluginManager *pluginManager(); static QList appList(); public: LiteApp(); virtual ~LiteApp(); virtual IExtension *extension(); virtual IApplication *newInstance(const QString &sessionName); virtual QList instanceList() const; virtual bool hasGoProxy() const; virtual IGoProxy *createGoProxy(QObject *parent); virtual IProjectManager *projectManager(); virtual IEditorManager *editorManager(); virtual IFileManager *fileManager(); virtual IActionManager *actionManager(); virtual IMimeTypeManager *mimeTypeManager(); virtual IOptionManager *optionManager(); virtual IToolWindowManager *toolWindowManager(); virtual IHtmlWidgetManager *htmlWidgetManager(); virtual IRecentManager *recentManager(); virtual QMainWindow *mainWindow() const; virtual QSettings *settings(); virtual QMap &globalCookie(); virtual QString rootPath() const; virtual QString applicationPath() const; virtual QString toolPath() const; virtual QString resourcePath() const; virtual QString pluginPath() const; virtual QString storagePath() const; virtual QString ideVersion() const; virtual QString ideFullName() const; virtual QString ideName() const; virtual QString ideCopyright() const; virtual QList pluginList() const; virtual void loadSession(const QString &session); virtual void saveSession(const QString &session); virtual QStringList sessionList() const; virtual QString currentSession() const; virtual void loadState(); virtual void saveState(); virtual void appendLog(const QString &model, const QString &log = QString(), bool error = false); virtual void sendBroadcast(const QString &module, const QString &id, const QVariant ¶m = QVariant()); public: void load(const QString &sessionName, IApplication *baseApp); void createActions(); void createMenus(); void createToolBars(); void loadPlugins(); void loadMimeType(); void initPlugins(); void setPluginPath(const QString &path); void setResourcePath(const QString &path); protected slots: void goproxyDone(const QByteArray &reply); void dbclickLogOutput(QTextCursor); void projectReloaded(); void currentProjectChanged(LiteApi::IProject *project); void currentEditorChanged(LiteApi::IEditor *editor); void editorModifyChanged(bool); void cleanup(); void aboutPlugins(); void escape(); void newWindow(); void closeWindow(); void exit(); void applyOption(QString id); protected: QString m_currentSession; QString m_rootPath; QString m_applicationPath; QString m_toolPath; QString m_pluginPath; QString m_resourcePath; QString m_storagePath; QSettings *m_settings; Extension *m_extension; MainWindow *m_mainwindow; ToolWindowManager *m_toolWindowManager; HtmlWidgetManager *m_htmlWidgetManager; RecentManager *m_recentManager; ActionManager *m_actionManager; ProjectManager *m_projectManager; EditorManager *m_editorManager; FileManager *m_fileManager; MimeTypeManager *m_mimeTypeManager; OptionManager *m_optionManager; TextOutput *m_logOutput; QAction *m_logAct; LiteAppOptionFactory *m_liteAppOptionFactory; QList m_pluginList; AppIdleTimer *m_idleTimer; public: static QMap s_cookie; static QList s_appList; protected: QAction *m_newAct; QAction *m_openFileAct; QAction *m_openFolderAct; QAction *m_openFolderNewWindowAct; QAction *m_closeAllFolderAct; QAction *m_newWindow; QAction *m_closeWindow; QAction *m_closeAct; QAction *m_closeAllAct; QAction *m_openProjectAct; QAction *m_saveProjectAct; QAction *m_closeProjectAct; QAction *m_saveAct; QAction *m_saveAsAct; QAction *m_saveAllAct; QAction *m_exitAct; QAction *m_optionAct; QAction *m_aboutAct; QAction *m_aboutPluginsAct; QAction *m_fullScreent; QToolBar *m_stdToolBar; QMenu *m_fileMenu; QMenu *m_viewMenu; QMenu *m_helpMenu; protected: GoProxy *m_goProxy; }; #endif // LITEAPP_H ================================================ FILE: liteidex/src/liteapp/liteapp.pri ================================================ LIBS *= -l$$qtLibraryName(liteapp) ================================================ FILE: liteidex/src/liteapp/liteapp.pro ================================================ #------------------------------------------------- # # Project created by QtCreator 2011-03-18T16:21:43 # #------------------------------------------------- include (../../liteidex.pri) include (../rpath.pri) include (../api/liteapi/liteapi.pri) include (../utils/fileutil/fileutil.pri) include (../utils/mimetype/mimetype.pri) include (../utils/textoutput/textoutput.pri) include (../utils/extension/extension.pri) include (../utils/folderview/folderview.pri) include (../utils/symboltreeview/symboltreeview.pri) include (../utils/colorstyle/colorstyle.pri) include (../utils/tabwidget/tabwidget.pri) include (../3rdparty/elidedlabel/elidedlabel.pri) include (../3rdparty/qtc_editutil/qtc_editutil.pri) include (../3rdparty/qtc_itemview/qtc_itemview.pri) isEmpty(PRECOMPILED_HEADER):PRECOMPILED_HEADER = $$IDE_SOURCE_TREE/src/pch/liteide_gui_pch.h QT += core gui macx { QT += xml } DESTDIR = $$IDE_APP_PATH TEMPLATE = app TARGET = $$qtLibraryName(liteapp) contains(DEFINES, LITEAPP_LIBRARY) { TEMPLATE = lib win32 { DESTDIR = $$IDE_APP_PATH } else:macx { DESTDIR = $$IDE_BIN_PATH } else { DESTDIR = $$IDE_LIBRARY_PATH } } LIBS += -L$$IDE_LIBRARY_PATH macx { LIBS += -framework AppKit } INCLUDEPATH += $$IDE_SOURCE_TREE/src/api INCLUDEPATH += $$IDE_SOURCE_TREE/src/utils INCLUDEPATH += $$IDE_SOURCE_TREE/src/3rdparty SOURCES += main.cpp\ mainwindow.cpp \ liteapp.cpp \ filemanager.cpp \ editormanager.cpp \ projectmanager.cpp \ pluginmanager.cpp \ actionmanager.cpp \ aboutdialog.cpp \ pluginsdialog.cpp \ mimetypemanager.cpp \ optionmanager.cpp \ newfiledialog.cpp \ optionsbrowser.cpp \ liteappoption.cpp \ liteappoptionfactory.cpp \ toolmainwindow.cpp \ tooldockwidget.cpp \ rotationtoolbutton.cpp \ toolwindowmanager.cpp \ folderproject.cpp \ folderprojectfactory.cpp \ goproxy.cpp \ htmlwidgetmanager.cpp \ textbrowserhtmlwidget.cpp \ splitwindowstyle.cpp \ sidewindowstyle.cpp \ outputoption.cpp \ openeditorswidget.cpp \ idletimer.cpp \ recentmanager.cpp \ multifolderwindow.cpp \ splitfolderwindow.cpp HEADERS += mainwindow.h \ liteapp.h \ liteapp_global.h \ filemanager.h \ editormanager.h \ projectmanager.h \ pluginmanager.h \ actionmanager.h \ aboutdialog.h \ pluginsdialog.h \ mimetypemanager.h \ optionmanager.h \ newfiledialog.h \ optionsbrowser.h \ liteappoption.h \ liteappoptionfactory.h \ toolmainwindow.h \ tooldockwidget.h \ rotationtoolbutton.h \ toolwindowmanager.h \ folderproject.h \ folderprojectfactory.h \ goproxy.h \ cdrv.h \ htmlwidgetmanager.h \ textbrowserhtmlwidget.h \ windowstyle.h \ splitwindowstyle.h \ sidewindowstyle.h \ outputoption.h \ openeditorswidget.h \ idletimer.h \ recentmanager.h \ multifolderwindow.h \ splitfolderwindow.h FORMS += \ aboutdialog.ui \ pluginsdialog.ui \ newfiledialog.ui \ optionswidget.ui \ liteappoption.ui \ outputoption.ui RESOURCES += \ liteapp.qrc macx { HEADERS += macsupport.h OBJECTIVE_SOURCES += macsupport.mm } contains(DEFINES, LITEAPP_LIBRARY) { win32 { target.path = /bin INSTALLS += target RC_FILE += liteapp.rc } else:macx { ICON = images/liteide.icns QMAKE_INFO_PLIST = Info.plist } else { target.path = $$LIBPREFIX INSTALLS += target } } ================================================ FILE: liteidex/src/liteapp/liteapp.qrc ================================================ images/closefile.png images/closeproject.png images/new.png images/openfile.png images/openproject.png images/redo.png images/save.png images/saveproject.png images/undo.png images/saveall.png images/closepage.png images/listpage.png images/addpage.png images/fileitem.png images/folderitem.png images/projectitem.png images/cleanoutput.png images/hideoutput.png images/logo/dui.png images/logo/gen.png images/logo/kan.png images/logo/kun.png images/logo/li.png images/logo/qian.png images/logo/space.png images/logo/xun.png images/logo/zhen.png images/backward.png images/forward.png images/reload.png images/gopher.png images/editclear.png images/close.png images/movemenu.png images/openfolder.png images/hidesidebar.png images/copy.png images/cut.png images/paste.png images/lock.png images/unlock.png images/liteide-logo64.png images/liteide16.png images/liteide24.png images/liteide32.png images/liteide48.png images/liteide64.png images/liteide128.png images/liteide-logo128.png images/config.png images/godoc.png images/gopath.png images/home.png images/filter.png images/sync.png images/setup.png images/darkclosebutton.png images/options.png images/closetab.png images/hidetool.png ================================================ FILE: liteidex/src/liteapp/liteapp.rc ================================================ IDI_ICON1 ICON DISCARDABLE "images/liteide.ico" ================================================ FILE: liteidex/src/liteapp/liteapp_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteapp_global.h // Creator: visualfc #ifndef LITEAPP_GLOBAL_H #define LITEAPP_GLOBAL_H #include #if defined(LITEAPP_LIBRARY) # define LITEIDESHARED_EXPORT Q_DECL_EXPORT #else # define LITEIDESHARED_EXPORT Q_DECL_IMPORT #endif #define LITEIDE_STORELOCAL "LiteIDE/StoreLocal" #define OPTION_LITEAPP "option/liteapp" #define OPTION_LITEOUTPUT "option/liteoutput" #define LITEAPP_MAXRECENTFILES "LiteApp/MaxRecentFile" #define LITEAPP_MAXEDITORCOUNT "LiteApp/MaxEditorCount" #define LITEAPP_AUTOCLOSEPROEJCTFILES "LiteApp/AutoCloseProjectEditors" #define LITEAPP_AUTOLOADLASTSESSION "LiteApp/AutoLoadLastSession" #define LITEAPP_AUTOIDLESAVEDOCUMENTS "LiteApp/AutoIdleSaveDocuments" #define LITEAPP_AUTOIDLESAVEDOCUMENTS_TIME "LiteApp/AutoIdelSaveDocumentsTime" #define LITEAPP_AUTOIDLESAVEDOCUMENTS_EMITMESSAGE "LiteApp/AutoIdelSaveDocumentsEmitMessage" #define LITEAPP_LANGUAGE "General/Language" #define LITEAPP_STYLE "LiteApp/WindowStyle" #define LITEAPP_SPLASHVISIBLE "LiteApp/SplashVisible" #define LITEAPP_WELCOMEPAGEVISIBLE "General/WelcomePageVisible" #define LITEAPP_TOOLBARICONSIZE "General/ToolBarIconSize" #define LITEAPP_EDITTABSCLOSABLE "LiteApp/EditTabsClosable" #define LITEAPP_EDITTABSENABLEWHELL "LiteApp/EditTabEnableWhell" #define LITEAPP_SHOWEDITTOOLBAR "LiteApp/ShowEditToolbar" #define LITEAPP_QSS "LiteApp/Qss" #define LITEAPP_FULLSCREEN "LiteApp/FullScreen" #define LITEAPP_WINSTATE "LiteApp/WinState" #define LITEAPP_SHORTCUTS "keybord_shortcuts/" #define LITEAPP_OPTNFOLDERINNEWWINDOW "LiteApp/OpenFolderInNewWindow" #define LITEAPP_FOLDERSHOWHIDENFILES "LiteApp/FolderShowHidenFiles" #define LITEAPP_FOLDERSHOWDETAILS "LiteApp/FolderShowDetails" #define LITEAPP_FOLDERSSYNCEDITOR "FileManager/synceditor" #define LITEAPP_FOLDERSPLITMODE "LiteApp/FolderSplitMode" #define LITEAPP_STARTUPRELOADFILES "LiteApp/StartupReloadFiles" #define LITEAPP_STARTUPRELOADFOLDERS "LiteApp/StartupReloadFolders" #define LITEAPP_FILEWATCHERAUTORELOAD "LiteApp/FileWatcherAutoReload" #define LITEIDE_CUSTOMEICONPATH "LiteApp/CustomeIconPath" #define LITEIDE_CUSTOMEICON "LiteApp/CustomeIcon" #define LITEAPP_TOOLWINDOW_SHORTCUTS "LiteApp/ToolWindowShortcuts" #define LITEAPP_USE_LIBGOPHER "LiteApp/UseLibgopher" #define LITEAPP_EDITORMOUSEEXTNAVIGATE "LiteApp/EditorMouseExtNavigate" #define OUTPUT_FAMILY "output/family" #define OUTPUT_FONTSIZE "output/fontsize" #define OUTPUT_FONTZOOM "output/fontzoom" #define OUTPUT_ANTIALIAS "output/antialias" #define OUTPUT_MAXLINES "output/maxlines" #define OUTPUT_USECOLORSCHEME "output/colorscheme" #define LITEAPP_FILESFILTER_MAXCOUNT "LiteApp/FilesFilterMaxCount" #define LITEAPP_SESSIONLIST "LiteApp/SessionList" enum TOOLBAR_ICONSIZE { TOOLBAR_ICONSIZE_16 = 0, TOOLBAR_ICONSIZE_18, TOOLBAR_ICONSIZE_20, TOOLBAR_ICONSIZE_22, TOOLBAR_ICONSIZE_24 }; #endif // LITEAPP_GLOBAL_H ================================================ FILE: liteidex/src/liteapp/liteappoption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteappoption.cpp // Creator: visualfc #include "liteappoption.h" #include "actionmanager.h" #include "liteapp_global.h" #include "ui_liteappoption.h" #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end LiteAppOption::LiteAppOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::LiteAppOption) { ui->setupUi(m_widget); const QString &liteideTrPath = m_liteApp->resourcePath()+"/translations"; QLocale eng(QLocale::English); ui->langComboBox->addItem(QLocale::languageToString(QLocale::English),eng.name()); QDir dir(liteideTrPath); if (dir.exists()) { foreach (QFileInfo info,dir.entryInfoList(QStringList() << "liteide_*.qm")) { QString base = info.baseName(); QLocale lc(base.right(base.length()-8)); if (lc.name().isEmpty()) { continue; } QLocale::Language lang = lc.language(); QString text = QString("%1 (%2)").arg(QLocale::languageToString(lang)).arg(lc.name()); ui->langComboBox->addItem(text,lc.name()); } } connect(ui->customIconCheckBox,SIGNAL(toggled(bool)),ui->iconPathComboBox,SLOT(setEnabled(bool))); QDir iconDir(m_liteApp->resourcePath()+"/liteapp/qrc"); foreach (QFileInfo info, iconDir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot)) { ui->iconPathComboBox->addItem(info.fileName()); } m_keysModel = new QStandardItemModel(0,5,this); m_keysModel->setHeaderData(0,Qt::Horizontal,tr("Command")); m_keysModel->setHeaderData(1,Qt::Horizontal,tr("Label")); m_keysModel->setHeaderData(2,Qt::Horizontal,tr("Shortcuts")); m_keysModel->setHeaderData(3,Qt::Horizontal,tr("NativeText")); m_keysModel->setHeaderData(4,Qt::Horizontal,tr("Standard")); ui->keysTreeView->setModel(m_keysModel); #if QT_VERSION >= 0x050000 ui->keysTreeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); #else ui->keysTreeView->header()->setResizeMode(QHeaderView::ResizeToContents); #endif #ifndef Q_OS_MAC ui->keysTreeView->header()->hideSection(3); #endif ui->styleComboBox->addItem(tr("SideBarStyle"),"sidebar"); ui->styleComboBox->addItem(tr("SplitterStyle"),"splitter"); const QString &liteQssPath = m_liteApp->resourcePath()+"/liteapp/qss"; QDir qssDir(liteQssPath); if (qssDir.exists()) { foreach (QFileInfo info, qssDir.entryInfoList(QStringList() << "*.qss")) { ui->qssComboBox->addItem(info.fileName()); } } // if (libgopher.isValid()) { // ui->gopherInfoLabel->setText(tr("libgopher is valid")); // } else { // ui->gopherInfoLabel->setText(tr("libgopher is invalid!")); // } // bool useGopher = m_liteApp->settings()->value(LITEAPP_USE_LIBGOPHER,false).toBool(); // ui->useLibgopherCheckBox->setChecked(useGopher); connect(m_keysModel,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(shortcutsChanaged(QStandardItem*))); connect(ui->resetAllButton,SIGNAL(clicked()),this,SLOT(resetAllShortcuts())); connect(ui->resetButton,SIGNAL(clicked()),this,SLOT(resetShortcuts())); connect(ui->importButton,SIGNAL(clicked()),this,SLOT(importShortcuts())); connect(ui->exportButton,SIGNAL(clicked()),this,SLOT(exportShortcuts())); connect(ui->standardCheckBox,SIGNAL(toggled(bool)),this,SLOT(reloadShortcuts())); connect(ui->autoLoadLastSessionCheckBox,SIGNAL(toggled(bool)),this,SLOT(autoLoadLastSessionToggled(bool))); connect(ui->autoIdleSaveDocumentsCheckBox,SIGNAL(toggled(bool)),this,SLOT(autoIdleSaveDocumentsToggled(bool))); connect(ui->autoIdleSaveDocumentsCheckBox,SIGNAL(toggled(bool)),ui->autoIdleSaveDocumentsTimeSpinBox,SLOT(setEnabled(bool))); } LiteAppOption::~LiteAppOption() { delete m_widget; delete ui; } QWidget *LiteAppOption::widget() { return m_widget; } QString LiteAppOption::name() const { return "LiteApp"; } QString LiteAppOption::mimeType() const { return OPTION_LITEAPP; } void LiteAppOption::save() { bool storeLocal = ui->storeLocalCheckBox->isChecked(); QSettings global(m_liteApp->resourcePath()+"/liteapp/config/global.ini",QSettings::IniFormat); global.setValue(LITEIDE_STORELOCAL,storeLocal); int index = ui->langComboBox->currentIndex(); if (index >= 0 && index < ui->langComboBox->count()) { QString lc = ui->langComboBox->itemData(index).toString(); m_liteApp->settings()->setValue(LITEAPP_LANGUAGE,lc); } index = ui->styleComboBox->currentIndex(); if (index >= 0 && index < ui->styleComboBox->count()) { QString style = ui->styleComboBox->itemData(index).toString(); m_liteApp->settings()->setValue(LITEAPP_STYLE,style); } //QString max = ui->maxRecentLineEdit->text(); int max = ui->maxRecentFilesSpinBox->value(); m_liteApp->settings()->setValue(LITEAPP_MAXRECENTFILES,max); max = ui->maxEditorCountSpinBox->value(); m_liteApp->settings()->setValue(LITEAPP_MAXEDITORCOUNT,max); //bool b = ui->autoCloseProjecEditorsCheckBox->isChecked(); // m_liteApp->settings()->setValue(LITEAPP_AUTOCLOSEPROEJCTFILES,b); bool b1 = ui->autoLoadLastSessionCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_AUTOLOADLASTSESSION,b1); bool b2 = ui->splashVisibleCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_SPLASHVISIBLE,b2); bool b3 = ui->welcomeVisibleCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_WELCOMEPAGEVISIBLE,b3); bool b4 = ui->editorTabsClosableCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_EDITTABSCLOSABLE,b4); bool b5 = ui->startupReloadFilesCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_STARTUPRELOADFILES,b5); // bool b6 = ui->startupReloadFoldersCheckBox->isChecked(); // m_liteApp->settings()->setValue(LITEAPP_STARTUPRELOADFOLDERS,b6); bool b7 = ui->fileWatcherAutoReloadCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_FILEWATCHERAUTORELOAD,b7); bool b8 = ui->editorTabsEnableWhellCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_EDITTABSENABLEWHELL,b8); bool b9 = ui->autoIdleSaveDocumentsCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_AUTOIDLESAVEDOCUMENTS,b9); int time = ui->autoIdleSaveDocumentsTimeSpinBox->value(); m_liteApp->settings()->setValue(LITEAPP_AUTOIDLESAVEDOCUMENTS_TIME,time); bool toolwindowshortcuts = ui->toolWindowShortcutsCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_TOOLWINDOW_SHORTCUTS,toolwindowshortcuts); bool ext = ui->editorMouseExtNavigateCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEAPP_EDITORMOUSEEXTNAVIGATE,ext); int size = ui->buttonGroup->buttons().size(); for (int i = 0; i < size; i++) { if (ui->buttonGroup->buttons().at(i)->isChecked()) { m_liteApp->settings()->setValue(LITEAPP_TOOLBARICONSIZE,i); break; } } // bool useGopher = ui->useLibgopherCheckBox->isChecked(); // bool oldUseGopher = m_liteApp->settings()->value(LITEAPP_USE_LIBGOPHER,false).toBool(); // if (useGopher != oldUseGopher) { // m_liteApp->settings()->setValue(LITEAPP_USE_LIBGOPHER,useGopher); // if (!libgopher.isValid()) { // m_liteApp->appendLog("LiteApp",QString("libgopher is invalid")); // } else { // m_liteApp->appendLog("LiteApp",useGopher ? QString("enable use libgopher"):QString("disable use libgopher")); // } // } QString qss = ui->qssComboBox->currentText(); if (!qss.isEmpty()) { QFile f(m_liteApp->resourcePath()+"/liteapp/qss/"+qss); if (f.open(QFile::ReadOnly)) { m_liteApp->settings()->setValue(LITEAPP_QSS,qss); QString styleSheet = QLatin1String(f.readAll()); qApp->setStyleSheet(styleSheet); } } bool customelIcon = ui->customIconCheckBox->isChecked(); m_liteApp->settings()->setValue(LITEIDE_CUSTOMEICON,customelIcon); QString iconPath = ui->iconPathComboBox->currentText(); m_liteApp->settings()->setValue(LITEIDE_CUSTOMEICONPATH,iconPath); for (int i = 0; i < m_keysModel->rowCount(); i++) { QStandardItem *root = m_keysModel->item(i,0); if (!root) { continue; } LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->actionContextForName(root->text()); if (!actionContext) { continue; } for (int j = 0; j < root->rowCount(); j++) { QStandardItem *id = root->child(j,0); if (!id) { continue; } QStandardItem *bind = root->child(j,2); if (!bind) { continue; } m_liteApp->actionManager()->setActionShourtcuts(id->text(),bind->text()); } } } void LiteAppOption::load() { QSettings global(m_liteApp->resourcePath()+"/liteapp/config/global.ini",QSettings::IniFormat); bool storeLocal = global.value(LITEIDE_STORELOCAL,false).toBool(); ui->storeLocalCheckBox->setChecked(storeLocal); QString locale = QLocale::system().name(); locale = m_liteApp->settings()->value(LITEAPP_LANGUAGE,locale).toString(); if (!locale.isEmpty()) { for (int i = 0; i < ui->langComboBox->count(); i++) { if (locale == ui->langComboBox->itemData(i).toString()) { ui->langComboBox->setCurrentIndex(i); break; } } } QString style = m_liteApp->settings()->value(LITEAPP_STYLE,"sidebar").toString(); for (int i = 0; i < ui->styleComboBox->count(); i++) { if (style == ui->styleComboBox->itemData(i).toString()) { ui->styleComboBox->setCurrentIndex(i); break; } } bool customeIcon = m_liteApp->settings()->value(LITEIDE_CUSTOMEICON,false).toBool(); ui->customIconCheckBox->setChecked(customeIcon); ui->iconPathComboBox->setEnabled(customeIcon); QString qss = m_liteApp->settings()->value(LITEAPP_QSS,"default.qss").toString(); int index = ui->qssComboBox->findText(qss,Qt::MatchFixedString); if (index >= 0 && index < ui->qssComboBox->count()) { ui->qssComboBox->setCurrentIndex(index); } int max = m_liteApp->settings()->value(LITEAPP_MAXRECENTFILES,32).toInt(); //ui->maxRecentLineEdit->setText(QString("%1").arg(max)); ui->maxRecentFilesSpinBox->setValue(max); max = m_liteApp->settings()->value(LITEAPP_MAXEDITORCOUNT,64).toInt(); ui->maxEditorCountSpinBox->setValue(max); //bool b = m_liteApp->settings()->value(LITEAPP_AUTOCLOSEPROEJCTFILES,true).toBool(); //ui->autoCloseProjecEditorsCheckBox->setChecked(b); bool b1 = m_liteApp->settings()->value(LITEAPP_AUTOLOADLASTSESSION,true).toBool(); ui->autoLoadLastSessionCheckBox->setChecked(b1); bool b2 = m_liteApp->settings()->value(LITEAPP_SPLASHVISIBLE,true).toBool(); ui->splashVisibleCheckBox->setChecked(b2); bool b3 = m_liteApp->settings()->value(LITEAPP_WELCOMEPAGEVISIBLE,true).toBool(); ui->welcomeVisibleCheckBox->setChecked(b3); bool b4 = m_liteApp->settings()->value(LITEAPP_EDITTABSCLOSABLE,true).toBool(); ui->editorTabsClosableCheckBox->setChecked(b4); // bool b5 = m_liteApp->settings()->value(LITEAPP_STARTUPRELOADFOLDERS,true).toBool(); // ui->startupReloadFoldersCheckBox->setChecked(b5); bool b6 = m_liteApp->settings()->value(LITEAPP_STARTUPRELOADFILES,true).toBool(); ui->startupReloadFilesCheckBox->setChecked(b6); bool b7 = m_liteApp->settings()->value(LITEAPP_FILEWATCHERAUTORELOAD,false).toBool(); ui->fileWatcherAutoReloadCheckBox->setChecked(b7); bool b8 = m_liteApp->settings()->value(LITEAPP_EDITTABSENABLEWHELL,true).toBool(); ui->editorTabsEnableWhellCheckBox->setChecked(b8); int id = m_liteApp->settings()->value(LITEAPP_TOOLBARICONSIZE,0).toInt(); if (id >= 0 && id < ui->buttonGroup->buttons().size()) { ui->buttonGroup->buttons().at(id)->setChecked(true); } bool b9 = m_liteApp->settings()->value(LITEAPP_AUTOIDLESAVEDOCUMENTS,false).toBool(); ui->autoIdleSaveDocumentsCheckBox->setChecked(b9); int time = m_liteApp->settings()->value(LITEAPP_AUTOIDLESAVEDOCUMENTS_TIME,3).toInt(); if (time < 1) { time = 1; } ui->autoIdleSaveDocumentsTimeSpinBox->setValue(time); bool toolwndshortcuts = m_liteApp->settings()->value(LITEAPP_TOOLWINDOW_SHORTCUTS,true).toBool(); ui->toolWindowShortcutsCheckBox->setChecked(toolwndshortcuts); bool ext = m_liteApp->settings()->value(LITEAPP_EDITORMOUSEEXTNAVIGATE,true).toBool(); ui->editorMouseExtNavigateCheckBox->setChecked(ext); QString iconPath = m_liteApp->settings()->value(LITEIDE_CUSTOMEICONPATH,"default").toString(); index = ui->iconPathComboBox->findText(iconPath,Qt::MatchFixedString); if (index >= 0 && index < ui->iconPathComboBox->count()) { ui->iconPathComboBox->setCurrentIndex(index); } ui->standardCheckBox->setChecked(true); autoLoadLastSessionToggled(ui->autoLoadLastSessionCheckBox->isChecked()); this->reloadShortcuts(); } void LiteAppOption::reloadShortcuts() { m_keysModel->removeRows(0,m_keysModel->rowCount()); bool bCheckStandard = ui->standardCheckBox->isChecked(); foreach(QString name, m_liteApp->actionManager()->actionContextNameList() ) { LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->actionContextForName(name); if (actionContext) { QStandardItem *root = new QStandardItem(name); root->setEditable(false); foreach(QString id, actionContext->actionKeys()) { LiteApi::ActionInfo *info = actionContext->actionInfo(id); if (!info) { continue; } if (bCheckStandard && info->standard && (info->ks == info->defks)) { continue; } QStandardItem *item = new QStandardItem(id); item->setEditable(false); QStandardItem *label = new QStandardItem(info->label); label->setEditable(false); QStandardItem *std = new QStandardItem; std->setCheckable(true); std->setEnabled(false); std->setCheckState(info->standard?Qt::Checked:Qt::Unchecked); QStandardItem *bind = new QStandardItem(info->ks); bind->setEditable(true); if (info->ks != info->defks) { QFont font = bind->font(); font.setBold(true); bind->setFont(font); } QStandardItem *native = new QStandardItem(ActionManager::formatShortcutsNativeString(info->ks)); native->setEditable(false); root->appendRow(QList() << item << label << bind << native << std); } m_keysModel->appendRow(root); } } ui->keysTreeView->expandAll(); } void LiteAppOption::shortcutsChanaged(QStandardItem *bind) { if (!bind) { return; } QStandardItem *root = bind->parent(); if (!root) { return; } LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->actionContextForName(root->text()); if (!actionContext) { return; } QStandardItem *item = root->child(bind->row(),0); if (!item) { return; } QStandardItem *native = root->child(bind->row(),3); LiteApi::ActionInfo *info = actionContext->actionInfo(item->text()); if (!info) { return; } m_keysModel->blockSignals(true); bind->setText(ActionManager::formatShortcutsString(bind->text())); native->setText(ActionManager::formatShortcutsNativeString(bind->text())); m_keysModel->blockSignals(false); QFont font = bind->font(); if (info->defks != bind->text()) { font.setBold(true); } else { font.setBold(false); } bind->setFont(font); } void LiteAppOption::resetAllShortcuts() { for (int i = 0; i < m_keysModel->rowCount(); i++) { QStandardItem *root = m_keysModel->item(i,0); if (!root) { continue; } LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->actionContextForName(root->text()); if (!actionContext) { continue; } for (int j = 0; j < root->rowCount(); j++) { QStandardItem *id = root->child(j,0); if (!id) { continue; } QStandardItem *bind = root->child(j,2); if (!bind) { continue; } LiteApi::ActionInfo *info = actionContext->actionInfo(id->text()); if (!info) { continue; } bind->setText(info->defks); QFont font = bind->font(); font.setBold(false); bind->setFont(font); } } } void LiteAppOption::resetShortcuts() { QModelIndex index = ui->keysTreeView->currentIndex(); if (!index.isValid()) { return; } QModelIndex rootIndex = index.parent(); if (!rootIndex.isValid()) { return; } QStandardItem *root = m_keysModel->item(rootIndex.row()); if (!root) { return; } LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->actionContextForName(root->text()); if (!actionContext) { return; } QStandardItem *id = root->child(index.row(),0); if (!id) { return; } QStandardItem *bind = root->child(index.row(),2); if (!bind) { return; } LiteApi::ActionInfo *info = actionContext->actionInfo(id->text()); if (!info) { return; } bind->setText(info->defks); QFont font = bind->font(); font.setBold(false); bind->setFont(font); } void LiteAppOption::importShortcuts() { QString dir = m_liteApp->resourcePath()+"/liteapp/kms"; QString filePath = QFileDialog::getOpenFileName(m_liteApp->mainWindow(),tr("Import Keyboard Mapping Scheme"),dir,QString(tr("Keyboard Mapping Scheme (%1)")).arg("*.kms")); if (filePath.isEmpty()) { return; } QSettings read(filePath,QSettings::IniFormat); int version = read.value("liteidex/version",0).toInt(); if (version < 1) { QMessageBox::critical(m_liteApp->mainWindow(),"Import Error",QString(tr("Could not read scheme from %1!")).arg(filePath)); return; } for (int i = 0; i < m_keysModel->rowCount(); i++) { QStandardItem *root = m_keysModel->item(i,0); for (int j = 0; j < root->rowCount(); j++) { QStandardItem *id = root->child(j,0); if (!id) { continue; } QStandardItem *bind = root->child(j,2); if (!bind) { continue; } QVariant val = read.value(root->text()+"/"+id->text()); if (!val.isValid()) { continue; } bind->setText(ActionManager::formatShortcutsString(val.toString())); } } } void LiteAppOption::exportShortcuts() { QString dir = m_liteApp->resourcePath()+"/liteapp/kms"; QString filePath = QFileDialog::getSaveFileName(m_liteApp->mainWindow(),tr("Export Keyboard Mapping Scheme"),dir,QString(tr("Keyboard Mapping Scheme (%1)")).arg("*.kms")); if (filePath.isEmpty()) { return; } QFileInfo info(filePath); if (info.suffix() != "kms") { filePath += ".kms"; } QSettings write(filePath,QSettings::IniFormat); if (!write.isWritable()) { QMessageBox::critical(m_liteApp->mainWindow(),"Export Error",QString(tr("Could not write scheme to %1!")).arg(filePath)); return; } write.clear(); write.setValue("liteidex/version",1); for (int i = 0; i < m_keysModel->rowCount(); i++) { QStandardItem *root = m_keysModel->item(i,0); for (int j = 0; j < root->rowCount(); j++) { QStandardItem *id = root->child(j,0); if (!id) { continue; } QStandardItem *bind = root->child(j,2); if (!bind) { continue; } write.setValue(root->text()+"/"+id->text(),bind->text()); } } } void LiteAppOption::autoLoadLastSessionToggled(bool b) { //ui->startupReloadFoldersCheckBox->setEnabled(b); ui->startupReloadFilesCheckBox->setEnabled(b); } void LiteAppOption::autoIdleSaveDocumentsToggled(bool /*b*/) { } ================================================ FILE: liteidex/src/liteapp/liteappoption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteappoption.h // Creator: visualfc #ifndef LITEAPPOPTION_H #define LITEAPPOPTION_H #include "liteapi/liteapi.h" namespace Ui { class LiteAppOption; } class QStandardItemModel; class QStandardItem; class LiteAppOption : public LiteApi::IOption { Q_OBJECT public: explicit LiteAppOption(LiteApi::IApplication *app, QObject *parent = 0); ~LiteAppOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void save(); virtual void load(); public slots: void reloadShortcuts(); void shortcutsChanaged(QStandardItem*); void resetAllShortcuts(); void resetShortcuts(); void importShortcuts(); void exportShortcuts(); void autoLoadLastSessionToggled(bool b); void autoIdleSaveDocumentsToggled(bool); private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::LiteAppOption *ui; QStandardItemModel *m_keysModel; //GopherLib libgopher; }; #endif // LITEAPPOPTION_H ================================================ FILE: liteidex/src/liteapp/liteappoption.ui ================================================ LiteAppOption 0 0 640 435 Form 0 Generic Store [*] false Store settings to local ini file Interface [*] Language: 0 0 Style: Use tool window shortcuts Qt::Horizontal QSizePolicy::Expanding 40 20 Theme [*] Theme: Qt::Horizontal 40 20 Icon [*] false Fallback build-in icon library and liteapp/qrc/default Load the external file icon library Qt::Horizontal 40 20 Automatically save documents Automatically save documents when application is idle sec 1 120 Qt::Horizontal 40 20 Monitoring files for modifications Auto reload or close editor buffer,if underlying file is modified/deleted. Qt::Vertical 20 40 groupBox groupBox_4 groupBox_5 groupBox_10 Session Session Reload session on startup Qt::Horizontal QSizePolicy::Fixed 40 20 Reload files in session Recent Files Max Count: 0-99 Qt::Horizontal QSizePolicy::Expanding 40 20 Editor Tabs Max Count: 10-999 10 999 Qt::Horizontal 40 20 Qt::Vertical 20 48 Display Display [*] Show splash screen on startup Show welcome page on startup Toolbar Icon Size [*] 16x16 buttonGroup 18x18 buttonGroup 20x20 buttonGroup 22x22 buttonGroup 24x24 buttonGroup Qt::Vertical 20 40 Editor Editor tab [*] Show close buttons on each editor tab Enable mouse wheel navigation on tabs Editor navigate Enable mouse extra 'Back' button and 'Forward' button for go back and forward Qt::Vertical 20 270 Keyboard Format: {Ctrl+B},{Ctrl+Shift+B},{Ctrl+K,Ctrl+U},{Ctrl+Shift+Z;Ctrl+Y} Hide standard commands Reset Reset All Qt::Horizontal 40 20 Import... Export... ================================================ FILE: liteidex/src/liteapp/liteappoptionfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteappoptionfactory.cpp // Creator: visualfc #include "liteappoption.h" #include "outputoption.h" #include "liteappoptionfactory.h" #include "liteapp_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end LiteAppOptionFactory::LiteAppOptionFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IOptionFactory(parent), m_liteApp(app) { } QStringList LiteAppOptionFactory::mimeTypes() const { return QStringList() << OPTION_LITEAPP << OPTION_LITEOUTPUT; } LiteApi::IOption *LiteAppOptionFactory::create(const QString &mimeType) { if (mimeType == OPTION_LITEAPP) { return new LiteAppOption(m_liteApp,this); } else if (mimeType == OPTION_LITEOUTPUT) { return new OutputOption(m_liteApp,this); } return 0; } ================================================ FILE: liteidex/src/liteapp/liteappoptionfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: liteappoptionfactory.h // Creator: visualfc #ifndef LITEAPPOPTIONFACTORY_H #define LITEAPPOPTIONFACTORY_H #include "liteapi/liteapi.h" class LiteAppOptionFactory : public LiteApi::IOptionFactory { public: LiteAppOptionFactory(LiteApi::IApplication *app, QObject *parent); virtual QStringList mimeTypes() const; virtual LiteApi::IOption *create(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; }; #endif // LITEAPPOPTIONFACTORY_H ================================================ FILE: liteidex/src/liteapp/macsupport.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: macsupport.h // Creator: visualfc #ifndef MACSUPPORT_H #define MACSUPPORT_H #include #include class MacSupport { public: static void setFullScreen(QMainWindow *window); static bool isLionOrHigh() { return QSysInfo::MacintoshVersion > QSysInfo::MV_10_6; } }; #endif // MACSUPPORT_H ================================================ FILE: liteidex/src/liteapp/macsupport.mm ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 visualfc. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: macsupport.mm // Creator: visualfc #include "macsupport.h" #include #include #ifndef NSWindowCollectionBehaviorFullScreenPrimary #define NSWindowCollectionBehaviorFullScreenPrimary 1 << 7 #endif void MacSupport::setFullScreen(QMainWindow *window) { NSView *nsview = (NSView*)window->winId(); NSWindow *nswindow = [nsview window]; [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; } ================================================ FILE: liteidex/src/liteapp/main.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: main.cpp // Creator: visualfc #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #ifdef Q_OS_MACOS #include #endif #include #include #include "mainwindow.h" #include "liteapp.h" #include "goproxy.h" #include "cdrv.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end #ifdef Q_OS_MACOS class LiteIDEApplication : public QApplication { public: IApplication *liteApp = nullptr; LiteIDEApplication(int &argc, char **argv) : QApplication(argc, argv) {} bool event(QEvent *event) override { if (event->type() == QEvent::FileOpen) { QString filePath = static_cast(event)->file(); if (liteApp == nullptr) { // Cold start, wait liteApp ready QFuture future = QtConcurrent::run([this, filePath](){ while(this->liteApp == nullptr) QThread::sleep(1); QMetaObject::invokeMethod(this, [this, filePath]() { openFileOrFolder(filePath); }, Qt::QueuedConnection); }); } else { openFileOrFolder(filePath); } } return QApplication::event(event); } private: void openFileOrFolder(QString filePath) { QFileInfo f(filePath); if (!f.exists() || liteApp == nullptr) return; if (f.isFile()) { liteApp->fileManager()->openEditor(filePath); } else if (f.isDir()) { liteApp->fileManager()->addFolderList(filePath); } } }; #endif #ifdef LITEAPP_LIBRARY int liteapp_main(int argc, char *argv[]) #else int main(int argc, char *argv[]) #endif { #ifndef LITEAPP_LIBRARY #if defined(_MSC_VER) && defined(_DEBUG) _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); #endif #endif #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif #ifdef Q_OS_MACOS LiteIDEApplication app(argc, argv); #else QApplication app(argc, argv); #endif QStringList arguments = app.arguments(); //init load file or folder list QStringList fileList; //liteide --select-env [system|win32|cross-linux64|...] select init environment id //liteide --reset-setting reset current setting //liteide --local-setting force user local setting //liteide --user-setting force use user setting QString flagSelectEnv = "--select-env"; QString argSelectEnv; QString flagResetSetting = "--reset-setting"; QString flagLocalSetting = "--local-setting"; QString flagUserSetting = "--user-setting"; bool argResetSetting = false; bool argLocalSetting = false; bool argUserSetting = false; for(int i = 1; i < arguments.size(); i++) { QString arg = arguments[i]; if (arg.startsWith("-")) { if (arg.indexOf(flagSelectEnv+"=") == 0) { argSelectEnv = arg.mid(flagSelectEnv.length()+1); } else if (arg == flagSelectEnv) { i++; if (i < arguments.size()) { argSelectEnv = arguments[i]; } } else if (arg == flagResetSetting) { argResetSetting = true; } else if (arg == flagLocalSetting) { argLocalSetting = true; } else if (arg == flagUserSetting) { argUserSetting = true; } continue; } fileList.append(arg); } //save to global if (!argSelectEnv.isEmpty()) { LiteApp::s_cookie.insert(flagSelectEnv,argSelectEnv); } if (argLocalSetting) { LiteApp::s_cookie.insert(flagLocalSetting,true); } if (argUserSetting) { LiteApp::s_cookie.insert(flagUserSetting,true); } #if QT_VERSION >= 0x050100 app.setAttribute(Qt::AA_UseHighDpiPixmaps); #endif //QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande"); QTranslator translator; QTranslator qtTranslator; QString resPath = LiteApp::getResoucePath(); QString locale = QLocale::system().name(); QString qss; QSettings global(resPath+"/liteapp/config/global.ini",QSettings::IniFormat); bool storeLocal = global.value(LITEIDE_STORELOCAL,false).toBool(); if (argUserSetting) { storeLocal = false; } else if (argLocalSetting) { storeLocal = true; } if (storeLocal) { QSettings settings(resPath+"/liteapp/config/liteide.ini", QSettings::IniFormat); if (argResetSetting) { settings.clear(); } locale = settings.value(LITEAPP_LANGUAGE,locale).toString(); qss = settings.value(LITEAPP_QSS,"default.qss").toString(); } else { QSettings settings(QSettings::IniFormat,QSettings::UserScope,"liteide","liteide"); if (argResetSetting) { settings.clear(); } locale = settings.value(LITEAPP_LANGUAGE,locale).toString(); qss = settings.value(LITEAPP_QSS,"default.qss").toString(); } if (!locale.isEmpty()) { const QString &liteideTrPath = resPath+"/translations"; if (translator.load(QLatin1String("liteide_") + locale, liteideTrPath)) { const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); const QString &qtTrFile = QLatin1String("qt_") + locale; // Binary installer puts Qt tr files into creatorTrPath app.installTranslator(&translator); if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, liteideTrPath)) { app.installTranslator(&qtTranslator); } app.setProperty("liteide_locale", locale); } } if (!qss.isEmpty()) { QFile f(resPath+"/liteapp/qss/"+qss); if (f.open(QFile::ReadOnly)) { QString styleSheet = QLatin1String(f.readAll()); app.setStyleSheet(styleSheet); } } IApplication *liteApp = LiteApp::NewApplication("default",0); #ifdef Q_OS_MACOS app.liteApp = liteApp; #endif foreach(QString file, fileList) { QFileInfo f(file); if (f.isFile()) { liteApp->fileManager()->openEditor(file); } else if (f.isDir()) { liteApp->fileManager()->addFolderList(file); } } int ret = app.exec(); return ret; } int cdrv_main(int argc, char **argv) { return liteapp_main(argc,argv); } ================================================ FILE: liteidex/src/liteapp/mainwindow.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: mainwindow.cpp // Creator: visualfc #include "mainwindow.h" #include "aboutdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end QMenu* MainWindow::s_macDocMenu = 0; QMap MainWindow::s_windowActions; MainWindow::MainWindow(IApplication *app, QWidget *parent) : ToolMainWindow(parent), m_liteApp(app), m_windowClosedCheck(false) { this->setAttribute(Qt::WA_DeleteOnClose); QIcon icon; icon.addFile("icon:images/liteide16.png"); icon.addFile("icon:images/liteide24.png"); icon.addFile("icon:images/liteide32.png"); icon.addFile("icon:images/liteide48.png"); icon.addFile("icon:images/liteide64.png"); icon.addFile("icon:images/liteide128.png"); this->setWindowIcon(icon); this->setContextMenuPolicy(Qt::CustomContextMenu); this->setAcceptDrops(true); m_mainSplitter = new QSplitter(Qt::Vertical,this); setCentralWidget(m_mainSplitter); #if QT_VERSION >= 0x050200 #ifdef Q_OS_OSX if (!s_macDocMenu) { s_macDocMenu = new QMenu; s_macDocMenu->setAsDockMenu(); } if (s_macDocMenu) { QAction *act = new QAction("macOS",this); act->setCheckable(true); s_macDocMenu->addAction(act); connect(act,SIGNAL(triggered(bool)),this,SLOT(triggeredWindowsAct())); s_windowActions.insert(this,act); } #endif #endif } QSplitter *MainWindow::splitter() { return m_mainSplitter; } void MainWindow::setWindowStyle(IWindowStyle *style) { ToolMainWindow::setWindowStyle(style); //loadInitToolState(m_liteApp->settings()->value("liteapp/toolState").toByteArray()); } MainWindow::~MainWindow() { s_windowActions.remove(this); delete m_liteApp; } void MainWindow::closeEvent(QCloseEvent *event) { if (this->m_windowClosedCheck) { return; } m_liteApp->saveSession(m_liteApp->currentSession()); m_liteApp->saveState(); m_liteApp->projectManager()->closeProject(); if (m_liteApp->editorManager()->closeAllEditors()) { this->m_windowClosedCheck = true; this->hideAllToolWindows(); event->accept(); } else { event->ignore(); } } void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasUrls()) event->acceptProposedAction(); } void MainWindow::changeEvent(QEvent *e) { if (e->type() == QEvent::WindowStateChange) { bool b = (windowState() & Qt::WindowFullScreen) != 0; emit fullScreenStateChanged(b); } } bool MainWindow::event(QEvent *event) { if (event->type() == QEvent::WindowActivate) { setActiveWindowAction(this); } return ToolMainWindow::event(event); } void MainWindow::setFullScreen(bool b) { if (bool(windowState() & Qt::WindowFullScreen) == b) return; if (b) { setWindowState(windowState() | Qt::WindowFullScreen); } else { setWindowState(windowState() & ~Qt::WindowFullScreen); } } void MainWindow::dropEvent(QDropEvent *event) { QList urls = event->mimeData()->urls(); if (urls.isEmpty()) return; QStringList folders; foreach (QUrl url, urls) { QString fileName = url.toLocalFile(); if (fileName.isEmpty()) { return; } QFileInfo info(fileName); if (info.isFile()) { m_liteApp->fileManager()->openFile(fileName); } else if(info.isDir()) { folders.append(info.filePath()); } } if (!folders.isEmpty()) { foreach (QString folder, folders) { m_liteApp->fileManager()->addFolderList(folder); } } } void MainWindow::setWindowTitle(const QString &name, const QString &filePath, bool isModify) { QAction *act = s_windowActions.value(this); if (act) { QString title = QString("(%1)").arg(m_liteApp->currentSession()); if (!name.isEmpty()) { title = name + " - "+title; } act->setText(title); } QString title = QString("LiteIDE (%1)").arg(m_liteApp->currentSession()); if (!filePath.isEmpty()) { QString path = QDir::toNativeSeparators(filePath); if (isModify) { path += "*"; } title = path + " - "+title; } else if (!name.isEmpty()) { title = name + " - "+title; } ToolMainWindow::setWindowTitle(title); } void MainWindow::currentEditorChanged(IEditor *editor) { QString name; QString filePath; bool isModified = false; if (editor) { name = editor->name(); filePath = editor->filePath(); isModified = editor->isModified(); } this->setWindowTitle(name,filePath,isModified); } void MainWindow::editorModifyChanged(IEditor *editor, bool b) { QString name; QString filePath; if (editor) { name = editor->name(); filePath = editor->filePath(); } this->setWindowTitle(name,filePath,b); } void MainWindow::about() { AboutDialog *dlg = new AboutDialog(m_liteApp,m_liteApp->mainWindow()); dlg->setAttribute(Qt::WA_DeleteOnClose); dlg->exec(); } void MainWindow::triggeredWindowsAct() { QAction *act = (QAction*)sender(); if (!act) { return; } QWidget *widget = s_windowActions.key(act,0); if (!widget) { return; } QWidget *window = widget->window(); if (window == this) { act->setChecked(true); this->setWindowState(windowState() & ~Qt::WindowMinimized); } window->raise(); window->activateWindow(); } void MainWindow::setActiveWindowAction(QWidget *window) { QMapIterator it(s_windowActions); while (it.hasNext()) { it.next(); it.value()->setChecked(it.key() == window); } } ================================================ FILE: liteidex/src/liteapp/mainwindow.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: mainwindow.h // Creator: visualfc #ifndef MAINWINDOW_H #define MAINWINDOW_H #include "liteapi/liteapi.h" #include "toolmainwindow.h" #include "windowstyle.h" class IMainWindow : public QObject { Q_OBJECT public: IMainWindow(QObject *parent) : QObject(parent) {} virtual QMainWindow *mainWindow() = 0; virtual LiteApi::IToolWindowManager *toolWindowManager() = 0; signals: void fullScreenStateChanged(bool b); public slots: virtual void setFullScreen(bool b) = 0; virtual void editorModifyChanged(bool b) = 0; virtual void currentEditorChanged(LiteApi::IEditor *editor) = 0; }; using namespace LiteApi; class QSplitter; class MainWindow : public ToolMainWindow { Q_OBJECT public: MainWindow(IApplication *app, QWidget *parent = 0); ~MainWindow(); public: QSplitter *splitter(); void setWindowStyle(IWindowStyle *style); protected: virtual void closeEvent(QCloseEvent *event); virtual void dropEvent(QDropEvent *event); virtual void dragEnterEvent(QDragEnterEvent *event); virtual void changeEvent(QEvent *e); virtual bool event(QEvent *event); signals: void fullScreenStateChanged(bool b); public slots: void setFullScreen(bool b); void currentEditorChanged(LiteApi::IEditor *editor); void editorModifyChanged(LiteApi::IEditor *editor, bool b); void about(); void triggeredWindowsAct(); protected: IApplication *m_liteApp; QAction *m_aboutAct; QSplitter *m_mainSplitter; bool m_windowClosedCheck; protected: void setActiveWindowAction(QWidget *window); void setWindowTitle(const QString &name, const QString &filePath, bool isModify); static QMap s_windowActions; static QMenu *s_macDocMenu; }; #endif // MAINWINDOW_H ================================================ FILE: liteidex/src/liteapp/mimetypemanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: mimetypemanager.cpp // Creator: visualfc #include "mimetypemanager.h" #include "mimetype/mimetype.h" #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end MimeTypeManager::~MimeTypeManager() { qDeleteAll(m_mimeTypeList); } bool MimeTypeManager::addMimeType(IMimeType *mimeType) { foreach (IMimeType *m, m_mimeTypeList) { if (m->type() == mimeType->type()) { m->merge(mimeType); return false; } } m_mimeTypeList.append(mimeType); return true; } void MimeTypeManager::removeMimeType(IMimeType *mimeType) { m_mimeTypeList.removeOne(mimeType); } QList MimeTypeManager::mimeTypeList() const { return m_mimeTypeList; } IMimeType *MimeTypeManager::findMimeType(const QString &type) const { foreach(IMimeType *mimeType, m_mimeTypeList) { if (mimeType->type() == type) { return mimeType; } } return 0; } QString MimeTypeManager::findPackageByMimeType(const QString &type) const { if (type.isEmpty()) { return QString(); } foreach(IMimeType *mimeType, m_mimeTypeList) { if (mimeType->type() == type) { return mimeType->package(); } } return QString(); } QString MimeTypeManager::findMimeTypeByFile(const QString &fileName) const { QFileInfo info(fileName); QString name = info.fileName(); //first check full name foreach (IMimeType *mimeType, m_mimeTypeList) { foreach (QString pattern, mimeType->allPatterns()) { if (!pattern.startsWith("*")) { if (name == pattern) { return mimeType->type(); } } } } //check *.ext QString find = info.suffix(); if (find.isEmpty()) { return QString(); } find = "*."+find; foreach (IMimeType *mimeType, m_mimeTypeList) { foreach (QString pattern, mimeType->allPatterns()) { if (find.compare(pattern,Qt::CaseInsensitive) == 0) { return mimeType->type(); } } } return QString(); } QString MimeTypeManager::findMimeTypeBySuffix(const QString &suffix) const { QString find = "*."+suffix; foreach (IMimeType *mimeType, m_mimeTypeList) { foreach (QString pattern, mimeType->allPatterns()) { if (find.compare(pattern,Qt::CaseInsensitive) == 0) { return mimeType->type(); } } } return QString(); } QString MimeTypeManager::findMimeTypeByScheme(const QString &scheme) const { foreach (IMimeType *mimeType, m_mimeTypeList) { QString type = mimeType->scheme(); if (type.isEmpty()) { type = "file"; } if (scheme == type) { return mimeType->type(); } } return QString(); } void MimeTypeManager::loadMimeTypes(const QString &path) { QDir dir = path; dir.setFilter(QDir::Files | QDir::NoSymLinks); dir.setNameFilters(QStringList("*.xml")); foreach (QString fileName, dir.entryList()) { bool b = MimeType::loadMimeTypes(this,QFileInfo(dir,fileName).absoluteFilePath()); m_liteApp->appendLog("LiteApp",QString("%1 MIME %2").arg(b?"Loaded":"ERROR loading").arg(fileName),!b); } } QStringList MimeTypeManager::findAllFilesByMimeType(const QString &dirPath, const QString &type, int deep) const { LiteApi::IMimeType *mimeType = findMimeType(type); if (mimeType) { QDir dir(dirPath); for (int i = 0; i <= deep; i++) { QStringList files = dir.entryList(QStringList() << mimeType->allPatterns(),QDir::Files); if (!files.isEmpty()) { return files; } dir.cdUp(); } } return QStringList(); } ================================================ FILE: liteidex/src/liteapp/mimetypemanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: mimetypemanager.h // Creator: visualfc #ifndef MIMETYPEMANAGER_H #define MIMETYPEMANAGER_H #include "liteapi/liteapi.h" using namespace LiteApi; class MimeTypeManager : public IMimeTypeManager { public: ~MimeTypeManager(); virtual bool addMimeType(IMimeType *mimeType); virtual void removeMimeType(IMimeType *mimeType); virtual QList mimeTypeList() const; virtual IMimeType *findMimeType(const QString &type) const; virtual QString findPackageByMimeType(const QString &type) const; virtual QString findMimeTypeByFile(const QString &fileName) const; virtual QString findMimeTypeBySuffix(const QString &suffix) const; virtual QString findMimeTypeByScheme(const QString &scheme) const; virtual QStringList findAllFilesByMimeType(const QString &dir, const QString &type, int deep = 0) const; void loadMimeTypes(const QString &path); protected: QList m_mimeTypeList; }; #endif // MIMETYPEMANAGER_H ================================================ FILE: liteidex/src/liteapp/multifolderwindow.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2018 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: multifolderwindow.cpp // Creator: visualfc #include "multifolderwindow.h" #include "liteapp_global.h" #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end MultiFolderWindow::MultiFolderWindow(LiteApi::IApplication *app, QObject *parent) : IFolderWindow(parent) { m_liteApp = app; m_folderListView = new MultiFolderView(app); QDir::Filters filters = QDir::AllDirs | QDir::Files | QDir::Drives | QDir::Readable| QDir::Writable | QDir::Executable /*| QDir::Hidden*/ | QDir::NoDotAndDotDot; m_folderListView->setFilter(filters); m_bSyncEditor = false; connect(m_folderListView,SIGNAL(aboutToShowContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo)),this,SLOT(aboutToShowFolderContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo))); connect(m_folderListView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedFolderView(QModelIndex))); connect(m_folderListView,SIGNAL(enterKeyPressed(QModelIndex)),this,SLOT(enterKeyPressedFolderView(QModelIndex))); connect(m_liteApp->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*))); } MultiFolderWindow::~MultiFolderWindow() { delete m_folderListView; } QWidget *MultiFolderWindow::widget() const { return m_folderListView; } QString MultiFolderWindow::id() const { return "folderwindow/multifolder"; } void MultiFolderWindow::setShowHideFiles(bool b) { QDir::Filters filters = m_folderListView->filter(); if (b) { filters |= QDir::Hidden; } else if (filters.testFlag(QDir::Hidden)){ filters ^= QDir::Hidden; } m_folderListView->setFilter(filters); } void MultiFolderWindow::setShowDetails(bool b) { m_folderListView->setShowDetails(b); } void MultiFolderWindow::setSyncEditor(bool b) { m_bSyncEditor = b; if (b) { this->currentEditorChanged(m_liteApp->editorManager()->currentEditor()); } } void MultiFolderWindow::doubleClickedFolderView(const QModelIndex &index) { if (!index.isValid()) { return; } QFileInfo info = m_folderListView->fileInfo(index); if (info.isFile()) { m_liteApp->fileManager()->openEditor(info.filePath()); } } void MultiFolderWindow::enterKeyPressedFolderView(const QModelIndex &index) { if (!index.isValid()) { return; } QFileInfo info = m_folderListView->fileInfo(index); if (info.isFile()) { m_liteApp->fileManager()->openEditor(info.filePath()); } else { m_folderListView->setExpanded(index,!m_folderListView->isExpanded(index)); } } QStringList MultiFolderWindow::folderList() const { return m_folderListView->rootPathList(); } void MultiFolderWindow::setFolderList(const QStringList &folders) { QStringList all = folders; all.removeDuplicates(); m_folderListView->setRootPathList(all); foreach (QString folder, all) { m_liteApp->recentManager()->addRecent(folder,"folder"); } if (m_folderListView->rootPathList().size() == 1) { m_folderListView->expandFolder(m_folderListView->rootPathList().first(),true); } } void MultiFolderWindow::addFolderList(const QString &folder) { if (!m_folderListView->addRootPath(folder)) { return; } m_liteApp->recentManager()->addRecent(folder,"folder"); m_folderListView->expandFolder(folder,true); } void MultiFolderWindow::closeAllFolders() { m_folderListView->closeAllFolders(); } void MultiFolderWindow::currentEditorChanged(LiteApi::IEditor *editor) { if (!editor || !m_bSyncEditor) { return; } QString fileName = editor->filePath(); if (fileName.isEmpty()) { return; } QList indexList = m_folderListView->indexForPath(fileName); if (indexList.isEmpty()) { return; } QModelIndex index = indexList.first(); m_folderListView->scrollTo(index,QAbstractItemView::EnsureVisible); m_folderListView->clearSelection(); m_folderListView->setCurrentIndex(index); } void MultiFolderWindow::aboutToShowFolderContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info) { m_liteApp->fileManager()->emitAboutToShowFolderContextMenu(menu,flag,info,"liteapp/folder"); } ================================================ FILE: liteidex/src/liteapp/multifolderwindow.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2018 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: multifolderwindow.h // Creator: visualfc #ifndef FOLDERWINDOW_H #define FOLDERWINDOW_H #include #include "folderview/multifolderview.h" #include "filemanager.h" class MultiFolderWindow : public IFolderWindow { Q_OBJECT public: explicit MultiFolderWindow(LiteApi::IApplication *app, QObject *parent = 0); virtual ~MultiFolderWindow(); virtual QString id() const; virtual QWidget *widget() const; virtual QStringList folderList() const; virtual void setFolderList(const QStringList &folders); virtual void addFolderList(const QString &folder); virtual void closeAllFolders(); virtual void setShowHideFiles(bool b); virtual void setShowDetails(bool b); virtual void setSyncEditor(bool b); public slots: void doubleClickedFolderView(const QModelIndex &index); void enterKeyPressedFolderView(const QModelIndex &index); void currentEditorChanged(LiteApi::IEditor *editor); void aboutToShowFolderContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info); protected: LiteApi::IApplication *m_liteApp; MultiFolderView *m_folderListView; bool m_bSyncEditor; }; #endif // FOLDERWINDOW_H ================================================ FILE: liteidex/src/liteapp/newfiledialog.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: newfiledialog.cpp // Creator: visualfc #include "newfiledialog.h" #include "ui_newfiledialog.h" #include "liteapi/liteqt.h" #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end NewFileDialog::NewFileDialog(QWidget *parent) : QDialog(parent), ui(new Ui::NewFileDialog) { ui->setupUi(this); m_templateModel = new QStandardItemModel(this); m_pathModel = new QStringListModel(this); ui->templateTreeView->setModel(m_templateModel); ui->pathTreeView->setModel(m_pathModel); ui->pathTreeView->setEditTriggers(0); ui->pathTreeView->setRootIsDecorated(false); ui->pathTreeView->setHeaderHidden(true); ui->templateTreeView->setEditTriggers(0); ui->templateTreeView->setRootIsDecorated(false); ui->templateTreeView->setHeaderHidden(true); connect(ui->templateTreeView,SIGNAL(clicked(QModelIndex)),this,SLOT(activeTemplate(QModelIndex))); connect(ui->nameLineEdit,SIGNAL(textChanged(QString)),this,SLOT(nameLineChanged(QString))); connect(ui->locationLineEdit,SIGNAL(textChanged(QString)),this,SLOT(locationLineChanged(QString))); connect(ui->pathTreeView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(activePath(QModelIndex))); } NewFileDialog::~NewFileDialog() { delete ui; } void NewFileDialog::setPathList(const QStringList &pathList) { m_pathModel->setStringList(pathList); if (m_gopath.isEmpty() && !pathList.isEmpty()) { m_gopath = pathList.first(); } } void NewFileDialog::setGopath(const QString &path) { m_gopath = path; } void NewFileDialog::setProjectLocation(const QString &path) { m_projectLocation = path; } void NewFileDialog::setFileLocation(const QString &path) { m_fileLocation = path; } void NewFileDialog::updateLocation() { ui->nameLineEdit->clear(); QModelIndex index = ui->templateTreeView->currentIndex(); if (index.isValid()) { activeTemplate(index); } } void NewFileDialog::accept() { if (!m_cur.isValid()) { return; } QString location = ui->locationLineEdit->text().trimmed(); QString name = ui->nameLineEdit->text().trimmed(); if (name.isEmpty() || location.isEmpty()) { return; } QDir dir(location); if (!dir.exists()) { if (!dir.mkpath(location)) { QMessageBox::warning(this,tr("Error"),tr("Could not create the target directory: %1").arg(location)); return; } } else { if (m_cur.type != "file" && !dir.entryList(QDir::Files).isEmpty()) { int ret = QMessageBox::warning(this,tr("Warning"),QString(tr("Location %1 is not empty.\nUse the target directory anyway?")).arg(location), QMessageBox::Yes|QMessageBox::No,QMessageBox::No); if (ret != QMessageBox::Yes) { return; } } } static const char * const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; m_stringMap.clear(); m_stringMap.insert("$ROOT$",QFileInfo(name).fileName()); QDate dt = QDate::currentDate(); QTime tm = QTime::currentTime(); m_stringMap.insert("$DATE$", QString("%1 %2 %3").arg(dt.day()).arg(shortMonthNames[dt.month()-1]).arg(dt.year())); m_stringMap.insert("$DATETIME$",QString("%1 %2 %3 %4").arg(tm.toString("hh:mm")).arg(dt.day()).arg(shortMonthNames[dt.month()-1]).arg(dt.year())); m_openFiles.clear(); m_openPath = location; QStringList ofiles; foreach (QString file, m_cur.files) { QString infile = QFileInfo(m_cur.dir,file).absoluteFilePath(); QString ofile = file; QFileInfo oi(name); QString base = oi.fileName(); if (!oi.suffix().isEmpty() && (oi.suffix() == QFileInfo(infile).suffix())) { ofile.replace("root",base.left(base.length()-oi.suffix().length()-1)); } else { ofile.replace("root",base); } QString outfile = QFileInfo(location,ofile).absoluteFilePath(); if (QFile::exists(outfile)) { int ret = QMessageBox::warning(this,tr("Overwrite File"),QString(tr("%1 already exists.\nDo you want to replace it?").arg(outfile)), QMessageBox::Yes|QMessageBox::No|QMessageBox::Abort,QMessageBox::Abort); if (ret == QMessageBox::Abort) { return; } else if (ret == QMessageBox::No) { continue; } } if (processFile(infile,outfile)) { ofiles.append(outfile); if (m_cur.open.contains(file)) { m_openFiles.append(QDir::toNativeSeparators(outfile)); } } } if (ofiles.isEmpty()) { QMessageBox::warning(this,tr("Error"),tr("No files could be created.")); return; } QDialog::accept(); } void NewFileDialog::activePath(QModelIndex index) { if (!index.isValid()) { return; } if (m_cur.type == "project") { m_projectLocation = index.data(Qt::DisplayRole).toString(); } else if (m_cur.type == "file"){ m_fileLocation = index.data(Qt::DisplayRole).toString(); } else if (m_cur.type == "gopath") { m_gopath = index.data(Qt::DisplayRole).toString(); } QModelIndex i = ui->templateTreeView->currentIndex(); if (i.isValid()) { activeTemplate(i); } } void NewFileDialog::loadTemplate(const QString &root) { m_templateModel->clear(); m_cur.clear(); ui->nameLineEdit->clear(); ui->locationLineEdit->clear(); QStringList files; files << "file.sub" << "project.sub"; foreach (QString file, files) { QFile f(root+"/"+file); if (!f.open(QIODevice::ReadOnly)) { continue; } while (!f.atEnd()) { QString line = f.readLine().trimmed(); QString setup = root+"/"+line+"/setup.inf"; QSettings set(setup,QSettings::IniFormat); if (set.status() != QSettings::NoError) { continue; } QString name = set.value("SETUP/NAME").toString(); QString type = set.value("SETUP/type").toString(); if (!name.isEmpty()) { QStandardItem *item = new QStandardItem(name); item->setData(setup); QFont font = item->font(); if (type == "file") { font.setItalic(true); } else { font.setBold(true); } item->setFont(font); m_templateModel->appendRow(item); } } f.close(); } if (m_templateModel->rowCount() > 0) { QModelIndex index = m_templateModel->index(0,0); ui->templateTreeView->setCurrentIndex(index); activeTemplate(index); } } void NewFileDialog::activeTemplate(QModelIndex index) { m_cur.clear(); if (index.isValid()) { QString fileName = index.data(Qt::UserRole+1).toString(); QSettings set(fileName,QSettings::IniFormat); if (set.status() != QSettings::NoError) { return; } m_cur.dir = QFileInfo(fileName).absolutePath(); m_cur.name = set.value("SETUP/NAME").toString(); m_cur.author = set.value("SETUP/AUTHOR").toString(); m_cur.info = set.value("SETUP/INFO").toString(); m_cur.type = set.value("SETUP/TYPE").toString().toLower(); m_cur.files = set.value("SETUP/FILES").toString().trimmed().split(" ",qtSkipEmptyParts); m_cur.open = set.value("SETUP/OPEN").toString().trimmed().split(" ",qtSkipEmptyParts); m_cur.scheme = set.value("SETUP/SCHEME").toString().toLower(); if (m_cur.open.isEmpty() && m_cur.files.count() > 0) { m_cur.open.append(m_cur.files.at(0)); } if (m_cur.type.isEmpty()) { m_cur.type = "file"; } } if (m_cur.type == "file") { ui->typeLabel->setText(tr("File template details:")); } else { ui->typeLabel->setText(tr("Project template details:")); } QStringList infos; if (!m_cur.name.isEmpty()) { infos.append("Name = "+m_cur.name); } if (!m_cur.author.isEmpty()) { infos.append("Author = "+m_cur.author); } if (!m_cur.info.isEmpty()) { infos.append("Info = "+m_cur.info); } ui->infoLabel->setText(infos.join("\n")); QString location; bool b = true; if (m_cur.type == "gopath") { location = QFileInfo(m_gopath,"src").filePath(); //b = false; } else if (m_cur.type == "project") { location = m_projectLocation; } else { location = m_fileLocation; } ui->locationLineEdit->setEnabled(b); ui->locationBrowseButton->setEnabled(b); ui->locationLineEdit->setText(QDir::toNativeSeparators(location)); //update nameLineChanged(ui->nameLineEdit->text()); } bool NewFileDialog::processFile(const QString &infile, const QString &outfile) { QFile in(infile); if (!in.open(QIODevice::ReadOnly|QIODevice::Text)) { return false; } QFile out(outfile); if (!out.open(QIODevice::WriteOnly|QIODevice::Text)) { return false; } QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QString all = codec->toUnicode(in.readAll()); QMapIterator i(m_stringMap); while (i.hasNext()) { i.next(); all.replace(i.key(),i.value()); } out.write(codec->fromUnicode(all)); in.close(); out.close(); return true; } QStringList NewFileDialog::openFiles() const { return m_openFiles; } QString NewFileDialog::type() const { return m_cur.type; } QString NewFileDialog::scheme() const { return m_cur.scheme; } QString NewFileDialog::openPath() const { return m_openPath; } void NewFileDialog::on_locationBrowseButton_clicked() { QString location = ui->locationLineEdit->text(); location = QFileDialog::getExistingDirectory(this,tr("Choose a directory for the new content:"),location); if (location.isEmpty()) { return; } ui->locationLineEdit->setText(location); if (m_cur.type == "project") { m_projectLocation = location; } else if (m_cur.type == "file"){ m_fileLocation = location; } } void NewFileDialog::locationLineChanged(QString) { QString location = ui->locationLineEdit->text(); if (location.isEmpty()) { return; } if (m_cur.type == "project") { m_projectLocation = location; } else if (m_cur.type == "file"){ m_fileLocation = location; } } void NewFileDialog::nameLineChanged(QString) { if (m_cur.type == "file") { return; } QString name = ui->nameLineEdit->text(); QString location; if (m_cur.type == "gopath") { location = QFileInfo(m_gopath,"src").filePath(); } else if (m_cur.type == "project") { location = m_projectLocation; } else { location = m_fileLocation; } location = QFileInfo(location,name).absoluteFilePath(); ui->locationLineEdit->blockSignals(true); ui->locationLineEdit->setText(QDir::toNativeSeparators(location)); ui->locationLineEdit->blockSignals(false); } ================================================ FILE: liteidex/src/liteapp/newfiledialog.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: newfiledialog.h // Creator: visualfc #ifndef NEWFILEDIALOG_H #define NEWFILEDIALOG_H #include #include namespace Ui { class NewFileDialog; } class QStandardItemModel; class QStringListModel; class TemplateInfo { public: void clear() { name.clear(); author.clear(); type.clear(); info.clear(); files.clear(); open.clear(); scheme.clear(); } bool isValid() { return !name.isEmpty() && !files.isEmpty(); } QString name; QString author; QString type; QString info; QStringList files; QStringList open; QString scheme; QString dir; }; class NewFileDialog : public QDialog { Q_OBJECT public: explicit NewFileDialog(QWidget *parent = 0); ~NewFileDialog(); void setPathList(const QStringList &pathList); void setGopath(const QString &path); void setProjectLocation(const QString &path); void setFileLocation(const QString &path); void updateLocation(); virtual void accept(); bool processFile(const QString &infile, const QString &outfile); QStringList openFiles() const; QString type() const; QString scheme() const; QString openPath() const; public slots: void loadTemplate(const QString &root); void activePath(QModelIndex); void activeTemplate(QModelIndex); void nameLineChanged(QString); void locationLineChanged(QString); private slots: void on_locationBrowseButton_clicked(); private: Ui::NewFileDialog *ui; QStandardItemModel *m_templateModel; QStringListModel *m_pathModel; QString m_projectLocation; QString m_fileLocation; QString m_gopath; QString m_openPath; QStringList m_openFiles; QMap m_stringMap; TemplateInfo m_cur; }; #endif // NEWFILEDIALOG_H ================================================ FILE: liteidex/src/liteapp/newfiledialog.ui ================================================ NewFileDialog 0 0 552 403 New Project or File GOPATH: Template: Type 0 0 QFrame::Panel QFrame::Sunken Information true Name: Qt::Horizontal 40 20 Location: Browse... Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox infoLabel typeLabel buttonBox accepted() NewFileDialog accept() 248 254 157 274 buttonBox rejected() NewFileDialog reject() 316 260 286 274 ================================================ FILE: liteidex/src/liteapp/openeditorswidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: openeditorswidget.cpp // Creator: visualfc #include "openeditorswidget.h" #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end OpenEditorsWidget::OpenEditorsWidget(LiteApi::IApplication *app) : m_liteApp(app) { //m_model = new Core::ProxyModel(this); setWindowTitle(tr("Open Documents")); setDragEnabled(true); setDragDropMode(QAbstractItemView::DragOnly); setCloseButtonVisible(true); m_model = new QSortFilterProxyModel(this); this->setModel(m_model); setContextMenuPolicy(Qt::CustomContextMenu); this->setEditTriggers(QTreeView::NoEditTriggers); this->header()->setCascadingSectionResizes( true ); connect(m_liteApp->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(updateCurrentItem(LiteApi::IEditor*))); connect(this,SIGNAL(activated(QModelIndex)),this,SLOT(handleActivated(QModelIndex))); connect(this,SIGNAL(closeActivated(QModelIndex)),this,SLOT(closeDocument(QModelIndex))); connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuRequested(QPoint))); } void OpenEditorsWidget::setEditorModel(QAbstractItemModel *model) { m_model->setSourceModel(model); } void OpenEditorsWidget::handleActivated(const QModelIndex &index) { if (index.column() == 0) { activateEditor(index); } else if (index.column() == 1) { // the funky close button closeDocument(index); // work around a bug in itemviews where the delegate wouldn't get the QStyle::State_MouseOver QPoint cursorPos = QCursor::pos(); QWidget *vp = viewport(); QMouseEvent e(QEvent::MouseMove, vp->mapFromGlobal(cursorPos), cursorPos, Qt::NoButton, 0, 0); QCoreApplication::sendEvent(vp, &e); } } void OpenEditorsWidget::updateCurrentItem(LiteApi::IEditor *editor) { QModelIndex index = indexFromEditor(editor); if (!index.isValid()) { clearSelection(); return; } setCurrentIndex(index); selectionModel()->select(currentIndex(), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); scrollTo(currentIndex()); } void OpenEditorsWidget::contextMenuRequested(QPoint /*pos*/) { } void OpenEditorsWidget::activateEditor(const QModelIndex &index) { LiteApi::IEditor *editor = editorFormIndex(index); if (editor) { m_liteApp->editorManager()->setCurrentEditor(editor); } } void OpenEditorsWidget::closeDocument(const QModelIndex &index) { LiteApi::IEditor *editor = editorFormIndex(index); if (editor) { m_liteApp->editorManager()->closeEditor(editor); } updateCurrentItem(m_liteApp->editorManager()->currentEditor()); } LiteApi::IEditor *OpenEditorsWidget::editorFormIndex(const QModelIndex &index) { QString filePath = index.data(Qt::ToolTipRole).toString(); if (filePath.isEmpty()) { return 0; } return m_liteApp->editorManager()->findEditor(filePath,true); } QModelIndex OpenEditorsWidget::indexFromEditor(LiteApi::IEditor *editor) { QModelIndex r; if (!editor) { return r; } QString filePath = editor->filePath(); if (filePath.isEmpty()) { return r; } for (int i = 0; i < model()->rowCount(); i++) { QModelIndex index = model()->index(i,0); if (index.data(Qt::ToolTipRole).toString() == filePath) { return index; } } return r; } ================================================ FILE: liteidex/src/liteapp/openeditorswidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: openeditorswidget.h // Creator: visualfc #ifndef OPENEDITORSWIDGET_H #define OPENEDITORSWIDGET_H #include #include #include class QSortFilterProxyModel; class OpenEditorsWidget : public Core::OpenDocumentsTreeView { Q_OBJECT public: OpenEditorsWidget(LiteApi::IApplication *app); void setEditorModel(QAbstractItemModel *model); public slots: void handleActivated(const QModelIndex &index); void updateCurrentItem(LiteApi::IEditor *editor); void contextMenuRequested(QPoint); void activateEditor(const QModelIndex &index); void closeDocument(const QModelIndex &index); protected: LiteApi::IEditor *editorFormIndex(const QModelIndex &index); QModelIndex indexFromEditor(LiteApi::IEditor *editor); protected: LiteApi::IApplication *m_liteApp; QSortFilterProxyModel *m_model; }; #endif // OPENEDITORSWIDGET_H ================================================ FILE: liteidex/src/liteapp/optionmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: optionmanager.cpp // Creator: visualfc #include "optionmanager.h" #include "optionsbrowser.h" #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end OptionManager::OptionManager() : m_browser(0) { } OptionManager::~OptionManager() { if (m_browser) { delete m_browser; } } bool OptionManager::initWithApp(IApplication *app) { if (!IManager::initWithApp(app)) { return false; } return true; } void OptionManager::addFactory(IOptionFactory *factory) { m_factoryList.append(factory); } void OptionManager::removeFactory(IOptionFactory *factory) { m_factoryList.removeOne(factory); } QList OptionManager::factoryList() const { return m_factoryList; } void OptionManager::emitApplyOption(const QString &mimetype) { emit applyOption(mimetype); } void OptionManager::exec(const QString &mimeType) { if (!m_browser) { m_browser = new OptionsBrowser(m_liteApp,m_liteApp->mainWindow()); QRect rc = qApp->desktop()->screenGeometry(m_browser); int width = rc.width(); if (width > 900) { width = 900; } int height = rc.height(); if (height > 600) { height = 600; } m_browser->resize(width,height); connect(m_browser,SIGNAL(applyOption(QString)),this,SIGNAL(applyOption(QString))); foreach (IOptionFactory *f, m_factoryList) { QStringList mimeTypes = f->mimeTypes(); foreach (QString mimeType, mimeTypes) { IOption *opt = f->create(mimeType); if (opt) { m_browser->addOption(opt); } } } } QString last = m_liteApp->globalCookie().value("optionmanager/current").toString(); if (!mimeType.isEmpty()) { last = mimeType; } m_browser->execute(last); m_liteApp->globalCookie().insert("optionmanager/current",m_browser->currenMimeType()); } void OptionManager::loadOption(const QString &opt) { foreach (IOptionFactory *f, m_factoryList) { QStringList mimeTypes = f->mimeTypes(); foreach (QString mimeType, mimeTypes) { if (opt == mimeType) { emit applyOption(mimeType); } } } } ================================================ FILE: liteidex/src/liteapp/optionmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: optionmanager.h // Creator: visualfc #ifndef OPTIONMANAGER_H #define OPTIONMANAGER_H #include "liteapi/liteapi.h" using namespace LiteApi; class OptionsBrowser; class BrowserEditorImpl; class OptionManager : public IOptionManager { Q_OBJECT public: OptionManager(); ~OptionManager(); virtual bool initWithApp(IApplication *app); virtual void addFactory(IOptionFactory *factory); virtual void removeFactory(IOptionFactory *factory); virtual QList factoryList() const; virtual void emitApplyOption(const QString &mimetype); public slots: virtual void exec(const QString &mimeType = QString()); void loadOption(const QString &opt); protected: OptionsBrowser *m_browser; QList m_factoryList; }; #endif // OPTIONMANAGER_H ================================================ FILE: liteidex/src/liteapp/optionsbrowser.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: optionsbrowser.cpp // Creator: visualfc #include "optionsbrowser.h" #include "ui_optionswidget.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end OptionsBrowser::OptionsBrowser(LiteApi::IApplication *app, QWidget *parent) : QDialog(parent), m_liteApp(app), ui(new Ui::OptionsWidget) { ui->setupUi(this); connect(ui->listWidget,SIGNAL(itemSelectionChanged()),this,SLOT(itemSelectionChanged())); connect(ui->buttonBox,SIGNAL(clicked(QAbstractButton*)),this,SLOT(clicked(QAbstractButton*))); } OptionsBrowser::~OptionsBrowser() { delete ui; //delete m_widget; } QString OptionsBrowser::name() const { return tr("Options"); } QString OptionsBrowser::mimeType() const { return "browser/options"; } void OptionsBrowser::addOption(LiteApi::IOption *opt) { if (!opt || !opt->widget()) { return; } QListWidgetItem *item = new QListWidgetItem; item->setIcon(opt->icon()); item->setText(opt->name()); item->setTextAlignment(Qt::AlignLeft);// | Qt::AlignHCenter); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); QLayout *layout = opt->widget()->layout(); if (layout) { layout->setMargin(0); } ui->listWidget->addItem(item); ui->stackedWidget->addWidget(opt->widget()); m_widgetOptionMap.insert(item,opt); } int OptionsBrowser::execute(const QString &mimeType) { if (ui->listWidget->count() == 0) { return exec(); } QListWidgetItem *item = ui->listWidget->item(0); QMapIterator i(m_widgetOptionMap); while (i.hasNext()) { i.next(); if (i.value()->mimeType() == mimeType) { item = i.key(); break; } } ui->listWidget->setCurrentItem(item); LiteApi::IOption *opt = m_widgetOptionMap.value(item); if (opt) { //ui->scrollArea->resize(opt->widget()->size()); opt->load(); } // this->setMinimumHeight(600); //#ifdef Q_OS_MAC // this->setMinimumWidth(900); //#else // this->setMinimumWidth(800); //#endif return exec(); } QString OptionsBrowser::currenMimeType() const { QListWidgetItem *item = ui->listWidget->currentItem(); if (item) { LiteApi::IOption *opt = m_widgetOptionMap.value(item); if (opt) { return opt->mimeType(); } } return QString(); } void OptionsBrowser::itemSelectionChanged() { QListWidgetItem *item = ui->listWidget->currentItem(); if (!item) { return; } LiteApi::IOption *opt = m_widgetOptionMap.value(item); if (opt) { opt->load(); ui->stackedWidget->setCurrentWidget(opt->widget()); ui->infoLabel->setText(QString("Name : %1 MimeType : %2").arg(opt->name()).arg(opt->mimeType())); opt->widget()->updateGeometry(); } } void OptionsBrowser::clicked(QAbstractButton *button) { QDialogButtonBox::ButtonRole role = ui->buttonBox->buttonRole(button); if (role == QDialogButtonBox::AcceptRole) { this->applay(); this->accept(); } else if (role == QDialogButtonBox::RejectRole) { this->reject(); } else if (role == QDialogButtonBox::ApplyRole) { this->applay(); } } void OptionsBrowser::applay() { QListWidgetItem *item = ui->listWidget->currentItem(); if (!item) { return; } LiteApi::IOption *opt = m_widgetOptionMap.value(item); if (opt) { opt->save(); emit applyOption(opt->mimeType()); } } ================================================ FILE: liteidex/src/liteapp/optionsbrowser.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: optionsbrowser.h // Creator: visualfc #ifndef OPTIONSBROWSER_H #define OPTIONSBROWSER_H #include #include #include "liteapi/liteapi.h" namespace Ui { class OptionsWidget; } class QListWidgetItem; class QAbstractButton; class OptionsBrowser : public QDialog//LiteApi::IBrowserEditor { Q_OBJECT public: explicit OptionsBrowser(LiteApi::IApplication *app, QWidget *parent = 0); ~OptionsBrowser(); virtual QString name() const; virtual QString mimeType() const; void addOption(LiteApi::IOption *opt); int execute(const QString &mimeType); QString currenMimeType() const; signals: void applyOption(QString); protected slots: void itemSelectionChanged(); private slots: void clicked(QAbstractButton*); void applay(); private: LiteApi::IApplication *m_liteApp; Ui::OptionsWidget *ui; QMap m_widgetOptionMap; }; #endif // OPTIONSBROWSER_H ================================================ FILE: liteidex/src/liteapp/optionswidget.ui ================================================ OptionsWidget 0 0 602 304 Options true 0 0 100 0 150 16777215 QFrame::Panel QFrame::Sunken 1 Info Qt::AlignCenter 2 Qt::ScrollBarAsNeeded Qt::ScrollBarAsNeeded true 0 0 448 188 0 0 [*] item request restart of LiteIDE Qt::Horizontal 40 20 QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok listWidget ================================================ FILE: liteidex/src/liteapp/outputoption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: outputoption.cpp // Creator: visualfc #include "outputoption.h" #include "ui_outputoption.h" #include "liteapp_global.h" #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end OutputOption::OutputOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::OutputOption) { ui->setupUi(m_widget); QFontDatabase db; m_familyList = db.families(); ui->familyComboBox->addItems(m_familyList); } OutputOption::~OutputOption() { delete m_widget; delete ui; } QWidget *OutputOption::widget() { return m_widget; } QString OutputOption::name() const { return "LiteOutput"; } QString OutputOption::mimeType() const { return OPTION_LITEOUTPUT; } void OutputOption::save() { m_fontFamily = ui->familyComboBox->currentText(); if (ui->sizeComboBox->count()) { const QString curSize = ui->sizeComboBox->currentText(); bool ok = true; int size = curSize.toInt(&ok); if (ok) { m_fontSize = size; } } int fontZoom = ui->fontZoomSpinBox->value(); if (fontZoom <= 10) { fontZoom = 10; } m_liteApp->settings()->setValue(OUTPUT_FAMILY,m_fontFamily); m_liteApp->settings()->setValue(OUTPUT_FONTSIZE,m_fontSize); m_liteApp->settings()->setValue(OUTPUT_FONTZOOM,fontZoom); bool antialias = ui->antialiasCheckBox->isChecked(); m_liteApp->settings()->setValue(OUTPUT_ANTIALIAS,antialias); bool colorScheme = ui->useColorSchemeCheckBox->isChecked(); int maxLines = ui->spinBoxOutputMaxLines->value(); m_liteApp->settings()->setValue(OUTPUT_USECOLORSCHEME,colorScheme); m_liteApp->settings()->setValue(OUTPUT_MAXLINES,maxLines); } void OutputOption::load() { #if defined(Q_OS_WIN) m_fontFamily = m_liteApp->settings()->value(OUTPUT_FAMILY,"Courier").toString(); #elif defined(Q_OS_LINUX) m_fontFamily = m_liteApp->settings()->value(OUTPUT_FAMILY,"Monospace").toString(); #elif defined(Q_OS_MAC) m_fontFamily = m_liteApp->settings()->value(OUTPUT_FAMILY,"Menlo").toString(); #else m_fontFamily = m_liteApp->settings()->value(OUTPUT_FAMILY,"Monospace").toString(); #endif m_fontSize = m_liteApp->settings()->value(OUTPUT_FONTSIZE,12).toInt(); int fontZoom = m_liteApp->settings()->value(OUTPUT_FONTZOOM,100).toInt(); bool antialias = m_liteApp->settings()->value(OUTPUT_ANTIALIAS,true).toBool(); ui->antialiasCheckBox->setChecked(antialias); const int idx = m_familyList.indexOf(m_fontFamily); ui->familyComboBox->setCurrentIndex(idx); updatePointSizes(); ui->fontZoomSpinBox->setValue(fontZoom); bool useColorScheme = m_liteApp->settings()->value(OUTPUT_USECOLORSCHEME,true).toBool(); ui->useColorSchemeCheckBox->setChecked(useColorScheme); int maxLines = m_liteApp->settings()->value(OUTPUT_MAXLINES,5000).toInt(); ui->spinBoxOutputMaxLines->setValue(maxLines); } void OutputOption::updatePointSizes() { // Update point sizes const int oldSize = m_fontSize; if (ui->sizeComboBox->count()) { ui->sizeComboBox->clear(); } const QList sizeLst = pointSizesForSelectedFont(); int idx = 0; int i = 0; for (; i < sizeLst.count(); ++i) { if (idx == 0 && sizeLst.at(i) >= oldSize) idx = i; ui->sizeComboBox->addItem(QString::number(sizeLst.at(i))); } if (ui->sizeComboBox->count()) ui->sizeComboBox->setCurrentIndex(idx); } QList OutputOption::pointSizesForSelectedFont() const { QFontDatabase db; const QString familyName = ui->familyComboBox->currentText(); QList sizeLst = db.pointSizes(familyName); if (!sizeLst.isEmpty()) return sizeLst; QStringList styles = db.styles(familyName); if (!styles.isEmpty()) sizeLst = db.pointSizes(familyName, styles.first()); if (sizeLst.isEmpty()) sizeLst = QFontDatabase::standardSizes(); return sizeLst; } ================================================ FILE: liteidex/src/liteapp/outputoption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: outputoption.h // Creator: visualfc #ifndef OUTPUTOPTION_H #define OUTPUTOPTION_H #include "liteapi/liteapi.h" namespace Ui { class OutputOption; } class OutputOption : public LiteApi::IOption { Q_OBJECT public: explicit OutputOption(LiteApi::IApplication *app, QObject *parent = 0); ~OutputOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void save(); virtual void load(); void updatePointSizes(); QList pointSizesForSelectedFont() const; protected: int m_fontSize; QString m_fontFamily; QStringList m_familyList; private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::OutputOption *ui; }; #endif // OUTPUTOPTION_H ================================================ FILE: liteidex/src/liteapp/outputoption.ui ================================================ OutputOption 0 0 455 161 Form Font Family: 0 0 Size: 0 0 Zoom: % 10 1000 10 100 Antialias Qt::Horizontal 40 20 Display Use editor color scheme Sets the maximum number of lines 10 10000000 5000 Qt::Horizontal 40 20 Qt::Vertical 20 33 ================================================ FILE: liteidex/src/liteapp/pluginmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: pluginmanager.cpp // Creator: visualfc #include "pluginmanager.h" #include "pluginsdialog.h" #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end PluginManager::~PluginManager() { qDeleteAll(m_factoryList); } QList PluginManager::factoryList() { return m_factoryList; } void PluginManager::loadPlugins(const QString &dir) { if (m_bLoaded) { return; } m_bLoaded = true; QDir pluginsDir = dir; pluginsDir.setFilter(QDir::Files | QDir::NoSymLinks); QMap idIndexMap; QMap idPlguinMap; foreach (QFileInfo info, pluginsDir.entryInfoList()) { QPluginLoader loader(info.filePath()); if (IPluginFactory *factory = qobject_cast(loader.instance())) { if (factory) { factory->setFilePath(info.filePath()); idIndexMap.insert(factory->id(),0); idPlguinMap.insert(factory->id(),factory); } } } if (idIndexMap.isEmpty()) { return; } foreach(IPluginFactory *p, idPlguinMap.values()) { foreach(QString depId, p->dependPluginList()) { idIndexMap.insert(depId,idIndexMap.value(depId)-1); } } QMultiMap deps; QMapIterator i(idIndexMap); while (i.hasNext()) { i.next(); deps.insertMulti(i.value(),idPlguinMap.value(i.key())); } QList keys = deps.keys().toSet().toList(); qSort(keys); foreach(int index, keys) { foreach(IPluginFactory *p, deps.values(index)) { m_factoryList.append(p); } } } bool PluginManager::isLoaded() const { return m_bLoaded; } PluginManager::PluginManager(QObject *parent) : QObject(parent), m_bLoaded(false) { } ================================================ FILE: liteidex/src/liteapp/pluginmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: pluginmanager.h // Creator: visualfc #ifndef PLUGINMANAGER_H #define PLUGINMANAGER_H #include "liteapi/liteapi.h" using namespace LiteApi; class PluginManager : public QObject { Q_OBJECT public: PluginManager(QObject *parent = 0); virtual ~PluginManager(); QList factoryList(); void loadPlugins(const QString &dir); bool isLoaded() const; protected: bool m_bLoaded; QAction *m_aboutPluginsAct; QList m_factoryList; }; #endif // PLUGINMANAGER_H ================================================ FILE: liteidex/src/liteapp/pluginsdialog.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: pluginsdialog.cpp // Creator: visualfc #include "pluginsdialog.h" #include "ui_pluginsdialog.h" #include "pluginmanager.h" #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end PluginsDialog::PluginsDialog(LiteApi::IApplication *app, QWidget *parent) : QDialog(parent), m_liteApp(app), ui(new Ui::PluginsDialog) { ui->setupUi(this); this->setAttribute(Qt::WA_DeleteOnClose); m_model = new QStandardItemModel(0,6,this); m_model->setHeaderData(0, Qt::Horizontal, tr("Name")); m_model->setHeaderData(1, Qt::Horizontal, tr("Enabled")); m_model->setHeaderData(2, Qt::Horizontal, tr("Details")); m_model->setHeaderData(3, Qt::Horizontal, tr("Author")); m_model->setHeaderData(4, Qt::Horizontal, tr("Version")); m_model->setHeaderData(5, Qt::Horizontal, tr("File Name")); ui->treeView->setModel(m_model); ui->treeView->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->treeView->setItemsExpandable(true); ui->treeView->setRootIsDecorated(false); #if QT_VERSION >= 0x050000 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); #else ui->treeView->header()->setResizeMode(QHeaderView::ResizeToContents); #endif connect(m_model,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(itemChanged(QStandardItem*))); } PluginsDialog::~PluginsDialog() { delete ui; } void PluginsDialog::appendInfo(const LiteApi::PluginInfo *info) { if (!info) { return; } QList items; items.append(new QStandardItem(info->name())); QStandardItem *load = new QStandardItem(); load->setCheckable(true); load->setData(info->id()); if (info->isMustLoad()) { load->setEnabled(false); } bool b = m_liteApp->settings()->value(QString("liteapp/%1_load").arg(info->id()),true).toBool(); if (b) { load->setCheckState(Qt::Checked); } else { load->setCheckState(Qt::Unchecked); } items.append(load); items.append(new QStandardItem(info->info())); items.append(new QStandardItem(info->author())); items.append(new QStandardItem(info->ver())); items.append(new QStandardItem(QFileInfo(info->filePath()).fileName())); items.at(5)->setToolTip(info->filePath()); m_model->appendRow(items); } void PluginsDialog::itemChanged(QStandardItem *item) { if (item && item->isCheckable()) { QString id = item->data(Qt::UserRole+1).toString(); if (!id.isEmpty()) { m_liteApp->settings()->setValue(QString("liteapp/%1_load").arg(id),item->checkState() == Qt::Checked); } } } ================================================ FILE: liteidex/src/liteapp/pluginsdialog.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: pluginsdialog.h // Creator: visualfc #ifndef PLUGINSDIALOG_H #define PLUGINSDIALOG_H #include #include "liteapi/liteapi.h" namespace Ui { class PluginsDialog; } class QStandardItemModel; class QStandardItem; class PluginManager; class PluginsDialog : public QDialog { Q_OBJECT public: explicit PluginsDialog(LiteApi::IApplication *app, QWidget *parent = 0); ~PluginsDialog(); void appendInfo(const LiteApi::PluginInfo *info); public slots: void itemChanged(QStandardItem*); private: LiteApi::IApplication *m_liteApp; Ui::PluginsDialog *ui; QStandardItemModel *m_model; }; #endif // PLUGINSDIALOG_H ================================================ FILE: liteidex/src/liteapp/pluginsdialog.ui ================================================ PluginsDialog 0 0 712 413 Installed Plugins 0 0 Qt::Horizontal 40 20 Close closeButton clicked() PluginsDialog accept() 431 328 244 177 ================================================ FILE: liteidex/src/liteapp/projectmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: projectmanager.cpp // Creator: visualfc #include "projectmanager.h" #include "liteapp_global.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fileutil/fileutil.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ProjectManager::ProjectManager() : m_widget(0), m_folderProject(0) { } ProjectManager::~ProjectManager() { if (m_folderProject) { delete m_folderProject; } if (m_widget) { m_liteApp->toolWindowManager()->removeToolWindow(m_widget); delete m_widget; } } bool ProjectManager::initWithApp(IApplication *app) { if (!IProjectManager::initWithApp(app)) { return false; } m_widget = new QScrollArea; m_widget->setFrameShape(QFrame::NoFrame); m_widget->setWidgetResizable(true); m_folderProject = new FolderProject(m_liteApp); //m_toolWindowAct = m_liteApp->toolWindowManager()->addToolWindow(Qt::LeftDockWidgetArea,m_widget,"projects",tr("Projects"),false); connect(m_liteApp,SIGNAL(loaded()),this,SLOT(appLoaded())); m_bAutoCloseProjectEditors = m_liteApp->settings()->value(LITEAPP_AUTOCLOSEPROEJCTFILES,true).toBool(); return true; } void ProjectManager::appLoaded() { foreach (IProjectFactory *factory, this->m_factoryList) { foreach(QString type, factory->mimeTypes()) { IMimeType *mimeType = m_liteApp->mimeTypeManager()->findMimeType(type); if (mimeType && !mimeType->scheme().isEmpty()) { QAction *act = new QAction(QString(tr("Project <%1>").arg(mimeType->scheme())),this); act->setData(mimeType->scheme()); connect(act,SIGNAL(triggered()),this,SLOT(openSchemeAct())); //m_importMenu->addAction(act); } } } } QWidget *ProjectManager::widget() { return m_widget; } void ProjectManager::triggeredProject(QAction* act) { QString fileName = act->text(); m_liteApp->fileManager()->openProject(fileName); } void ProjectManager::openSchemeDialog(const QString &scheme) { static QString last = QDir::homePath(); QString dir = QFileDialog::getExistingDirectory(m_liteApp->mainWindow(), QString(tr("Import Directory <%1>").arg(scheme)), last, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if (dir.isEmpty()) { return; } last = dir; m_liteApp->fileManager()->openProjectScheme(dir,scheme); } void ProjectManager::openSchemeAct() { QAction *act = (QAction*)sender(); if (!act) { return; } QString scheme = act->data().toString(); if (scheme.isEmpty()) { return; } openSchemeDialog(scheme); } void ProjectManager::currentEditorChanged(LiteApi::IEditor* editor) { if (!editor) { return; } // QString fileName = editor->fileName(); // IProject *project = 0; // foreach (IProjectFactory *factory , m_factoryList) { // project = factory->findByEditor(editor); // if (project) { // break; // } // } // if (project) { // QAction *act = m_mapNameToAction.value(fileName); // if (act == 0) { // act = m_projectActGroup->addAction(fileName); // act->setCheckable(true); // m_mapNameToAction.insert(fileName,act); // m_projectMenu->addAction(act); // } // setCurrentProject(project); // } } IFolderProject *ProjectManager::openFolder(const QString &folderPath) { m_folderProject->openFolder(folderPath); setCurrentProject(m_folderProject); return m_folderProject; } IProject *ProjectManager::openProject(const QString &fileName, const QString &mimeType) { if (m_currentProject && m_currentProject->filePath() == fileName) { return m_currentProject; } IProject *project = 0; foreach (IProjectFactory *factory , m_factoryList) { if (factory->mimeTypes().contains(mimeType)) { project = factory->open(fileName,mimeType); if (project) { break; } } } if (project) { setCurrentProject(project); } return project; } void ProjectManager::addFactory(IProjectFactory *factory) { m_factoryList.append(factory); } void ProjectManager::removeFactory(IProjectFactory *factory) { m_factoryList.removeOne(factory); } QList ProjectManager::factoryList() const { return m_factoryList; } QStringList ProjectManager::mimeTypeList() const { QStringList types; foreach(IProjectFactory *factory, m_factoryList) { types.append(factory->mimeTypes()); } return types; } void ProjectManager::setCurrentProject(IProject *project) { if (m_currentProject) { closeProjectHelper(m_currentProject); } m_currentProject = project; if (m_currentProject) { //m_toolWindowAct->setChecked(true); m_widget->setWidget(m_currentProject->widget()); m_currentProject->load(); m_liteApp->appendLog("ProjectManager","Loaded project "+m_currentProject->name()); } emit currentProjectChanged(project); } IProject *ProjectManager::currentProject() const { return m_currentProject; } QList ProjectManager::editorList(IProject *project) const { QList editors; if (project) { foreach (QString fileName, project->filePathList()) { foreach(IEditor *editor, m_liteApp->editorManager()->editorList()) { if (FileUtil::compareFile(editor->filePath(),fileName)) { editors << editor; break; } } } } return editors; } void ProjectManager::addImportAction(QAction*) { //m_importMenu->addAction(act); } void ProjectManager::saveProject(IProject *project) { IProject *cur = 0; if (project == 0) { cur = m_currentProject; } else { cur = project; } if (cur == 0) { return; } foreach (IEditor *editor, editorList(cur)) { if (editor->isModified()) { m_liteApp->editorManager()->saveEditor(editor); } } } void ProjectManager::closeProjectHelper(IProject *project) { IProject *cur = 0; if (project) { cur = project; } else { cur = m_currentProject; } if (cur == 0) { return; } //m_widget->clear(); emit projectAboutToClose(cur); m_widget->takeWidget(); if (m_bAutoCloseProjectEditors) { foreach (IEditor *editor, editorList(cur)) { m_liteApp->editorManager()->closeEditor(editor); } } m_liteApp->appendLog("ProjectManager","Closed project "+cur->name()); if (cur != m_folderProject) { delete cur; } else if (cur && (cur == m_currentProject) ){ m_currentProject = 0; } } void ProjectManager::closeProject(IProject *project) { //m_toolWindowAct->setChecked(false); closeProjectHelper(project); emit currentProjectChanged(0); } void ProjectManager::applyOption(QString id) { if (id != OPTION_LITEAPP) { return; } m_bAutoCloseProjectEditors = m_liteApp->settings()->value(LITEAPP_AUTOCLOSEPROEJCTFILES,true).toBool(); } ================================================ FILE: liteidex/src/liteapp/projectmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: projectmanager.h // Creator: visualfc #ifndef PROJECTMANAGER_H #define PROJECTMANAGER_H #include "liteapi/liteapi.h" #include "filesystem/filesystemwidget.h" #include "folderproject.h" #include using namespace LiteApi; class QComboBox; class QStackedWidget; class QStandardItem; class QStandardItemModel; class QVBoxLayout; class QComboBox; class QStackedLayout; class QActionGroup; class QScrollArea; class ProjectManager : public IProjectManager { Q_OBJECT public: ProjectManager(); ~ProjectManager(); virtual bool initWithApp(IApplication *app); virtual IFolderProject* openFolder(const QString &folderPath); virtual IProject *openProject(const QString &fileName, const QString &mimeType); virtual void addFactory(IProjectFactory *factory); virtual void removeFactory(IProjectFactory *factory); virtual QList factoryList() const; virtual QStringList mimeTypeList() const; public: virtual void setCurrentProject(IProject *project); virtual IProject *currentProject() const; virtual QList editorList(IProject *project) const; virtual void addImportAction(QAction *act); virtual QWidget *widget(); public slots: virtual void saveProject(IProject *project = 0); virtual void closeProject(IProject *project = 0); virtual void openSchemeDialog(const QString &scheme); void currentEditorChanged(LiteApi::IEditor*); void triggeredProject(QAction* act); void openSchemeAct(); void appLoaded(); void applyOption(QString); protected: virtual void closeProjectHelper(IProject *project); protected: QPointer m_currentProject; QList m_factoryList; QScrollArea *m_widget; //QAction *m_toolWindowAct; bool m_bAutoCloseProjectEditors; FolderProject *m_folderProject; }; #endif // PROJECTMANAGER_H ================================================ FILE: liteidex/src/liteapp/recentmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: recentmanager.cpp // Creator: visualfc #include "recentmanager.h" #include "liteapp_global.h" #include "liteapi/liteids.h" #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end RecentManager::RecentManager(QObject *parent) : IRecentManager(parent) { m_maxRecentFiles = 32; } bool RecentManager::initWithApp(IApplication *app) { if (!IRecentManager::initWithApp(app)) { return false; } m_maxRecentFiles = m_liteApp->settings()->value(LITEAPP_MAXRECENTFILES,32).toInt(); m_recentMenu = m_liteApp->actionManager()->loadMenu(ID_MENU_RECENT); QAction *clearAllRecent = new QAction(tr("Clear All History"),this); m_recentSeparator = m_recentMenu->addSeparator(); m_recentMenu->addAction(clearAllRecent); connect(clearAllRecent,SIGNAL(triggered(bool)),this,SLOT(clearAllRecentMenu())); registerRecent(new FileRecent(app,this)); registerRecent(new FolderRecent(app,this)); registerRecent(new SessionRecent(app,this)); connect(m_liteApp->optionManager(),SIGNAL(applyOption(QString)),this,SLOT(applyOption(QString))); return true; } void RecentManager::registerRecent(IRecent *recent) { if (m_recentTypeList.contains(recent->type())) { return; } m_recentTypeList.append(recent->type()); m_recentList.append(recent); updateRecentMenu(recent->type()); } QList RecentManager::recentList() const { return m_recentList; } IRecent *RecentManager::findRecent(const QString &type) const { foreach (IRecent *recent, m_recentList) { if (recent->type() == type) { return recent; } } return 0; } QStringList RecentManager::recentTypeList() const { return m_recentTypeList; } void RecentManager::addRecent(const QString &name, const QString &type) { IRecent *recent = findRecent(type); if (!recent) { return; } recent->addRecent(name,m_maxRecentFiles); updateAppListRecentMenu(type); } void RecentManager::removeRecent(const QString &name, const QString &type) { IRecent *recent = findRecent(type); if (!recent) { return; } recent->removeRecent(name); updateAppListRecentMenu(type); } QStringList RecentManager::recentNameList(const QString &type) { IRecent *recent = findRecent(type); if (!recent) { return QStringList(); } return recent->recentNameList(); } void RecentManager::clearRecentNameList(const QString &type) { IRecent *recent = findRecent(type); if (!recent) { return; } recent->clearRecentNameList(); updateAppListRecentMenu(type); } void RecentManager::openRecent(const QString &name, const QString &type) { IRecent *recent = findRecent(type); if (recent) { recent->openRecent(name); } } void RecentManager::updateRecentMenu(const QString &type) { IRecent *recent = findRecent(type); if (!recent) { return; } QMenu *menu = m_mapRecentTypeMenu.value(type,0); if (!menu) { QString name = recent->displyType(); QAction *act = new QAction(name,this); m_recentMenu->insertAction(m_recentSeparator,act); menu = new QMenu(type,m_recentMenu); act->setMenu(menu); m_mapRecentTypeMenu.insert(type,menu); } if (!menu) { return; } menu->clear(); QAction *sep = menu->addSeparator(); QAction *clear = menu->addAction(tr("Clear Menu")); clear->setData(type); connect(clear,SIGNAL(triggered(bool)),this,SLOT(clearRecentMenu())); int count = 0; foreach (QString name, this->recentNameList(type)) { if (count++ > m_maxRecentFiles) { return; } QAction *act = new QAction(name,menu); menu->insertAction(sep,act); act->setData(type); connect(act,SIGNAL(triggered()),this,SLOT(openRecentAction())); } } void RecentManager::updateAppListRecentMenu(const QString &type) { foreach (IApplication *app, m_liteApp->instanceList()) { app->recentManager()->updateRecentMenu(type); ((RecentManager*)app->recentManager())->emitRecentNameListChanged(type); } } void RecentManager::emitRecentNameListChanged(const QString &type) { emit recentNameListChanged(type); } void RecentManager::applyOption(const QString &opt) { if (opt != OPTION_LITEAPP) { return; } m_maxRecentFiles = m_liteApp->settings()->value(LITEAPP_MAXRECENTFILES,32).toInt(); } void RecentManager::openRecentAction() { QAction *act = (QAction*)sender(); if (!act) { return; } QString name = act->text(); QString type = act->data().toString(); IRecent *recent = findRecent(type); if (recent) { recent->openRecent(name); } } void RecentManager::clearRecentMenu() { QAction *act = (QAction*)sender(); if (!act) { return; } QString type = act->data().toString(); clearRecentNameList(type); } void RecentManager::clearAllRecentMenu() { foreach (IRecent *recent, m_recentList) { recent->clearRecentNameList(); updateAppListRecentMenu(recent->type()); } } ================================================ FILE: liteidex/src/liteapp/recentmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: recentmanager.h // Creator: visualfc #ifndef RECENTMANAGER_H #define RECENTMANAGER_H #include "liteapi/liteapi.h" using namespace LiteApi; class RecentManager : public IRecentManager { Q_OBJECT public: RecentManager(QObject *parent = 0); virtual bool initWithApp(IApplication *app); virtual void registerRecent(IRecent *recent); virtual QList recentList() const; virtual IRecent *findRecent(const QString &type) const; virtual QStringList recentTypeList() const; virtual void addRecent(const QString &name, const QString &type); virtual void removeRecent(const QString &name, const QString &type); virtual QStringList recentNameList(const QString &type); virtual void clearRecentNameList(const QString &type); virtual void openRecent(const QString &name, const QString &type); virtual void updateRecentMenu(const QString &type); protected: void updateAppListRecentMenu(const QString &type); void emitRecentNameListChanged(const QString &type); public slots: void applyOption(const QString &opt); void openRecentAction(); void clearRecentMenu(); void clearAllRecentMenu(); protected: QStringList m_recentTypeList; QList m_recentList; int m_maxRecentFiles; QMenu *m_recentMenu; QAction *m_recentSeparator; QMap m_mapRecentTypeMenu; }; class BookmarkRecent : public ISettingRecent { Q_OBJECT public: BookmarkRecent(LiteApi::IApplication *app, QObject *parent) : ISettingRecent(app->settings(),parent), m_liteApp(app) { } virtual QString type() const { return "bookmark"; } virtual QString displyType() const { return tr("Bookmarks"); } virtual void addRecent(const QString &name,int maxRecent) { ISettingRecent::addRecent(QDir::toNativeSeparators(name), maxRecent); } virtual void openRecent(const QString &name) { int pos = name.lastIndexOf(":"); if (pos == -1) { return; } bool ok = false; int line = name.mid(pos+1).toInt(&ok); if (!ok) { return; } QString filePath = name.left(pos); LiteApi::IEditor *editor = m_liteApp->fileManager()->openEditor(filePath,true,false); if (!editor) { return; } LiteApi::ITextEditor *textEditor = LiteApi::getTextEditor(editor); if (!textEditor) { return; } textEditor->gotoLine(line,0,true); } protected: virtual QString recentKey() const { return QString("Bookmark/%1").arg(type()); } LiteApi::IApplication *m_liteApp; }; class FileRecent : public ISettingRecent { Q_OBJECT public: FileRecent(LiteApi::IApplication *app, QObject *parent) : ISettingRecent(app->settings(),parent), m_liteApp(app) { } virtual QString type() const { return "file"; } virtual QString displyType() const { return tr("Files"); } virtual void addRecent(const QString &name,int maxRecent) { ISettingRecent::addRecent(QDir::toNativeSeparators(name), maxRecent); } virtual void openRecent(const QString &name) { m_liteApp->fileManager()->openFile(name); } protected: LiteApi::IApplication *m_liteApp; }; class FolderRecent : public ISettingRecent { Q_OBJECT public: FolderRecent(LiteApi::IApplication *app, QObject *parent) : ISettingRecent(app->settings(),parent), m_liteApp(app) { } virtual QString type() const { return "folder"; } virtual QString displyType() const { return tr("Folders"); } virtual void addRecent(const QString &name,int maxRecent) { ISettingRecent::addRecent(QDir::toNativeSeparators(name), maxRecent); } virtual void openRecent(const QString &name) { m_liteApp->fileManager()->addFolderList(name); } protected: LiteApi::IApplication *m_liteApp; }; class SessionRecent : public ISettingRecent { Q_OBJECT public: SessionRecent(LiteApi::IApplication *app, QObject *parent) : ISettingRecent(app->settings(),parent), m_liteApp(app) { } virtual QString type() const { return "session"; } virtual QString displyType() const { return tr("Sessions"); } virtual void addRecent(const QString &name, int maxRecent) { QString key = recentKey(); QStringList files = m_settings->value(key).toStringList(); files.removeAll(name); files.prepend(name); while (files.size() > maxRecent) { files.removeLast(); } m_settings->setValue(key, files); } virtual void removeRecent(const QString &name) { if (name == "default") { return; } ISettingRecent::removeRecent(name); } virtual QStringList recentNameList() { QString key = recentKey(); QStringList values = m_settings->value(key).toStringList(); values.prepend("default"); values.removeDuplicates(); return values; } virtual void clearRecentNameList() { QString key = recentKey(); QStringList values = m_settings->value(key).toStringList(); values.clear(); values.append("default"); m_settings->setValue(key, values); } virtual void openRecent(const QString &name) { if (name != m_liteApp->currentSession()) { m_liteApp->newInstance(name); } else { m_liteApp->loadSession(name); } } protected: LiteApi::IApplication *m_liteApp; }; #endif // RECENTMANAGER_H ================================================ FILE: liteidex/src/liteapp/rotationtoolbutton.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: rotationtoolbutton.cpp // Creator: visualfc #include "rotationtoolbutton.h" #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static const int Vertical_Mask = 0x02; RotationToolButton::RotationToolButton(QWidget *parent) : QToolButton(parent), rot(NoRotation) { } void RotationToolButton::setRotation(Rotation rotation) { if (rot != rotation) { rot = rotation; switch (rotation) { case NoRotation: case UpsideDown: setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); break; case Clockwise: case CounterClockwise: setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); break; default: break; } updateGeometry(); update(); } } RotationToolButton::Rotation RotationToolButton::rotation() const { return rot; } QSize RotationToolButton::sizeHint() const { QSize size; size = QToolButton::sizeHint(); if (rot & Vertical_Mask) size.transpose(); return size; } QSize RotationToolButton::minimumSizeHint() const { return sizeHint(); } void RotationToolButton::paintEvent(QPaintEvent*) { QStylePainter painter(this); painter.rotate(rot); switch (rot) { case UpsideDown: painter.translate(-width(), -height()); break; case Clockwise: painter.translate(0, -width()); break; case CounterClockwise: painter.translate(-height(), 0); break; default: // nothing to do break; } QStyleOptionToolButton opt; initStyleOption(&opt); if (rot & Vertical_Mask) { QSize size = opt.rect.size(); size.transpose(); opt.rect.setSize(size); } painter.drawComplexControl(QStyle::CC_ToolButton, opt); } ================================================ FILE: liteidex/src/liteapp/rotationtoolbutton.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: rotationtoolbutton.h // Creator: visualfc #ifndef ROTATIONTOOLBUTTON_H #define ROTATIONTOOLBUTTON_H #include class RotationToolButton : public QToolButton { Q_OBJECT public: enum Rotation { NoRotation = 0, UpsideDown = 180, Clockwise = 90, CounterClockwise = 270 }; explicit RotationToolButton(QWidget *parent = 0); void setRotation(Rotation rotation); Rotation rotation() const; QSize sizeHint() const; QSize minimumSizeHint() const; protected: void paintEvent(QPaintEvent *); protected: Rotation rot; }; #endif // ROTATIONTOOLBUTTON_H ================================================ FILE: liteidex/src/liteapp/sidewindowstyle.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: sidewindowstyle.cpp // Creator: visualfc #include "sidewindowstyle.h" #include "tooldockwidget.h" #include "rotationtoolbutton.h" #include "liteapp_global.h" #include "liteapi/liteids.h" #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end SideDockWidget::SideDockWidget(QSize iconSize, QWidget *parent) : BaseDockWidget(iconSize,parent) { } void SideDockWidget::createMenu(Qt::DockWidgetArea area) { m_area = area; m_moveMenu = new QMenu(tr("Move To"),this); QAction *sideAct = new QAction(this); if (area == Qt::LeftDockWidgetArea) { sideAct->setText(tr("RightSideBar")); sideAct->setData(Qt::RightDockWidgetArea); m_areaInfo = tr("LeftDockWidgt"); } else { sideAct->setText(tr("LeftSideBar")); sideAct->setData(Qt::LeftDockWidgetArea); m_areaInfo = tr("RightDockWidget"); } m_moveMenu->addAction(sideAct); QAction *outAct = new QAction(tr("OutputBar"),this); outAct->setData(Qt::BottomDockWidgetArea); m_moveMenu->addAction(outAct); connect(sideAct,SIGNAL(triggered()),this,SLOT(moveAction())); connect(outAct,SIGNAL(triggered()),this,SLOT(moveAction())); m_menu = new QMenu(this); QToolButton *btn = new QToolButton(m_toolBar); btn->setPopupMode(QToolButton::InstantPopup); btn->setIcon(QIcon("icon:images/movemenu.png")); btn->setMenu(m_menu); btn->setText(tr("SideBar")); btn->setToolTip(tr("Show SideBar")); btn->setStyleSheet("QToolButton::menu-indicator {image: none;}"); m_toolBar->insertWidget(m_closeAct,btn); } void SideDockWidget::moveAction() { QAction *action = static_cast(sender()); if (!action) { return; } this->setFloatingWindow(false); Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt(); emit moveActionTo(m_area,area,current); } void SideDockWidget::actionChanged() { } void SideDockWidget::activeComboBoxIndex(int index) { if (index < 0 || index >= m_comboBox->count()) { return; } QString objName = m_comboBox->itemData(index).toString(); foreach(QAction *act, m_actions) { if (act->objectName() == objName) { QAction *org = current.data(); current = act; emit currenActionChanged(org,act); break; } } } void SideDockWidget::topLevelChanged(bool b) { BaseDockWidget::topLevelChanged(b); if (b) { m_comboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); m_spacer->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum); } else { m_comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); m_spacer->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Minimum); } } void SideDockWidget::setCheckedAction(QAction *action) { current = action; for (int i = 0; i < m_comboBox->count(); i++) { if (m_comboBox->itemData(i).toString() == action->objectName()) { m_comboBox->setCurrentIndex(i); //m_titleLabel->setText(m_comboBox->currentText()); break; } } } static bool actionThan(const QAction *s1, const QAction *s2) { return s1->text() < s2->text(); } void SideDockWidget::setActions(const QMap &m) { m_actions = m.keys(); m_comboBox->clear(); int cur = 0; int index = 0; m_menu->clear(); // QMapIterator i(m); QList keys = m.keys(); qSort(keys.begin(),keys.end(),actionThan); for (int i = 0; i < keys.size(); i++) { QAction *act = keys[i]; m_comboBox->addItem(m.value(act)->title,act->objectName()); m_menu->addAction(act); if (current && (current->objectName() == act->objectName())) { cur = index; } index++; } // while(i.hasNext()) { // i.next(); // QAction *act = i.key(); // m_comboBox->addItem(i.value()->title,act->objectName()); // m_menu->addAction(act); // if (current && (current->objectName() == act->objectName())) { // cur = index; // } // index++; // } m_menu->addSeparator(); m_menu->addAction(m_floatAct); m_menu->addMenu(m_moveMenu); m_comboBox->setCurrentIndex(cur); } void SideDockWidget::setWindowTitle(const QString &text) { BaseDockWidget::setWindowTitle(m_areaInfo+" - "+text); } SideActionBar::SideActionBar(QSize iconSize, QMainWindow *window, Qt::DockWidgetArea area) : BaseActionBar(window), m_iconSize(iconSize), m_window(window),m_area(area), m_bHideToolBar(false) { m_toolBar = new QToolBar; m_toolBar->hide(); m_toolBar->setObjectName(QString("side_tool_%1").arg(m_area)); m_toolBar->setMovable(false); // QWidget *spacer = new QWidget; // spacer->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); // spacerAct = toolBar->addWidget(spacer); // toolBar->addSeparator(); } SideActionBar::~SideActionBar() { qDeleteAll(m_actionStateMap); } void SideActionBar::addAction(QAction *action, QWidget *widget, const QString &id, const QString &title, QList widgetActions, QList widgetList) { RotationToolButton *btn = new RotationToolButton; btn->setDefaultAction(action); if (m_area == Qt::LeftDockWidgetArea) { btn->setRotation(RotationToolButton::CounterClockwise); } else if (m_area == Qt::RightDockWidgetArea) { btn->setRotation(RotationToolButton::Clockwise); } SideDockWidget *dock = new SideDockWidget(m_iconSize, m_window); dock->setObjectName(dockWidgetObjName(id)); dock->setWindowTitle(title); dock->setAllowedAreas(m_area); dock->setFeatures(QDockWidget::DockWidgetClosable); dock->hide(); dock->createMenu(m_area); m_window->addDockWidget(m_area,dock); connect(dock,SIGNAL(visibilityChanged(bool)),this,SLOT(dockVisible(bool))); connect(dock,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*)),this,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*))); connect(dock,SIGNAL(currenActionChanged(QAction*,QAction*)),this,SLOT(currenActionChanged(QAction*,QAction*))); SideActionState *state = new SideActionState; state->toolBtn = btn; state->widget = widget; state->id = id; state->title = title; state->widgetActions = widgetActions; state->widgetList = widgetList; m_actionStateMap.insert(action,state); dock->setCheckedAction(action); //toolBar->insertWidget(spacerAct,btn); m_toolBar->addWidget(btn); if (m_toolBar->isHidden() && !m_bHideToolBar) { m_toolBar->show(); } m_dockList.append(dock); connect(action,SIGNAL(toggled(bool)),this,SLOT(toggledAction(bool))); //update actions foreach(SideDockWidget *dock, m_dockList) { dock->setActions(m_actionStateMap); } } void SideActionBar::removeAction(QAction *action) { for (int i = 0; i < m_dockList.size(); i++) { SideDockWidget *dock = m_dockList[i]; if (dock->checkedAction() == action) { dock->hide(); m_window->removeDockWidget(dock); m_dockList.removeAt(i); m_toolBar->removeAction(action); dock->deleteLater(); break; } } SideActionState *state = m_actionStateMap.value(action); if (state) { delete state->toolBtn; } m_actionStateMap.remove(action); delete state; foreach(SideDockWidget *dock, m_dockList) { dock->setActions(m_actionStateMap); } if (m_actionStateMap.isEmpty()) { m_toolBar->hide(); } } void SideActionBar::setHideToolBar(bool b) { m_bHideToolBar = b; if (m_bHideToolBar) { m_toolBar->hide(); } else { m_toolBar->show(); } } QAction *SideActionBar::findToolAction(QWidget *widget) const { QMapIterator i(m_actionStateMap); while (i.hasNext()) { i.next(); if (i.value()->widget == widget) { return i.key(); } } return 0; } void SideActionBar::dockVisible(bool b) { SideDockWidget *dock = (SideDockWidget*)sender(); QAction *action = dock->checkedAction(); if (action) { action->setChecked(dock->isVisible()); } else if (b && !dock->actions().isEmpty()) { dock->actions().first()->setChecked(true); } } QString SideActionBar::dockWidgetObjName(const QString &id) const { return QString("side_dock_x_%1").arg(id); } void SideActionBar::updateAction(QAction *action) { SideActionState *state = m_actionStateMap.value(action); foreach (SideDockWidget *dock, m_dockList) { if (dock->checkedAction() == action) { if (action->isChecked()) { if (dock->isHidden()) { dock->show(); } dock->setWidget(state->widget); if (!state->widgetList.isEmpty()) { dock->setWidgetList(state->widgetList); } else { dock->setWidgetActions(state->widgetActions); } dock->setObjectName(dockWidgetObjName(state->id)); dock->setWindowTitle(state->title); state->widget->setVisible(true); } else { dock->hide(); state->widget->setVisible(false); } break; } } } void SideActionBar::setShowToolBar(bool visible) { if (!visible) { m_toolBar->hide(); } else if (!m_actionStateMap.isEmpty()) { m_toolBar->show(); } } void SideActionBar::toggledAction(bool) { QAction *action = (QAction*)sender(); updateAction(action); } void SideActionBar::currenActionChanged(QAction *org, QAction *act) { if (org == act) { return; } SideDockWidget *curDock = (SideDockWidget*)sender(); foreach (SideDockWidget *dock, m_dockList) { if ((dock->checkedAction() == act) && (dock != curDock)) { dock->setCheckedAction(org); org->setChecked(act->isChecked()); updateAction(org); break; } } curDock->setCheckedAction(act); act->setChecked(true); updateAction(act); } OutputActionBar::OutputActionBar(QSize iconSize, QMainWindow *window, Qt::DockWidgetArea _area) : BaseActionBar(window), m_area(_area), m_bHideToolBar(false) { m_toolBar = new QToolBar; m_toolBar->hide(); m_toolBar->setObjectName(QString("side_tool_%1").arg(m_area)); m_toolBar->setMovable(false); // QWidget *spacer = new QWidget; // spacer->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); // spacerAct = toolBar->addWidget(spacer); // toolBar->addSeparator(); m_dock = new OutputDockWidget(iconSize, window); m_dock->setObjectName(QString("side_dock_%1").arg(m_area)); m_dock->setWindowTitle(QString("side_dock_%1").arg(m_area)); m_dock->setFeatures(QDockWidget::DockWidgetClosable); m_dock->hide(); m_dock->createMenu(m_area); window->addDockWidget(m_area,m_dock); connect(m_dock,SIGNAL(visibilityChanged(bool)),this,SLOT(dockVisible(bool))); connect(m_dock,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*)),this,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*))); } OutputActionBar::~OutputActionBar() { qDeleteAll(m_actionStateMap); } OutputDockWidget *OutputActionBar::dockWidget() const { return m_dock; } void OutputActionBar::addAction(QAction *action, QWidget *widget, const QString &id, const QString &title, QList widgetActions, QList widgetList) { RotationToolButton *btn = new RotationToolButton; btn->setDefaultAction(action); if (m_area == Qt::LeftDockWidgetArea) { btn->setRotation(RotationToolButton::CounterClockwise); } else if (m_area == Qt::RightDockWidgetArea) { btn->setRotation(RotationToolButton::Clockwise); } SideActionState *state = new SideActionState; state->toolBtn = btn; state->widget = widget; state->id = id; state->title = title; state->widgetActions = widgetActions; state->widgetList = widgetList; m_actionStateMap.insert(action,state); m_dock->addAction(action,title); //toolBar->insertWidget(spacerAct,btn); m_toolBar->addWidget(btn); if (m_toolBar->isHidden() && !m_bHideToolBar) { m_toolBar->show(); } connect(action,SIGNAL(toggled(bool)),this,SLOT(toggledAction(bool))); } void OutputActionBar::removeAction(QAction *action) { if (action->isChecked()) { action->setChecked(false); } SideActionState *state = m_actionStateMap.value(action); if (state) { delete state->toolBtn; } m_dock->removeAction(action); m_actionStateMap.remove(action); delete state; if (m_dock->actions().isEmpty()) { m_toolBar->hide(); } } void OutputActionBar::setHideToolBar(bool b) { m_bHideToolBar = b; if (m_bHideToolBar) { m_toolBar->hide(); } else { if (!m_dock->actions().isEmpty()){ m_toolBar->show(); } } } QAction *OutputActionBar::findToolAction(QWidget *widget) const { QMapIterator i(m_actionStateMap); while (i.hasNext()) { i.next(); if (i.value()->widget == widget) { return i.key(); } } return 0; } void OutputActionBar::dockVisible(bool b) { QAction *action = m_dock->checkedAction(); if (action) { action->setChecked(m_dock->isVisible()); } else if (b && !m_dock->actions().isEmpty()) { // m_dock->actions().first()->setChecked(true) int index = m_dock->currentIndex(); if (index >= 0 && index < m_dock->actions().size()) { m_dock->actions()[index]->setChecked(true); } } } void OutputActionBar::toggledAction(bool) { QAction *action = (QAction*)sender(); SideActionState *state = m_actionStateMap.value(action); if (!state) { return; } if (action->isChecked()) { if (m_dock->isHidden()) { m_dock->show(); } m_dock->setWidget(state->widget); if (!state->widgetList.isEmpty()) { m_dock->setWidgetList(state->widgetList); } else { m_dock->setWidgetActions(state->widgetActions); } m_dock->setWindowTitle(state->title); state->widget->setVisible(true); } else { if (!m_dock->checkedAction()) { m_dock->hide(); state->widget->setVisible(false); } } } SideWindowStyle::SideWindowStyle(LiteApi::IApplication *app, QMainWindow *window, QObject *parent) : IWindowStyle(parent),m_liteApp(app),m_mainWindow(window) { QSize iconSize = LiteApi::getToolBarIconSize(app); m_leftSideBar = new SideActionBar(iconSize,window,Qt::LeftDockWidgetArea); m_rightSideBar = new SideActionBar(iconSize,window,Qt::RightDockWidgetArea); m_outputBar = new OutputActionBar(iconSize,window,Qt::BottomDockWidgetArea); connect(m_leftSideBar,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*)),this,SLOT(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*))); connect(m_rightSideBar,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*)),this,SLOT(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*))); connect(m_outputBar,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*)),this,SLOT(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*))); m_actionBarMap[Qt::LeftDockWidgetArea] = m_leftSideBar; m_actionBarMap[Qt::RightDockWidgetArea] = m_rightSideBar; m_actionBarMap[Qt::BottomDockWidgetArea] = m_outputBar; m_mainWindow->addToolBar(Qt::LeftToolBarArea,m_leftSideBar->toolBar()); m_mainWindow->addToolBar(Qt::RightToolBarArea,m_rightSideBar->toolBar()); m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea,m_outputBar->dockWidget()); m_mainWindow->setDockNestingEnabled(true); m_mainWindow->setDockOptions(QMainWindow::AllowNestedDocks); m_statusBar = new QStatusBar; m_hideSideAct = new QAction(tr("Hide SideBar"),this); m_hideSideAct->setIcon(QIcon("icon:images/hidesidebar.png")); m_hideSideAct->setCheckable(true); QToolButton *btn = new QToolButton; btn->setDefaultAction(m_hideSideAct); btn->setStyleSheet("QToolButton {border:0}" "QToolButton:checked {background : qlineargradient(spread:pad, x1:0, y1:1, x2:1, y2:0, stop:0 rgba(55, 57, 59, 255), stop:1 rgba(255, 255, 255, 255));}"); m_statusBar->addWidget(btn); m_statusBar->setContentsMargins(0,0,0,0); m_statusBar->addWidget(m_outputBar->toolBar(),1); m_mainWindow->setStatusBar(m_statusBar); //m_mainWindow->addToolBar(Qt::BottomToolBarArea,m_outputBar->toolBar); m_sideMenu = 0; m_outputMenu = 0; connect(m_hideSideAct,SIGNAL(toggled(bool)),this,SLOT(hideSideBar(bool))); m_useShortcuts = m_liteApp->settings()->value(LITEAPP_TOOLWINDOW_SHORTCUTS,true).toBool(); } SideWindowStyle::~SideWindowStyle() { delete m_sideMenu; delete m_outputMenu; delete m_leftSideBar; delete m_rightSideBar; } void SideWindowStyle::createToolWindowMenu() { QMenu *menu = m_liteApp->actionManager()->loadMenu(ID_MENU_VIEW); if (menu) { menu->addAction(m_hideSideAct); m_sideMenu = menu->addMenu(tr("SideBar Windows")); m_outputMenu = menu->addMenu(tr("Output Windows")); } LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(m_liteApp,"App"); actionContext->regAction(m_hideSideAct,"HideSideBar",LiteApi::UseMacShortcuts?"Ctrl+Alt+0":"Alt+0"); } void SideWindowStyle::restoreHideToolWindows() { foreach(QAction *action,m_hideActionList) { action->setChecked(true); } m_hideActionList.clear(); } void SideWindowStyle::restoreHideSideToolWindows() { foreach(QAction *action,m_hideSideActionList) { action->setChecked(true); } m_hideSideActionList.clear(); m_leftSideBar->setShowToolBar(true); m_rightSideBar->setShowToolBar(true); } void SideWindowStyle::hideSideToolWindows() { m_hideSideActionList.clear(); foreach(QAction *action, m_leftSideBar->actionMap().keys()) { if (action->isChecked()) { m_hideSideActionList.append(action); action->setChecked(false); } } foreach(QAction *action, m_rightSideBar->actionMap().keys()) { if (action->isChecked()) { m_hideSideActionList.append(action); action->setChecked(false); } } m_leftSideBar->setShowToolBar(false); m_rightSideBar->setShowToolBar(false); } void SideWindowStyle::hideAllToolWindows() { m_hideActionList.clear(); foreach(QAction *action, m_leftSideBar->actionMap().keys()) { if (action->isChecked()) { m_hideActionList.append(action); action->setChecked(false); } } foreach(QAction *action, m_rightSideBar->actionMap().keys()) { if (action->isChecked()) { m_hideActionList.append(action); action->setChecked(false); } } foreach(QAction *action, m_outputBar->actionMap().keys()) { if (action->isChecked()) { m_hideActionList.append(action); action->setChecked(false); } } } void SideWindowStyle::hideSideBar(bool b) { if (b) { hideSideToolWindows(); } else { restoreHideSideToolWindows(); } } void SideWindowStyle::toggledSideBar(bool b) { if (b) { m_hideSideAct->setChecked(false); } } void SideWindowStyle::showOrHideToolWindow() { bool hide = false; foreach(QAction *action, m_leftSideBar->actionMap().keys()) { if (action->isChecked()) { hide = true; break; } } foreach(QAction *action, m_rightSideBar->actionMap().keys()) { if (action->isChecked()) { hide = true; break; } } if (hide) { hideAllToolWindows(); } else { restoreHideToolWindows(); } } void SideWindowStyle::hideOutputWindow() { foreach(QAction *act, m_outputBar->actionMap().keys()) { if (act->isChecked()) { act->setChecked(false); } } } void SideWindowStyle::saveToolState() const { m_liteApp->settings()->setValue("side_side_hide",m_hideSideAct->isChecked()); } void SideWindowStyle::restoreToolsState() { m_hideSideAct->setChecked(m_liteApp->settings()->value("side_side_hide").toBool()); } void SideWindowStyle::updateConer() { m_mainWindow->setCorner(Qt::BottomLeftCorner,Qt::LeftDockWidgetArea); m_mainWindow->setCorner(Qt::BottomRightCorner,Qt::RightDockWidgetArea); } void SideWindowStyle::moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action, bool /*split*/) { if (from == to) { return; } BaseActionBar *fromBar = m_actionBarMap[from]; BaseActionBar *toBar = m_actionBarMap[to]; if (!fromBar || !toBar) { return; } SideActionState *state = fromBar->actionMap().value(action); QWidget *widget = state->widget; QString id = state->id; QString title = state->title; QList widgetActions = state->widgetActions; QWidgetList widgetList = state->widgetList; fromBar->removeAction(action); toBar->addAction(action,widget,id,title,widgetActions,widgetList); action->setChecked(true); //save m_liteApp->settings()->setValue("sidebar_area/"+action->objectName(),to); if (from == Qt::BottomDockWidgetArea && to != Qt::BottomDockWidgetArea) { m_outputMenu->removeAction(action); m_sideMenu->addAction(action); action->setText(title); if (m_useShortcuts) { int index = m_leftSideBar->actionMap().size()+m_rightSideBar->actionMap().size(); if (index <= 9) { action->setText(QString("%1: %2").arg(index).arg(title)); QKeySequence ks(QString("Ctrl+Alt+%1").arg(index)); LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(m_liteApp,"App"); actionContext->regAction(action,"ToolWindow_"+id,ks.toString()); } else { LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(m_liteApp,"App"); actionContext->regAction(action,"ToolWindow_"+id,""); } } } else if (from != Qt::BottomDockWidgetArea && to == Qt::BottomDockWidgetArea) { m_sideMenu->removeAction(action); m_outputMenu->addAction(action); action->setText(title); if (m_useShortcuts) { int index = m_outputBar->actionMap().size(); if (index <= 9) { action->setText(QString("%1: %2").arg(index).arg(title)); #ifdef Q_OS_MAC QKeySequence ks(QString("Ctrl+Meta+%1").arg(index)); #else QKeySequence ks(QString("Ctrl+Shift+%1").arg(index)); #endif LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(m_liteApp,"App"); actionContext->regAction(action,"ToolWindow_"+id,ks.toString()); } else { LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(m_liteApp,"App"); actionContext->regAction(action,"ToolWindow_"+id,""); } } } } void SideWindowStyle::moveActionTo(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action) { this->moveToolWindow(from,to,action,false); } QAction *SideWindowStyle::findToolWindow(QWidget *widget) { QAction *act = m_leftSideBar->findToolAction(widget); if (act) { return act; } act = m_rightSideBar->findToolAction(widget); if (act) { return act; } return m_outputBar->findToolAction(widget); } void SideWindowStyle::removeToolWindow(QAction */*action*/) { } QAction *SideWindowStyle::addToolWindow(LiteApi::IApplication *app, Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool /*split*/, QList widgetActions, QList widgetList) { QAction *action = new QAction(this); action->setText(title); action->setCheckable(true); action->setObjectName(id); area = (Qt::DockWidgetArea)m_liteApp->settings()->value("sidebar_area/"+id,area).toInt(); if (area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) { m_outputBar->addAction(action,widget,id,title,widgetActions,widgetList); int index = m_outputBar->actionMap().size(); action->setText(title); if ((index <= 9) && m_useShortcuts) { action->setText(QString("%1: %2").arg(index).arg(title)); //QKeySequence ks(LiteApi::UseMacShortcuts?QString("Ctrl+Alt+%1").arg(index):QString("Alt+%1").arg(index)); #ifdef Q_OS_MAC QKeySequence ks(QString("Ctrl+Meta+%1").arg(index)); #else QKeySequence ks(QString("Ctrl+Shift+%1").arg(index)); #endif LiteApi::IActionContext *actionContext = app->actionManager()->getActionContext(app,"App"); actionContext->regAction(action,"ToolWindow_"+id,ks.toString()); } if (m_outputMenu) { m_outputMenu->addAction(action); } } else { SideActionBar *sideBar = (area == Qt::LeftDockWidgetArea) ? m_leftSideBar : m_rightSideBar; sideBar->addAction(action,widget,id,title,widgetActions,widgetList); int index = m_leftSideBar->actionMap().size()+m_rightSideBar->actionMap().size(); action->setText(title); if ((index <= 9) && m_useShortcuts) { action->setText(QString("%1: %2").arg(index).arg(title)); //QKeySequence ks(LiteApi::UseMacShortcuts?QString("Ctrl+Alt+%1").arg(index):QString("Ctrl+Alt+%1").arg(index)); QKeySequence ks(QString("Ctrl+Alt+%1").arg(index)); LiteApi::IActionContext *actionContext = app->actionManager()->getActionContext(app,"App"); actionContext->regAction(action,"ToolWindow_"+id,ks.toString()); } connect(action,SIGNAL(toggled(bool)),this,SLOT(toggledSideBar(bool))); if (m_sideMenu) { m_sideMenu->addAction(action); } } return action; } ================================================ FILE: liteidex/src/liteapp/sidewindowstyle.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: sidewindowstyle.h // Creator: visualfc #ifndef SIDEWINDOWSTYLE_H #define SIDEWINDOWSTYLE_H #include "windowstyle.h" #include "tooldockwidget.h" class SideDockWidget; class OutputDockWidget; class QToolButton; struct SideActionState { QWidget *toolBtn; QWidget *widget; QList widgetList; QList widgetActions; QString id; QString title; }; class SideDockWidget : public BaseDockWidget { Q_OBJECT public: explicit SideDockWidget(QSize iconSize, QWidget *parent = 0); void createMenu(Qt::DockWidgetArea area); void setCheckedAction(QAction *action); void setActions(const QMap &m); virtual void setWindowTitle(const QString &text); signals: void moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea, QAction*); void currenActionChanged(QAction *org, QAction *act); protected slots: void moveAction(); void actionChanged(); virtual void activeComboBoxIndex(int); virtual void topLevelChanged(bool b); protected: QMenu *m_menu; QMenu *m_moveMenu; Qt::DockWidgetArea m_area; QString m_areaInfo; }; class BaseActionBar : public QObject { Q_OBJECT public: BaseActionBar(QObject *parent) : QObject(parent) {} virtual void addAction(QAction *action, QWidget *widget, const QString &id, const QString &title, QList widgetActions, QList widgetList) = 0; virtual void removeAction(QAction *action) = 0; virtual QAction *findToolAction(QWidget *widget) const = 0; virtual QToolBar *toolBar() const = 0; virtual QMap actionMap() const = 0; }; class SideActionBar : public BaseActionBar { Q_OBJECT public: SideActionBar(QSize iconSize, QMainWindow *window, Qt::DockWidgetArea area); virtual ~SideActionBar(); void addAction(QAction *action, QWidget *widget, const QString &id, const QString &title, QList widgetActions, QList widgetList); void removeAction(QAction *action); QAction *findToolAction(QWidget *widget) const; virtual QToolBar *toolBar() const { return m_toolBar; } virtual QMap actionMap() const { return m_actionStateMap; } void updateAction(QAction *action); void setShowToolBar(bool visible); signals: void moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*); protected slots: void setHideToolBar(bool b); void dockVisible(bool); void toggledAction(bool b); void currenActionChanged(QAction *org, QAction *act); protected: QSize m_iconSize; QMainWindow *m_window; Qt::DockWidgetArea m_area; QToolBar *m_toolBar; //QAction *spacerAct; QList m_dockList; QMap m_actionStateMap; bool m_bHideToolBar; QString dockWidgetObjName(const QString &id) const; }; class OutputActionBar : public BaseActionBar { Q_OBJECT public: OutputActionBar(QSize iconSize, QMainWindow *window, Qt::DockWidgetArea m_area = Qt::BottomDockWidgetArea); virtual ~OutputActionBar(); OutputDockWidget *dockWidget() const; void addAction(QAction *action, QWidget *widget, const QString &id, const QString &title, QList widgetActions, QList widgetList); void removeAction(QAction *action); void setHideToolBar(bool b); virtual QAction *findToolAction(QWidget *widget) const; virtual QToolBar *toolBar() const { return m_toolBar; } virtual QMap actionMap() const { return m_actionStateMap; } signals: void moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*); protected slots: void dockVisible(bool); void toggledAction(bool b); protected: Qt::DockWidgetArea m_area; QToolBar *m_toolBar; // QAction *spacerAct; OutputDockWidget *m_dock; QMap m_actionStateMap; bool m_bHideToolBar; }; class SideWindowStyle : public IWindowStyle { Q_OBJECT public: SideWindowStyle(LiteApi::IApplication *app, QMainWindow *window, QObject *parent = 0); ~SideWindowStyle(); virtual void createToolWindowMenu(); virtual QAction *addToolWindow(LiteApi::IApplication *app, Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split = false, QList widgetActions = QList(), QList widgetList = QList()); virtual void removeToolWindow(QAction *action); virtual QAction *findToolWindow(QWidget *widget); virtual void moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action, bool split); virtual void saveToolState() const; virtual void restoreToolsState(); virtual void updateConer(); void restoreHideToolWindows(); void restoreHideSideToolWindows(); void hideSideToolWindows(); public slots: void moveActionTo(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction*action); virtual void hideOutputWindow(); virtual void showOrHideToolWindow(); virtual void hideAllToolWindows(); void hideSideBar(bool); void toggledSideBar(bool); protected: LiteApi::IApplication *m_liteApp; QMainWindow *m_mainWindow; SideActionBar *m_leftSideBar; SideActionBar *m_rightSideBar; OutputActionBar *m_outputBar; QMap m_actionBarMap; QStatusBar *m_statusBar; QAction *m_hideSideAct; QList m_hideActionList; QList m_hideSideActionList; QMenu *m_sideMenu; QMenu *m_outputMenu; bool m_useShortcuts; }; #endif // SIDEWINDOWSTYLE_H ================================================ FILE: liteidex/src/liteapp/splitfolderwindow.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2018 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: splitfolderwindow.cpp // Creator: visualfc #include "splitfolderwindow.h" #include "symboltreeview/symboltreeview.h" #include "liteapp_global.h" #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end SplitFolderWindow::SplitFolderWindow(IApplication *app, QObject *parent) : IFolderWindow(parent), m_liteApp(app) { m_spliter = new QSplitter(Qt::Vertical); m_tree = new SplitFolderView(app); m_tree->setHeaderHidden(true); m_tree->setRootIsDecorated(false); m_stacked = new QStackedWidget(); m_spliter->addWidget(m_tree); m_spliter->addWidget(m_stacked); m_spliter->setStretchFactor(0,0); m_spliter->setStretchFactor(1,1); m_filters = QDir::AllDirs | QDir::Files | QDir::Drives | QDir::Readable| QDir::Writable | QDir::Executable /*| QDir::Hidden*/ | QDir::NoDotAndDotDot; m_bShowDetails = false; m_bSyncEditor = false; connect(m_tree,SIGNAL(currentIndexChanged(QModelIndex,QModelIndex)),this,SLOT(currentIndexChanged(QModelIndex,QModelIndex))); connect(m_tree,SIGNAL(aboutToShowContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo)),this,SLOT(aboutToShowFolderContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo))); connect(m_tree,SIGNAL(closeFolderIndex(QModelIndex)),this,SLOT(closeFolderIndex(QModelIndex))); connect(m_tree,SIGNAL(reloadFolderIndex(QModelIndex)),this,SLOT(reloadFolderIndex(QModelIndex))); connect(m_liteApp->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*))); QByteArray state = m_liteApp->settings()->value("LiteApp/BoxFolderSplitter").toByteArray(); m_spliter->restoreState(state); } SplitFolderWindow::~SplitFolderWindow() { m_liteApp->settings()->setValue("LiteApp/BoxFolderSplitter",m_spliter->saveState()); delete m_spliter; } QString SplitFolderWindow::id() const { return "folderwindow/splitfolder"; } QWidget *SplitFolderWindow::widget() const { return m_spliter; } QStringList SplitFolderWindow::folderList() const { return m_folderList; } void SplitFolderWindow::setFolderList(const QStringList &folders) { foreach (QString folder, folders) { addFolderImpl(folder); } } void SplitFolderWindow::addFolderList(const QString &folder) { addFolderImpl(folder); } void SplitFolderWindow::closeAllFolders() { m_folderList.clear(); m_tree->clear(); int count = m_stacked->count(); while (count) { count--; QWidget *widget = m_stacked->widget(count); m_stacked->removeWidget(widget); delete widget; } } void SplitFolderWindow::currentIndexChanged(const QModelIndex &index, const QModelIndex &/*prev*/) { int row = findInStacked(index); if (row == -1) { return; } QString folder = index.data(Qt::UserRole+1).toString(); if (!QFileInfo(folder).exists()) { m_tree->closeFolder(); return; } FolderView *widget = (FolderView*)m_stacked->widget(row); if (widget->filter() != m_filters) { widget->setFilter(m_filters); } if (widget->isShowDetails() != m_bShowDetails) { widget->setShowDetails(m_bShowDetails); } m_stacked->setCurrentIndex(row); } void SplitFolderWindow::closeFolderIndex(const QModelIndex &index) { int row = findInStacked(index); if (row == -1) { return; } QWidget *widget = m_stacked->widget(row); m_stacked->removeWidget(widget); delete widget; m_folderList.removeAt(row); } void SplitFolderWindow::reloadFolderIndex(const QModelIndex &index) { int row = findInStacked(index); if (row == -1) { return; } FolderView *widget = (FolderView*)m_stacked->widget(row); widget->reload(); } void SplitFolderWindow::setShowHideFiles(bool b) { if (b) { m_filters |= QDir::Hidden; } else if (m_filters.testFlag(QDir::Hidden)) { m_filters ^= QDir::Hidden; } FolderView *widget = (FolderView*)m_stacked->currentWidget(); if (!widget) { return; } if (widget->filter() != m_filters) { widget->setFilter(m_filters); } } void SplitFolderWindow::setShowDetails(bool b) { m_bShowDetails = b; FolderView *widget = (FolderView*)m_stacked->currentWidget(); if (!widget) { return; } if (widget->isShowDetails() != b) { widget->setShowDetails(b); } } void SplitFolderWindow::setSyncEditor(bool b) { m_bSyncEditor = b; if (b) { this->currentEditorChanged(m_liteApp->editorManager()->currentEditor()); } } void SplitFolderWindow::currentEditorChanged(IEditor *editor) { if (!editor || !m_bSyncEditor) { return; } QString filePath = editor->filePath(); if (filePath.isEmpty()) { return; } filePath = QDir::toNativeSeparators(filePath); FolderView *widget = (FolderView*)m_stacked->currentWidget(); if (widget) { QModelIndex index = widget->indexForPath(filePath); if (index.isValid()) { widget->scrollTo(index); widget->clearSelection(); widget->setCurrentIndex(index); return; } } int count = m_folderList.count(); for (int i = 0; i < count; i++) { QString folder = m_folderList.at(i); if (!QFileInfo(folder).exists()) { continue; } FolderView *widget = (FolderView*)m_stacked->widget(i); QModelIndex index = widget->indexForPath(filePath); if (index.isValid()) { widget->scrollTo(index); widget->clearSelection(); widget->setCurrentIndex(index); m_tree->setCurrentIndex(m_tree->model()->index(i,0)); m_stacked->setCurrentIndex(i); return; } } } void SplitFolderWindow::doubleClickedFolderView(const QModelIndex &index) { if (!index.isValid()) { return; } FolderView *view = (FolderView*)(sender()); QFileInfo info = view->fileInfo(index); if (info.isFile()) { m_liteApp->fileManager()->openEditor(info.filePath()); } } void SplitFolderWindow::enterKeyPressedFolderView(const QModelIndex &index) { if (!index.isValid()) { return; } FolderView *view = (FolderView*)(sender()); QFileInfo info = view->fileInfo(index); if (info.isFile()) { m_liteApp->fileManager()->openEditor(info.filePath()); } else { view->setExpanded(index,!view->isExpanded(index)); } } void SplitFolderWindow::addFolderImpl(const QString &_folder) { QString folder = QDir::toNativeSeparators(_folder); if (m_folderList.contains(folder)) { return; } if (!QDir(folder).exists()) { return; } FolderView *view = new FolderView(true,m_liteApp); view->setFilter(m_filters); view->setShowDetails(m_bShowDetails); view->setRootPath(folder); connect(view,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedFolderView(QModelIndex))); connect(view,SIGNAL(enterKeyPressed(QModelIndex)),this,SLOT(enterKeyPressedFolderView(QModelIndex))); connect(view,SIGNAL(aboutToShowContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo)),this,SLOT(aboutToShowFolderContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo))); m_stacked->addWidget(view); m_folderList.append(folder); m_tree->addRootPath(folder); m_liteApp->recentManager()->addRecent(folder,"folder"); } int SplitFolderWindow::findInStacked(const QModelIndex &index) { if (!index.isValid()) { return -1; } QString folder = index.data(Qt::UserRole+1).toString(); return m_folderList.indexOf(folder); } void SplitFolderWindow::aboutToShowFolderContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info) { m_liteApp->fileManager()->emitAboutToShowFolderContextMenu(menu,flag,info,"liteapp/folder"); } SplitFolderView::SplitFolderView(IApplication *app, QWidget *parent) : BaseFolderView(app,parent) { m_model = new QStandardItemModel(this); this->setModel(m_model); m_contextMenu = new QMenu(); this->setContextMenuPolicy(Qt::CustomContextMenu); connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(customContextMenuRequested(QPoint))); } void SplitFolderView::addRootPath(const QString &folder) { QStandardItem *item = new QStandardItem(folder); item->setData(folder,Qt::UserRole+1); item->setToolTip(folder); m_model->appendRow(item); this->setCurrentIndex(m_model->indexFromItem(item)); } void SplitFolderView::clear() { m_model->clear(); } void SplitFolderView::openFolder() { m_liteApp->fileManager()->openFolder(); } void SplitFolderView::closeFolder() { QModelIndex index = this->currentIndex(); if (!index.isValid()) { return; } emit closeFolderIndex(index); m_model->removeRow(index.row()); } void SplitFolderView::reloadFolder() { QModelIndex index = this->currentIndex(); if (!index.isValid()) { return; } emit reloadFolderIndex(index); } void SplitFolderView::customContextMenuRequested(const QPoint &pos) { QModelIndex index = this->currentIndex(); if (!index.isValid()) { return; } QString dir = index.data(Qt::UserRole+1).toString(); QFileInfo fileInfo(dir); m_contextMenu->clear(); m_contextInfo = fileInfo; LiteApi::FILESYSTEM_CONTEXT_FLAG flag = LiteApi::FILESYSTEM_ROOTFOLDER; m_contextMenu->addAction(m_openInNewWindowAct); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_newFileAct); m_contextMenu->addAction(m_newFileWizardAct); m_contextMenu->addAction(m_newFolderAct); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_openFolderAct); m_contextMenu->addAction(m_reloadFolderAct); m_contextMenu->addAction(m_closeFolderAct); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_copyFullPathToClipboardAct); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_openExplorerAct); m_contextMenu->addAction(m_openShellAct); m_contextMenu->addAction(m_openTerminalAct); emit aboutToShowContextMenu(m_contextMenu,flag,m_contextInfo); m_contextMenu->exec(this->mapToGlobal(pos)); } ================================================ FILE: liteidex/src/liteapp/splitfolderwindow.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2018 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: splitfolderwindow.h // Creator: visualfc #ifndef SPLITFOLDERWINDOW_H #define SPLITFOLDERWINDOW_H #include "filemanager.h" #include "folderview/folderview.h" class QStackedWidget; class QTreeWidget; class QSplitter; class QStandardItemModel; class SplitFolderView; class SplitFolderWindow : public IFolderWindow { Q_OBJECT public: SplitFolderWindow(LiteApi::IApplication *app, QObject *parent = 0); virtual ~SplitFolderWindow(); virtual QString id() const; virtual QWidget *widget() const; virtual QStringList folderList() const; virtual void setFolderList(const QStringList &folders); virtual void addFolderList(const QString &folder); virtual void closeAllFolders(); virtual void setShowHideFiles(bool b); virtual void setShowDetails(bool b); virtual void setSyncEditor(bool b); public slots: void currentIndexChanged(const QModelIndex &index,const QModelIndex &prev); void closeFolderIndex(const QModelIndex &index); void reloadFolderIndex(const QModelIndex &index); void currentEditorChanged(LiteApi::IEditor *editor); void doubleClickedFolderView(const QModelIndex &index); void enterKeyPressedFolderView(const QModelIndex &index); void aboutToShowFolderContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info); protected: LiteApi::IApplication *m_liteApp; QSplitter *m_spliter; SplitFolderView *m_tree; QStandardItemModel *m_model; QStackedWidget *m_stacked; QStringList m_folderList; QDir::Filters m_filters; bool m_bShowDetails; bool m_bSyncEditor; protected: void addFolderImpl(const QString &folder); int findInStacked(const QModelIndex &index); }; class SplitFolderView : public BaseFolderView { Q_OBJECT public: SplitFolderView(LiteApi::IApplication *app, QWidget *parent = 0); void addRootPath(const QString &folder); void clear(); signals: void closeFolderIndex(const QModelIndex &index); void reloadFolderIndex(const QModelIndex &index); public slots: void customContextMenuRequested(const QPoint &pos); virtual void openFolder(); virtual void closeFolder(); virtual void reloadFolder(); protected: QStandardItemModel *m_model; QMenu *m_contextMenu; }; #endif // SPLITFOLDERWINDOW_H ================================================ FILE: liteidex/src/liteapp/splitwindowstyle.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: splitwindowstyle.cpp // Creator: visualfc #include "splitwindowstyle.h" #include "rotationtoolbutton.h" #include "tooldockwidget.h" #include "liteapp_global.h" #include "liteapi/liteids.h" #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ActionGroup::ActionGroup(QObject *parent) : QObject(parent) { current = 0; } QList ActionGroup::actions() const { return m_actions; } void ActionGroup::addAction(QAction *action) { if(!m_actions.contains(action)) { m_actions.append(action); QObject::connect(action, SIGNAL(changed()), this, SLOT(actionChanged())); } if (current && current->isChecked()) { current->setChecked(false); } if (action->isChecked()) { current = action; } } void ActionGroup::removeAction(QAction *action) { if (m_actions.removeAll(action)) { if (action == current) current = 0; QObject::disconnect(action, SIGNAL(changed()), this, SLOT(actionChanged())); } } QAction * ActionGroup::checkedAction () const { return current; } void ActionGroup::actionChanged() { QAction *action = qobject_cast(sender()); Q_ASSERT_X(action != 0, "ActionGroup::actionChanged", "internal error"); if (action->isChecked()) { if (action != current) { if(current) current->setChecked(false); current = action; } } else if (action == current) { current = 0; } } SplitActionToolBar::SplitActionToolBar(QSize iconSize, QWidget *parent, Qt::DockWidgetArea _area) : QObject(parent), area(_area), bHideToolBar(false) { toolBar = new QToolBar; toolBar->hide(); toolBar->setObjectName(QString("tool_%1").arg(area)); toolBar->setMovable(false); QWidget *spacer = new QWidget; spacer->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); spacerAct = toolBar->addWidget(spacer); toolBar->addSeparator(); QWidget *spacer2 = new QWidget; spacer2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); toolBar->addWidget(spacer2); dock1 = new SplitDockWidget(iconSize, parent); dock1->setObjectName(QString("dock_%1").arg(area)); dock1->setWindowTitle(QString("dock_%1").arg(area)); dock1->setFeatures(QDockWidget::DockWidgetClosable); dock1->hide(); dock1->createMenu(area,false); dock2 = new SplitDockWidget(iconSize,parent); dock2->setObjectName(QString("dock_%1_split").arg(area)); dock2->setWindowTitle(QString("dock_%1_split").arg(area)); dock2->setFeatures(QDockWidget::DockWidgetClosable); dock2->hide(); dock2->createMenu(area,true); connect(dock1,SIGNAL(visibilityChanged(bool)),this,SLOT(dock1Visible(bool))); connect(dock2,SIGNAL(visibilityChanged(bool)),this,SLOT(dock2Visible(bool))); connect(dock1,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*,bool)),this,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*,bool))); connect(dock2,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*,bool)),this,SIGNAL(moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*,bool))); } SplitDockWidget *SplitActionToolBar::dock(bool split) const { return split?dock2:dock1; } void SplitActionToolBar::addAction(QAction *action, const QString &title, bool split) { RotationToolButton *btn = new RotationToolButton; btn->setDefaultAction(action); if (area == Qt::LeftDockWidgetArea) { btn->setRotation(RotationToolButton::CounterClockwise); } else if (area == Qt::RightDockWidgetArea) { btn->setRotation(RotationToolButton::Clockwise); } m_actionWidgetMap.insert(action,btn); if (split) { dock2->addAction(action,title); toolBar->addWidget(btn); } else { dock1->addAction(action,title); toolBar->insertWidget(spacerAct,btn); } if (toolBar->isHidden() && !bHideToolBar) { toolBar->show(); } } void SplitActionToolBar::removeAction(QAction *action, bool split) { QWidget *widget = m_actionWidgetMap.value(action); if (widget) { delete widget; } m_actionWidgetMap.remove(action); if (split) { dock2->removeAction(action); } else { dock1->removeAction(action); } if (dock1->actions().isEmpty() && dock2->actions().isEmpty()) { toolBar->hide(); } } void SplitActionToolBar::setHideToolBar(bool b) { bHideToolBar = b; if (bHideToolBar) { toolBar->hide(); } else { if (!dock1->actions().isEmpty() || !dock2->actions().isEmpty()){ toolBar->show(); } } } void SplitActionToolBar::dock1Visible(bool b) { QAction *action = dock1->checkedAction(); if (action) { action->setChecked(dock1->isVisible()); } else if (b && !dock1->actions().isEmpty()) { dock1->actions().first()->setChecked(true); } } void SplitActionToolBar::dock2Visible(bool b) { QAction *action = dock2->checkedAction(); if (action) { action->setChecked(dock2->isVisible()); } else if (b && !dock2->actions().isEmpty()) { dock2->actions().first()->setChecked(true); } } SplitWindowStyle::SplitWindowStyle(LiteApi::IApplication *app, QMainWindow *window, QObject *parent) : IWindowStyle(parent), m_liteApp(app), m_mainWindow(window) { QSize iconSize = LiteApi::getToolBarIconSize(app); m_areaToolBar.insert(Qt::TopDockWidgetArea,new SplitActionToolBar(iconSize, m_mainWindow,Qt::TopDockWidgetArea)); m_areaToolBar.insert(Qt::BottomDockWidgetArea,new SplitActionToolBar(iconSize, m_mainWindow,Qt::BottomDockWidgetArea)); m_areaToolBar.insert(Qt::LeftDockWidgetArea,new SplitActionToolBar(iconSize, m_mainWindow,Qt::LeftDockWidgetArea)); m_areaToolBar.insert(Qt::RightDockWidgetArea,new SplitActionToolBar(iconSize, m_mainWindow,Qt::RightDockWidgetArea)); QMapIterator it(m_areaToolBar); while(it.hasNext()) { it.next(); Qt::DockWidgetArea area = it.key(); SplitActionToolBar *actionToolBar = it.value(); m_mainWindow->addToolBar((Qt::ToolBarArea)area,actionToolBar->toolBar); m_mainWindow->addDockWidget(area,actionToolBar->dock1); m_mainWindow->addDockWidget(area,actionToolBar->dock2); if (area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) m_mainWindow->splitDockWidget(actionToolBar->dock1,actionToolBar->dock2,Qt::Horizontal); else m_mainWindow->splitDockWidget(actionToolBar->dock1,actionToolBar->dock2,Qt::Vertical); connect(actionToolBar,SIGNAL(moveActionTo(Qt::DockWidgetArea, Qt::DockWidgetArea,QAction*,bool)),this,SLOT(moveToolWindow(Qt::DockWidgetArea, Qt::DockWidgetArea,QAction*,bool))); } m_mainWindow->setDockNestingEnabled(true); m_mainWindow->setDockOptions(QMainWindow::AllowNestedDocks); m_statusBar = new QStatusBar; m_hideSideAct = new QAction(tr("Hide Sidebars"),this); m_hideSideAct->setIcon(QIcon("icon:images/hidesidebar.png")); m_hideSideAct->setCheckable(true); QToolButton *btn = new QToolButton; btn->setDefaultAction(m_hideSideAct); btn->setStyleSheet("QToolButton {border:0}" "QToolButton:checked {background : qlineargradient(spread:pad, x1:0, y1:1, x2:1, y2:0, stop:0 rgba(55, 57, 59, 255), stop:1 rgba(255, 255, 255, 255));}"); m_statusBar->addWidget(btn); m_statusBar->setContentsMargins(0,0,0,0); SplitActionToolBar *bar = m_areaToolBar.value(Qt::BottomDockWidgetArea); if (bar) { m_statusBar->addWidget(bar->toolBar,1); } m_mainWindow->setStatusBar(m_statusBar); m_windowMenu = 0; connect(m_hideSideAct,SIGNAL(toggled(bool)),this,SLOT(hideSideBar(bool))); m_useShortcuts = m_liteApp->settings()->value(LITEAPP_TOOLWINDOW_SHORTCUTS,true).toBool(); } SplitWindowStyle::~SplitWindowStyle() { qDeleteAll(m_actStateMap); } void SplitWindowStyle::createToolWindowMenu() { QMenu *menu = m_liteApp->actionManager()->loadMenu(ID_MENU_VIEW); if (menu) { m_windowMenu = menu->addMenu(tr("Tool Windows")); } } void SplitWindowStyle::toggledAction(bool) { QAction *action = static_cast(sender()); if (!action) { return; } SplitActionState *state = m_actStateMap.value(action); if (!state) { return; } SplitDockWidget *dock = m_areaToolBar.value(state->area)->dock(state->split); if (action->isChecked()) { if (dock->isHidden()) { dock->show(); } dock->setWidget(state->widget); if (!state->widgetList.isEmpty()) { dock->setWidgetList(state->widgetList); } else { dock->setWidgetActions(state->widgetActions); } dock->setWindowTitle(state->title); state->widget->setVisible(true); } else { if (!dock->checkedAction()) { dock->hide(); state->widget->setVisible(false); } } } QAction *SplitWindowStyle::findToolWindow(QWidget *widget) { QMapIterator it(m_actStateMap); while (it.hasNext()) { it.next(); if (it.value()->widget == widget) { return it.key(); } } return NULL; } void SplitWindowStyle::removeToolWindow(QAction *action) { SplitActionState *state = m_actStateMap.value(action); if (!state) { return; } if (action->isChecked()) { action->setChecked(false); } SplitActionToolBar *actToolBar = m_areaToolBar.value(state->area); if (actToolBar) { actToolBar->removeAction(action,state->split); } } QAction *SplitWindowStyle::addToolWindow(LiteApi::IApplication *app,Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split, QList widgetActions, QList widgetList) { // QMap::iterator it = m_initIdStateMap.find(id); // if (it != m_initIdStateMap.end()) { // area = it.value().area; // split = it.value().split; // } area = (Qt::DockWidgetArea)m_liteApp->settings()->value("split_area/"+id,area).toInt(); split = m_liteApp->settings()->value("split_split/"+id,split).toBool(); SplitActionToolBar *actToolBar = m_areaToolBar.value(area); QAction *action = new QAction(this); action->setText(title); action->setCheckable(true); action->setObjectName(id); SplitActionState *state = new SplitActionState; state->area = area; state->split = split; state->widget = widget; state->widgetList = widgetList; state->widgetActions = widgetActions; state->id = id; state->title = title; actToolBar->addAction(action,title,split); action->setText(title); int index = m_actStateMap.size(); if ((index <= 9) && m_useShortcuts) { action->setText(QString("%1: %2").arg(index).arg(title)); QKeySequence ks(LiteApi::UseMacShortcuts?QString("Ctrl+Alt+%1").arg(index):QString("Alt+%1").arg(index)); LiteApi::IActionContext *actionContext = app->actionManager()->getActionContext(app,"App"); actionContext->regAction(action,"ToolWindow_"+id,ks.toString()); } m_actStateMap.insert(action,state); connect(action,SIGNAL(toggled(bool)),this,SLOT(toggledAction(bool))); if (m_windowMenu) { m_windowMenu->addAction(action); } return action; } void SplitWindowStyle::moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action, bool split) { SplitActionState *state = m_actStateMap.value(action); if (!state) { return; } if (state->area == to && state->split == split) { return; } SplitActionToolBar *actionToolBar = m_areaToolBar.value(to); SplitActionToolBar *oldActToolBar = m_areaToolBar.value(from); if (action->isChecked()) { action->setChecked(false); } oldActToolBar->removeAction(action,state->split); actionToolBar->addAction(action,state->title,split); state->area = to; state->split = split; action->setChecked(true); } void SplitWindowStyle::restoreToolWindows() { foreach(QAction *action,m_hideActionList) { action->setChecked(true); } m_hideActionList.clear(); } void SplitWindowStyle::showOrHideToolWindow() { bool hide = false; foreach(QAction *action, m_actStateMap.keys()) { if (action->isChecked()) { hide = true; break; } } if (hide) { hideAllToolWindows(); } else { restoreToolWindows(); } } void SplitWindowStyle::hideAllToolWindows() { m_hideActionList.clear(); foreach(QAction *action, m_actStateMap.keys()) { if (action->isChecked()) { m_hideActionList.append(action); action->setChecked(false); } } } void SplitWindowStyle::hideOutputWindow() { this->hideToolWindow(Qt::TopDockWidgetArea); this->hideToolWindow(Qt::BottomDockWidgetArea); } void SplitWindowStyle::hideSideBar(bool b) { QMapIterator it(m_areaToolBar); while (it.hasNext()) { it.next(); if (it.key() != Qt::BottomDockWidgetArea) { it.value()->setHideToolBar(b); } } } void SplitWindowStyle::saveToolState() const { QMapIterator i(m_actStateMap); while (i.hasNext()) { i.next(); SplitActionState *state = i.value(); m_liteApp->settings()->setValue("split_area/"+state->id,state->area); m_liteApp->settings()->setValue("split_split/"+state->id,state->split); m_liteApp->settings()->setValue("split_check/"+state->id,i.key()->isChecked()); } m_liteApp->settings()->setValue("split_side_hide",m_hideSideAct->isChecked()); } void SplitWindowStyle::restoreToolsState() { m_hideSideAct->setChecked(m_liteApp->settings()->value("split_side_hide").toBool()); } void SplitWindowStyle::updateConer() { m_mainWindow->setCorner(Qt::BottomLeftCorner,Qt::LeftDockWidgetArea); m_mainWindow->setCorner(Qt::BottomRightCorner,Qt::RightDockWidgetArea); } void SplitWindowStyle::hideToolWindow(Qt::DockWidgetArea area) { SplitActionToolBar *bar = m_areaToolBar.value(area); if (bar) { bar->dock1->close(); bar->dock2->close(); } } ================================================ FILE: liteidex/src/liteapp/splitwindowstyle.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: splitwindowstyle.h // Creator: visualfc #ifndef SPLITWINDOWSSTYLE_H #define SPLITWINDOWSSTYLE_H #include "windowstyle.h" #include #include #include class ActionGroup; class QSplitter; class RotationToolButton; class SplitDockWidget; class ActionGroup : public QObject { Q_OBJECT public: ActionGroup(QObject *parent); QList actions() const; void addAction(QAction *act); void removeAction(QAction *act); QAction * checkedAction () const; protected slots: void actionChanged(); protected: QList m_actions; QPointer current; }; class SplitActionToolBar : public QObject { Q_OBJECT public: SplitActionToolBar(QSize iconSize, QWidget *parent, Qt::DockWidgetArea area); SplitDockWidget *dock(bool split) const; void addAction(QAction *action, const QString &title, bool split); void removeAction(QAction *action, bool split); void setHideToolBar(bool b); signals: void moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea,QAction*,bool); protected slots: void dock1Visible(bool); void dock2Visible(bool); public: Qt::DockWidgetArea area; QToolBar *toolBar; QAction *spacerAct; SplitDockWidget *dock1; SplitDockWidget *dock2; QMap m_actionWidgetMap; bool bHideToolBar; }; struct SplitActionState { QWidget *widget; QList widgetList; QList widgetActions; Qt::DockWidgetArea area; bool split; QString id; QString title; }; class SplitWindowStyle : public IWindowStyle { Q_OBJECT public: SplitWindowStyle(LiteApi::IApplication *app, QMainWindow *window, QObject *parent = 0); ~SplitWindowStyle(); virtual void createToolWindowMenu(); virtual QAction *addToolWindow(LiteApi::IApplication *app, Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split = false, QList widgetActions = QList(), QList widgetList = QList() ); virtual void removeToolWindow(QAction *action); virtual QAction *findToolWindow(QWidget *wiget); virtual void saveToolState() const; virtual void restoreToolsState(); virtual void updateConer(); public slots: void hideToolWindow(Qt::DockWidgetArea area = Qt::BottomDockWidgetArea); void showOrHideToolWindow(); void hideAllToolWindows(); void hideOutputWindow(); void restoreToolWindows(); void hideSideBar(bool b); void moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action,bool split = false); protected slots: void toggledAction(bool); protected: LiteApi::IApplication *m_liteApp; QMainWindow *m_mainWindow; QMap m_areaToolBar; QMap m_actStateMap; QStatusBar *m_statusBar; QAction *m_hideSideAct; QMenu *m_windowMenu; QList m_hideActionList; bool m_useShortcuts; }; #endif // SPLITWINDOWSSTYLE_H ================================================ FILE: liteidex/src/liteapp/textbrowserhtmlwidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: textbrowserhtmlwidget.cpp // Creator: visualfc #include "textbrowserhtmlwidget.h" #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end TextBrowserHtmlWidget::TextBrowserHtmlWidget(QObject *parent) : IHtmlWidget(parent) { m_widget = new QTextBrowser; m_widget->setOpenLinks(false); m_widget->setOpenExternalLinks(false); connect(m_widget,SIGNAL(anchorClicked(QUrl)),this,SIGNAL(linkClicked(QUrl))); connect(m_widget,SIGNAL(highlighted(QUrl)),this,SIGNAL(linkHovered(QUrl))); } QWidget *TextBrowserHtmlWidget::widget() const { return m_widget; } QString TextBrowserHtmlWidget::className() const { return QLatin1String("QTextBrowser"); } void TextBrowserHtmlWidget::setSearchPaths(const QStringList &paths) { m_widget->setSearchPaths(paths); } void TextBrowserHtmlWidget::setHtml(const QString &html, const QUrl &url) { m_widget->setHtml(html); m_url = url; if (!url.isEmpty()) { QString file = url.toLocalFile(); if (!file.isEmpty()) { QFileInfo info(file); QStringList paths = m_widget->searchPaths(); paths.append(info.path()); paths.removeDuplicates(); m_widget->setSearchPaths(paths); } } emit contentsSizeChanged(); emit loadFinished(true); } QUrl TextBrowserHtmlWidget::url() const { return m_url; } void TextBrowserHtmlWidget::clear() { m_widget->clear(); } void TextBrowserHtmlWidget::scrollToAnchor(const QString &anchor) { m_widget->scrollToAnchor(anchor); emit anchorChanged(anchor); } void TextBrowserHtmlWidget::setScrollBarValue(Qt::Orientation orientation, int value) { if (orientation == Qt::Horizontal) { m_widget->horizontalScrollBar()->setValue(value); } else { m_widget->verticalScrollBar()->setValue(value); } } int TextBrowserHtmlWidget::scrollBarValue(Qt::Orientation orientation) const { if (orientation == Qt::Horizontal) { return m_widget->horizontalScrollBar()->value(); } return m_widget->verticalScrollBar()->value(); } int TextBrowserHtmlWidget::scrollBarMinimum(Qt::Orientation orientation) const { if (orientation == Qt::Horizontal) { return m_widget->horizontalScrollBar()->minimum(); } return m_widget->verticalScrollBar()->minimum(); } int TextBrowserHtmlWidget::scrollBarMaximum(Qt::Orientation orientation) const { if (orientation == Qt::Horizontal) { return m_widget->horizontalScrollBar()->maximum(); } return m_widget->verticalScrollBar()->maximum(); } QString TextBrowserHtmlWidget::selectedText() const { return m_widget->textCursor().selectedText(); } bool TextBrowserHtmlWidget::findText(const QString &exp, QTextDocument::FindFlags options) { QTextDocument *doc = m_widget->document(); if (!doc) { return false; } QTextCursor cursor = m_widget->cursorForPosition(QPoint(0,0)); int from = cursor.position(); if (cursor.hasSelection()) { if (options & QTextDocument::FindBackward) { from = cursor.selectionStart(); } else { from = cursor.selectionEnd(); } } QTextCursor find; find = doc->find(exp,from,options); if (!find.isNull()) { m_widget->setTextCursor(find); m_widget->ensureCursorVisible(); return true; } return false; } #ifndef QT_NO_PRINTER void TextBrowserHtmlWidget::print(QPrinter *printer) { m_widget->print(printer); } #endif TextBrowserHtmlWidgetFactory::TextBrowserHtmlWidgetFactory(QObject *parent) : IHtmlWidgetFactory(parent) { } QString TextBrowserHtmlWidgetFactory::className() const { return "QTextBrowser"; } IHtmlWidget *TextBrowserHtmlWidgetFactory::create(QObject *parent) { return new TextBrowserHtmlWidget(parent); } IHtmlDocument *TextBrowserHtmlWidgetFactory::createDocument(QObject *parent) { return new TextBrowserHtmlDocument(parent); } TextBrowserHtmlDocument::TextBrowserHtmlDocument(QObject *parent) : IHtmlDocument(parent) { m_doc = new QTextBrowser; m_doc->setVisible(false); } TextBrowserHtmlDocument::~TextBrowserHtmlDocument() { delete m_doc; } void TextBrowserHtmlDocument::setHtml(const QString &html, const QUrl &url) { m_doc->setHtml(html); if (!url.isEmpty()) { QString file = url.toLocalFile(); if (!file.isEmpty()) { QFileInfo info(file); QStringList paths = m_doc->searchPaths(); paths.append(info.path()); paths.removeDuplicates(); m_doc->setSearchPaths(paths); } } emit loadFinished(true); } #ifndef QT_NO_PRINTER void TextBrowserHtmlDocument::print(QPrinter *printer) { m_doc->print(printer); } #endif QString TextBrowserHtmlDocument::toHtml() const { return m_doc->toHtml(); } QString TextBrowserHtmlDocument::toPlainText() const { return m_doc->toPlainText(); } ================================================ FILE: liteidex/src/liteapp/textbrowserhtmlwidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: textbrowserhtmlwidget.h // Creator: visualfc #ifndef TEXTBROWSERHTMLWIDGET_H #define TEXTBROWSERHTMLWIDGET_H #include "liteapi/litehtml.h" using namespace LiteApi; class QTextBrowser; class TextBrowserHtmlWidget : public IHtmlWidget { Q_OBJECT public: TextBrowserHtmlWidget(QObject *parent); public: virtual QWidget *widget() const; virtual QString className() const; virtual void setSearchPaths(const QStringList &paths); virtual void setHtml(const QString &html, const QUrl &url); virtual QUrl url() const; virtual void clear(); virtual void scrollToAnchor(const QString &anchor); virtual void setScrollBarValue(Qt::Orientation orientation, int value) ; virtual int scrollBarValue(Qt::Orientation orientation) const; virtual int scrollBarMinimum(Qt::Orientation orientation) const; virtual int scrollBarMaximum(Qt::Orientation orientation) const; virtual QString selectedText() const; virtual bool findText(const QString & exp, QTextDocument::FindFlags options); public slots: #ifndef QT_NO_PRINTER virtual void print(QPrinter *printer); #endif protected: QTextBrowser *m_widget; QUrl m_url; }; class TextBrowserHtmlDocument : public IHtmlDocument { Q_OBJECT public: TextBrowserHtmlDocument(QObject *parent); virtual ~TextBrowserHtmlDocument(); public: virtual void setHtml(const QString &html, const QUrl &url); public slots: #ifndef QT_NO_PRINTER virtual void print(QPrinter *printer); #endif virtual QString toHtml () const; virtual QString toPlainText () const; protected: QTextBrowser *m_doc; }; class TextBrowserHtmlWidgetFactory : public IHtmlWidgetFactory { Q_OBJECT public: TextBrowserHtmlWidgetFactory(QObject *parent = 0); virtual QString className() const; virtual IHtmlWidget *create(QObject *parent); virtual IHtmlDocument *createDocument(QObject *parent); }; #endif // TEXTBROWSERHTMLWIDGET_H ================================================ FILE: liteidex/src/liteapp/tooldockwidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: tooldockwidget.cpp // Creator: visualfc #include "tooldockwidget.h" #include "liteapi/liteapi.h" #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end BaseDockWidget::BaseDockWidget(QSize iconSize, QWidget *parent) : QDockWidget(parent), current(0) { m_mainWidget = new QWidget; m_widget = 0; QDockWidget::setWidget(m_mainWidget); m_mainLayout = new QVBoxLayout; m_mainLayout->setMargin(0); m_mainLayout->setSpacing(1); m_mainWidget->setLayout(m_mainLayout); m_comboBox = new QComboBox; m_comboBox->setMinimumContentsLength(4); //m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); m_comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); //m_comboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); m_toolBar = new QToolBar(this); m_toolBar->setContentsMargins(0, 0, 0, 0); m_toolBar->setIconSize(iconSize); //m_toolBar->setFixedHeight(24); // m_titleLabel = new QLabel; // m_titleLabel->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum); m_comboBoxAct = m_toolBar->addWidget(m_comboBox); // m_titleLabelAct = m_toolBar->addWidget(m_titleLabel); // m_titleLabelAct->setChecked(false); m_spacer = new QWidget; m_spacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); m_toolBar->addSeparator(); m_spacerAct = m_toolBar->addWidget(m_spacer); m_closeAct = new QAction(tr("Hide"), m_toolBar); m_closeAct->setToolTip(tr("Hide Tool Window")); m_closeAct->setIcon(QIcon("icon:images/hidetool.png")); m_toolBar->addAction(m_closeAct); connect(m_closeAct,SIGNAL(triggered()),this,SLOT(close())); connect(m_comboBox,SIGNAL(activated(int)),this,SLOT(activeComboBoxIndex(int))); this->setTitleBarWidget(m_toolBar); m_floatAct = new QAction(tr("Floating Window"),this); m_floatAct->setCheckable(true); connect(m_floatAct,SIGNAL(triggered(bool)),this,SLOT(setFloatingWindow(bool))); connect(this,SIGNAL(topLevelChanged(bool)),this,SLOT(topLevelChanged(bool))); /* m_toolBar->setStyleSheet("QToolBar {border: 1px ; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #eeeeee, stop: 1 #ababab); }"\ "QToolBar QToolButton { border:1px ; border-radius: 1px; }"\ "QToolBar QToolButton::hover { background-color: #ababab;}"\ "QToolBar::separator {width:2px; margin-left:2px; margin-right:2px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #dedede, stop: 1 #a0a0a0);}"); */ } void BaseDockWidget::setWindowTitle(const QString &text) { QDockWidget::setWindowTitle(text); } QAction *BaseDockWidget::addWidget(QWidget *widget) { return m_toolBar->insertWidget(m_closeAct,widget); } void BaseDockWidget::setToolMenu(QMenu *menu) { QToolButton *btn = new QToolButton; btn->setPopupMode(QToolButton::InstantPopup); btn->setMenu(menu); btn->setStyleSheet("QToolButton::menu-indicator{image:none;}"); m_toolBar->insertWidget(m_closeAct,btn); } void BaseDockWidget::setWidgetActions(QList actions) { foreach(QAction *action, m_widgetActions) { m_toolBar->removeAction(action); } m_widgetActions = actions; //m_spacerAct->setVisible(!m_widgetActions.isEmpty()); foreach(QAction *action, m_widgetActions) { m_toolBar->insertAction(m_spacerAct,action); if (action->menu()) { QWidget *w = m_toolBar->widgetForAction(action); QToolButton *btn = qobject_cast(w); if (btn) { btn->setPopupMode(QToolButton::InstantPopup); btn->setStyleSheet("QToolButton::menu-indicator{image:none;}"); } } } } void BaseDockWidget::setWidgetList(QList widgets) { foreach(QAction *action, m_widgetActions) { m_toolBar->removeAction(action); } m_widgetActions.clear(); m_widgetList = widgets; //m_spacerAct->setVisible(!m_widgetActions.isEmpty()); foreach(QWidget *widget, m_widgetList) { QAction *action = m_toolBar->insertWidget(m_spacerAct,widget); m_widgetActions.push_back(action); if (action->menu()) { QWidget *w = m_toolBar->widgetForAction(action); QToolButton *btn = qobject_cast(w); if (btn) { btn->setPopupMode(QToolButton::InstantPopup); btn->setStyleSheet("QToolButton::menu-indicator{image:none;}"); } } } } QList BaseDockWidget::actions() const { return m_actions; } void BaseDockWidget::removeAction(QAction *action) { if (m_actions.removeAll(action)) { if (action == current) current = 0; int index = m_comboBox->findData(action->objectName()); if (index >= 0) { m_comboBox->removeItem(index); } QObject::disconnect(action, SIGNAL(changed()), this, SLOT(actionChanged())); } } void BaseDockWidget::setWidget(QWidget *widget) { if (m_widget) { m_mainLayout->removeWidget(m_widget); } m_widget = widget; if (m_widget) { m_mainLayout->addWidget(m_widget); } } QWidget *BaseDockWidget::widget() const { return m_widget; } QAction * BaseDockWidget::checkedAction () const { return current; } void BaseDockWidget::actionChanged() { QAction *action = qobject_cast(sender()); Q_ASSERT_X(action != 0, "ActionGroup::actionChanged", "internal error"); if (action->isChecked()) { if (action != current) { if(current) current->setChecked(false); current = action; int index = m_comboBox->findData(action->objectName()); if (index >= 0) { m_comboBox->setCurrentIndex(index); //m_titleLabel->setText(m_comboBox->currentText()); } } } else if (action == current) { current = 0; } } void BaseDockWidget::activeComboBoxIndex(int index) { if (index < 0 || index >= m_comboBox->count()) { return; } QString objName = m_comboBox->itemData(index).toString(); foreach(QAction *act, m_actions) { if (act->objectName() == objName) { if (!act->isChecked()) { act->setChecked(true); } break; } } } void BaseDockWidget::topLevelChanged(bool b) { // m_comboBoxAct->setVisible(!b); // m_titleLabel->setText(m_comboBox->currentText()); // m_titleLabelAct->setVisible(b); m_closeAct->setVisible(!b); DockWidgetFeatures flags = this->features(); if (b) { this->setTitleBarWidget(0); m_mainLayout->insertWidget(0,m_toolBar); m_mainLayout->setMargin(2); m_toolBar->setVisible(true); flags |= QDockWidget::DockWidgetFloatable; } else { m_mainLayout->setMargin(0); m_toolBar->setVisible(false); m_mainLayout->removeWidget(m_toolBar); this->setTitleBarWidget(m_toolBar); flags &= (~QDockWidget::DockWidgetFloatable); } this->setFeatures(flags); m_floatAct->setChecked(b); } void BaseDockWidget::setFloatingWindow(bool b) { if (this->isFloating() != b) { DockWidgetFeatures flags = this->features(); if (b) { flags |= QDockWidget::DockWidgetFloatable; } else { flags &= (~QDockWidget::DockWidgetFloatable); } this->setFeatures(flags); this->setFloating(b); } if (m_floatAct->isChecked() != b) { m_floatAct->setChecked(b); } } void BaseDockWidget::addAction(QAction *action, const QString &title) { if(!m_actions.contains(action)) { m_actions.append(action); m_comboBox->addItem(title,action->objectName()); QObject::connect(action, SIGNAL(changed()), this, SLOT(actionChanged())); } if (current && current->isChecked()) { current->setChecked(false); } if (action->isChecked()) { current = action; } } SplitDockWidget::SplitDockWidget(QSize iconSize, QWidget *parent) : BaseDockWidget(iconSize,parent) { } void SplitDockWidget::createMenu(Qt::DockWidgetArea area, bool split) { m_area = area; QMenu *moveMenu = new QMenu(tr("Move To"),this); if (area != Qt::TopDockWidgetArea) { QAction *act = new QAction(tr("Top"),this); act->setData(Qt::TopDockWidgetArea); moveMenu->addAction(act); connect(act,SIGNAL(triggered()),this,SLOT(moveAction())); QAction *act1 = new QAction(tr("Top (Split)"),this); act1->setData(Qt::TopDockWidgetArea); moveMenu->addAction(act1); connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit())); } if (area != Qt::BottomDockWidgetArea) { QAction *act = new QAction(tr("Bottom"),this); act->setData(Qt::BottomDockWidgetArea); moveMenu->addAction(act); connect(act,SIGNAL(triggered()),this,SLOT(moveAction())); QAction *act1 = new QAction(tr("Bottom (Split)"),this); act1->setData(Qt::BottomDockWidgetArea); moveMenu->addAction(act1); connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit())); } if (area != Qt::LeftDockWidgetArea) { QAction *act = new QAction(tr("Left"),this); act->setData(Qt::LeftDockWidgetArea); moveMenu->addAction(act); connect(act,SIGNAL(triggered()),this,SLOT(moveAction())); QAction *act1 = new QAction(tr("Left (Split)"),this); act1->setData(Qt::LeftDockWidgetArea); moveMenu->addAction(act1); connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit())); } if (area != Qt::RightDockWidgetArea) { QAction *act = new QAction(tr("Right"),this); act->setData(Qt::RightDockWidgetArea); moveMenu->addAction(act); connect(act,SIGNAL(triggered()),this,SLOT(moveAction())); QAction *act1 = new QAction(tr("Right (Split)"),this); act1->setData(Qt::RightDockWidgetArea); moveMenu->addAction(act1); connect(act1,SIGNAL(triggered()),this,SLOT(moveActionSplit())); } if (area == Qt::TopDockWidgetArea) { m_areaInfo = split ? tr("TopDockWidget (Split)") : tr("TopDockWidget"); } else if (area == Qt::BottomDockWidgetArea) { m_areaInfo = split ? tr("BottomDockWidget (Split)") : tr("BottomDockWidget"); } else if (area == Qt::LeftDockWidgetArea) { m_areaInfo = split ? tr("LeftDockWidget (Split)") : tr("LeftDockWidget"); } else if (area == Qt::RightDockWidgetArea) { m_areaInfo = split ? tr("RightDockWidget (Split)") : tr("RightDockWidget"); } QMenu *menu = new QMenu(this); menu->addAction(m_floatAct); if (split) { QAction *unsplitAct = new QAction(tr("Unsplit"),this); unsplitAct->setData(area); connect(unsplitAct,SIGNAL(triggered()),this,SLOT(unsplitAction())); menu->addAction(unsplitAct); } else { QAction *splitAct = new QAction(tr("Split"),this); splitAct->setData(area); connect(splitAct,SIGNAL(triggered()),this,SLOT(splitAction())); menu->addAction(splitAct); } menu->addAction(moveMenu->menuAction()); if (area == Qt::BottomDockWidgetArea || area == Qt::TopDockWidgetArea) { m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); m_comboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); QWidget *spacer = new QWidget; spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); m_toolBar->insertWidget(m_closeAct,spacer); } QToolButton *btn = new QToolButton(m_toolBar); btn->setPopupMode(QToolButton::InstantPopup); btn->setIcon(QIcon("icon:images/movemenu.png")); btn->setMenu(menu); btn->setText(tr("Move To")); btn->setToolTip(tr("Move To")); btn->setStyleSheet("QToolButton::menu-indicator {image: none;}"); m_toolBar->insertWidget(m_closeAct,btn); } void SplitDockWidget::setWindowTitle(const QString &text) { BaseDockWidget::setWindowTitle(m_areaInfo+" - "+text); } void SplitDockWidget::moveAction() { QAction *action = static_cast(sender()); if (!action) { return; } Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt(); emit moveActionTo(m_area,area,current,false); } void SplitDockWidget::moveActionSplit() { QAction *action = static_cast(sender()); if (!action) { return; } Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt(); emit moveActionTo(m_area,area,current,true); } void SplitDockWidget::splitAction() { QAction *action = static_cast(sender()); if (!action) { return; } Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt(); emit moveActionTo(m_area,area,current,true); } void SplitDockWidget::unsplitAction() { QAction *action = static_cast(sender()); if (!action) { return; } Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt(); emit moveActionTo(m_area,area,current,false); } OutputDockWidget::OutputDockWidget(QSize iconSize, QWidget *parent) : BaseDockWidget(iconSize,parent) { m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); m_comboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); QWidget *spacer = new QWidget; spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); m_toolBar->insertWidget(m_closeAct,spacer); } void OutputDockWidget::createMenu(Qt::DockWidgetArea area) { this->setAllowedAreas(area); QMenu *moveMenu = new QMenu(tr("Move To"),this); QAction *leftAct = new QAction(tr("LeftSideBar"),this); QAction *rightAct = new QAction(tr("RightSideBar"),this); leftAct->setData(Qt::LeftDockWidgetArea); rightAct->setData(Qt::RightDockWidgetArea); moveMenu->addAction(leftAct); moveMenu->addAction(rightAct); connect(leftAct,SIGNAL(triggered()),this,SLOT(moveAction())); connect(rightAct,SIGNAL(triggered()),this,SLOT(moveAction())); QMenu *menu = new QMenu(this); menu->addAction(m_floatAct); menu->addAction(moveMenu->menuAction()); m_comboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); m_comboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); QWidget *spacer = new QWidget; spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); m_toolBar->insertWidget(m_closeAct,spacer); QToolButton *btn = new QToolButton(m_toolBar); btn->setPopupMode(QToolButton::InstantPopup); btn->setIcon(QIcon("icon:images/movemenu.png")); btn->setMenu(menu); btn->setText(tr("Move To")); btn->setToolTip(tr("Move To")); btn->setStyleSheet("QToolButton::menu-indicator {image: none;}"); m_toolBar->insertWidget(m_closeAct,btn); } void OutputDockWidget::setWindowTitle(const QString &text) { BaseDockWidget::setWindowTitle(QString(tr("BottomDockWidget"))+" - "+text); } void OutputDockWidget::setWidget(QWidget *widget) { if (m_widget) { m_mainLayout->removeWidget(m_widget); m_widget->setVisible(false); } m_widget = widget; if (m_widget) { m_mainLayout->addWidget(m_widget); m_widget->setVisible(true); } } void OutputDockWidget::moveAction() { QAction *action = static_cast(sender()); if (!action) { return; } this->setFloatingWindow(false); Qt::DockWidgetArea area = (Qt::DockWidgetArea)action->data().toInt(); emit moveActionTo(Qt::BottomDockWidgetArea,area,current); } ================================================ FILE: liteidex/src/liteapp/tooldockwidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: tooldockwidget.h // Creator: visualfc #ifndef TOOLDOCKWIDGET_H #define TOOLDOCKWIDGET_H #include #include #include #include #include #include class QVBoxLayout; class BaseDockWidget : public QDockWidget { Q_OBJECT public: explicit BaseDockWidget(QSize iconSize, QWidget *parent = 0); virtual QAction *addWidget(QWidget *widget); virtual void setWindowTitle(const QString &text); virtual QList actions() const; virtual QAction * checkedAction() const; virtual void setToolMenu(QMenu *menu); virtual void setWidgetActions(QList actions); virtual void setWidgetList(QList widgets); virtual void addAction(QAction *act, const QString &title); virtual void removeAction(QAction *act); virtual void setWidget(QWidget *widget); virtual QWidget *widget() const; int currentIndex() const { return m_comboBox->currentIndex(); } protected slots: virtual void actionChanged(); virtual void activeComboBoxIndex(int); virtual void topLevelChanged(bool); void setFloatingWindow(bool b); protected: QToolBar *m_toolBar; QWidget *m_widget; QWidget *m_mainWidget; QVBoxLayout *m_mainLayout; //QLabel *m_titleLabel; QComboBox *m_comboBox; QAction *m_comboBoxAct; //QAction *m_titleLabelAct; QWidget *m_spacer; QAction *m_spacerAct; QAction *m_closeAct; QAction *m_floatAct; QMap m_idActionMap; QList m_widgetActions; QList m_widgetList; QList m_actions; QPointer current; }; class SplitDockWidget : public BaseDockWidget { Q_OBJECT public: explicit SplitDockWidget(QSize iconSize, QWidget *parent = 0); void createMenu(Qt::DockWidgetArea area, bool split); void setWindowTitle(const QString &text); signals: void moveActionTo(Qt::DockWidgetArea, Qt::DockWidgetArea, QAction*, bool); protected slots: void moveAction(); void splitAction(); void unsplitAction(); void moveActionSplit(); protected: Qt::DockWidgetArea m_area; QString m_areaInfo; }; class OutputDockWidget : public BaseDockWidget { Q_OBJECT public: explicit OutputDockWidget(QSize iconSize, QWidget *parent = 0); void createMenu(Qt::DockWidgetArea area); virtual void setWindowTitle(const QString &text); virtual void setWidget(QWidget *widget); signals: void moveActionTo(Qt::DockWidgetArea,Qt::DockWidgetArea, QAction*); protected slots: void moveAction(); }; #endif // TOOLDOCKWIDGET_H ================================================ FILE: liteidex/src/liteapp/toolmainwindow.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: toolmainwindow.cpp // Creator: visualfc #include "toolmainwindow.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ToolMainWindow::ToolMainWindow(QWidget *parent) : QMainWindow(parent), m_windowStyle(0) { } ToolMainWindow::~ToolMainWindow() { if (m_windowStyle) { delete m_windowStyle; } } void ToolMainWindow::setWindowStyle(IWindowStyle *style) { m_windowStyle = style; } void ToolMainWindow::createToolWindowMenu() { m_windowStyle->createToolWindowMenu(); } QAction *ToolMainWindow::findToolWindow(QWidget *widget) { return m_windowStyle->findToolWindow(widget); } QByteArray ToolMainWindow::saveState(int version) const { m_windowStyle->saveToolState(); return QMainWindow::saveState(version); } bool ToolMainWindow::restoreState(const QByteArray &state, int version) { bool b = QMainWindow::restoreState(state,version); m_windowStyle->restoreToolsState(); return b; } void ToolMainWindow::updateConer() { m_windowStyle->updateConer(); } void ToolMainWindow::removeToolWindow(QAction *action) { m_windowStyle->removeToolWindow(action); } QAction *ToolMainWindow::addToolWindow(LiteApi::IApplication *app, Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split, QList widgetActions, QList widgetList) { return m_windowStyle->addToolWindow(app,area,widget,id,title,split,widgetActions,widgetList); } void ToolMainWindow::moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action, bool split) { m_windowStyle->moveToolWindow(from,to,action,split); } void ToolMainWindow::showOrHideToolWindow() { m_windowStyle->showOrHideToolWindow(); } void ToolMainWindow::hideOutputWindow() { m_windowStyle->hideOutputWindow(); } void ToolMainWindow::hideAllToolWindows() { m_windowStyle->hideAllToolWindows(); } ================================================ FILE: liteidex/src/liteapp/toolmainwindow.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: toolmainwindow.h // Creator: visualfc #ifndef TOOLMAINWINDOW_H #define TOOLMAINWINDOW_H #include "liteapi/liteapi.h" #include "windowstyle.h" class ToolMainWindow : public QMainWindow { Q_OBJECT public: ToolMainWindow(QWidget *parent = 0); ~ToolMainWindow(); void setWindowStyle(IWindowStyle *style); void createToolWindowMenu(); QAction *addToolWindow(LiteApi::IApplication *app, Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split = false, QList widgetActions = QList(), QList widgetList = QList()); void removeToolWindow(QAction *action); QAction *findToolWindow(QWidget *wiget); QByteArray saveState(int version = 0) const; bool restoreState(const QByteArray &state, int version = 0); void updateConer(); public slots: void showOrHideToolWindow(); void hideOutputWindow(); void hideAllToolWindows(); void moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action,bool split = false); protected: IWindowStyle *m_windowStyle; }; #endif // TOOLMAINWINDOW_H ================================================ FILE: liteidex/src/liteapp/toolwindowmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: toolwindowmanager.cpp // Creator: visualfc #include "toolwindowmanager.h" #include "toolmainwindow.h" #include "liteapp_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end QAction *ToolWindowManager::addToolWindow(Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split, QList widgetActions, QList widgetList) { return ((ToolMainWindow*)m_liteApp->mainWindow())->addToolWindow(m_liteApp,area,widget,id,title,split,widgetActions,widgetList); } void ToolWindowManager::moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to, QAction *action, bool split) { ((ToolMainWindow*)m_liteApp->mainWindow())->moveToolWindow(from,to,action,split); } QAction *ToolWindowManager::findToolWindow(QWidget *widget) { return ((ToolMainWindow*)m_liteApp->mainWindow())->findToolWindow(widget); } void ToolWindowManager::removeToolWindow(QAction *action) { ((ToolMainWindow*)m_liteApp->mainWindow())->removeToolWindow(action); } void ToolWindowManager::removeToolWindow(QWidget *widget) { QAction *act = this->findToolWindow(widget); if (act) { this->removeToolWindow(act); } } ================================================ FILE: liteidex/src/liteapp/toolwindowmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: toolwindowmanager.h // Creator: visualfc #ifndef TOOLWINDOWMANAGER_H #define TOOLWINDOWMANAGER_H #include "liteapi/liteapi.h" using namespace LiteApi; class ToolWindowManager : public IToolWindowManager { public: virtual QAction *addToolWindow(Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split, QList widgetActions = QList(), QList widgetList = QList()); virtual void moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to,QAction *action, bool split); virtual QAction *findToolWindow(QWidget *widget); virtual void removeToolWindow(QAction *action); virtual void removeToolWindow(QWidget *widget); }; #endif // TOOLWINDOWMANAGER_H ================================================ FILE: liteidex/src/liteapp/windowstyle.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: windowstyle.h // Creator: visualfc #ifndef WINDOWSTYLE_H #define WINDOWSTYLE_H #include class IWindowStyle : public QObject { Q_OBJECT public: IWindowStyle(QObject *parent) : QObject(parent) {} virtual void createToolWindowMenu() = 0; virtual QAction *addToolWindow(LiteApi::IApplication *app, Qt::DockWidgetArea area, QWidget *widget, const QString &id, const QString &title, bool split = false, QList widgetActions = QList(), QList widgetList = QList()) = 0; virtual void removeToolWindow(QAction *action) = 0; virtual QAction *findToolWindow(QWidget *wiget) = 0; virtual void moveToolWindow(Qt::DockWidgetArea from, Qt::DockWidgetArea to,QAction *action,bool split) = 0; virtual void saveToolState() const = 0; virtual void restoreToolsState() = 0; virtual void updateConer() = 0; public slots: virtual void hideOutputWindow() = 0; virtual void showOrHideToolWindow() = 0; virtual void hideAllToolWindows() = 0; }; #endif // WINDOWSTYLE_H ================================================ FILE: liteidex/src/liteide/Info.plist ================================================ NSPrincipalClass NSApplication NSHighResolutionCapable True NSHumanReadableCopyright Copyright © 2011-2025 visualfc. All rights reserved. CFBundleIconFile liteide.icns CFBundlePackageType APPL CFBundleSignature ???? CFBundleExecutable LiteIDE CFBundleIdentifier com.visualfc.liteide CFBundleVersion X38 CFBundleShortVersionString 38.4 CFBundleDocumentTypes CFBundleTypeExtensions h CFBundleTypeIconFile c.icns CFBundleTypeName C header file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions c CFBundleTypeIconFile c.icns CFBundleTypeName C source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions gitattributes gitconfig gitignore CFBundleTypeIconFile config.icns CFBundleTypeName Git configuration file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions asp aspx cshtml jshtm jsp phtml shtml CFBundleTypeIconFile html.icns CFBundleTypeName HTML template document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions bat cmd CFBundleTypeIconFile bat.icns CFBundleTypeName Windows command script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions bowerrc CFBundleTypeIconFile Bower.icns CFBundleTypeName Bower document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions config editorconfig ini cfg CFBundleTypeIconFile config.icns CFBundleTypeName Configuration file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions hh hpp hxx h++ CFBundleTypeIconFile cpp.icns CFBundleTypeName C++ header file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions cc cpp cxx c++ CFBundleTypeIconFile cpp.icns CFBundleTypeName C++ source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions m CFBundleTypeIconFile default.icns CFBundleTypeName Objective-C source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions mm CFBundleTypeIconFile cpp.icns CFBundleTypeName Objective-C++ source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions cs csx CFBundleTypeIconFile csharp.icns CFBundleTypeName C# source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions css CFBundleTypeIconFile css.icns CFBundleTypeName CSS CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions go CFBundleTypeIconFile go.icns CFBundleTypeName Go source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions htm html xhtml CFBundleTypeIconFile HTML.icns CFBundleTypeName HTML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions jade CFBundleTypeIconFile Jade.icns CFBundleTypeName Jade document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions jav java CFBundleTypeIconFile Java.icns CFBundleTypeName Java document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions js jscsrc jshintrc mjs cjs CFBundleTypeIconFile Javascript.icns CFBundleTypeName Javascript file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions json CFBundleTypeIconFile JSON.icns CFBundleTypeName JSON document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions less CFBundleTypeIconFile Less.icns CFBundleTypeName Less document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions markdown md mdoc mdown mdtext mdtxt mdwn mkd mkdn CFBundleTypeIconFile Markdown.icns CFBundleTypeName Markdown document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions php CFBundleTypeIconFile PHP.icns CFBundleTypeName PHP source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ps1 psd1 psm1 CFBundleTypeIconFile Powershell.icns CFBundleTypeName Powershell script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions py pyi CFBundleTypeIconFile Python.icns CFBundleTypeName Python script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions gemspec rb erb CFBundleTypeIconFile Ruby.icns CFBundleTypeName Ruby source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions scss sass CFBundleTypeIconFile SASS.icns CFBundleTypeName SASS file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions sql CFBundleTypeIconFile SQL.icns CFBundleTypeName SQL script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ts CFBundleTypeIconFile TypeScript.icns CFBundleTypeName TypeScript file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions tsx jsx CFBundleTypeIconFile React.icns CFBundleTypeName React source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions vue CFBundleTypeIconFile Vue.icns CFBundleTypeName Vue source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ascx csproj dtd plist wxi wxl wxs xml xaml CFBundleTypeIconFile XML.icns CFBundleTypeName XML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions eyaml eyml yaml yml CFBundleTypeIconFile YAML.icns CFBundleTypeName YAML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions bash bash_login bash_logout bash_profile bashrc profile rhistory rprofile sh zlogin zlogout zprofile zsh zshenv zshrc CFBundleTypeIconFile Shell.icns CFBundleTypeName Shell script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions clj cljs cljx clojure CFBundleTypeIconFile default.icns CFBundleTypeName Clojure source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions code-workspace CFBundleTypeIconFile default.icns CFBundleTypeName VS Code workspace file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions coffee CFBundleTypeIconFile default.icns CFBundleTypeName CoffeeScript source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions csv CFBundleTypeIconFile default.icns CFBundleTypeName Comma Separated Values CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions cmake CFBundleTypeIconFile default.icns CFBundleTypeName CMake script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions dart CFBundleTypeIconFile default.icns CFBundleTypeName Dart script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions diff CFBundleTypeIconFile default.icns CFBundleTypeName Diff file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions dockerfile CFBundleTypeIconFile default.icns CFBundleTypeName Dockerfile CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions gradle CFBundleTypeIconFile default.icns CFBundleTypeName Gradle file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions groovy CFBundleTypeIconFile default.icns CFBundleTypeName Groovy script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions makefile mk CFBundleTypeIconFile default.icns CFBundleTypeName Makefile CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions lua CFBundleTypeIconFile default.icns CFBundleTypeName Lua script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions pug CFBundleTypeIconFile default.icns CFBundleTypeName Pug document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions ipynb CFBundleTypeIconFile default.icns CFBundleTypeName Jupyter CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions lock CFBundleTypeIconFile default.icns CFBundleTypeName Lockfile CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions log CFBundleTypeIconFile default.icns CFBundleTypeName Log file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions txt CFBundleTypeIconFile default.icns CFBundleTypeName Plain Text File CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions xcodeproj CFBundleTypeIconFile default.icns CFBundleTypeName Xcode project file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions xcworkspace CFBundleTypeIconFile default.icns CFBundleTypeName Xcode workspace file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions vb CFBundleTypeIconFile default.icns CFBundleTypeName Visual Basic script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions r CFBundleTypeIconFile default.icns CFBundleTypeName R source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions rs CFBundleTypeIconFile default.icns CFBundleTypeName Rust source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions rst CFBundleTypeIconFile default.icns CFBundleTypeName Restructured Text document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions tex cls CFBundleTypeIconFile default.icns CFBundleTypeName LaTeX document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions fs CFBundleTypeIconFile default.icns CFBundleTypeName F# source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions fsi CFBundleTypeIconFile default.icns CFBundleTypeName F# signature file CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions fsx fsscript CFBundleTypeIconFile default.icns CFBundleTypeName F# script CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions svg svgz CFBundleTypeIconFile default.icns CFBundleTypeName SVG document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions toml CFBundleTypeIconFile default.icns CFBundleTypeName TOML document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions swift CFBundleTypeIconFile default.icns CFBundleTypeName Swift source code CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions containerfile ctp dot edn handlebars hbs ml mli pl pl6 pm pm6 pod pp properties psgi rt t CFBundleTypeIconFile default.icns CFBundleTypeName Visual Studio Code document CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor CFBundleTypeExtensions CFBundleTypeIconFile default.icns CFBundleTypeName Folder CFBundleTypeOSTypes TEXT utxt TUTX **** CFBundleTypeRole Editor LSItemContentTypes public.folder ================================================ FILE: liteidex/src/liteide/liteide.pro ================================================ #------------------------------------------------- # # Project created by QtCreator 2012-11-19T17:09:35 # #------------------------------------------------- include (../../liteidex.pri) include (../liteapp/liteapp.pri) QT += core gui macx { QT += xml } TARGET = $$IDE_APP_TARGET DESTDIR = $$IDE_APP_PATH TEMPLATE = app LIBS += -L$$IDE_LIBRARY_PATH macx { LIBS += -L$$IDE_BIN_PATH } else { LIBS += -L$$IDE_APP_PATH } linux-*|freebsd-*|openbsd-*|netbsd-* { #do the rpath by hand since it's not possible to use ORIGIN in QMAKE_RPATHDIR # this expands to $ORIGIN (after qmake and make), it does NOT read a qmake var QMAKE_RPATHDIR += \$\$ORIGIN QMAKE_RPATHDIR += \$\$ORIGIN/../$$IDE_LIBRARY_BASENAME/liteide IDE_PLUGIN_RPATH = $$join(QMAKE_RPATHDIR, ":") QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${IDE_PLUGIN_RPATH}\' QMAKE_RPATHDIR = } SOURCES += main.cpp win32 { target.path = /bin INSTALLS += target RC_FILE += liteide.rc } else:macx { ICON = liteide.icns QMAKE_INFO_PLIST = Info.plist } else { target.path = $$BINPREFIX INSTALLS += target } ================================================ FILE: liteidex/src/liteide/liteide.rc ================================================ IDI_ICON1 ICON DISCARDABLE "liteide.ico" ================================================ FILE: liteidex/src/liteide/main.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2012 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: main.cpp // Creator: visualfc #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end #include "../liteapp/cdrv.h" int main(int argc, char *argv[]) { #if defined(_MSC_VER) && defined(_DEBUG) _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); #endif return cdrv_main(argc,argv); } ================================================ FILE: liteidex/src/liteideapi.pri ================================================ include (../liteidex.pri) DESTDIR = $$IDE_LIBRARY_PATH LIBS += -L$$IDE_LIBRARY_PATH INCLUDEPATH += $$IDE_SOURCE_TREE/src/api isEmpty(TARGET) { error("liteideapi.pri: You must provide a TARGET") } contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols !macx { target.path = $$LIBPREFIX INSTALLS += target } TARGET = $$qtLibraryTarget($$TARGET) ================================================ FILE: liteidex/src/liteideplugin.pri ================================================ include (../liteidex.pri) include (api/liteapi/liteapi.pri) isEmpty(PRECOMPILED_HEADER):PRECOMPILED_HEADER = $$IDE_SOURCE_TREE/src/pch/liteide_gui_pch.h DESTDIR = $$IDE_PLUGIN_PATH LIBS += -L$$IDE_PLUGIN_PATH LIBS += -L$$IDE_LIBRARY_PATH INCLUDEPATH += $$IDE_SOURCE_TREE/src/api INCLUDEPATH += $$IDE_SOURCE_TREE/src/utils INCLUDEPATH += $$IDE_SOURCE_TREE/src/3rdparty isEmpty(TARGET) { error("liteideplugin.pri: You must provide a TARGET") } macx { QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../PlugIns/ } else:linux-* { #do the rpath by hand since it's not possible to use ORIGIN in QMAKE_RPATHDIR QMAKE_RPATHDIR += \$\$ORIGIN QMAKE_RPATHDIR += \$\$ORIGIN/.. QMAKE_RPATHDIR += \$\$ORIGIN/../.. IDE_PLUGIN_RPATH = $$join(QMAKE_RPATHDIR, ":") QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${IDE_PLUGIN_RPATH}\' QMAKE_RPATHDIR = } contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols CONFIG += plugin plugin_with_soname !macx { target.path = $$PLUGINPREFIX INSTALLS += target } TARGET = $$qtLibraryTarget($$TARGET) ================================================ FILE: liteidex/src/liteideutils.pri ================================================ include (../liteidex.pri) isEmpty(PRECOMPILED_HEADER):PRECOMPILED_HEADER = $$IDE_SOURCE_TREE/src/pch/liteide_gui_pch.h DESTDIR = $$IDE_LIBRARY_PATH LIBS += -L$$IDE_LIBRARY_PATH LIBS += -L$$IDE_PLUGIN_PATH INCLUDEPATH += $$IDE_SOURCE_TREE/src/api INCLUDEPATH += $$IDE_SOURCE_TREE/src/api/liteapi INCLUDEPATH += $$IDE_SOURCE_TREE/src/utils INCLUDEPATH += $$IDE_SOURCE_TREE/src/3rdparty isEmpty(TARGET) { error("liteideutils.pri: You must provide a TARGET") } contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols !macx { target.path = $$LIBPREFIX INSTALLS += target } TARGET = $$qtLibraryTarget($$TARGET) ================================================ FILE: liteidex/src/liteshell/ReadMe.txt ================================================ ======================================================================== DYNAMIC LINK LIBRARY : liteshell ======================================================================== AppWizard has created this liteshell DLL for you. This file contains a summary of what you will find in each of the files that make up your liteshell application. liteshell.dsp This file (the project file) contains information at the project level and is used to build a single project or subproject. Other users can share the project (.dsp) file, but they should export the makefiles locally. liteshell.cpp This is the main DLL source file. When created, this DLL does not export any symbols. As a result, it will not produce a .lib file when it is built. If you wish this project to be a project dependency of some other project, you will either need to add code to export some symbols from the DLL so that an export library will be produced, or you can check the "doesn't produce lib" checkbox in the Linker settings page for this project. ///////////////////////////////////////////////////////////////////////////// Other standard files: StdAfx.h, StdAfx.cpp These files are used to build a precompiled header (PCH) file named liteshell.pch and a precompiled types file named StdAfx.obj. ///////////////////////////////////////////////////////////////////////////// Other notes: AppWizard uses "TODO:" to indicate parts of the source code you should add to or customize. ///////////////////////////////////////////////////////////////////////////// ================================================ FILE: liteidex/src/liteshell/StdAfx.cpp ================================================ // stdafx.cpp : source file that includes just the standard includes // liteshell.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file ================================================ FILE: liteidex/src/liteshell/StdAfx.h ================================================ // stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #if !defined(AFX_STDAFX_H__7D13489B_7727_47BC_A405_EA7AEA845BC6__INCLUDED_) #define AFX_STDAFX_H__7D13489B_7727_47BC_A405_EA7AEA845BC6__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // Insert your headers here #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include // TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__7D13489B_7727_47BC_A405_EA7AEA845BC6__INCLUDED_) ================================================ FILE: liteidex/src/liteshell/liteshell.cpp ================================================ // liteshell.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include #include BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { CoInitialize(NULL); } return TRUE; } extern "C" _declspec(dllexport) BOOL BrowseToFile(const wchar_t* filename) { ITEMIDLIST *pidl = ILCreateFromPath(filename); if(pidl) { SHOpenFolderAndSelectItems(pidl,0,0,0); ILFree(pidl); return TRUE; } return FALSE; } ================================================ FILE: liteidex/src/liteshell/liteshell.dsp ================================================ # Microsoft Developer Studio Project File - Name="liteshell" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=liteshell - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "liteshell.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "liteshell.mak" CFG="liteshell - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "liteshell - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "liteshell - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "liteshell - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LITESHELL_EXPORTS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "LITESHELL_EXPORTS" /Yu"stdafx.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x804 /d "NDEBUG" # ADD RSC /l 0x804 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../liteide/bin/liteshell.dll" !ELSEIF "$(CFG)" == "liteshell - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LITESHELL_EXPORTS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /D "LITESHELL_EXPORTS" /Yu"stdafx.h" /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x804 /d "_DEBUG" # ADD RSC /l 0x804 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "liteshell - Win32 Release" # Name "liteshell - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\liteshell.cpp # End Source File # Begin Source File SOURCE=.\StdAfx.cpp # ADD CPP /Yc"stdafx.h" # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\StdAfx.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # Begin Source File SOURCE=.\ReadMe.txt # End Source File # End Target # End Project ================================================ FILE: liteidex/src/liteshell/liteshell.dsw ================================================ Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "liteshell"=".\liteshell.dsp" - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### ================================================ FILE: liteidex/src/memleak_readme.txt ================================================ Not support leak check for QIcon ================================================ FILE: liteidex/src/memleak_remove.lua ================================================ local tmp = "/tmp" local sep = "/" local upper = ".." require"lfs" print (lfs._VERSION) local memcheck = [[ //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ]] function update_memleak(file,name) local f = io.open(file,"r") if f == nil then return end local data = f:read("*all") f:close() local i1,j1 = string.find(data,[[//lite_memory_check_begin]]) local i2,j2 = string.find(data,[[//lite_memory_check_end]]) if i1 == nil or j1 == nil or i2 == nil or j2 == nil then print("no find memleak",file,i1,j1,i2,j2) return end f = io.open(file,"w") if f == nil then return end f:write(string.sub(data,1,i1-1)..string.sub(data,j2+2,#data)) f:close() end function process_file(file,name) local ext = string.match(file,"%.%w+$") if ext == ".cpp" then print(file) update_memleak(file,name) end end function attrdir (path) for file in lfs.dir(path) do if file ~= "." and file ~= ".." then local f = path..sep..file local attr = lfs.attributes (f) assert (type(attr) == "table") if attr.mode == "directory" then attrdir (f) else process_file(f,file) end end end end attrdir("./liteapp") attrdir("./api") attrdir("./plugins") attrdir("./utils") ================================================ FILE: liteidex/src/memleak_update.lua ================================================ local tmp = "/tmp" local sep = "/" local upper = ".." require"lfs" print (lfs._VERSION) local memcheck = [[ //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ]] function update_memleak(file,name) local f = io.open(file,"r") if f == nil then return end local data = f:read("*all") f:close() local find = string.find(data,"//lite_memory_check_begin") if find ~= nil then print("skip file:",file) return end print(">>process file:",file) local i = 0 local last = 0 while true do i = string.find(data,"#include",i+1) if i == nil then break end last = i end i = string.find(data,"\n",last+1) if i == nil then return end f = io.open(file,"w") if f == nil then return end f:write(string.sub(data,1,i)..memcheck..string.sub(data,i+1,#data)) f:close() end function process_file(file,name) local ext = string.match(file,"%.%w+$") if ext == ".cpp" then update_memleak(file,name) end end function attrdir (path) for file in lfs.dir(path) do if file ~= "." and file ~= ".." then local f = path..sep..file local attr = lfs.attributes (f) assert (type(attr) == "table") if attr.mode == "directory" then attrdir (f) else process_file(f,file) end end end end attrdir("./liteapp") attrdir("./api") attrdir("./plugins") attrdir("./utils") ================================================ FILE: liteidex/src/pch/liteide_gui_pch.h ================================================ /* * This is a precompiled header file for use in Xcode / Mac GCC / * GCC >= 3.4 / VC to greatly speed the building of Qt Creator. */ #include "liteide_pch.h" #if defined __cplusplus #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif ================================================ FILE: liteidex/src/pch/liteide_pch.h ================================================ /* * This is a precompiled header file for use in Xcode / Mac GCC / * GCC >= 3.4 / VC to greatly speed the building of Qt Creator. */ #if defined __cplusplus #include #ifdef Q_WS_WIN # define _POSIX_ # include # undef _POSIX_ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarkmanager.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: bookmarkmanager.cpp // Creator: visualfc #include "bookmarkmanager.h" #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end BookmarkManager::BookmarkManager(QObject *parent) : LiteApi::IManager(parent) { } BookmarkManager::~BookmarkManager() { delete m_contextMenu; delete m_treeView; } bool BookmarkManager::initWithApp(LiteApi::IApplication *app) { if (!IManager::initWithApp(app)) { return false; } LiteApi::IEditorMarkManager *manager = LiteApi::getEditorMarkManager(app); if (!manager) { return false; } manager->registerMark(BookMarkType,QIcon("icon:bookmarks/images/bookmark16.png")); m_toggleBookmarkAct = new QAction(tr("Toggle Bookmark"),this); LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(this,"Bookmarks"); #ifdef Q_OS_MAC actionContext->regAction(m_toggleBookmarkAct,"ToggleBookmark","Meta+M"); #else actionContext->regAction(m_toggleBookmarkAct,"ToggleBookmark","Ctrl+M"); #endif connect(m_toggleBookmarkAct,SIGNAL(triggered()),this,SLOT(toggledBookmark())); connect(m_liteApp->editorManager(),SIGNAL(editorCreated(LiteApi::IEditor*)),this,SLOT(editorCreated(LiteApi::IEditor*))); connect(m_liteApp->editorManager(),SIGNAL(editorAboutToClose(LiteApi::IEditor*)),this,SLOT(editorAboutToClose(LiteApi::IEditor*))); connect(manager,SIGNAL(editorMarkListChanged(LiteApi::IEditorMark*,int)),this,SLOT(editorMarkListChanged(LiteApi::IEditorMark*,int))); connect(manager,SIGNAL(editorMarkNodeCreated(LiteApi::IEditorMark*,LiteApi::IEditorMarkNode*)),this,SLOT(editorMarkNodeCreated(LiteApi::IEditorMark*,LiteApi::IEditorMarkNode*))); connect(manager,SIGNAL(editorMarkNodeRemoved(LiteApi::IEditorMark*,LiteApi::IEditorMarkNode*)),this,SLOT(editorMarkNodeRemoved(LiteApi::IEditorMark*,LiteApi::IEditorMarkNode*))); connect(manager,SIGNAL(editorMarkNodeChanged(LiteApi::IEditorMark*,LiteApi::IEditorMarkNode*)),this,SLOT(editorMarkNodeChanged(LiteApi::IEditorMark*,LiteApi::IEditorMarkNode*))); m_treeView = new SymbolTreeView(); m_treeView->setHeaderHidden(true); m_treeView->setEditTriggers(QTreeView::NoEditTriggers); m_treeView->setRootIsDecorated(false); m_bookmarkModel = new BookmarkModel(this); m_proxyModel = new BookmarkSortProxyModel(this); m_proxyModel->setSourceModel(m_bookmarkModel); m_proxyModel->sort(0); m_treeView->setModel(m_proxyModel); m_treeView->setItemDelegate(new BookmarkDelegate(this)); m_treeView->setFrameStyle(QFrame::NoFrame); m_treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_treeView->setContextMenuPolicy(Qt::CustomContextMenu); m_gotoBookmarkAct = new QAction(tr("Goto bookmark"),this); m_removeBookmarkAct = new QAction(tr("Remove bookmark"),this); m_removeFileBookmaraksAct = new QAction(tr("Remove all bookmarks for this file"),this); m_removeAllFileBookmarksAct = new QAction(tr("Remove all bookmarks for all files"),this); m_contextMenu = new QMenu; m_contextMenu->addAction(m_gotoBookmarkAct); m_contextMenu->addAction(m_removeBookmarkAct); m_contextMenu->addAction(m_removeFileBookmaraksAct); m_contextMenu->addAction(m_removeAllFileBookmarksAct); // m_treeView->setFocusPolicy(Qt::NoFocus); // m_treeView->setSelectionModel(manager->selectionModel()); // m_treeView->setSelectionMode(QAbstractItemView::SingleSelection); // m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows); // m_treeView->setDragEnabled(true); // m_treeView->setDragDropMode(QAbstractItemView::DragOnly); m_liteApp->toolWindowManager()->addToolWindow(Qt::LeftDockWidgetArea,m_treeView,"Bookmarks",tr("Bookmarks"),true); connect(m_treeView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(gotoBookmark(QModelIndex))); connect(m_treeView,SIGNAL(enterKeyPressed(QModelIndex)),this,SLOT(gotoBookmark(QModelIndex))); connect(m_treeView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuRequested(QPoint))); connect(m_gotoBookmarkAct,SIGNAL(triggered(bool)),this,SLOT(gotoBookmarkAction())); connect(m_removeBookmarkAct,SIGNAL(triggered(bool)),this,SLOT(removeBookmarkAction())); connect(m_removeFileBookmaraksAct,SIGNAL(triggered(bool)),this,SLOT(removeFileBookmarksAction())); connect(m_removeAllFileBookmarksAct,SIGNAL(triggered(bool)),this,SLOT(removeAllFileBookmarksAction())); return true; } void BookmarkManager::editorCreated(LiteApi::IEditor *editor) { if (!editor) { return; } LiteApi::IEditorMark *mark = LiteApi::getEditorMark(editor); if (!mark) { return; } QMenu *menu = LiteApi::getEditMenu(editor); if (menu) { menu->addSeparator(); menu->addAction(m_toggleBookmarkAct); } menu = LiteApi::getContextMenu(editor); if (menu) { menu->addSeparator(); menu->addAction(m_toggleBookmarkAct); } bool ok; QString key = QString("bookmarks/%1").arg(editor->filePath()); QList bpList; foreach(QString bp, m_liteApp->settings()->value(key).toStringList()) { int i = bp.toInt(&ok); if (ok) { bpList << i; } } mark->addMarkList(bpList,BookMarkType); } void BookmarkManager::editorAboutToClose(LiteApi::IEditor *editor) { if (!editor) { return; } LiteApi::IEditorMark *mark = LiteApi::getEditorMark(editor); if (!mark) { return; } QList bpList = mark->markLinesByType(BookMarkType); QStringList save; foreach(int bp, bpList) { save.append(QString("%1").arg(bp)); } QString key = QString("bookmarks/%1").arg(editor->filePath()); if (save.isEmpty()) { m_liteApp->settings()->remove(key); } else { m_liteApp->settings()->setValue(key,save); } mark->removeMarkList(bpList,BookMarkType); } void BookmarkManager::toggledBookmark() { LiteApi::IEditor *editor = m_liteApp->editorManager()->currentEditor(); if (!editor) { return; } LiteApi::IEditorMark *mark = LiteApi::getEditorMark(editor); if (!mark) { return; } LiteApi::ITextEditor *textEditor = LiteApi::getTextEditor(editor); int line = textEditor->line(); QList types = mark->markTypesByLine(line); if (types.contains(BookMarkType)) { mark->removeMark(line,BookMarkType); } else { mark->addMark(line,BookMarkType); } } void BookmarkManager::editorMarkListChanged(LiteApi::IEditorMark *mark, int type) { if (type != BookMarkType) { return; } } void BookmarkManager::editorMarkNodeCreated(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) { if (node->type() != BookMarkType) { return; } // MarkNodeItem *item = new MarkNodeItem(); // item->mark = mark; // item->node = node; // item->setText(QString("%1\t%2").arg(mark->fileName()).arg(node->lineNumber())); // item->setToolTip(QString("%1").arg(mark->filePath())); // m_bookmarkModel->appendRow(item); m_bookmarkModel->addNode(mark,node); } void BookmarkManager::editorMarkNodeRemoved(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) { if (node->type() != BookMarkType) { return; } m_bookmarkModel->removeNode(mark,node); // for (int i = 0; i < m_bookmarkModel->rowCount(); i++) { // MarkNodeItem *item = (MarkNodeItem*)m_bookmarkModel->item(i,0); // if (item->mark == mark && item->node == node) { // m_bookmarkModel->removeRow(i); // break; // } // } } void BookmarkManager::editorMarkNodeChanged(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) { if (node->type() != BookMarkType) { return; } m_bookmarkModel->updateNode(mark,node); // for (int i = 0; i < m_bookmarkModel->rowCount(); i++) { // MarkNodeItem *item = (MarkNodeItem*)m_bookmarkModel->item(i,0); // if (item->mark == mark && item->node == node) { // item->setText(QString("%1\t%2").arg(mark->fileName()).arg(node->lineNumber())); // break; // } // } } void BookmarkManager::gotoBookmark(const QModelIndex &index) { if (!index.isValid()) { return; } QString filePath = index.data(BookmarkModel::FilePath).toString(); int lineNumber = index.data(BookmarkModel::LineNumber).toInt(); if (!filePath.isEmpty() && (lineNumber > 0)) { LiteApi::gotoLine(m_liteApp,filePath,lineNumber-1,0,true,true); } } void BookmarkManager::contextMenuRequested(QPoint pt) { QModelIndex index = m_treeView->indexAt(pt); m_contextIndex = index; if (!index.isValid()) { return; } m_contextMenu->popup(m_treeView->mapToGlobal(pt)); } void BookmarkManager::gotoBookmarkAction() { gotoBookmark(m_contextIndex); } void BookmarkManager::removeBookmarkAction() { if (!m_contextIndex.isValid()) { return; } QString filePath = m_contextIndex.data(BookmarkModel::FilePath).toString(); int line = m_contextIndex.data(BookmarkModel::LineNumber).toInt()-1; LiteApi::IEditor *editor = m_liteApp->editorManager()->findEditor(filePath,true); if (!editor) { return; } LiteApi::IEditorMark *mark = LiteApi::getEditorMark(editor); if (!mark) { return; } QList types = mark->markTypesByLine(line); if (types.contains(BookMarkType)) { mark->removeMark(line,BookMarkType); } } void BookmarkManager::removeFileBookmarksAction() { if (!m_contextIndex.isValid()) { return; } QString filePath = m_contextIndex.data(BookmarkModel::FilePath).toString(); removeFileBookmarks(filePath); } void BookmarkManager::removeFileBookmarks(const QString &filePath) { LiteApi::IEditor *editor = m_liteApp->editorManager()->findEditor(filePath,true); if (!editor) { return; } LiteApi::IEditorMark *mark = LiteApi::getEditorMark(editor); if (!mark) { return; } QList lines = mark->markLinesByType(BookMarkType); mark->removeMarkList(lines,BookMarkType); } void BookmarkManager::removeAllFileBookmarksAction() { int count = m_bookmarkModel->rowCount(); QSet files; for (int i = 0; i < count; i++) { QModelIndex index = m_bookmarkModel->index(i,0); QString filePath = index.data(BookmarkModel::FilePath).toString(); files.insert(filePath); } foreach (QString file, files) { removeFileBookmarks(file); } } ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarkmanager.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: bookmarkmanager.h // Creator: visualfc #ifndef BOOKMARKMANAGER_H #define BOOKMARKMANAGER_H #include "liteapi/liteapi.h" #include "liteeditorapi/liteeditorapi.h" #include "symboltreeview/symboltreeview.h" #include "bookmarkmodel.h" #include enum BOOKMARK_EDITOR_MARKTYPE { BookMarkType = 1000 }; class QTreeView; class BookmarkManager : public LiteApi::IManager { Q_OBJECT public: BookmarkManager(QObject *parent = 0); virtual ~BookmarkManager(); virtual bool initWithApp(LiteApi::IApplication *app); public slots: void editorCreated(LiteApi::IEditor *editor); void editorAboutToClose(LiteApi::IEditor *editor); void toggledBookmark(); void editorMarkListChanged(LiteApi::IEditorMark *mark, int type); void editorMarkNodeCreated(LiteApi::IEditorMark *mark,LiteApi::IEditorMarkNode *node); void editorMarkNodeRemoved(LiteApi::IEditorMark *mark,LiteApi::IEditorMarkNode *node); void editorMarkNodeChanged(LiteApi::IEditorMark *mark,LiteApi::IEditorMarkNode *node); void gotoBookmark(const QModelIndex &index); void contextMenuRequested(QPoint pt); void gotoBookmarkAction(); void removeBookmarkAction(); void removeFileBookmarksAction(); void removeAllFileBookmarksAction(); protected: void removeFileBookmarks(const QString &filePath); protected: QAction *m_toggleBookmarkAct; BookmarkModel *m_bookmarkModel; BookmarkSortProxyModel *m_proxyModel; SymbolTreeView *m_treeView; QAction *m_gotoBookmarkAct; QAction *m_removeBookmarkAct; QAction *m_removeFileBookmaraksAct; QAction *m_removeAllFileBookmarksAct; QMenu *m_contextMenu; QModelIndex m_contextIndex; }; #endif // BOOKMARKMANAGER_H ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarkmodel.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: bookmarkmodel.cpp // Creator: visualfc #include "bookmarkmodel.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end void BookmarkModel::addNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) { beginInsertRows(QModelIndex(), m_nodeList.size(), m_nodeList.size()); BookmarkNode *bn = createBookmarkNode(mark,node); m_nodeList.append(bn); m_nodeMap.insert(node,bn); endInsertRows(); //selectionModel()->setCurrentIndex(index(m_bookmarksList.size()-1 , 0, QModelIndex()), QItemSelectionModel::Select | QItemSelectionModel::Clear); } void BookmarkModel::removeNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) { BookmarkNode *bn = findBookmarkNode(mark,node); if (!bn) { return; } int idx = m_nodeList.indexOf(bn); beginRemoveRows(QModelIndex(), idx, idx); m_nodeMap.remove(node); delete bn; m_nodeList.removeAt(idx); endRemoveRows(); // if (selectionModel()->currentIndex().isValid()) // selectionModel()->setCurrentIndex(selectionModel()->currentIndex(), QItemSelectionModel::Select | QItemSelectionModel::Clear); } void BookmarkModel::updateNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) { BookmarkNode *bn = findBookmarkNode(mark,node); if (!bn) { return; } bn->setLineNumber(node->blockNumber()+1); bn->setLineText(node->block().text()); int idx = m_nodeList.indexOf(bn); QModelIndex i = index(idx,0,QModelIndex()); emit dataChanged(i,i); } BookmarkNode *BookmarkModel::createBookmarkNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) const { BookmarkNode *n = new BookmarkNode(); n->setFilePath(mark->filePath()); n->setLineNumber(node->blockNumber()+1); n->setLineText(node->block().text()); return n; } BookmarkNode *BookmarkModel::bookmarkNodeForIndex(const QModelIndex &index) const { if (!index.isValid() || index.row() >= m_nodeList.size()) return 0; return m_nodeList.at(index.row()); } BookmarkNode *BookmarkModel::findBookmarkNode(LiteApi::IEditorMark */*mark*/, LiteApi::IEditorMarkNode *node) const { return m_nodeMap.value(node); } BookmarkModel::BookmarkModel(QObject *parent) : QAbstractItemModel(parent) { } QModelIndex BookmarkModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid()) return QModelIndex(); else return createIndex(row, column); } QModelIndex BookmarkModel::parent(const QModelIndex &index) const { return QModelIndex(); } int BookmarkModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return m_nodeList.size(); } int BookmarkModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return 1; } QVariant BookmarkModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.column() !=0 || index.row() < 0 || index.row() >= m_nodeList.count()) return QVariant(); BookmarkNode *node = m_nodeList.at(index.row()); if (role == BookmarkModel::FileName) return node->fileName(); if (role == BookmarkModel::LineNumber) return node->lineNumber(); if (role == BookmarkModel::FilePath) return node->filePath(); if (role == BookmarkModel::LineText) return node->lineText(); if (role == BookmarkModel::Note) return node->noteText(); if (role == Qt::ToolTipRole) return QDir::toNativeSeparators(node->filePath()); return QVariant(); } BookmarkDelegate::BookmarkDelegate(QObject *parent) : QStyledItemDelegate(parent) { } QSize BookmarkDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); QFontMetrics fm(option.font); QSize s; s.setWidth(option.rect.width()); s.setHeight(fm.height() * 2 + 10); return s; } void BookmarkDelegate::generateGradientPixmap(int width, int height, const QColor &color, bool selected) const { QColor c = color; c.setAlpha(0); QPixmap pixmap(width+1, height); pixmap.fill(c); QPainter painter(&pixmap); painter.setPen(Qt::NoPen); QLinearGradient lg; lg.setCoordinateMode(QGradient::ObjectBoundingMode); lg.setFinalStop(1,0); lg.setColorAt(0, c); lg.setColorAt(0.4, color); painter.setBrush(lg); painter.drawRect(0, 0, width+1, height); if (selected) m_selectedPixmap = pixmap; else m_normalPixmap = pixmap; } void BookmarkDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem opt = option; initStyleOption(&opt, index); painter->save(); QFontMetrics fm(opt.font); static int lwidth = fm.width(QLatin1String("8888")) + 18; QColor backgroundColor; QColor textColor; bool selected = opt.state & QStyle::State_Selected; if (selected) { painter->setBrush(opt.palette.highlight().color()); backgroundColor = opt.palette.highlight().color(); if (!m_selectedPixmap) generateGradientPixmap(lwidth, fm.height()+1, backgroundColor, selected); } else { painter->setBrush(opt.palette.background().color()); backgroundColor = opt.palette.background().color(); if (!m_normalPixmap) generateGradientPixmap(lwidth, fm.height(), backgroundColor, selected); } painter->setPen(Qt::NoPen); painter->drawRect(opt.rect); // Set Text Color if (opt.state & QStyle::State_Selected) textColor = opt.palette.highlightedText().color(); else textColor = opt.palette.text().color(); painter->setPen(textColor); // TopLeft QString topLeft = index.data(BookmarkModel::FileName).toString(); //painter->drawText(6, 2 + opt.rect.top() + fm.ascent(), topLeft); QString topRight = index.data(BookmarkModel::LineNumber).toString(); // Check whether we need to be fancy and paint some background int fwidth = fm.width(topLeft); if (fwidth + lwidth > opt.rect.width()) { int left = opt.rect.right() - lwidth; painter->drawPixmap(left, opt.rect.top(), selected ? m_selectedPixmap : m_normalPixmap); } // topRight painter->drawText(opt.rect.right() - fm.width(topRight) - 6 , 2 + opt.rect.top() + fm.ascent(), topRight); // Directory QColor mix; mix.setRgbF(0.7 * textColor.redF() + 0.3 * backgroundColor.redF(), 0.7 * textColor.greenF() + 0.3 * backgroundColor.greenF(), 0.7 * textColor.blueF() + 0.3 * backgroundColor.blueF()); painter->setPen(mix); QString directory = index.data(BookmarkModel::FilePath).toString(); int availableSpace = opt.rect.width() - fm.width("888"); if (fm.width(directory) > availableSpace) { // We need a shorter directory availableSpace -= fm.width("..."); int pos = directory.size(); int idx; forever { idx = directory.lastIndexOf("/", pos-1); if (idx == -1) { // Can't happen, this means the string did fit after all? break; } int width = fm.width(directory.mid(idx, pos-idx)); if (width > availableSpace) { directory = "..." + directory.mid(pos); break; } else { pos = idx; availableSpace -= width; } } } //painter->drawText(3, opt.rect.top() + fm.ascent() + fm.height() + 6, directory); painter->drawText(6, 2 + opt.rect.top() + fm.ascent(), directory); QString lineText = index.data(BookmarkModel::Note).toString().trimmed(); if (lineText.isEmpty()) lineText = index.data(BookmarkModel::LineText).toString().trimmed(); painter->drawText(6, opt.rect.top() + fm.ascent() + fm.height() + 6, lineText); // Separator lines const QRectF innerRect = QRectF(opt.rect).adjusted(0.5, 0.5, -0.5, -0.5); painter->setPen(QColor::fromRgb(150,150,150)); painter->drawLine(innerRect.bottomLeft(), innerRect.bottomRight()); painter->restore(); } ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarkmodel.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: bookmarkmodel.h // Creator: visualfc #ifndef BOOKMARKMODEL_H #define BOOKMARKMODEL_H #include #include #include #include #include #include #include "liteeditorapi/liteeditorapi.h" class BookmarkNode { public: BookmarkNode() : m_lineNumber(-1) { } public: void setFilePath(const QString &filePath) { m_filePath = QDir::toNativeSeparators(filePath); m_fileName = QFileInfo(m_filePath).fileName(); } void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; } void setLineText(const QString &text) { m_lineText = text; m_lineText.replace("\t"," "); } void setNodeText(const QString &node) { m_nodeText = node; } public: QString fileName() const { return m_fileName; } QString filePath() const { return m_filePath; } int lineNumber() const { return m_lineNumber; } QString lineText() const { return m_lineText; } QString noteText() const { return m_nodeText; } protected: int m_lineNumber; QString m_filePath; QString m_fileName; QString m_lineText; QString m_nodeText; }; class BookmarkModel : public QAbstractItemModel { Q_OBJECT public: enum Roles { FileName = Qt::UserRole, LineNumber = Qt::UserRole + 1, FilePath = Qt::UserRole + 2, LineText = Qt::UserRole + 3, Note = Qt::UserRole + 4 }; void addNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node); void removeNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node); void updateNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node); BookmarkNode *createBookmarkNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) const; BookmarkNode *bookmarkNodeForIndex(const QModelIndex &index) const; BookmarkNode *findBookmarkNode(LiteApi::IEditorMark *mark, LiteApi::IEditorMarkNode *node) const; public: explicit BookmarkModel(QObject *parent = 0); // Basic functionality: QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &index) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; private: QList m_nodeList; QMap m_nodeMap; }; class BookmarkSortProxyModel : public QSortFilterProxyModel { public: explicit BookmarkSortProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) { } virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { QString leftPath = source_left.data(BookmarkModel::FilePath).toString(); QString rightPath = source_right.data(BookmarkModel::FilePath).toString(); if (leftPath == rightPath) { int leftNumber = source_left.data(BookmarkModel::LineNumber).toInt(); int rightNumber = source_right.data(BookmarkModel::LineNumber).toInt(); return leftNumber < rightNumber; } return leftPath < rightPath; } }; class BookmarkDelegate : public QStyledItemDelegate { Q_OBJECT public: BookmarkDelegate(QObject *parent = 0); private: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; void generateGradientPixmap(int width, int height, const QColor &color, bool selected) const; mutable QPixmap m_normalPixmap; mutable QPixmap m_selectedPixmap; }; #endif // BOOKMARKMODEL_H ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarks.pro ================================================ TARGET = bookmarks TEMPLATE = lib include(../../liteideplugin.pri) include (../../api/liteeditorapi/liteeditorapi.pri) include (../../utils/symboltreeview/symboltreeview.pri) DEFINES += BOOKMARKS_LIBRARY SOURCES += bookmarksplugin.cpp \ bookmarkmanager.cpp \ bookmarkmodel.cpp HEADERS += bookmarksplugin.h\ bookmarks_global.h \ bookmarkmanager.h \ bookmarkmodel.h DISTFILES += RESOURCES += \ bookmarks.qrc ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarks.qrc ================================================ images/bookmark16.png images/bookmark32.png ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarks_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: bookmarks_global.h // Creator: visualfc #ifndef BOOKMARKS_GLOBAL_H #define BOOKMARKS_GLOBAL_H #include #if defined(BOOKMARKS_LIBRARY) # define BOOKMARKSSHARED_EXPORT Q_DECL_EXPORT #else # define BOOKMARKSSHARED_EXPORT Q_DECL_IMPORT #endif #endif // BOOKMARKS_GLOBAL_H ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarksplugin.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: bookmarksplugin.cpp // Creator: visualfc #include "bookmarksplugin.h" #include "bookmarkmanager.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end BookmarksPlugin::BookmarksPlugin() { } bool BookmarksPlugin::load(LiteApi::IApplication *app) { BookmarkManager *manager = new BookmarkManager(app); if (!manager->initWithApp(app)) { return false; } return true; } #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(PluginFactory,PluginFactory) #endif ================================================ FILE: liteidex/src/plugins/bookmarks/bookmarksplugin.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: bookmarksplugin.h // Creator: visualfc #ifndef BOOKMARKSPLUGIN_H #define BOOKMARKSPLUGIN_H #include "bookmarks_global.h" #include "liteapi/liteapi.h" class BookmarksPlugin : public LiteApi::IPlugin { Q_OBJECT public: BookmarksPlugin(); virtual bool load(LiteApi::IApplication *app); }; class PluginFactory : public LiteApi::PluginFactoryT { Q_OBJECT Q_INTERFACES(LiteApi::IPluginFactory) #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "liteidex.BookmarksPlugin") #endif public: PluginFactory() { m_info->setId("plugin/Bookmarks"); m_info->setVer("X38.1"); m_info->setName("Bookmarks"); m_info->setAuthor("visualfc"); m_info->setInfo("Bookmarks"); //m_info->setMustLoad(true); m_info->appendDepend("plugin/liteeditor"); } }; #endif // BOOKMARKSPLUGIN_H ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebugger.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebugger.cpp // Creator: visualfc #include "dlvdebugger.h" #include "fileutil/fileutil.h" #include "processex/processex.h" #include "dlvdebuggeroption.h" #include "../litedebug/litedebug_global.h" #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static void GdbMiValueToItem(QStandardItem *item, const GdbMiValue &value) { switch (value.type()) { case GdbMiValue::Invalid: item->appendRow(new QStandardItem("Invalid")); break; case GdbMiValue::Const: if (value.name().isEmpty()) { item->appendRow(new QStandardItem(QString(value.data()))); } else { item->appendRow(new QStandardItem(QString(value.name()+"="+value.data()))); } break; case GdbMiValue::List: { QStandardItem *in = new QStandardItem(QString(value.name())); item->appendRow(in); for (int i = 0; i < value.childCount(); i++) { QStandardItem *iv = new QStandardItem(QString("[%1]").arg(i)); in->appendRow(iv); GdbMiValueToItem(iv,value.childAt(i)); } break; } case GdbMiValue::Tuple: { QStandardItem *iv = item; if (!value.name().isEmpty()) { iv = new QStandardItem(QString(value.name())); item->appendRow(iv); } foreach (const GdbMiValue &v, value.children()) { GdbMiValueToItem(iv,v); } break; } } } DlvDebugger::DlvDebugger(LiteApi::IApplication *app, QObject *parent) : LiteApi::IDebugger(parent), m_liteApp(app), m_envManager(0) { m_process = new LiteProcess(m_liteApp,this); m_process->setUseCtrlC(true); m_asyncModel = new QStandardItemModel(this); m_asyncItem = new QStandardItem; m_asyncModel->appendRow(m_asyncItem); /* m_asyncModel->setHeaderData(0,Qt::Horizontal,"Reason"); m_asyncModel->setHeaderData(1,Qt::Horizontal,"Address"); m_asyncModel->setHeaderData(2,Qt::Horizontal,"Function"); m_asyncModel->setHeaderData(3,Qt::Horizontal,"File"); m_asyncModel->setHeaderData(4,Qt::Horizontal,"Line"); m_asyncModel->setHeaderData(5,Qt::Horizontal,"Thread ID"); m_asyncModel->setHeaderData(6,Qt::Horizontal,"Stoped Threads"); */ m_varsModel = new QStandardItemModel(0,2,this); m_varsModel->setHeaderData(0,Qt::Horizontal,"Name"); m_varsModel->setHeaderData(1,Qt::Horizontal,"Value"); //m_varsModel->setHeaderData(2,Qt::Horizontal,"Type"); m_watchModel = new QStandardItemModel(0,2,this); m_watchModel->setHeaderData(0,Qt::Horizontal,"Name"); m_watchModel->setHeaderData(1,Qt::Horizontal,"Value"); //m_watchModel->setHeaderData(2,Qt::Horizontal,"Type"); m_framesModel = new QStandardItemModel(0,5,this); m_framesModel->setHeaderData(0,Qt::Horizontal,"Level"); m_framesModel->setHeaderData(1,Qt::Horizontal,"Address"); m_framesModel->setHeaderData(2,Qt::Horizontal,"Function"); m_framesModel->setHeaderData(3,Qt::Horizontal,"File"); m_framesModel->setHeaderData(4,Qt::Horizontal,"Line"); m_libraryModel = new QStandardItemModel(0,2,this); m_libraryModel->setHeaderData(0,Qt::Horizontal,"Id"); m_libraryModel->setHeaderData(1,Qt::Horizontal,"Thread Groups"); m_dlvInit = false; m_dlvExit = false; m_readDataBusy = false; m_writeDataBusy = false; m_headlessMode = true; m_headlessInitAddress = false; m_headlessProcess = new LiteProcess(m_liteApp,this); m_headlessProcess->setUseCtrlC(true); m_dlvRunningCmdList << "c" << "continue" << "n" << "next" << "s" << "step" << "si" << "step-instruction" << "stepout"; connect(app,SIGNAL(loaded()),this,SLOT(appLoaded())); connect(m_process,SIGNAL(started()),this,SIGNAL(debugStarted())); connect(m_process,SIGNAL(finished(int)),this,SLOT(finished(int))); connect(m_process,SIGNAL(error(QProcess::ProcessError)),this,SLOT(error(QProcess::ProcessError))); connect(m_process,SIGNAL(readyReadStandardError()),this,SLOT(readStdError())); connect(m_process,SIGNAL(readyReadStandardOutput()),this,SLOT(readStdOutput())); connect(m_headlessProcess,SIGNAL(started()),this,SIGNAL(debugStarted())); connect(m_headlessProcess,SIGNAL(finished(int)),this,SLOT(headlessFinished(int))); connect(m_headlessProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(headlessError(QProcess::ProcessError))); connect(m_headlessProcess,SIGNAL(readyReadStandardError()),this,SLOT(headlessReadStdError())); connect(m_headlessProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(headlessReadStdOutput())); } DlvDebugger::~DlvDebugger() { stop(); } void DlvDebugger::appLoaded() { m_envManager = LiteApi::findExtensionObject(m_liteApp,"LiteApi.IEnvManager"); } QString DlvDebugger::mimeType() const { return QLatin1String("debugger/delve1"); } QAbstractItemModel *DlvDebugger::debugModel(LiteApi::DEBUG_MODEL_TYPE type) { if (type == LiteApi::ASYNC_MODEL) { return m_asyncModel; } else if (type == LiteApi::VARS_MODEL) { return m_varsModel; } else if (type == LiteApi::WATCHES_MODEL) { return m_watchModel; }else if (type == LiteApi::FRAMES_MODEL) { return m_framesModel; } else if (type == LiteApi::LIBRARY_MODEL) { return m_libraryModel; } return 0; } void DlvDebugger::setWorkingDirectory(const QString &dir) { m_headlessProcess->setWorkingDirectory(dir); m_process->setWorkingDirectory(dir); } void DlvDebugger::setEnvironment (const QStringList &environment) { m_headlessProcess->setEnvironment(environment); m_process->setEnvironment(environment); } bool DlvDebugger::start(const QString &cmd, const QString &arguments) { if (!m_envManager) { return false; } QProcessEnvironment env = LiteApi::getGoEnvironment(m_liteApp); QString goroot = env.value("GOROOT"); if (!goroot.isEmpty()) { m_runtimeFilePath = QFileInfo(QDir(goroot),"src/pkg/runtime/").path(); } QString dlv = FileUtil::lookupGoBin("dlv",m_liteApp,env,true); if (dlv.isEmpty()) { dlv = FileUtil::lookPath("dlv",env,false); } m_dlvFilePath = dlv; //m_checkFuncDecl = false; if (m_dlvFilePath.isEmpty()) { m_liteApp->appendLog("DlvDebugger","dlv was not found on system PATH (hint: is Delve installed?)",true); return false; } clear(); if (m_headlessMode) { QStringList argsList; argsList << "--headless" << "--api-version=2" << "--accept-multiclient"; argsList << "exec" << cmd; if (!arguments.isEmpty()) { argsList << "--" << arguments; } #ifdef Q_OS_WIN //m_headlessProcess->setNativeArguments(argsList.join(" ")); m_headlessProcess->startEx("\""+m_dlvFilePath+"\"", argsList.join(" ")); #else m_headlessProcess->startEx(m_dlvFilePath, argsList.join(" ")); #endif QString log = QString("%1 %2 [%3]").arg(m_dlvFilePath).arg(argsList.join(" ")).arg(m_headlessProcess->workingDirectory()); emit debugLog(LiteApi::DebugRuntimeLog,log); } else { QStringList argsList; argsList << "exec" << cmd; if (!arguments.isEmpty()) { argsList << "--" << arguments; } #ifdef Q_OS_WIN //m_process->setNativeArguments(argsList.join(" ")); m_process->startEx("\""+m_dlvFilePath+"\"",argsList.join(" ")); #else m_process->startEx(m_dlvFilePath,argsList.join(" ")); #endif QString log = QString("%1 %2 [%3]").arg(m_dlvFilePath).arg(argsList.join(" ")).arg(m_process->workingDirectory()); emit debugLog(LiteApi::DebugRuntimeLog,log); } return true; } void DlvDebugger::stop() { if (m_dlvExit) { return; } m_dlvExit = true; if (m_headlessMode) { if (!m_headlessProcess->isStop()) { m_headlessProcess->interrupt(); } if (!m_process->isStop()) { m_process->interrupt(); } if (!m_headlessProcess->isStop() && !m_headlessProcess->waitForFinished(500)) { m_headlessProcess->kill(); } if (!m_process->isStop() && !m_process->waitForFinished(500)) { command_helper("exit",true); if (!m_process->waitForFinished(500)) { m_process->kill(); } } } else { if (!m_process->isStop()) { m_process->interrupt(); } command_helper("exit",true); if (!m_process->isStop() && !m_process->waitForFinished(1000)) { m_process->kill(); } } } bool DlvDebugger::isRunning() { return m_process->state() != QProcess::NotRunning; } void DlvDebugger::continueRun() { command("continue"); } void DlvDebugger::stepOver() { command("next"); } void DlvDebugger::stepInto() { command("step"); } void DlvDebugger::stepOut() { command("stepout"); // QString cmd = LiteApi::getGotools(m_liteApp); // QProcess process; // process.setEnvironment(LiteApi::getCurrentEnvironment(m_liteApp).toStringList()); // QFileInfo info(m_lastFileName); // process.setWorkingDirectory(info.path()); // QStringList args; // args << "finddecl" << "-file" << info.fileName() << "-line" << QString("%1").arg(m_lastFileLine+1); // process.start(cmd,args); // if (!process.waitForFinished(3000)) { // emit debugLog(LiteApi::DebugErrorLog,"error wait find decl process"); // process.kill(); // return; // } // if (process.exitCode() != 0) { // emit debugLog(LiteApi::DebugErrorLog,"error get find decl result"); // return; // } // QByteArray data = process.readAll().trimmed(); // QStringList ar = QString::fromUtf8(data).split(" "); // if (ar.size() != 4 || ar[0] != "func") { // emit debugLog(LiteApi::DebugErrorLog,"error find func decl in line"); // return; // } // m_funcDecl.fileName = m_lastFileName; // m_funcDecl.funcName = ar[1]; // m_funcDecl.start = ar[2].toInt()-1; // m_funcDecl.end = ar[3].toInt()-1; // m_checkFuncDecl = true; // command("next"); } void DlvDebugger::runToLine(const QString &fileName, int line) { bool find = findBreakPoint(fileName,line); if (!find) { insertBreakPoint(fileName,line); command("continue"); removeBreakPoint(fileName,line); } else { command("continue"); } } void DlvDebugger::createWatch(const QString &var) { QString cmd = "vars "+QRegExp::escape(var); m_updateCmdHistroy.push_back(cmd); command_helper(cmd.toUtf8(),true); } void DlvDebugger::removeWatch(const QString &value) { m_watchNameMap.remove(value); for (int i = 0; i < m_watchModel->rowCount(); i++) { QStandardItem *nameItem = m_watchModel->item(i,0); if (nameItem->text() == value) { m_watchModel->removeRow(i); break; } } emit watchRemoved(value); } void DlvDebugger::removeAllWatch() { m_watchNameMap.clear(); m_watchModel->removeRows(0,m_watchModel->rowCount()); } void DlvDebugger::showFrame(QModelIndex index) { QStandardItem* file = m_framesModel->item( index.row(), 3 ); QStandardItem* line = m_framesModel->item( index.row(), 4 ); if( !file || !line ) { return; } QString filename = file->text(); int lineno = line->text().toInt(); if( lineno <= 0 ) { return; } emit gotoLine(filename, lineno - 1 ); } void DlvDebugger::dbclickItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type) { } void DlvDebugger::expandItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type) { QStandardItem *parent = 0; if (type == LiteApi::VARS_MODEL) { parent = m_varsModel->itemFromIndex(index); } else if (type == LiteApi::WATCHES_MODEL) { parent = m_watchModel->itemFromIndex(index); } if (!parent) { return; } if (parent->data(VarExpanded).toInt() == 1) { return; } parent->setData(1,VarExpanded); } void DlvDebugger::setInitBreakTable(const QMultiMap &bks) { m_initBks = bks; } void DlvDebugger::setInitWatchList(const QStringList &names) { foreach (QString name, names) { m_watchNameMap.insert(name,""); } } void DlvDebugger::insertBreakPoint(const QString &fileName, int line) { insertBreakPointHelper(fileName,line,false); } void DlvDebugger::insertBreakPointHelper(const QString &fileName, int line, bool force) { line++; QString location = QString("%1:%2").arg(fileName).arg(line); if (m_locationBkMap.contains(location)) { return; } QString id = QString("bk%1").arg(qHash(location)); m_locationBkMap.insert(location,id); QStringList args; args << "break"; args << id; args << QString("%1:%2").arg(fileName).arg(line); command_helper(args.join(" ").toUtf8(),force); } void DlvDebugger::removeBreakPoint(const QString &fileName, int line) { line++; QString location = QString("%1:%2").arg(fileName).arg(line); QString id = m_locationBkMap.value(location); if (id.isEmpty()) { return; } m_locationBkMap.remove(location); QStringList args; args << "clear"; args << id; command_helper(args.join(" ").toUtf8(),false); } bool DlvDebugger::findBreakPoint(const QString &fileName, int line) { QString location = QString("%1:%2").arg(fileName).arg(line); QString id = m_locationBkMap.value(location); return m_locationBkMap.contains(location); } void DlvDebugger::command_helper(const QByteArray &cmd, bool force) { if (m_writeDataBusy && !force) { return; } m_writeDataBusy = true; m_lastCmd = cmd; if (m_dlvRunningCmdList.contains(cmd)) { m_asyncItem->removeRows(0,m_asyncItem->rowCount()); m_asyncItem->setText("runing"); } #ifdef Q_OS_WIN m_process->write(cmd+"\r\n"); #else m_process->write(cmd+"\n"); #endif } void DlvDebugger::enterAppText(const QString &text) { m_updateCmdList.clear(); m_updateCmdHistroy.clear(); QString cmd = text.trimmed(); if (cmd == "r" || cmd == "restart") { m_processId.clear(); } if (m_headlessMode) { m_headlessProcess->write(text.toUtf8()); } else { m_process->write(text.toUtf8()); } } void DlvDebugger::enterDebugText(const QString &text) { m_updateCmdList.clear(); m_updateCmdHistroy.clear(); QString cmd = text.trimmed(); if (cmd == "r" || cmd == "restart") { m_processId.clear(); } command(text.toUtf8()); } void DlvDebugger::command(const QByteArray &cmd) { command_helper(cmd,false); } void DlvDebugger::readStdError() { //Process 4084 has exited with status 0 QString data = QString::fromUtf8(m_process->readAllStandardError()); // qDebug() << data << m_processId; //QRegExp reg; emit debugLog(LiteApi::DebugConsoleLog,data); foreach (QString line, data.split("\n",qtSkipEmptyParts)) { if (line.startsWith("Process "+m_processId)) { m_processId.clear(); this->stop(); } } } //static bool isNameChar(char c) //{ // // could be 'stopped' or 'shlibs-added' // return (c >= 'a' && c <= 'z') || c == '-'; //} void DlvDebugger::handleResponse(const QByteArray &buff) { if (buff.isEmpty()) { return; } if (!m_headlessMode) { if (m_processId.isEmpty()) { //Process restarted with PID int n = buff.indexOf("PID"); if (n != -1) { m_processId = buff.mid(n+3).replace("(dlv)","").trimmed(); } } } //Process restarted with PID 4532 //> main.main() H:/goproj/src/hello/main.go:13 (hits goroutine(1):1 total:1) (PC: 0x401172) //> main.main() H:/goproj/src/hello/main.go:14 (PC: 0x401179) //> main.main() H:/goproj/src/hello/main.go:21 (hits goroutine(1):1 total:1) (PC: 0x40161a) //> fmt.Println() c:/go/go1.6/src/fmt/print.go:263 (PC: 0x45aeca) //> runtime.convT2E() c:/go/go1.6/src/runtime/iface.go:128 (PC: 0x40caaa)" //> github.com/derekparker/delve/cmd/dlv/cmds.New() /src/github.com/derekparker/delve/cmd/dlv/cmds/commands.go:61 (PC: 0x45d09f) //> [bk6767010] main.test() H:/goproj/src/hello/main.go:12 (hits goroutine(1):1 total:1) (PC: 0x401066) //> [bk101903173] github.com/derekparker/delve/vendor/github.com/spf13/cobra.(*Command).Execute() github.com/derekparker/delve/vendor/github.com/spf13/cobra/command.go:615 (hits goroutine(1):1 total:1) (PC: 0x524ea6) //> qlang.io/qlang%2espec%2ev1.Import() //> main.main() goapi/_test/_testmain.go:50 (hits goroutine(1):1 total:1) (PC: 0x4011ca) if (buff.contains("> ")) { static QRegExp reg(">(\\s+\\[[\\w\\d]+\\])?\\s+([\\w\\d_\\.\\%\\*\\(\\)\\/]+)\\(\\)\\s+((?:[a-zA-Z]:)?[\\w\\d_@\\s\\-\\/\\.\\\\]+):(\\d+)\\s?(.*)\\s?(\\(PC:\\s+.*)"); int n = reg.indexIn(QString::fromUtf8(buff)); if (n < 0) { return; } QString fileName = reg.cap(3); if (fileName.startsWith("./")) { fileName = QDir::cleanPath(m_process->workingDirectory()+"/"+fileName); } QString line = reg.cap(4); if (!fileName.isEmpty() && !line.isEmpty()) { bool ok = false; int n = line.toInt(&ok); if (ok) { m_lastFileName = fileName; m_lastFileLine = n-1; //check step out emit setCurrentLine(fileName,n-1); } } m_handleState.setStopped(true); m_asyncItem->removeRows(0,m_asyncItem->rowCount()); m_asyncItem->setText("stopped"); QString func = reg.cap(2).trimmed(); //hack if (func.contains("%")) { func.replace("%2e","."); } QString hits = reg.cap(5).trimmed(); QString pc = reg.cap(6).trimmed(); int pos = pc.indexOf('\n'); if (pos != -1) { pc.truncate(pos); } if (!hits.isEmpty()) { m_asyncItem->appendRow(new QStandardItem(hits)); } m_asyncItem->appendRow(new QStandardItem(pc)); m_asyncItem->appendRow(new QStandardItem("func="+func)); m_asyncItem->appendRow(new QStandardItem("file="+fileName)); m_asyncItem->appendRow(new QStandardItem("line="+line)); emit setExpand(LiteApi::ASYNC_MODEL,m_asyncModel->indexFromItem(m_asyncItem),true); } } void DlvDebugger::cleanup() { stop(); } void DlvDebugger::clear() { m_headlessInitAddress = false; m_lastFileLine = 0; m_lastFileName.clear(); m_dlvInit = false; m_dlvExit = false; m_readDataBusy = false; m_writeDataBusy = false; m_handleState.clear(); m_varNameMap.clear(); m_watchNameMap.clear(); m_watchList.clear(); m_updateCmdHistroy.clear(); m_nameItemMap.clear(); m_varChangedItemList.clear(); m_inbuffer.clear(); m_locationBkMap.clear(); m_cmdList.clear(); m_framesModel->removeRows(0,m_framesModel->rowCount()); m_libraryModel->removeRows(0,m_libraryModel->rowCount()); m_varsModel->removeRows(0,m_varsModel->rowCount()); m_watchModel->removeRows(0,m_watchModel->rowCount()); } void DlvDebugger::initDebug() { //get thread id m_processId.clear(); if (!m_headlessMode) { command_helper("restart",true); } QMapIterator i(m_initBks); while (i.hasNext()) { i.next(); QString fileName = i.key(); QList lines = m_initBks.values(fileName); foreach(int line, lines) { insertBreakPointHelper(fileName,line,true); } } if (m_liteApp->settings()->value(LITEDEBUG_AUTOBREAKMAIN,false).toBool()) { command_helper("break main.main",true); } command_helper("continue",true); emit debugLoaded(); } static QString valueToolTip(const QString &value) { int offset = 0; QString toolTip; QString text = value; text.replace(", ",","); for (int i = 0; i < text.size(); i++) { // if (text[i] == '[') { // int j = i; // for (; j++; j < text.size()) { // if (text[j] == ']') { // break; // } // } // toolTip += text.mid(i,j+1-i); // i = j; // continue; // } if (text[i] == '{') { if ( (i+1) < text.size() && text[i+1] == '}' ) { toolTip += "{}"; i++; } else { offset++; toolTip += text[i]; toolTip += "\n"+QString("\t").repeated(offset); } } else if (text[i] == '}') { offset--; toolTip += "\n"+QString("\t").repeated(offset); toolTip += text[i]; } else if (text[i] == ',') { toolTip += text[i]; int pos = text.lastIndexOf(QRegExp("\\{|\\[|\\]|\\}"),i-1); if (pos != -1 && text[pos] == '[') { continue; } toolTip += "\n"+QString("\t").repeated(offset); } else { toolTip += text[i]; } } return toolTip; } void DlvDebugger::readStdOutput() { QByteArray data = m_process->readAllStandardOutput(); if (!m_dlvInit) { m_dlvInit = true; initDebug(); } m_writeDataBusy = false; if (m_dlvExit) { return; } int newstart = 0; int scan = m_inbuffer.size(); m_inbuffer.append(data); //hack check (dlv) static bool first_check = true; static bool dlv_check = false; if (first_check) { first_check = false; dlv_check = m_inbuffer.indexOf("(dlv)") != -1; } if (dlv_check && !m_inbuffer.endsWith("(dlv) ")) { return; } // This can trigger when a dialog starts a nested event loop. if (m_readDataBusy) return; QStringList dataList; while (newstart < m_inbuffer.size()) { int start = newstart; int end = m_inbuffer.indexOf('\n', scan); if (end < 0) { //m_inbuffer.remove(0, start); //return; end = m_inbuffer.size()-1; } newstart = end + 1; scan = newstart; if (end == start) continue; #ifdef Q_OS_WIN if (m_inbuffer.at(end - 1) == '\r') { --end; if (end == start) continue; } #endif m_readDataBusy = true; QByteArray data = QByteArray::fromRawData(m_inbuffer.constData() + start, end - start); dataList.append(QString::fromUtf8(data)); handleResponse(data); m_readDataBusy = false; } // if (m_checkFuncDecl) { // if (m_lastFileName == m_funcDecl.fileName && m_lastFileLine >= m_funcDecl.start && m_lastFileLine <= m_funcDecl.end) { // command("next"); // m_inbuffer.clear(); // return; // } // m_checkFuncDecl = false; // m_funcDecl.clear(); // } bool emitLog = true; if (!m_updateCmdHistroy.isEmpty()) { QString cmdHistroy = m_updateCmdHistroy.takeFirst(); if (cmdHistroy == "stack") { // 0 0x000000000040135a in main.main // at H:/goproj/src/hello/main.go:24 // 1 0x000000000042c629 in runtime.main // at c:/go/go1.6/src/runtime/proc.go:188 // 2 0x0000000000456560 in runtime.goexit // at c:/go/go1.6/src/runtime/asm_amd64.s:1998 m_framesModel->removeRows(0,m_framesModel->rowCount()); QString data = QString::fromUtf8(m_inbuffer); QStringList dataList = data.split("\n",qtSkipEmptyParts); bool head = true; QList items; foreach (QString data, dataList) { if (head) { // data. items.clear(); QStringList ar = data.split(" ",qtSkipEmptyParts); if (ar.size() == 4) { items << new QStandardItem(ar[0]); items << new QStandardItem(ar[1]); items << new QStandardItem(ar[3]); } } else { data = data.trimmed(); if (data.startsWith("at")) { data = data.mid(2).trimmed(); int n = data.lastIndexOf(":"); if (n > 0) { items << new QStandardItem(data.left(n)); items << new QStandardItem(data.mid(n+1)); m_framesModel->appendRow(items); } } } head = !head; } } else if (cmdHistroy == "stack 0 -full") { // s = " \x04S\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00" // v = []int len: 0, cap: 4257785, []" // args = []string len: 1, cap: 1, ["H:\\goproj\\src\\hello\\debug"] m_varsModel->removeRows(0,m_varsModel->rowCount()); QString data = QString::fromUtf8(m_inbuffer); QStringList dataList = data.split("\n",qtSkipEmptyParts); QMap nameMap; foreach(QString text, dataList) { int n = text.indexOf("="); if (n == -1) { continue; } QString name = text.left(n).trimmed(); QString value = text.mid(n+1).trimmed(); n = value.indexOf("(unreadable"); if (n != -1) { value = value.left(n)+"(unreadable ..."; } nameMap.insert(name,value); QStandardItem *nameItem = new QStandardItem(name); QStandardItem *valueItem = new QStandardItem(value); valueItem->setToolTip(valueToolTip(value)); QMap::iterator it = m_varNameMap.find(name); if (it != m_varNameMap.end() && it.value() != value) { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::red),Qt::TextColorRole); #else valueItem->setData(Qt::red,Qt::TextColorRole); #endif } m_varsModel->appendRow(QList() << nameItem << valueItem); } m_varNameMap = nameMap; } else if (cmdHistroy.startsWith("vars ")) { foreach (QString data, QString::fromUtf8(m_inbuffer).split("\n",qtSkipEmptyParts)) { int n = data.indexOf("="); if (n >= 0) { QString name = data.left(n-1); QString value = data.mid(n+1).trimmed(); if (name.isEmpty() || value.isEmpty() || name.contains(" ")) { continue; } bool find = false; for (int i = 0; i < m_watchModel->rowCount(); i++) { QStandardItem *nameItem = m_watchModel->item(i,0); QStandardItem *valueItem = m_watchModel->item(i,1); if (nameItem->text() == name) { find = true; if (m_watchNameMap.value(name) == value) { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::black),Qt::TextColorRole); #else valueItem->setData(Qt::black,Qt::TextColorRole); #endif } else { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::red),Qt::TextColorRole); #else valueItem->setData(Qt::red,Qt::TextColorRole); #endif valueItem->setText(value); } } } if (!find) { QStandardItem *nameItem = new QStandardItem(name); nameItem->setData(name,VarNameRole); QStandardItem *valueItem = new QStandardItem(value); valueItem->setToolTip(valueToolTip(value)); m_watchModel->appendRow(QList() << nameItem << valueItem ); emit watchCreated(name,name); } m_watchNameMap.insert(name,value); } } } emitLog = false; } else if (!m_headlessMode) { emit debugLog(LiteApi::DebugApplationLog,QString::fromUtf8(m_inbuffer)); } if (emitLog) { emit debugLog(LiteApi::DebugConsoleLog,QString::fromUtf8(m_inbuffer)); } m_inbuffer.clear(); if (m_handleState.exited() && !m_dlvExit) { m_dlvExit = true; stop(); } else if (m_handleState.stopped()) { m_updateCmdList.clear(); m_updateCmdList << "stack" << "stack 0 -full"; foreach (QString s, m_watchNameMap.keys()) { if (s.isEmpty()) { continue; } m_updateCmdList << "vars "+QRegExp::escape(s); } } m_handleState.clear(); if (!m_updateCmdList.isEmpty()) { foreach(QString cmd, m_updateCmdList.takeFirst().split("|")) { m_updateCmdHistroy.push_back(cmd.trimmed()); command(cmd.trimmed().toUtf8()); } } } void DlvDebugger::finished(int code) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv exited with code %1").arg(code)); cleanup(); } void DlvDebugger::error(QProcess::ProcessError err) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv error! %1").arg(ProcessEx::processErrorText(err))); cleanup(); } void DlvDebugger::readTty(const QByteArray &data) { emit debugLog(LiteApi::DebugApplationLog,QString::fromUtf8(data)); } void DlvDebugger::headlessReadStdError() { QString data = QString::fromUtf8(m_headlessProcess->readAllStandardError()); //qDebug() << data; emit debugLog(LiteApi::DebugErrorLog,data); } void DlvDebugger::headlessReadStdOutput() { QString data = QString::fromUtf8(m_headlessProcess->readAllStandardOutput()); //API server listening at: 127.0.0.1:54151 if (!m_headlessInitAddress) { QString tmp = data.trimmed(); QString addr; if (tmp.startsWith("API")) { int pos = tmp.lastIndexOf(" "); if (pos != -1) { addr = tmp.mid(pos+1); if (addr.indexOf(":") > 0) { m_headlessInitAddress = true; } } } if (m_headlessInitAddress) { QStringList argsList; argsList << "connect" << addr; #ifdef Q_OS_WIN m_process->setNativeArguments(argsList.join(" ")); m_process->start("\""+m_dlvFilePath+"\""); #else m_process->start(m_dlvFilePath + " " + argsList.join(" ")); #endif QString log = QString("%1 %2 [%3]").arg(m_dlvFilePath).arg(argsList.join(" ")).arg(m_process->workingDirectory()); emit debugLog(LiteApi::DebugRuntimeLog,log); } } emit debugLog(LiteApi::DebugApplationLog,data); } void DlvDebugger::headlessFinished(int code) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv server exited with code %1").arg(code)); cleanup(); } void DlvDebugger::headlessError(QProcess::ProcessError err) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv server error! %1").arg(ProcessEx::processErrorText(err))); cleanup(); } ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebugger.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebugger.h // Creator: visualfc #ifndef DLVDEBUGGER_H #define DLVDEBUGGER_H #include "litedebugapi/litedebugapi.h" #include "liteenvapi/liteenvapi.h" #include "litettyapi/litettyapi.h" #include "qtc_gdbmi/gdbmi.h" #include class QProcess; class LiteProcess; class DlvHandleState { public: DlvHandleState() : m_exited(false),m_stopped(false) {} void clear() { m_reason.clear(); m_exited = false; m_stopped = false; } void setExited(bool b) {m_exited = b;} void setStopped(bool b) {m_stopped = b;} void setReason(const QByteArray &reason) { m_reason = reason; } bool exited() const { return m_exited; } bool stopped() const { return m_stopped; } QByteArray reason() const { return m_reason; } public: bool m_exited; bool m_stopped; QByteArray m_reason; }; class QStandardItemModel; class QStandardItem; class DlvDebugger : public LiteApi::IDebugger { Q_OBJECT public: DlvDebugger(LiteApi::IApplication *app, QObject *parent = 0); ~DlvDebugger(); enum VarItemDataRole{ VarNameRole = Qt::UserRole + 1, VarNumChildRole, VarExpanded }; public: virtual QString mimeType() const; virtual QAbstractItemModel *debugModel(LiteApi::DEBUG_MODEL_TYPE type); virtual void setWorkingDirectory(const QString &dir); virtual void setEnvironment (const QStringList &environment); virtual bool start(const QString &cmd, const QString &arguments); virtual void stop(); virtual bool isRunning(); virtual void stepOver(); virtual void stepInto(); virtual void stepOut(); virtual void continueRun(); virtual void runToLine(const QString &fileName, int line); virtual void command(const QByteArray &cmd); virtual void enterAppText(const QString &text); virtual void enterDebugText(const QString &text); virtual void expandItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type); virtual void setInitBreakTable(const QMultiMap &bks); virtual void setInitWatchList(const QStringList &names); virtual void insertBreakPoint(const QString &fileName, int line); virtual void removeBreakPoint(const QString &fileName, int line); bool findBreakPoint(const QString &fileName,int line); public: virtual void createWatch(const QString &var); virtual void removeWatch(const QString &value); virtual void removeAllWatch(); virtual void dbclickItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type); void showFrame(QModelIndex index); protected: void insertBreakPointHelper(const QString &fileName, int line, bool force); void command_helper(const QByteArray &cmd, bool force); public slots: void appLoaded(); void readStdError(); void readStdOutput(); void finished(int); void error(QProcess::ProcessError); void readTty(const QByteArray &data); void headlessReadStdError(); void headlessReadStdOutput(); void headlessFinished(int); void headlessError(QProcess::ProcessError err); protected: void handleResponse(const QByteArray &buff); protected: void cleanup(); void clear(); void initDebug(); protected: QString m_lastFileName; int m_lastFileLine; LiteApi::IApplication *m_liteApp; LiteApi::IEnvManager *m_envManager; QMap m_watchNameMap; QStringList m_updateCmdList; QStringList m_updateCmdHistroy; QString m_lastCmd; QString m_processId; LiteProcess *m_process; LiteProcess *m_headlessProcess; QStandardItemModel *m_asyncModel; QStandardItemModel *m_varsModel; QStandardItemModel *m_watchModel; QStandardItemModel *m_framesModel; QStandardItemModel *m_libraryModel; QStandardItem *m_asyncItem; QMap m_varNameMap; QList m_watchList; QMap m_nameItemMap; QSet m_varChangedItemList; QString m_dlvFilePath; QString m_runtimeFilePath; QByteArray m_inbuffer; DlvHandleState m_handleState; QMultiMap m_initBks; QMap m_locationBkMap; QList m_cmdList; QList m_dlvRunningCmdList; bool m_readDataBusy; bool m_writeDataBusy; bool m_dlvInit; bool m_dlvExit; bool m_headlessInitAddress; bool m_headlessMode; }; #endif // DLVDEBUGGER_H ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebugger.pro ================================================ TARGET = dlvdebugger TEMPLATE = lib CONFIG += liteide_use_dlvclient include(../../liteideplugin.pri) include(../../api/litedebugapi/litedebugapi.pri) include(../../utils/fileutil/fileutil.pri) include(../../utils/processex/processex.pri) include(../../3rdparty/qtc_gdbmi/qtc_gdbmi.pri) contains(CONFIG, liteide_use_dlvclient) { QT += network DEFINES += USE_DLVCLIENT include(../../utils/dlvclient/dlvclient.pri) include(../../3rdparty/qjsonrpc/qjsonrpc.pri) SOURCES += dlvrpcdebugger.cpp HEADERS += dlvrpcdebugger.h } DEFINES += GDBDEBUGER_LIBRARY SOURCES += dlvdebuggerplugin.cpp \ dlvdebugger.cpp \ dlvdebuggeroptionfactory.cpp \ dlvdebuggeroption.cpp HEADERS += dlvdebuggerplugin.h\ dlvdebugger_global.h \ dlvdebugger.h \ dlvdebuggeroptionfactory.h \ dlvdebuggeroption.h FORMS += \ dlvdebuggeroption.ui ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebugger_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebugger_global.h // Creator: visualfc #ifndef DLVDEBUGGER_GLOBAL_H #define DLVDEBUGGER_GLOBAL_H #include #if defined(GDBDEBUGER_LIBRARY) # define GDBDEBUGERSHARED_EXPORT Q_DECL_EXPORT #else # define GDBDEBUGERSHARED_EXPORT Q_DECL_IMPORT #endif #define OPTION_DLVDEBUGGER "option/dlvdebugger" #define DLVDEBUGGER_EXTFLAGS "dlvdebugger/extflags" #define DLVDEBUGGER_ASMSYNTAX "dlvdebugger/asmsyntax" #endif // DLVDEBUGGER_GLOBAL_H ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebuggeroption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebuggeroption.cpp // Creator: visualfc #include "dlvdebuggeroption.h" #include "ui_dlvdebuggeroption.h" #include "dlvdebugger_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end DlvDebuggerOption::DlvDebuggerOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::DlvDebuggerOption) { ui->setupUi(m_widget); } DlvDebuggerOption::~DlvDebuggerOption() { delete m_widget; delete ui; } QWidget *DlvDebuggerOption::widget() { return m_widget; } QString DlvDebuggerOption::name() const { return "DlvDebugger"; } QString DlvDebuggerOption::mimeType() const { return OPTION_DLVDEBUGGER; } void DlvDebuggerOption::load() { ui->flagsLineEdit->setText(m_liteApp->settings()->value(DLVDEBUGGER_EXTFLAGS,"").toString()); int id = m_liteApp->settings()->value(DLVDEBUGGER_ASMSYNTAX,1).toInt(); if (id >= 0 && id < ui->buttonGroup->buttons().size()) { ui->buttonGroup->buttons().at(id)->setChecked(true); } } void DlvDebuggerOption::save() { m_liteApp->settings()->setValue(DLVDEBUGGER_EXTFLAGS,ui->flagsLineEdit->text()); int size = ui->buttonGroup->buttons().size(); for (int i = 0; i < size; i++) { if (ui->buttonGroup->buttons().at(i)->isChecked()) { m_liteApp->settings()->setValue(DLVDEBUGGER_ASMSYNTAX,i); break; } } } ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebuggeroption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebuggeroption.h // Creator: visualfc #ifndef DLVDEBUGGEROPTION_H #define DLVDEBUGGEROPTION_H #include "liteapi/liteapi.h" namespace Ui { class DlvDebuggerOption; } class DlvDebuggerOption : public LiteApi::IOption { Q_OBJECT public: explicit DlvDebuggerOption(LiteApi::IApplication *app, QObject *parent = 0); ~DlvDebuggerOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void load(); virtual void save(); private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::DlvDebuggerOption *ui; }; bool isGdbDebuggerUseTty(LiteApi::IApplication *app); #endif // DLVDEBUGGEROPTION_H ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebuggeroption.ui ================================================ DlvDebuggerOption 0 0 473 213 Form Delve Pass Flags example --check-go-version=false Assembly Syntax Gnu buttonGroup Intel buttonGroup Go buttonGroup Qt::Vertical 20 40 ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebuggeroptionfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebuggeroptionfactory.cpp // Creator: visualfc #include "dlvdebuggeroption.h" #include "dlvdebuggeroptionfactory.h" #include "dlvdebugger_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end DlvDebuggerOptionFactory::DlvDebuggerOptionFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IOptionFactory(parent), m_liteApp(app) { } QStringList DlvDebuggerOptionFactory::mimeTypes() const { return QStringList() << OPTION_DLVDEBUGGER; } LiteApi::IOption *DlvDebuggerOptionFactory::create(const QString &mimeType) { if (mimeType == OPTION_DLVDEBUGGER) { return new DlvDebuggerOption(m_liteApp,this); } return 0; } ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebuggeroptionfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebuggeroptionfactory.h // Creator: visualfc #ifndef DLVDEBUGGEROPTIONFACTORY_H #define DLVDEBUGGEROPTIONFACTORY_H #include "liteapi/liteapi.h" class DlvDebuggerOptionFactory : public LiteApi::IOptionFactory { public: DlvDebuggerOptionFactory(LiteApi::IApplication *app, QObject *parent); virtual QStringList mimeTypes() const; virtual LiteApi::IOption *create(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; }; #endif // DLVDEBUGGEROPTIONFACTORY_H ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebuggerplugin.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebuggerplugin.cpp // Creator: visualfc #include "dlvdebuggerplugin.h" #include "dlvdebugger.h" #ifdef USE_DLVCLIENT #include "dlvrpcdebugger.h" #endif #include "dlvdebuggeroptionfactory.h" #include "litedebugapi/litedebugapi.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end DlvDebuggerPlugin::DlvDebuggerPlugin() { } bool DlvDebuggerPlugin::load(LiteApi::IApplication *app) { LiteApi::IDebuggerManager *manager = LiteApi::getDebugManager(app); if (!manager) { return false; } #ifdef USE_DLVCLIENT DlvRpcDebugger *debug = new DlvRpcDebugger(app); #else DlvDebugger *debug = new DlvDebugger(app); #endif manager->addDebugger(debug); manager->setCurrentDebugger(debug); app->optionManager()->addFactory(new DlvDebuggerOptionFactory(app,this)); return true; } QStringList DlvDebuggerPlugin::dependPluginList() const { return QStringList() << "plugin/litedebug"; } #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(PluginFactory,PluginFactory) #endif ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvdebuggerplugin.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvdebuggerplugin.h // Creator: visualfc #ifndef DLVDEBUGGERPLUGIN_H #define DLVDEBUGGERPLUGIN_H #include "dlvdebugger_global.h" #include "liteapi/liteapi.h" #include class DlvDebuggerPlugin : public LiteApi::IPlugin { Q_OBJECT public: DlvDebuggerPlugin(); virtual bool load(LiteApi::IApplication *app); virtual QStringList dependPluginList() const; }; class PluginFactory : public LiteApi::PluginFactoryT { Q_OBJECT Q_INTERFACES(LiteApi::IPluginFactory) #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "liteidex.DlvDebuggerPlugin") #endif public: PluginFactory() { m_info->setId("plugin/DlvDebugger"); m_info->setName("DlvDebugger"); m_info->setAuthor("visualfc"); m_info->setVer("X38.2"); m_info->setInfo("Core Delve Debugger"); m_info->setMustLoad(true); } }; #endif // DLVDEBUGGERPLUGIN_H ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvrpcdebugger.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvrpcdebugger.cpp // Creator: visualfc #include "dlvrpcdebugger.h" #include "fileutil/fileutil.h" #include "processex/processex.h" #include "dlvdebuggeroption.h" #include "dlvdebugger_global.h" #include "../litedebug/litedebug_global.h" #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static void GdbMiValueToItem(QStandardItem *item, const GdbMiValue &value) { switch (value.type()) { case GdbMiValue::Invalid: item->appendRow(new QStandardItem("Invalid")); break; case GdbMiValue::Const: if (value.name().isEmpty()) { item->appendRow(new QStandardItem(QString(value.data()))); } else { item->appendRow(new QStandardItem(QString(value.name()+"="+value.data()))); } break; case GdbMiValue::List: { QStandardItem *in = new QStandardItem(QString(value.name())); item->appendRow(in); for (int i = 0; i < value.childCount(); i++) { QStandardItem *iv = new QStandardItem(QString("[%1]").arg(i)); in->appendRow(iv); GdbMiValueToItem(iv,value.childAt(i)); } break; } case GdbMiValue::Tuple: { QStandardItem *iv = item; if (!value.name().isEmpty()) { iv = new QStandardItem(QString(value.name())); item->appendRow(iv); } foreach (const GdbMiValue &v, value.children()) { GdbMiValueToItem(iv,v); } break; } } } DlvRpcDebugger::DlvRpcDebugger(LiteApi::IApplication *app, QObject *parent) : LiteApi::IDebugger(parent), m_liteApp(app), m_envManager(0) { m_process = new LiteProcess(m_liteApp,this); m_process->setUseCtrlC(true); m_asyncModel = new QStandardItemModel(0,1,this); m_asyncItem = new QStandardItem; m_asyncModel->appendRow(m_asyncItem); /* m_asyncModel->setHeaderData(0,Qt::Horizontal,"Reason"); m_asyncModel->setHeaderData(1,Qt::Horizontal,"Address"); m_asyncModel->setHeaderData(2,Qt::Horizontal,"Function"); m_asyncModel->setHeaderData(3,Qt::Horizontal,"File"); m_asyncModel->setHeaderData(4,Qt::Horizontal,"Line"); m_asyncModel->setHeaderData(5,Qt::Horizontal,"Thread ID"); m_asyncModel->setHeaderData(6,Qt::Horizontal,"Stoped Threads"); */ m_varsModel = new QStandardItemModel(0,4,this); m_varsModel->setHeaderData(0,Qt::Horizontal,"Name"); m_varsModel->setHeaderData(1,Qt::Horizontal,"Type"); m_varsModel->setHeaderData(2,Qt::Horizontal,"Value"); m_varsModel->setHeaderData(3,Qt::Horizontal,"Address"); m_watchModel = new QStandardItemModel(0,4,this); m_watchModel->setHeaderData(0,Qt::Horizontal,"Name"); m_watchModel->setHeaderData(1,Qt::Horizontal,"Type"); m_watchModel->setHeaderData(2,Qt::Horizontal,"Value"); m_watchModel->setHeaderData(3,Qt::Horizontal,"Address"); connect(m_watchModel,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(watchItemChanged(QStandardItem*))); m_framesModel = new QStandardItemModel(0,5,this); m_framesModel->setHeaderData(0,Qt::Horizontal,"Level"); m_framesModel->setHeaderData(1,Qt::Horizontal,"Address"); m_framesModel->setHeaderData(2,Qt::Horizontal,"Function"); m_framesModel->setHeaderData(3,Qt::Horizontal,"File"); m_framesModel->setHeaderData(4,Qt::Horizontal,"Line"); m_goroutinesModel = new QStandardItemModel(0,5,this); m_goroutinesModel->setHeaderData(0,Qt::Horizontal,"Goroutine"); m_goroutinesModel->setHeaderData(1,Qt::Horizontal,"Address"); m_goroutinesModel->setHeaderData(2,Qt::Horizontal,"Function"); m_goroutinesModel->setHeaderData(3,Qt::Horizontal,"File"); m_goroutinesModel->setHeaderData(4,Qt::Horizontal,"Line"); m_threadsModel = new QStandardItemModel(0,6,this); m_threadsModel->setHeaderData(0,Qt::Horizontal,"Thread"); m_threadsModel->setHeaderData(1,Qt::Horizontal,"Goroutine"); m_threadsModel->setHeaderData(2,Qt::Horizontal,"Address"); m_threadsModel->setHeaderData(3,Qt::Horizontal,"Function"); m_threadsModel->setHeaderData(4,Qt::Horizontal,"File"); m_threadsModel->setHeaderData(5,Qt::Horizontal,"Line"); m_registersModel = new QStandardItemModel(0,2,this); m_registersModel->setHeaderData(0,Qt::Horizontal,"Name"); m_registersModel->setHeaderData(1,Qt::Horizontal,"Value"); //m_libraryModel->setHeaderData(0,Qt::Horizontal,"Id"); //m_libraryModel->setHeaderData(1,Qt::Horizontal,"Thread Groups");` // m_asynJsonItem = new QStandardItem(0,2); // m_asynJsonItem->setText("stop"); //m_libraryModel->appendRow(m_asynJsonItem); m_asmModel = new QStandardItemModel(0,6,this); m_asmModel->setHeaderData(0,Qt::Horizontal,"State"); m_asmModel->setHeaderData(1,Qt::Horizontal,"Address"); m_asmModel->setHeaderData(2,Qt::Horizontal,"Code"); m_asmModel->setHeaderData(3,Qt::Horizontal,"Text"); m_asmModel->setHeaderData(4,Qt::Horizontal,"File"); m_asmModel->setHeaderData(5,Qt::Horizontal,"Line"); m_dlvInit = false; m_dlvExit = false; m_readDataBusy = false; m_writeDataBusy = false; m_headlessInitAddress = false; m_headlessProcess = new Process(this); // m_headlessProcess->setUseCtrlC(true); m_dlvClient = new DlvClient(this); connect(m_dlvClient,SIGNAL(commandSuccess(QString,DebuggerState,QVariant)),this,SLOT(clientCommandSuccess(QString,DebuggerState,QVariant))); m_dlvRunningCmdList << "c" << "continue" << "n" << "next" << "s" << "step" << "si" << "step-instruction" << "stepout"; connect(app,SIGNAL(loaded()),this,SLOT(appLoaded())); connect(m_process,SIGNAL(started()),this,SIGNAL(debugStarted())); connect(m_process,SIGNAL(finished(int)),this,SLOT(finished(int))); connect(m_process,SIGNAL(error(QProcess::ProcessError)),this,SLOT(error(QProcess::ProcessError))); connect(m_process,SIGNAL(readyReadStandardError()),this,SLOT(readStdError())); connect(m_process,SIGNAL(readyReadStandardOutput()),this,SLOT(readStdOutput())); connect(m_headlessProcess,SIGNAL(started()),this,SIGNAL(debugStarted())); connect(m_headlessProcess,SIGNAL(finished(int)),this,SLOT(headlessFinished(int))); connect(m_headlessProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(headlessError(QProcess::ProcessError))); connect(m_headlessProcess,SIGNAL(readyReadStandardError()),this,SLOT(headlessReadStdError())); connect(m_headlessProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(headlessReadStdOutput())); } DlvRpcDebugger::~DlvRpcDebugger() { stop(); } void DlvRpcDebugger::appLoaded() { m_envManager = LiteApi::findExtensionObject(m_liteApp,"LiteApi.IEnvManager"); } QString DlvRpcDebugger::mimeType() const { return QLatin1String("debugger/delve"); } QAbstractItemModel *DlvRpcDebugger::debugModel(LiteApi::DEBUG_MODEL_TYPE type) { if (type == LiteApi::ASYNC_MODEL) { return m_asyncModel; } else if (type == LiteApi::VARS_MODEL) { return m_varsModel; } else if (type == LiteApi::WATCHES_MODEL) { return m_watchModel; }else if (type == LiteApi::FRAMES_MODEL) { return m_framesModel; } else if (type == LiteApi::GOROUTINES_MODEL) { return m_goroutinesModel; } else if (type == LiteApi::THREADS_MODEL) { return m_threadsModel; } else if (type == LiteApi::REGS_MODEL) { return m_registersModel; } else if (type == LiteApi::ASM_MODEL) { return m_asmModel; } return 0; } void DlvRpcDebugger::setWorkingDirectory(const QString &dir) { m_headlessProcess->setWorkingDirectory(dir); m_process->setWorkingDirectory(dir); } void DlvRpcDebugger::setEnvironment (const QStringList &environment) { m_headlessProcess->setEnvironment(environment); m_process->setEnvironment(environment); } bool DlvRpcDebugger::start(const QString &cmd, const QString &arguments) { if (!m_envManager) { return false; } QProcessEnvironment env = LiteApi::getGoEnvironment(m_liteApp); QString goroot = env.value("GOROOT"); if (!goroot.isEmpty()) { m_runtimeFilePath = QFileInfo(QDir(goroot),"src/pkg/runtime/").path(); } QString dlv = FileUtil::lookupGoBin("dlv",m_liteApp,env,true); if (dlv.isEmpty()) { dlv = FileUtil::lookPath("dlv",env,false); } m_dlvFilePath = dlv; //m_checkFuncDecl = false; if (m_dlvFilePath.isEmpty()) { m_liteApp->appendLog("DlvRpcDebugger","dlv was not found on system PATH (hint: is Delve installed? \"go install github.com/go-delve/delve/cmd/dlv@latest\")",true); return false; } clear(); QStringList argsList; argsList << "--headless" << "--api-version=2" << "--accept-multiclient"; QStringList flags = m_liteApp->settings()->value(DLVDEBUGGER_EXTFLAGS).toString().split(" ",qtSkipEmptyParts); if (!flags.isEmpty()) { foreach(QString flag, flags) { if (flag.startsWith("--")) { argsList << flag; } } } //argsList << "--log"; argsList << "exec" << cmd; if (!arguments.isEmpty()) { argsList << "--" << arguments; } #ifdef Q_OS_WIN //m_headlessProcess->setNativeArguments(argsList.join(" ")); m_headlessProcess->startEx("\""+m_dlvFilePath+"\"", argsList.join(" ")); #else m_headlessProcess->startEx(m_dlvFilePath, argsList.join(" ")); #endif QString log = QString("%1 %2 [%3]").arg(m_dlvFilePath).arg(argsList.join(" ")).arg(m_headlessProcess->workingDirectory()); emit debugLog(LiteApi::DebugRuntimeLog,log); return true; } void DlvRpcDebugger::stop() { m_dlvExit = true; if (!m_headlessProcess->isStop()) { m_dlvClient->Detach(); m_headlessProcess->waitForFinished(500); } if (!m_process->isStop()) { m_process->interrupt(); } if (!m_headlessProcess->isStop() && !m_headlessProcess->waitForFinished(500)) { m_headlessProcess->kill(); } if (!m_process->isStop() && !m_process->waitForFinished(500)) { command_helper("exit",true); if (!m_process->waitForFinished(500)) { m_process->kill(); } } } bool DlvRpcDebugger::isRunning() { return m_headlessProcess->state() != QProcess::NotRunning; } void DlvRpcDebugger::continueRun() { command("continue"); } void DlvRpcDebugger::stepOver() { command("next"); } void DlvRpcDebugger::stepInto() { command("step"); } void DlvRpcDebugger::stepOut() { command("stepout"); } void DlvRpcDebugger::runToLine(const QString &fileName, int line) { bool find = findBreakPoint(fileName,line); if (!find) { insertBreakPointHelper(fileName,line,true); command_helper("continue",true); removeBreakPointHelper(fileName,line,true); } else { command("continue"); } } void DlvRpcDebugger::createWatch(const QString &var) { if (var.isEmpty()) { return; } if (m_watchList.contains(var)) { return; } //m_watchNameMap.insert(var,""); m_watchList.push_back(var); emit watchCreated(var,var); if (var.contains(".")) { updateWatch(-1); return; } DebuggerState state = m_dlvClient->GetState(); if (!state.pCurrentThread) { return; } updateWatch(state.pCurrentThread->GoroutineID); // QString cmd = "vars "+QRegExp::escape(var); // m_updateCmdHistroy.push_back(cmd); // command_helper(cmd.toUtf8(),true); } void DlvRpcDebugger::removeWatch(const QString &value) { //m_watchNameMap.remove(value); m_watchList.removeAll(value); for (int i = 0; i < m_watchModel->rowCount(); i++) { QStandardItem *nameItem = m_watchModel->item(i,0); if (nameItem->text() == value) { m_watchModel->removeRow(i); break; } } emit watchRemoved(value); } void DlvRpcDebugger::removeAllWatch() { m_watchNameMap.clear(); m_watchList.clear(); m_watchModel->removeRows(0,m_watchModel->rowCount()); } void DlvRpcDebugger::gotoFileByIndex(const QStandardItemModel *model, QModelIndex index, int ifile, int iline) { QVariant file = index.sibling(index.row(),ifile).data(); QVariant line = index.sibling(index.row(),iline).data(); if( !file.isValid() || !line.isValid() ) { return; } QString filename = file.toString(); int lineno = line.toInt(); if( lineno <= 0 ) { return; } emit gotoLine(filename, lineno - 1 ); } void DlvRpcDebugger::dbclickItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type) { switch (type) { case LiteApi::FRAMES_MODEL: gotoFileByIndex(m_framesModel,index,3,4); break; case LiteApi::THREADS_MODEL: gotoFileByIndex(m_threadsModel,index,4,5); break; case LiteApi::GOROUTINES_MODEL: gotoFileByIndex(m_goroutinesModel,index,3,4); break; case LiteApi::ASM_MODEL: gotoFileByIndex(m_asmModel,index,4,5); break; } } void DlvRpcDebugger::expandItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type) { QStandardItem *parent = 0; if (type == LiteApi::VARS_MODEL) { parent = m_varsModel->itemFromIndex(index); } else if (type == LiteApi::WATCHES_MODEL) { parent = m_watchModel->itemFromIndex(index); } if (!parent) { return; } if (parent->data(VarExpanded).toInt() == 1) { return; } parent->setData(1,VarExpanded); } void DlvRpcDebugger::setInitBreakTable(const QMultiMap &bks) { m_initBks = bks; } void DlvRpcDebugger::setInitWatchList(const QStringList &names) { m_watchList = names; foreach (QString name, names) { emit watchCreated(name,name); } } void DlvRpcDebugger::insertBreakPoint(const QString &fileName, int line) { insertBreakPointHelper(fileName,line,false); } void DlvRpcDebugger::insertBreakPointHelper(const QString &fileName, int line, bool force) { line++; QString location = QString("%1:%2").arg(fileName).arg(line); if (m_locationBkMap.contains(location)) { return; } QString id = QString("bk%1").arg(qHash(location)); m_locationBkMap.insert(location,id); QStringList args; args << "break"; args << id; args << QString("%1:%2").arg(fileName).arg(line); command_helper(args.join(" ").toUtf8(),force); } void DlvRpcDebugger::removeBreakPoint(const QString &fileName, int line) { removeBreakPointHelper(fileName,line,false); } void DlvRpcDebugger::removeBreakPointHelper(const QString &fileName, int line, bool force) { line++; QString location = QString("%1:%2").arg(fileName).arg(line); QString id = m_locationBkMap.value(location); if (id.isEmpty()) { return; } m_locationBkMap.remove(location); QStringList args; args << "clear"; args << id; command_helper(args.join(" ").toUtf8(),force); } bool DlvRpcDebugger::findBreakPoint(const QString &fileName, int line) { QString location = QString("%1:%2").arg(fileName).arg(line); QString id = m_locationBkMap.value(location); return m_locationBkMap.contains(location); } void DlvRpcDebugger::command_helper(const QByteArray &cmd, bool force) { if (m_writeDataBusy && !force) { return; } m_writeDataBusy = true; m_lastCmd = cmd; if (m_dlvRunningCmdList.contains(cmd)) { m_asyncItem->removeRows(0,m_asyncItem->rowCount()); m_asyncItem->setText("runing"); } #ifdef Q_OS_WIN m_process->write(cmd+"\r\n"); #else m_process->write(cmd+"\n"); #endif } void DlvRpcDebugger::enterAppText(const QString &text) { m_updateCmdList.clear(); m_updateCmdHistroy.clear(); QString cmd = text.trimmed(); if (cmd == "r" || cmd == "restart") { m_processId.clear(); } m_headlessProcess->write(text.toUtf8()); } void DlvRpcDebugger::enterDebugText(const QString &text) { m_updateCmdList.clear(); m_updateCmdHistroy.clear(); QString cmd = text.trimmed(); if (cmd == "r" || cmd == "restart") { m_processId.clear(); } command(text.toUtf8()); } void DlvRpcDebugger::command(const QByteArray &cmd) { command_helper(cmd,false); } void DlvRpcDebugger::readStdError() { //Process 4084 has exited with status 0 QString data = QString::fromUtf8(m_process->readAllStandardError()); // qDebug() << data << m_processId; //QRegExp reg; emit debugLog(LiteApi::DebugConsoleLog,data); foreach (QString line, data.split("\n",qtSkipEmptyParts)) { if (line.startsWith("Process "+m_processId)) { m_processId.clear(); this->stop(); } } } //static bool isNameChar(char c) //{ // // could be 'stopped' or 'shlibs-added' // return (c >= 'a' && c <= 'z') || c == '-'; //} void DlvRpcDebugger::handleResponse(const QByteArray &buff) { if (buff.isEmpty()) { return; } //Process restarted with PID 4532 //> main.main() H:/goproj/src/hello/main.go:13 (hits goroutine(1):1 total:1) (PC: 0x401172) //> main.main() H:/goproj/src/hello/main.go:14 (PC: 0x401179) //> main.main() H:/goproj/src/hello/main.go:21 (hits goroutine(1):1 total:1) (PC: 0x40161a) //> fmt.Println() c:/go/go1.6/src/fmt/print.go:263 (PC: 0x45aeca) //> runtime.convT2E() c:/go/go1.6/src/runtime/iface.go:128 (PC: 0x40caaa)" //> github.com/derekparker/delve/cmd/dlv/cmds.New() /src/github.com/derekparker/delve/cmd/dlv/cmds/commands.go:61 (PC: 0x45d09f) //> [bk6767010] main.test() H:/goproj/src/hello/main.go:12 (hits goroutine(1):1 total:1) (PC: 0x401066) //> [bk101903173] github.com/derekparker/delve/vendor/github.com/spf13/cobra.(*Command).Execute() github.com/derekparker/delve/vendor/github.com/spf13/cobra/command.go:615 (hits goroutine(1):1 total:1) (PC: 0x524ea6) //> qlang.io/qlang%2espec%2ev1.Import() //> main.main() goapi/_test/_testmain.go:50 (hits goroutine(1):1 total:1) (PC: 0x4011ca) //> [bk3711824616] main.test[go.shape.int_0]() ./main.go:9 (hits goroutine(1):1 total:1) (PC: 0x10b2be2) //> [bk1584098684] main.(*My[go.shape.int]).Test1() c:/dev/demo/main.go:16 (hits goroutine(1):1 total:1) (PC: 0x4daa88) if (buff.contains("> ")) { // [bk] main.test[shape]() file:line static QRegExp reg(">(\\s+\\[[\\w\\d]+\\])?\\s+([\\w\\d_\\-\\.\\%\\*\\[\\]\\(\\)\\/]+)\\(\\)\\s+((?:[a-zA-Z]:)?[\\w\\d_@\\s\\-\\/\\.\\\\]+):(\\d+)\\s?(.*)\\s?(\\(PC:\\s+.*)"); int n = reg.indexIn(QString::fromUtf8(buff)); if (n < 0) { return; } QString fileName = reg.cap(3); if (fileName.startsWith("./")) { fileName = QDir::cleanPath(m_process->workingDirectory()+"/"+fileName); } QString line = reg.cap(4); if (!fileName.isEmpty() && !line.isEmpty()) { bool ok = false; int n = line.toInt(&ok); if (ok) { m_lastFileName = fileName; m_lastFileLine = n-1; //check step out emit setCurrentLine(fileName,n-1); } } m_handleState.setStopped(true); m_asyncItem->removeRows(0,m_asyncItem->rowCount()); m_asyncItem->setText("stopped"); QString func = reg.cap(2).trimmed(); //hack if (func.contains("%")) { func.replace("%2e","."); } QString hits = reg.cap(5).trimmed(); QString pc = reg.cap(6).trimmed(); int pos = pc.indexOf('\n'); if (pos != -1) { pc.truncate(pos); } if (!hits.isEmpty()) { m_asyncItem->appendRow(new QStandardItem(hits)); } m_asyncItem->appendRow(new QStandardItem(pc)); m_asyncItem->appendRow(new QStandardItem("func="+func)); m_asyncItem->appendRow(new QStandardItem("file="+fileName)); m_asyncItem->appendRow(new QStandardItem("line="+line)); emit setExpand(LiteApi::ASYNC_MODEL,m_asyncModel->indexFromItem(m_asyncItem),true); } } void DlvRpcDebugger::cleanup() { stop(); } void DlvRpcDebugger::clear() { m_headlessInitAddress = false; m_lastFileLine = 0; m_lastFileName.clear(); m_dlvInit = false; m_dlvExit = false; m_readDataBusy = false; m_writeDataBusy = false; m_handleState.clear(); m_checkVarsMap.clear(); m_watchNameMap.clear(); m_watchList.clear(); m_updateCmdHistroy.clear(); m_nameItemMap.clear(); m_varChangedItemList.clear(); m_inbuffer.clear(); m_locationBkMap.clear(); m_cmdList.clear(); m_framesModel->removeRows(0,m_framesModel->rowCount()); m_threadsModel->removeRows(0,m_threadsModel->rowCount()); m_goroutinesModel->removeRows(0,m_goroutinesModel->rowCount()); m_varsModel->removeRows(0,m_varsModel->rowCount()); m_watchModel->removeRows(0,m_watchModel->rowCount()); m_asmModel->removeRows(0,m_asmModel->rowCount()); } void DlvRpcDebugger::initDebug() { //get thread id m_processId.clear(); QMapIterator i(m_initBks); while (i.hasNext()) { i.next(); QString fileName = i.key(); QList lines = m_initBks.values(fileName); foreach(int line, lines) { insertBreakPointHelper(fileName,line,true); } } if (m_liteApp->settings()->value(LITEDEBUG_AUTOBREAKMAIN,false).toBool()) { command_helper("break main.main",true); } command_helper("continue",true); emit debugLoaded(); } static QString valueToolTip(const QString &value) { int offset = 0; QString toolTip; QString text = value; text.replace(", ",","); for (int i = 0; i < text.size(); i++) { // if (text[i] == '[') { // int j = i; // for (; j++; j < text.size()) { // if (text[j] == ']') { // break; // } // } // toolTip += text.mid(i,j+1-i); // i = j; // continue; // } if (text[i] == '{') { if ( (i+1) < text.size() && text[i+1] == '}' ) { toolTip += "{}"; i++; } else { offset++; toolTip += text[i]; toolTip += "\n"+QString("\t").repeated(offset); } } else if (text[i] == '}') { offset--; toolTip += "\n"+QString("\t").repeated(offset); toolTip += text[i]; } else if (text[i] == ',') { toolTip += text[i]; int pos = text.lastIndexOf(QRegExp("\\{|\\[|\\]|\\}"),i-1); if (pos != -1 && text[pos] == '[') { continue; } toolTip += "\n"+QString("\t").repeated(offset); } else { toolTip += text[i]; } } return toolTip; } void DlvRpcDebugger::readStdOutput() { QByteArray data = m_process->readAllStandardOutput(); if (!m_dlvInit) { m_dlvInit = true; initDebug(); } m_writeDataBusy = false; if (m_dlvExit) { return; } int newstart = 0; int scan = m_inbuffer.size(); m_inbuffer.append(data); //hack check (dlv) static bool first_check = true; static bool dlv_check = false; if (first_check) { first_check = false; dlv_check = m_inbuffer.indexOf("(dlv)") != -1; } if (dlv_check && !m_inbuffer.endsWith("(dlv) ")) { return; } // This can trigger when a dialog starts a nested event loop. if (m_readDataBusy) return; QStringList dataList; while (newstart < m_inbuffer.size()) { int start = newstart; int end = m_inbuffer.indexOf('\n', scan); if (end < 0) { //m_inbuffer.remove(0, start); //return; end = m_inbuffer.size()-1; } newstart = end + 1; scan = newstart; if (end == start) continue; #ifdef Q_OS_WIN if (m_inbuffer.at(end - 1) == '\r') { --end; if (end == start) continue; } #endif m_readDataBusy = true; QByteArray data = QByteArray::fromRawData(m_inbuffer.constData() + start, end - start); dataList.append(QString::fromUtf8(data)); handleResponse(data); m_readDataBusy = false; } // if (m_checkFuncDecl) { // if (m_lastFileName == m_funcDecl.fileName && m_lastFileLine >= m_funcDecl.start && m_lastFileLine <= m_funcDecl.end) { // command("next"); // m_inbuffer.clear(); // return; // } // m_checkFuncDecl = false; // m_funcDecl.clear(); // } bool emitLog = true; if (!m_updateCmdHistroy.isEmpty()) { QString cmdHistroy = m_updateCmdHistroy.takeFirst(); if (cmdHistroy == "stack") { // 0 0x000000000040135a in main.main // at H:/goproj/src/hello/main.go:24 // 1 0x000000000042c629 in runtime.main // at c:/go/go1.6/src/runtime/proc.go:188 // 2 0x0000000000456560 in runtime.goexit // at c:/go/go1.6/src/runtime/asm_amd64.s:1998 m_framesModel->removeRows(0,m_framesModel->rowCount()); QString data = QString::fromUtf8(m_inbuffer); QStringList dataList = data.split("\n",qtSkipEmptyParts); bool head = true; QList items; foreach (QString data, dataList) { if (head) { // data. items.clear(); QStringList ar = data.split(" ",qtSkipEmptyParts); if (ar.size() == 4) { items << new QStandardItem(ar[0]); items << new QStandardItem(ar[1]); items << new QStandardItem(ar[3]); } } else { data = data.trimmed(); if (data.startsWith("at")) { data = data.mid(2).trimmed(); int n = data.lastIndexOf(":"); if (n > 0) { QString fileName = data.left(n); QString fileLine = data.mid(n+1); if (fileName.startsWith("./")) { fileName = QDir::cleanPath(m_process->workingDirectory()+"/"+fileName); } items << new QStandardItem(fileName); items << new QStandardItem(fileLine); m_framesModel->appendRow(items); } } } head = !head; } } else if (cmdHistroy == "stack 0 -full") { // s = " \x04S\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00" // v = []int len: 0, cap: 4257785, []" // args = []string len: 1, cap: 1, ["H:\\goproj\\src\\hello\\debug"] m_varsModel->removeRows(0,m_varsModel->rowCount()); QString data = QString::fromUtf8(m_inbuffer); QStringList dataList = data.split("\n",qtSkipEmptyParts); QMap nameMap; foreach(QString text, dataList) { int n = text.indexOf("="); if (n == -1) { continue; } QString name = text.left(n).trimmed(); QString value = text.mid(n+1).trimmed(); n = value.indexOf("(unreadable"); if (n != -1) { value = value.left(n)+"(unreadable ..."; } nameMap.insert(name,value); QStandardItem *nameItem = new QStandardItem(name); QStandardItem *valueItem = new QStandardItem(value); valueItem->setToolTip(valueToolTip(value)); QMap::iterator it = m_checkVarsMap.find(name); if (it != m_checkVarsMap.end() && it.value() != value) { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::red),Qt::TextColorRole); #else valueItem->setData(Qt::red,Qt::TextColorRole); #endif } m_varsModel->appendRow(QList() << nameItem << valueItem); } m_checkVarsMap = nameMap; } else if (cmdHistroy.startsWith("vars ")) { foreach (QString data, QString::fromUtf8(m_inbuffer).split("\n",qtSkipEmptyParts)) { int n = data.indexOf("="); if (n >= 0) { QString name = data.left(n-1); QString value = data.mid(n+1).trimmed(); if (name.isEmpty() || value.isEmpty() || name.contains(" ")) { continue; } bool find = false; for (int i = 0; i < m_watchModel->rowCount(); i++) { QStandardItem *nameItem = m_watchModel->item(i,0); QStandardItem *valueItem = m_watchModel->item(i,1); if (nameItem->text() == name) { find = true; if (m_watchNameMap.value(name) == value) { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::black),Qt::TextColorRole); #else valueItem->setData(Qt::black,Qt::TextColorRole); #endif } else { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::red),Qt::TextColorRole); #else valueItem->setData(Qt::red,Qt::TextColorRole); #endif valueItem->setText(value); } } } if (!find) { QStandardItem *nameItem = new QStandardItem(name); nameItem->setData(name,VarNameRole); QStandardItem *valueItem = new QStandardItem(value); valueItem->setToolTip(valueToolTip(value)); m_watchModel->appendRow(QList() << nameItem << valueItem ); emit watchCreated(name,name); } m_watchNameMap.insert(name,value); } } } emitLog = false; } if (emitLog) { emit debugLog(LiteApi::DebugConsoleLog,QString::fromUtf8(m_inbuffer)); } m_inbuffer.clear(); if (m_handleState.exited() && !m_dlvExit) { m_dlvExit = true; stop(); } else if (m_handleState.stopped()) { DebuggerState state = m_dlvClient->GetState(); if (state.pCurrentThread) { m_updateCmdList.clear(); //m_updateCmdList << "stack";// << "stack 0 -full"; int id = state.pCurrentThread->GoroutineID; updateStackframe(id); updateVariable(id); updateWatch(id); updateThreads(state.Threads); updateGoroutines(); updateRegisters(state.pCurrentThread->ID,true); updateAsm(id,state.pCurrentThread->PC); } } m_handleState.clear(); if (!m_updateCmdList.isEmpty()) { foreach(QString cmd, m_updateCmdList.takeFirst().split("|")) { m_updateCmdHistroy.push_back(cmd.trimmed()); command(cmd.trimmed().toUtf8()); } } } void DlvRpcDebugger::updateWatch(int id) { QList watch; QList errList; foreach (QString s, m_watchList) { if (s.isEmpty()) { continue; } int gid = id; if (s.contains(".")) { gid = -1; } VariablePointer pt = m_dlvClient->EvalVariable(EvalScope(gid),s,LoadConfig::Long128(3)); if (pt) { watch.push_back(*pt); } else { errList.push_back(s); } } emit beginUpdateModel(LiteApi::WATCHES_MODEL); m_watchModel->removeRows(0,m_watchModel->rowCount()); foreach (QString name, errList) { QStandardItem *item = new QStandardItem(name); item->setData(name,VarNameRole); QStandardItem *type = new QStandardItem("not find"); #if QT_VERSION >= 0x050000 type->setData(QColor(Qt::red),Qt::TextColorRole); #else type->setData(Qt::red,Qt::TextColorRole); #endif m_watchModel->appendRow(QList() << item << type); } QMap saveMap; updateVariableHelper(watch,m_watchModel,0,"",0,saveMap,m_checkWatchMap); m_checkWatchMap = saveMap; emit endUpdateModel(LiteApi::WATCHES_MODEL); } void DlvRpcDebugger::updateVariable(int id) { QList vars = m_dlvClient->ListLocalVariables(EvalScope(id),LoadConfig::Long128(3)); QList args = m_dlvClient->ListFunctionArgs(EvalScope(id),LoadConfig::Long128(3)); QMap saveMap; emit beginUpdateModel(LiteApi::VARS_MODEL); m_varsModel->removeRows(0,m_varsModel->rowCount()); updateVariableHelper(args,m_varsModel,0,"",0,saveMap,m_checkVarsMap); updateVariableHelper(vars,m_varsModel,0,"",0,saveMap,m_checkVarsMap); m_checkVarsMap = saveMap; emit endUpdateModel(LiteApi::VARS_MODEL); } void DlvRpcDebugger::updateStackframe(int id) { QList frames = m_dlvClient->Stacktrace(id,128,LoadConfig::Long128(3)); emit beginUpdateModel(LiteApi::FRAMES_MODEL); m_framesModel->removeRows(0,m_framesModel->rowCount()); int index = 0; foreach(Stackframe f, frames) { QList items; items << new QStandardItem(QString("%1").arg(index)); items << new QStandardItem(QString("0x%1").arg(f.PC,0,16)); if (f.pFunction) { items << new QStandardItem(f.pFunction->Name); } else { items << new QStandardItem(""); } items << new QStandardItem(f.File); items << new QStandardItem(QString("%1").arg(f.Line)); m_framesModel->appendRow(items); index++; } emit endUpdateModel(LiteApi::FRAMES_MODEL); } static bool threadIdThan(const Thread &s1, const Thread &s2) { if (s1.GoroutineID != s2.GoroutineID) { return s1.GoroutineID > s2.GoroutineID; } return s1.ID < s2.ID; } void DlvRpcDebugger::updateThreads(const QList &threads) { QList ths = threads; qSort(ths.begin(),ths.end(),threadIdThan); emit beginUpdateModel(LiteApi::THREADS_MODEL); m_threadsModel->removeRows(0,m_threadsModel->rowCount()); foreach (Thread t, ths) { QStandardItem *item = new QStandardItem(QString("%1").arg(t.ID)); QStandardItem *gitem = new QStandardItem(QString("%1").arg(t.GoroutineID)); QStandardItem *file = new QStandardItem(t.File); QStandardItem *line = new QStandardItem(QString("%1").arg(t.Line)); QStandardItem *pc = new QStandardItem(QString("0x%1").arg(t.PC,0,16)); QStandardItem *func = new QStandardItem; if (t.pFunction) { func->setText(t.pFunction->Name); } m_threadsModel->appendRow(QList() << item << gitem << pc << func << file << line); } emit endUpdateModel(LiteApi::THREADS_MODEL); } static void appendLocationItem(QStandardItem *parent, const QString &name, const Location &loc) { QStandardItem *item = new QStandardItem(name); QStandardItem *file = new QStandardItem(loc.File); QStandardItem *line = new QStandardItem(QString("%1").arg(loc.Line)); QStandardItem *pc = new QStandardItem(QString("0x%1").arg(loc.PC,0,16)); QStandardItem *func = new QStandardItem; if (loc.pFunction) { func->setText(loc.pFunction->Name); } parent->appendRow(QList() << item << pc << func << file << line); } static void appendLocationRoot(QStandardItemModel *parent, QStandardItem *item, const Location &loc) { QStandardItem *file = new QStandardItem(loc.File); QStandardItem *line = new QStandardItem(QString("%1").arg(loc.Line)); QStandardItem *pc = new QStandardItem(QString("0x%1").arg(loc.PC,0,16)); QStandardItem *func = new QStandardItem; if (loc.pFunction) { func->setText(loc.pFunction->Name); } parent->appendRow(QList() << item << pc << func << file << line); } /* const ( Gidle uint64 = iota // 0 Grunnable // 1 runnable and on a run queue Grunning // 2 Gsyscall // 3 Gwaiting // 4 GmoribundUnused // 5 currently unused, but hardcoded in gdb scripts Gdead // 6 Genqueue // 7 Only the Gscanenqueue is used. Gcopystack // 8 in this state when newstack is moving the stack ) */ void DlvRpcDebugger::updateGoroutines() { QList lst = m_dlvClient->ListGoroutines(); emit beginUpdateModel(LiteApi::GOROUTINES_MODEL); m_goroutinesModel->removeRows(0,m_goroutinesModel->rowCount()); foreach (Goroutine g, lst) { QString value; if (g.ThreadId != 0) { value = QString("(thread %1)").arg(g.ThreadId); } if ( (g.Status == 4 || g.Status == 3) && g.WaitReason != 0) { if (!value.isEmpty()) { value += " "; } value += "["+waitReason(int(g.WaitReason)); if (g.WaitSince > 0) { value += QString(" %1").arg(g.WaitSince); } value += "]"; } QStandardItem *item = new QStandardItem(QString("Goroutine %1 %2").arg(g.ID).arg(value)); appendLocationItem(item,"Runtime",g.CurrentLoc); appendLocationItem(item,"Go",g.GoStatementLoc); appendLocationItem(item,"Star",g.StartLoc); appendLocationRoot(m_goroutinesModel,item,g.UserCurrentLoc); } emit endUpdateModel(LiteApi::GOROUTINES_MODEL); } void DlvRpcDebugger::updateAsm(int id, quint64 pc) { int flag = m_liteApp->settings()->value(DLVDEBUGGER_ASMSYNTAX,1).toInt(); QList asms = m_dlvClient->DisassemblePC(EvalScope(id),pc,AssemblyFlavour(flag)); emit beginUpdateModel(LiteApi::ASM_MODEL); m_asmModel->removeRows(0,m_asmModel->rowCount()); QModelIndex at; foreach(AsmInstruction a, asms) { QString head; if (a.AtPC) { head = "=>"; } if (a.Breakpoint) { head += "*"; } QStandardItem *item = new QStandardItem(head); QStandardItem *pc = new QStandardItem(QString("0x%1").arg(a.Loc.PC,0,16)); QStandardItem *file = new QStandardItem(a.Loc.File); QStandardItem *line = new QStandardItem(QString("%1").arg(a.Loc.Line)); QStandardItem *inst = new QStandardItem(QString(a.Bytes.toHex())); QStandardItem *text = new QStandardItem(a.Text); m_asmModel->appendRow(QList() << item << pc << inst << text << file << line); if (a.AtPC) { at = m_asmModel->indexFromItem(item); } } emit endUpdateModel(LiteApi::ASM_MODEL); if (at.isValid()) { emit scrollTo(LiteApi::ASM_MODEL, at); } } void DlvRpcDebugger::updateRegisters(int threadid, bool includeFp) { QList regs = m_dlvClient->ListRegisters(threadid,includeFp); emit beginUpdateModel(LiteApi::REGS_MODEL); m_registersModel->removeRows(0,m_registersModel->rowCount()); QMap saveMap; foreach (Register r, regs) { QStandardItem *name = new QStandardItem(r.Name); QStandardItem *valueItem = new QStandardItem(r.Value); QMap::const_iterator it = m_checkRegsMap.find(r.Name); if (it != m_checkRegsMap.end() && it.value() != r.Value) { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::red),Qt::TextColorRole); #else valueItem->setData(Qt::red,Qt::TextColorRole); #endif } saveMap.insert(r.Name,r.Value); m_registersModel->appendRow(QList() << name << valueItem); } m_checkRegsMap = saveMap; emit endUpdateModel(LiteApi::REGS_MODEL); } static Variable parserRealVar(const Variable &var) { if (var.Type.startsWith("*")) { if (var.Children.size() == 1) { return parserRealVar(var.Children[0]); } } return var; } void DlvRpcDebugger::updateVariableHelper(const QList &vars, QStandardItemModel *model, QStandardItem *parent, const QString &parentName, int flag, QMap &saveMap, const QMap &checkMap) { int index = -1; foreach (Variable var, vars) { index++; QStandardItem *nameItem = new QStandardItem(var.Name); nameItem->setData(var.Name,VarNameRole); QStandardItem *typeItem = new QStandardItem(var.Type); QStandardItem *valueItem = new QStandardItem(var.Value); valueItem->setToolTip(var.Value); QStandardItem *addrItem = new QStandardItem(QString("0x%1").arg(var.Addr,0,16)); QString checkName = parentName+"."+var.Name; // slice [] if (flag == 2) { checkName = parentName+"."+QString("%1").arg(index); nameItem->setText(QString("[%1]").arg(index)); } QString rtype = var.Type; int rlen = var.Len; int rcap = var.Cap; QList children = var.Children; if (var.Type.startsWith("*")) { Variable rv = parserRealVar(var); rtype = rv.Type; rlen = rv.Len; rcap = rv.Cap; children = rv.Children; if (var.Addr != rv.Addr) { addrItem->setText(QString("0x%1 => 0x%2").arg(var.Addr,0,16).arg(rv.Addr,0,16)); } } //children flag int cflag = 1; if (rtype.startsWith("[]")) { cflag = 2; typeItem->setText(QString("%1 ").arg(var.Type).arg(rlen).arg(rcap)); //valueItem->setText(QString("(len:%1,cap:%2)").arg(var.Len).arg(var.Cap)); } else if (rtype.startsWith("map[")) { cflag = 3; typeItem->setText(QString("%1 ").arg(var.Type).arg(rlen)); } else if (rtype == "string") { cflag = 4; typeItem->setText(QString("%1 ").arg(var.Type).arg(rlen)); } else if (!children.isEmpty()) { cflag = 5; if (rlen > 0) { typeItem->setText(QString("%1 ").arg(var.Type).arg(rlen)); } } if (!children.isEmpty()) { updateVariableHelper(children,model,nameItem,checkName,cflag,saveMap,checkMap); } QMap::const_iterator it = checkMap.find(checkName); if (it != checkMap.end() && it.value() != var.Value) { #if QT_VERSION >= 0x050000 valueItem->setData(QColor(Qt::red),Qt::TextColorRole); #else valueItem->setData(Qt::red,Qt::TextColorRole); #endif } saveMap.insert(checkName,var.Value); if (parent) { parent->appendRow(QList() << nameItem << typeItem << valueItem << addrItem); } else { model->appendRow(QList() << nameItem << typeItem << valueItem << addrItem); } } } void DlvRpcDebugger::finished(int code) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv exited with code %1").arg(code)); cleanup(); } void DlvRpcDebugger::error(QProcess::ProcessError err) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv error! %1").arg(ProcessEx::processErrorText(err))); cleanup(); } void DlvRpcDebugger::readTty(const QByteArray &data) { emit debugLog(LiteApi::DebugApplationLog,QString::fromUtf8(data)); } void DlvRpcDebugger::headlessReadStdError() { QString data = QString::fromUtf8(m_headlessProcess->readAllStandardError()); //qDebug() << data; emit debugLog(LiteApi::DebugErrorLog,data); } static void buildMap(QStandardItem *item, const QMap &m) { QMapIterator i(m); while (i.hasNext()) { i.next(); QString key = i.key(); QVariant value = i.value(); if (!key.isEmpty() && value.isValid()) { if (value.type() == QVariant::Map) { QStandardItem *child = new QStandardItem(key); buildMap(child,value.toMap()); item->appendRow(child); } else if (value.type() == QVariant::List) { QStandardItem *child = new QStandardItem(key); item->appendRow(child); int index = 0; foreach (QVariant v, value.toList()) { QStandardItem *aitem = new QStandardItem(QString("[%1]").arg(index++)); child->appendRow(aitem); if (v.type() == QVariant::Map) { buildMap(aitem,v.toMap()); } else { aitem->appendColumn(QList() << new QStandardItem(v.toString())); } } } else { item->appendRow(QList() << new QStandardItem(key) << new QStandardItem(value.toString())); } } } } static void buildMapId(QStandardItem *item, const QVariant &var, const QString &id) { item->setText(id); buildMap(item,var.toMap().value(id).toMap()); } static void buildListId(QStandardItem *item, const QVariant &var, const QString &id) { item->setText(id); //buildMap(item,var.toMap().value(id).toList()); foreach (QVariant li, var.toMap().value(id).toList()) { buildMap(item,li.toMap()); } } void DlvRpcDebugger::headlessReadStdOutput() { QString data = QString::fromUtf8(m_headlessProcess->readAllStandardOutput()); //API server listening at: 127.0.0.1:54151 if (!m_headlessInitAddress) { QString tmp = data.trimmed(); QString addr; if (tmp.startsWith("API")) { int pos = tmp.lastIndexOf(" "); if (pos != -1) { addr = tmp.mid(pos+1); if (addr.indexOf(":") > 0) { m_headlessInitAddress = true; } } } if (m_headlessInitAddress) { m_dlvClient->Connect(addr); // b = m_dlvInfo->Connect(addr); // if (b) { // QMapIterator i(m_initBks); // while (i.hasNext()) { // i.next(); // QString fileName = i.key(); // QList lines = m_initBks.values(fileName); // foreach(int line, lines) { // //insertBreakPointHelper(fileName,line,true); // Breakpoint bp; // bp.File = fileName; // bp.Line = line; // BreakpointPointer p = m_dlvClient->CreateBreakpoint(bp); // qDebug() << p; // } // } // m_dlvClient->CreateBreakpointByFuncName("main.main"); // DebuggerState state = m_dlvClient->Continue(); // updateState(state,m_dlvClient->LastJsonData()); // //command_helper("break main.main",true); // //command_helper("continue",true); // emit debugLoaded(); // return; // } QStringList argsList; argsList << "connect" << addr; #ifdef Q_OS_WIN m_process->setNativeArguments(argsList.join(" ")); m_process->start("\""+m_dlvFilePath+"\""); #else m_process->start(m_dlvFilePath + " " + argsList.join(" ")); #endif QString log = QString("%1 %2 [%3]").arg(m_dlvFilePath).arg(argsList.join(" ")).arg(m_process->workingDirectory()); emit debugLog(LiteApi::DebugRuntimeLog,log); } } emit debugLog(LiteApi::DebugApplationLog,data); } void DlvRpcDebugger::headlessFinished(int code) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv server exited with code %1").arg(code)); cleanup(); } void DlvRpcDebugger::headlessError(QProcess::ProcessError err) { emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Dlv server error! %1").arg(ProcessEx::processErrorText(err))); cleanup(); } void DlvRpcDebugger::clientCommandSuccess(const QString &/*method*/, const DebuggerState &/*state*/, const QVariant &/*jsonData*/) { } void DlvRpcDebugger::updateState(const DebuggerState &state, const QVariant &jsonData) { if (state.Exited) { stop(); } if (state.NextInProgress) { m_asyncItem->setText("Running"); } else { m_asyncItem->setText("Stopped"); } m_asyncItem->removeRows(0,m_asyncItem->rowCount()); if (state.pCurrentThread) { QString fileName = state.pCurrentThread->File; int line = state.pCurrentThread->Line; if (!fileName.isEmpty() && line >= 0) { emit setCurrentLine(fileName,line-1); } QList items; items << new QStandardItem(QString("goroutine(%1)").arg(state.pCurrentThread->GoroutineID)); if (state.pCurrentThread->pFunction) { items << new QStandardItem(QString("func=%1").arg(state.pCurrentThread->pFunction->Name)); } items << new QStandardItem(QString("file=%1").arg(fileName)); items << new QStandardItem(QString("line=%1").arg(line)); m_asyncItem->appendRows(items); } // m_asyncItem->removeRows(0,m_asyncItem->rowCount()); // buildMapId(m_asyncItem,jsonData,"State"); // if (!state.pCurrentThread.isNull()) { // QString fileName = state.pCurrentThread->File; // int line = state.pCurrentThread->Line; // if (!fileName.isEmpty() && line >= 0) { // emit setCurrentLine(fileName,line-1); // } // } emit setExpand(LiteApi::ASYNC_MODEL,m_asyncModel->indexFromItem(m_asyncItem),true); } void DlvRpcDebugger::watchItemChanged(QStandardItem *item) { if (!item || item->column() != 0) { return; } QString oldName = item->data(VarNameRole).toString(); QString newName = item->text(); if (oldName == newName) { return; } emit watchRemoved(oldName); if (!m_watchList.contains(newName)) { int i = m_watchList.indexOf(oldName); if (i >= 0) { m_watchList.replace(i,newName); } emit watchCreated(newName,newName); } else { m_watchList.removeAll(oldName); } DebuggerState state = m_dlvClient->GetState(); if (!state.pCurrentThread) { return; } updateWatch(state.pCurrentThread->GoroutineID); } ================================================ FILE: liteidex/src/plugins/dlvdebugger/dlvrpcdebugger.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2018 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: dlvrpcdebugger.h // Creator: visualfc #ifndef DLVRPCDEBUGGER_H #define DLVRPCDEBUGGER_H #include "litedebugapi/litedebugapi.h" #include "liteenvapi/liteenvapi.h" #include "litettyapi/litettyapi.h" #include "qtc_gdbmi/gdbmi.h" #include "dlvclient/dlvclient.h" #include class QProcess; class LiteProcess; class Process; class GdbHandleState { public: GdbHandleState() : m_exited(false),m_stopped(false) {} void clear() { m_reason.clear(); m_exited = false; m_stopped = false; } void setExited(bool b) {m_exited = b;} void setStopped(bool b) {m_stopped = b;} void setReason(const QByteArray &reason) { m_reason = reason; } bool exited() const { return m_exited; } bool stopped() const { return m_stopped; } QByteArray reason() const { return m_reason; } public: bool m_exited; bool m_stopped; QByteArray m_reason; }; class QStandardItemModel; class QStandardItem; struct funcDecl { funcDecl() { clear(); } void clear() { fileName.clear();; funcName.clear(); start = -1; end = -1; } QString fileName; QString funcName; int start; int end; }; class DlvRpcDebugger : public LiteApi::IDebugger { Q_OBJECT public: DlvRpcDebugger(LiteApi::IApplication *app, QObject *parent = 0); ~DlvRpcDebugger(); enum VarItemDataRole{ VarNameRole = Qt::UserRole + 1, VarNumChildRole, VarExpanded }; public: virtual QString mimeType() const; virtual QAbstractItemModel *debugModel(LiteApi::DEBUG_MODEL_TYPE type); virtual void setWorkingDirectory(const QString &dir); virtual void setEnvironment (const QStringList &environment); virtual bool start(const QString &cmd, const QString &arguments); virtual void stop(); virtual bool isRunning(); virtual void stepOver(); virtual void stepInto(); virtual void stepOut(); virtual void continueRun(); virtual void runToLine(const QString &fileName, int line); virtual void command(const QByteArray &cmd); virtual void enterAppText(const QString &text); virtual void enterDebugText(const QString &text); virtual void expandItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type); virtual void setInitBreakTable(const QMultiMap &bks); virtual void setInitWatchList(const QStringList &names); virtual void insertBreakPoint(const QString &fileName, int line); virtual void removeBreakPoint(const QString &fileName, int line); bool findBreakPoint(const QString &fileName,int line); public: virtual void createWatch(const QString &var); virtual void removeWatch(const QString &value); virtual void removeAllWatch(); virtual void dbclickItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type); void gotoFileByIndex(const QStandardItemModel *model, QModelIndex index, int file, int line); protected: void insertBreakPointHelper(const QString &fileName, int line, bool force); void removeBreakPointHelper(const QString &fileName, int line, bool force); void command_helper(const QByteArray &cmd, bool force); void updateWatch(int id); void updateVariable(int id); void updateStackframe(int id); void updateThreads(const QList &ths); void updateGoroutines(); void updateAsm(int id, quint64 pc); void updateRegisters(int threadid, bool includeFp); void updateVariableHelper(const QList &vars, QStandardItemModel *model, QStandardItem *parent, const QString &parentName, int flag, QMap &saveMap, const QMap &checkMap); public slots: void appLoaded(); void readStdError(); void readStdOutput(); void finished(int); void error(QProcess::ProcessError); void readTty(const QByteArray &data); void headlessReadStdError(); void headlessReadStdOutput(); void headlessFinished(int); void headlessError(QProcess::ProcessError err); void clientCommandSuccess(const QString &method, const DebuggerState &state, const QVariant &jsonData); void updateState(const DebuggerState &state, const QVariant &jsonData); void watchItemChanged(QStandardItem* item); protected: void handleResponse(const QByteArray &buff); protected: void cleanup(); void clear(); void initDebug(); protected: QString m_lastFileName; int m_lastFileLine; LiteApi::IApplication *m_liteApp; LiteApi::IEnvManager *m_envManager; QMap m_watchNameMap; QStringList m_updateCmdList; QStringList m_updateCmdHistroy; QString m_lastCmd; QString m_processId; LiteProcess *m_process; Process *m_headlessProcess; DlvClient *m_dlvClient; QStandardItemModel *m_asyncModel; QStandardItemModel *m_varsModel; QStandardItemModel *m_watchModel; QStandardItemModel *m_framesModel; QStandardItemModel *m_threadsModel; QStandardItemModel *m_goroutinesModel; QStandardItemModel *m_registersModel; QStandardItemModel *m_asmModel; QStandardItem *m_asyncItem; QStandardItem *m_varsItem; QMap m_checkVarsMap; QMap m_checkWatchMap; QMap m_checkRegsMap; QList m_watchList; QMap m_nameItemMap; QSet m_varChangedItemList; QString m_dlvFilePath; QString m_runtimeFilePath; QByteArray m_inbuffer; GdbHandleState m_handleState; QMultiMap m_initBks; QMap m_locationBkMap; QList m_cmdList; QList m_dlvRunningCmdList; bool m_readDataBusy; bool m_writeDataBusy; bool m_dlvInit; bool m_dlvExit; bool m_headlessInitAddress; }; #endif // DLVRPCDEBUGGER_H ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimedit.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimedit.cpp // Creator: jsuppe #include "fakevim/fakevim/fakevimhandler.h" #include "fakevim/fakevim/fakevimactions.h" #include "fakevimedit.h" #include "fakevimedit_global.h" #include "qtc_editutil/uncommentselection.h" #include "litebuildapi/litebuildapi.h" #include "fileutil/fileutil.h" #include #include #include #include #include #include #include #include #include "liteeditorapi/liteeditorapi.h" #include "../liteeditor/liteeditor_global.h" using namespace FakeVim::Internal; //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FakeVimEdit::FakeVimEdit(LiteApi::IApplication *app, QObject *parent) : QObject(parent), m_liteApp(app), m_enableUseFakeVim(false), m_commandLabel(0) { connect(m_liteApp->editorManager(),SIGNAL(editorCreated(LiteApi::IEditor*)),this,SLOT(editorCreated(LiteApi::IEditor*))); connect(m_liteApp->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*))); connect(m_liteApp->optionManager(),SIGNAL(applyOption(QString)),this,SLOT(applyOption(QString))); this->applyOption(OPTION_FAKEVIMEDIT); m_enableUseFakeVim = m_liteApp->settings()->value(FAKEVIMEDIT_USEFAKEVIM,false).toBool(); m_enableUseFakeVimAct = new QAction(tr("Use FakeVim Editing"),this); m_enableUseFakeVimAct->setCheckable(true); m_enableUseFakeVimAct->setChecked(m_enableUseFakeVim); connect(m_enableUseFakeVimAct,SIGNAL(toggled(bool)),this,SLOT(toggledEnableUseFakeVim(bool))); if (m_enableUseFakeVim) { _enableFakeVim(); } } void FakeVimEdit::toggledEnableUseFakeVim(bool b) { m_enableUseFakeVim = b; m_liteApp->settings()->setValue(FAKEVIMEDIT_USEFAKEVIM,b); if(m_enableUseFakeVim){ _enableFakeVim(); }else{ _disableFakeVim(); } } void FakeVimEdit::applyOption(const QString &option) { if (option != OPTION_FAKEVIMEDIT) { return; } m_initCommandList = m_liteApp->settings()->value(FAKEVIMEDIT_INITCOMMANDS,initCommandList()).toStringList(); } void FakeVimEdit::_enableFakeVim(){ LiteApi::IEditor *editor = m_liteApp->editorManager()->currentEditor(); _addCommandLabel(); _addFakeVimToEditor(editor); } void FakeVimEdit::_disableFakeVim(){ LiteApi::IEditor *editor = m_liteApp->editorManager()->currentEditor(); _removeFakeVimFromEditor(editor); _removeCommandLabel(); } QFont FakeVimEdit::commandLabelFont(){ QFont font; font.setStyleHint(QFont::Monospace); font.setBold(true); return font; } void FakeVimEdit::_addCommandLabel(){ QFont font = commandLabelFont(); _removeCommandLabel(); m_commandLabel = new QLabel(m_liteApp->mainWindow()); m_commandLabel->setFont(font); m_liteApp->mainWindow()->statusBar()->addPermanentWidget(m_commandLabel); } void FakeVimEdit::_removeCommandLabel(){ if(!m_commandLabel){ return; } m_liteApp->mainWindow()->statusBar()->removeWidget(m_commandLabel); delete m_commandLabel; m_commandLabel = NULL; } void FakeVimEdit::_removeFakeVimFromEditor(LiteApi::IEditor *editor){ LiteApi::ILiteEditor *ed = LiteApi::getLiteEditor(editor); if (!ed) { return; } QString mime = editor->mimeType(); bool tabToSpace = false; int tabWidth = 4; LiteApi::IMimeType *im = m_liteApp->mimeTypeManager()->findMimeType(mime); if (im) { tabToSpace = im->tabToSpace(); tabWidth = im->tabWidth(); } tabWidth = m_liteApp->settings()->value(MIMETYPE_TABWIDTH+mime,tabWidth).toInt(); tabToSpace = m_liteApp->settings()->value(MIMETYPE_TABTOSPACE+mime,tabToSpace).toBool(); ed->setTabOption(tabWidth,tabToSpace); QPlainTextEdit *ped = LiteApi::getPlainTextEdit(ed); if(!ped){ return; } if(FakeVimHandler *fakeVimHandler = m_editorMap.value(ped)){ delete fakeVimHandler; m_editorMap.remove(ped); } } void FakeVimEdit::_addFakeVimToEditor(LiteApi::IEditor *editor){ LiteApi::ILiteEditor *ed = LiteApi::getLiteEditor(editor); if (!ed) { return; } QPlainTextEdit *ped = LiteApi::getPlainTextEdit(ed); if(!ped){ return; } if(m_editorMap.contains(ped)){ return; } FakeVimHandler *fakeVimHandler; fakeVimHandler = new FakeVimHandler(ped,0); connect(fakeVimHandler, SIGNAL(handleExCommandRequested(bool*,ExCommand)), this, SLOT(handleExCommandRequested(bool*,ExCommand))); connect(fakeVimHandler, SIGNAL(commandBufferChanged(QString,int,int,int,QObject*)), this, SLOT(showMessage(QString,int))); connect(fakeVimHandler, SIGNAL(moveToMatchingParenthesis(bool *, bool *, QTextCursor *)), this, SLOT(moveToMatchingParenthesis(bool *, bool *,QTextCursor *))); //init command list { fakeVimHandler->handleCommand("set shiftwidth=4"); fakeVimHandler->handleCommand("set tabstop=4"); foreach(QString cmd, m_initCommandList) { if (cmd.startsWith("#")) { continue; } fakeVimHandler->handleCommand(cmd); } fakeVimHandler->handleInput(""); } fakeVimHandler->setCurrentFileName(ed->filePath()); fakeVimHandler->installEventFilter(); fakeVimHandler->setupWidget(); connect(ped, SIGNAL(destroyed(QObject*)), this, SLOT(plainTextEditDestroyed(QObject*))); m_editorMap[ped] = fakeVimHandler; } void FakeVimEdit::plainTextEditDestroyed(QObject *obj) { m_editorMap.remove(obj); } void FakeVimEdit::handleExCommandRequested(bool *b, ExCommand c) { // Save if(c.cmd == "w" ){ m_liteApp->editorManager()->saveEditor(m_editor); *b = true; } // Save & Close if(c.cmd == "x"){ m_liteApp->editorManager()->saveEditor(m_editor); m_liteApp->editorManager()->closeEditor(m_editor); *b = true; } // Close if(c.cmd == "q"){ if(c.hasBang){ m_editor->reload(); } m_liteApp->editorManager()->closeEditor(m_editor); *b = true; } } void FakeVimEdit::moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor) { LiteApi::IEditor *editor = m_editor; LiteApi::IActionContext *actionContext = m_liteApp->actionManager()->getActionContext(editor,"Editor"); LiteApi::ActionInfo *info = actionContext->actionInfo("GotoMatchBrace"); info->action->trigger(); int oldPos = cursor->position(); int newPos = this->m_editor->textCursor().position(); cursor->setPosition(newPos); if(oldPos <= newPos){ *forward = true; }else{ *forward = false; } if(oldPos == newPos){ *moved = false; }else{ *moved = true; } } void FakeVimEdit::editorCreated(LiteApi::IEditor *editor) { if (!editor) { return; } QMenu *menu = LiteApi::getEditMenu(editor); if (menu) { menu->addSeparator(); menu->addAction(m_enableUseFakeVimAct); } if (!m_enableUseFakeVim){ return; } m_editor = LiteApi::getLiteEditor(editor); if (m_editor) { m_plainTextEdit = LiteApi::getPlainTextEdit(editor); }else{ return; } if(!m_enableUseFakeVim) return; _addFakeVimToEditor(editor); } void FakeVimEdit::currentEditorChanged(LiteApi::IEditor *editor) { if (!editor) { return; } m_editor = LiteApi::getLiteEditor(editor); QPlainTextEdit *ped = LiteApi::getPlainTextEdit(editor); if (m_enableUseFakeVim){ if(!m_editorMap.contains(ped)) { _addFakeVimToEditor(editor); } }else{ if (m_editorMap.contains(ped)) { _removeFakeVimFromEditor(editor); } } } void FakeVimEdit::showMessage(QString contents, int cursorPos) { if(!m_commandLabel){ return; } QString m_statusMessage = cursorPos == -1 ? contents : contents.left(cursorPos) + QChar(10073) + contents.mid(cursorPos); int slack = 14 - m_statusMessage.size(); QString msg = m_statusMessage + QString(slack, QLatin1Char(' ')); m_commandLabel->setText(msg); } ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimedit.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimedit.h // Creator: jsuppe #ifndef FAKEVIMEDIT_H #define FAKEVIMEDIT_H #include #include #include #include "processex/processex.h" #include "textoutput/textoutput.h" #include "fakevim/fakevim/fakevimhandler.h" using namespace FakeVim::Internal; class QLabel; class FakeVimEdit : public QObject { Q_OBJECT public: explicit FakeVimEdit(LiteApi::IApplication *app, QObject *parent = 0); virtual ~FakeVimEdit(){} static QFont commandLabelFont(); public slots: void applyOption(const QString &option); void editorCreated(LiteApi::IEditor*); void currentEditorChanged(LiteApi::IEditor*); void toggledEnableUseFakeVim(bool b); protected slots: void showMessage(QString contents, int); void plainTextEditDestroyed(QObject *); void handleExCommandRequested(bool*,ExCommand); private slots: void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor); private: FakeVimEdit(const FakeVimEdit&); FakeVimEdit& operator=(const FakeVimEdit&); void _addFakeVimToEditor(LiteApi::IEditor *editor); void _removeFakeVimFromEditor(LiteApi::IEditor *editor); void _addCommandLabel(); void _removeCommandLabel(); void _enableFakeVim(); void _disableFakeVim(); LiteApi::IApplication *m_liteApp; LiteApi::ILiteEditor *m_editor; QPlainTextEdit *m_plainTextEdit; bool m_enableUseFakeVim; QLabel *m_commandLabel; QMap m_editorMap; QAction *m_enableUseFakeVimAct; QStringList m_initCommandList; }; #endif // FAKEVIMEDIT_H ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimedit.pro ================================================ TARGET = fakevimedit TEMPLATE = lib include (../../liteideplugin.pri) include (../../api/litefindapi/litefindapi.pri) include (../../api/liteeditorapi/liteeditorapi.pri) include (../../3rdparty/fakevim/fakevim/fakevim.pri) DEFINES += FAKEVIMEDIT_LIBRARY SOURCES += fakevimeditplugin.cpp \ fakevimedit.cpp \ fakevimeditoption.cpp \ fakevimeditoptionfactory.cpp HEADERS += fakevimeditplugin.h\ fakevimedit_global.h \ fakevimedit.h \ fakevimeditoption.h \ fakevimeditoptionfactory.h FORMS += \ fakevimeditoption.ui ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimedit_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimedit_global.h // Creator: jsuppe #ifndef FAKEVIMEDIT_GLOBAL_H #define FAKEVIMEDIT_GLOBAL_H #include #if defined(FAKEVIMEDIT_LIBRARY) # define FAKEVIMEDITSHARED_EXPORT Q_DECL_EXPORT #else # define FAKEVIMEDITSHARED_EXPORT Q_DECL_IMPORT #endif #define OPTION_FAKEVIMEDIT "option/fakevimedit" #define FAKEVIMEDIT_USEFAKEVIM "fakevimedit/usefakevim" #define FAKEVIMEDIT_INITCOMMANDS "fakevimedit/initcommands" inline QStringList make_init_list() { QStringList list; list << "#this is fakevim init command list"; list << "set nopasskeys"; list << "set nopasscontrolkey"; list << "set shiftwidth=4"; list << "set tabstop=4"; list << "set autoindent"; //list << "#source fakevimrc"; return list; } inline QStringList initCommandList() { static QStringList list = make_init_list(); return list; } #endif // FAKEVIMEDIT_GLOBAL_H ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimeditoption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimeditoption.cpp // Creator: jsuppe #include "fakevimeditoption.h" #include "ui_fakevimeditoption.h" #include "fakevimedit_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FakeVimEditOption::FakeVimEditOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::FakeVimEditOption) { ui->setupUi(m_widget); connect(ui->resetCommandsButton,SIGNAL(clicked(bool)),this,SLOT(on_resetCommandsButton_clicked())); } FakeVimEditOption::~FakeVimEditOption() { delete m_widget; delete ui; } QWidget *FakeVimEditOption::widget() { return m_widget; } QString FakeVimEditOption::name() const { return "FakeVimEdit"; } QString FakeVimEditOption::mimeType() const { return OPTION_FAKEVIMEDIT; } void FakeVimEditOption::load() { QStringList cmds = m_liteApp->settings()->value(FAKEVIMEDIT_INITCOMMANDS,initCommandList()).toStringList(); ui->textInitCommands->setPlainText(cmds.join("\n")); } void FakeVimEditOption::save() { //bool useFakeVim = ui->enableUseFakeVimCheckBox->isChecked(); QStringList cmds = ui->textInitCommands->toPlainText().split("\n",qtSkipEmptyParts); m_liteApp->settings()->setValue(FAKEVIMEDIT_INITCOMMANDS,cmds); } void FakeVimEditOption::on_resetCommandsButton_clicked() { ui->textInitCommands->setPlainText(initCommandList().join("\n")); } ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimeditoption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimeditoption.h // Creator: jsuppe #ifndef FAKEVIMEDITOPTION_H #define FAKEVIMEDITOPTION_H #include "liteapi/liteapi.h" namespace Ui { class FakeVimEditOption; } class FakeVimEditOption : public LiteApi::IOption { Q_OBJECT public: explicit FakeVimEditOption(LiteApi::IApplication *app, QObject *parent = 0); ~FakeVimEditOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void load(); virtual void save(); private slots: void on_resetCommandsButton_clicked(); private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::FakeVimEditOption *ui; }; #endif // FAKEVIMEDITOPTION_H ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimeditoption.ui ================================================ FakeVimEditOption 0 0 395 242 Form FakeVim initialization command list (# start is comment): Load default init command list Qt::Horizontal 40 20 Qt::Vertical 20 40 ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimeditoptionfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimeditoptionfactory.cpp // Creator: jsuppe #include "fakevimeditoption.h" #include "fakevimeditoptionfactory.h" #include "fakevimedit_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FakeVimEditOptionFactory::FakeVimEditOptionFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IOptionFactory(parent), m_liteApp(app) { } QStringList FakeVimEditOptionFactory::mimeTypes() const { return QStringList() << OPTION_FAKEVIMEDIT; } LiteApi::IOption *FakeVimEditOptionFactory::create(const QString &mimeType) { if (mimeType == OPTION_FAKEVIMEDIT) { return new FakeVimEditOption(m_liteApp,this); } return 0; } ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimeditoptionfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimeditoptionfactory.h // Creator: jsuppe #ifndef FAKEVIMEDITOPTIONFACTORY_H #define FAKEVIMEDITOPTIONFACTORY_H #include "liteapi/liteapi.h" class FakeVimEditOptionFactory : public LiteApi::IOptionFactory { public: FakeVimEditOptionFactory(LiteApi::IApplication *app, QObject *parent); virtual QStringList mimeTypes() const; virtual LiteApi::IOption *create(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; }; #endif // FAKEVIMEDITOPTIONFACTORY_H ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimeditplugin.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimeditplugin.cpp // Creator: jsuppe #include "fakevimedit.h" #include "fakevimeditplugin.h" #include "fakevimeditoptionfactory.h" #include "liteeditorapi/liteeditorapi.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FakeVimEditPlugin::FakeVimEditPlugin() { } bool FakeVimEditPlugin::load(LiteApi::IApplication *app) { app->optionManager()->addFactory(new FakeVimEditOptionFactory(app,this)); new FakeVimEdit(app,this); return true; } #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(PluginFactory,PluginFactory) #endif ================================================ FILE: liteidex/src/plugins/fakevimedit/fakevimeditplugin.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: fakevimeditplugin.h // Creator: jsuppe #ifndef FAKEVIMEDITPLUGIN_H #define FAKEVIMEDITPLUGIN_H #include "liteapi/liteapi.h" class FakeVimEditPlugin : public LiteApi::IPlugin { Q_OBJECT public: FakeVimEditPlugin(); virtual bool load(LiteApi::IApplication *app); }; class PluginFactory : public LiteApi::PluginFactoryT { Q_OBJECT Q_INTERFACES(LiteApi::IPluginFactory) #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "liteidex.FakeVimEditPlugin") #endif public: PluginFactory() { m_info->setId("plugin/FakeVimEdit"); m_info->setVer("X31"); m_info->setName("FakeVimEdit"); m_info->setAuthor("jsuppe"); m_info->setInfo("Fake Vim Edit Support"); m_info->appendDepend("plugin/liteeditor"); } }; #endif // FAKEVIMEDITPLUGIN_H ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowser.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowser.cpp // Creator: visualfc #include "filebrowser.h" #include "golangdocapi/golangdocapi.h" #include "liteenvapi/liteenvapi.h" #include "litebuildapi/litebuildapi.h" #include "litedebugapi/litedebugapi.h" #include "fileutil/fileutil.h" #include "filebrowser_global.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end #endif FileBrowser::FileBrowser(LiteApi::IApplication *app, QObject *parent) : QObject(parent), m_liteApp(app) { m_widget = new QWidget; QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->setMargin(0); mainLayout->setSpacing(0); QDir::Filters filters = QDir::AllDirs | QDir::Files | QDir::Drives | QDir::Readable| QDir::Writable | QDir::Executable /*| QDir::Hidden*/ | QDir::NoDotAndDotDot; bool bShowHiddenFiles = m_liteApp->settings()->value(FILEBROWSER_SHOWHIDDENFILES,false).toBool(); if (bShowHiddenFiles) { filters |= QDir::Hidden; } bool bShowDetails = m_liteApp->settings()->value(FILEBROWSER_SHOWDETAILS,false).toBool(); #ifdef Q_OS_WIN // Symlinked directories can cause file watcher warnings on Win32. filters |= QDir::NoSymLinks; #endif //create filter toolbar //m_filterToolBar = new QToolBar(m_widget); //m_filterToolBar->setIconSize(QSize(16,16)); #ifdef Q_OS_MAC m_folderView = new FolderView(true,m_liteApp); #else m_folderView = new FolderView(false,m_liteApp); #endif m_folderView->setRootIsDecorated(true); m_folderView->setFilter(filters); m_syncAct = new QAction(QIcon("icon:images/sync.png"),tr("Synchronize with editor"),this); m_syncAct->setCheckable(true); m_reloadAct = new QAction(QIcon("icon:filebrowser/images/reload.png"),tr("Reload Folder"),this); m_showHideFilesAct = new QAction(tr("Show Hidden Files"),this); m_showHideFilesAct->setCheckable(true); if (bShowHiddenFiles) { m_showHideFilesAct->setChecked(true); } connect(m_showHideFilesAct,SIGNAL(triggered(bool)),this,SLOT(showHideFiles(bool))); m_showDetailsAct = new QAction(tr("Show Details"),this); m_showDetailsAct->setCheckable(true); if (bShowDetails) { m_showDetailsAct->setChecked(true); } connect(m_showDetailsAct,SIGNAL(triggered(bool)),m_folderView,SLOT(setShowDetails(bool))); m_folderView->setShowDetails(bShowDetails); m_executeFileAct = new QAction(tr("Execute File"),this); connect(m_executeFileAct,SIGNAL(triggered()),this,SLOT(executeFile())); m_debugFileAct = new QAction(tr("Debug File"),this); connect(m_debugFileAct,SIGNAL(triggered()),this,SLOT(debugFile())); // m_filterCombo = new QComboBox; // m_filterCombo->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); // m_filterCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); // m_filterCombo->setEditable(true); // m_filterCombo->addItem("*"); // m_filterCombo->addItem("Makefile;*.go;*.cgo;*.s;*.goc;*.y;*.e64;*.pro"); // m_filterCombo->addItem("*.sh;Makefile;*.go;*.cgo;*.s;*.goc;*.y;*.*.c;*.cpp;*.h;*.hpp;*.e64;*.pro"); //m_filterToolBar->addAction(m_syncAct); //m_filterToolBar->addSeparator(); //m_filterToolBar->addWidget(m_filterCombo); //create root toolbar m_rootToolBar = new QToolBar(m_widget); m_rootToolBar->setIconSize(QSize(16,16)); m_cdupAct = new QAction(QIcon("icon:filebrowser/images/cdup.png"),tr("Open Parent"),this); m_rootCombo = new QComboBox; m_rootCombo->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); m_rootCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); m_rootCombo->setEditable(false); m_rootToolBar->addAction(m_cdupAct); m_rootToolBar->addAction(m_reloadAct); m_rootToolBar->addSeparator(); m_rootToolBar->addWidget(m_rootCombo); //mainLayout->addWidget(m_filterToolBar); mainLayout->addWidget(m_rootToolBar); mainLayout->addWidget(m_folderView); m_widget->setLayout(mainLayout); m_setRootAct = new QAction(tr("Set As Root Folder"),this); m_openFolderInNewWindowAct = new QAction(tr("Open Folder in New Window"),this); m_addToFoldersAct = new QAction(tr("Add to Folders"),this); connect(m_setRootAct,SIGNAL(triggered()),this,SLOT(setFolderToRoot())); connect(m_cdupAct,SIGNAL(triggered()),this,SLOT(cdUp())); connect(m_openFolderInNewWindowAct,SIGNAL(triggered()),this,SLOT(openFolderInNewWindow())); connect(m_addToFoldersAct,SIGNAL(triggered()),this,SLOT(addToFolders())); QList actions; m_filterMenu = new QMenu(tr("Filter")); m_filterMenu->setIcon(QIcon("icon:images/filter.png")); m_filterMenu->addAction(m_showHideFilesAct); m_filterMenu->addAction(m_showDetailsAct); actions << m_filterMenu->menuAction() << m_syncAct; m_toolWindowAct = m_liteApp->toolWindowManager()->addToolWindow(Qt::LeftDockWidgetArea,m_widget,"FileSystem",tr("File System"),true,actions); connect(m_toolWindowAct,SIGNAL(toggled(bool)),this,SLOT(visibilityChanged(bool))); //connect(m_filterCombo,SIGNAL(activated(QString)),this,SLOT(activatedFilter(QString))); connect(m_rootCombo,SIGNAL(activated(QString)),this,SLOT(activatedRoot(QString))); connect(m_syncAct,SIGNAL(triggered(bool)),this,SLOT(syncFileModel(bool))); connect(m_reloadAct,SIGNAL(triggered()),this,SLOT(reloadFileModel())); connect(m_liteApp->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*))); connect(m_folderView,SIGNAL(aboutToShowContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo)),this,SLOT(aboutToShowContextMenu(QMenu*,LiteApi::FILESYSTEM_CONTEXT_FLAG,QFileInfo))); //connect(m_folderView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(openEditor(QModelIndex))); connect(m_folderView,SIGNAL(enterKeyPressed(QModelIndex)),this,SLOT(enterKeyPressedFolderView(QModelIndex))); connect(m_folderView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedFolderView(QModelIndex))); QString root = m_liteApp->settings()->value("FileBrowser/root","").toString(); if (!root.isEmpty()) { addFolderToRoot(root); } bool b = m_liteApp->settings()->value("FileBrowser/synceditor",true).toBool(); if (b) { m_syncAct->setChecked(true); } } FileBrowser::~FileBrowser() { QString root = m_rootCombo->currentText(); m_liteApp->settings()->setValue("FileBrowser/root",root); m_liteApp->settings()->setValue("FileBrowser/synceditor",m_syncAct->isChecked()); m_liteApp->settings()->setValue(FILEBROWSER_SHOWHIDDENFILES,m_showHideFilesAct->isChecked()); m_liteApp->settings()->setValue(FILEBROWSER_SHOWDETAILS,m_showDetailsAct->isChecked()); delete m_filterMenu; delete m_widget; } void FileBrowser::visibilityChanged(bool) { } void FileBrowser::currentEditorChanged(LiteApi::IEditor *editor) { if (!m_syncAct->isChecked()) { return; } if (!editor) { return; } QString fileName = editor->filePath(); if (fileName.isEmpty()) { return; } QFileInfo info(fileName); addFolderToRoot(info.path()); QModelIndex index = m_folderView->indexForPath(fileName); if (!index.isValid()) { return; } m_folderView->scrollTo(index,QAbstractItemView::EnsureVisible); m_folderView->clearSelection(); m_folderView->setCurrentIndex(index); } void FileBrowser::syncFileModel(bool b) { if (b == false) { return; } else { currentEditorChanged(m_liteApp->editorManager()->currentEditor()); } } void FileBrowser::reloadFileModel() { m_folderView->reload(); } void FileBrowser::aboutToShowContextMenu(QMenu *menu, LiteApi::FILESYSTEM_CONTEXT_FLAG flag, const QFileInfo &info) { m_liteApp->fileManager()->emitAboutToShowFolderContextMenu(menu,flag,info,"filebrowser"); if (flag == LiteApi::FILESYSTEM_FILES) { QString cmd = FileUtil::lookPathInDir(info.fileName(),info.path()); if (!cmd.isEmpty()) { QAction *act = 0; if (!menu->actions().isEmpty()) { act = menu->actions().at(0); } menu->insertAction(act,m_executeFileAct); bool hasGo = false; foreach(QFileInfo info, QDir(info.path()).entryInfoList(QDir::Files)) { if (info.suffix() == "go") { hasGo = true; break; } } if (hasGo) { menu->insertAction(act,m_debugFileAct); } menu->insertSeparator(act); } } else if (flag == LiteApi::FILESYSTEM_FOLDER || flag == LiteApi::FILESYSTEM_ROOTFOLDER) { menu->addSeparator(); if (flag == LiteApi::FILESYSTEM_ROOTFOLDER) { menu->addAction(m_cdupAct); } else { menu->addAction(m_setRootAct); } menu->addAction(m_addToFoldersAct); menu->addAction(m_openFolderInNewWindowAct); } } void FileBrowser::showHideFiles(bool b) { if (isShowHideFiles() == b) { return; } QDir::Filters filters = m_folderView->filter(); if (b) { filters |= QDir::Hidden; } else { filters ^= QDir::Hidden; } m_folderView->setFilter(filters); } bool FileBrowser::isShowHideFiles() const { return m_folderView->filter() & QDir::Hidden; } void FileBrowser::openFolderInNewWindow() { QDir dir = m_folderView->contextDir(); m_liteApp->fileManager()->openFolderInNewWindow(dir.path()); } void FileBrowser::addToFolders() { QDir dir = m_folderView->contextDir(); m_liteApp->fileManager()->addFolderList(dir.path()); } void FileBrowser::executeFile() { LiteApi::ILiteBuild *build = LiteApi::getLiteBuild(m_liteApp); if (build) { QFileInfo info = m_folderView->contextFileInfo(); QString cmd = FileUtil::lookPathInDir(info.fileName(),info.path()); if (!cmd.isEmpty()) { build->execCommand(cmd,QString(),info.path(),true,true,false); } } } void FileBrowser::debugFile() { LiteApi::ILiteDebug *debug = LiteApi::getLiteDebug(m_liteApp); if (debug) { QFileInfo info = m_folderView->contextFileInfo(); debug->startDebug(info.fileName(),"",info.path()); } } void FileBrowser::enterKeyPressedFolderView(const QModelIndex &index) { QFileInfo info = m_folderView->fileInfo(index); if (info.isFile()) { m_liteApp->fileManager()->openEditor(info.filePath()); } else if (info.isDir()) { m_folderView->setExpanded(index,!m_folderView->isExpanded(index)); } } void FileBrowser::doubleClickedFolderView(const QModelIndex &index) { QFileInfo info = m_folderView->fileInfo(index); if (info.isFile()) { m_liteApp->fileManager()->openEditor(info.filePath()); } } void FileBrowser::addFolderToRoot(const QString &path) { int index = -1; for (int i = 0; i < m_rootCombo->count(); i++) { QString text = m_rootCombo->itemText(i); if (text == path) { index = i; break; } } if (index == -1) { m_rootCombo->addItem(path); index = m_rootCombo->count()-1; } m_rootCombo->setCurrentIndex(index); activatedRoot(path); } void FileBrowser::setFolderToRoot() { QDir dir = m_folderView->contextDir(); addFolderToRoot(dir.path()); } void FileBrowser::activatedRoot(QString path) { m_folderView->setRootPath(path); } void FileBrowser::cdUp() { QString path = m_folderView->rootPath(); if (path.isEmpty()) { return; } QDir dir(path); if (!dir.path().isEmpty() && dir.cdUp()) { addFolderToRoot(dir.path()); } } ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowser.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowser.h // Creator: visualfc #ifndef FILEBROWSER_H #define FILEBROWSER_H #include "liteapi/liteapi.h" #include "folderview/folderview.h" #include class QComboBox; class QLineEdit; class FileBrowser : public QObject { Q_OBJECT public: explicit FileBrowser(LiteApi::IApplication *app,QObject *parent = 0); virtual ~FileBrowser(); public slots: void showHideFiles(bool b); bool isShowHideFiles() const; void visibilityChanged(bool); void activatedRoot(QString); void syncFileModel(bool); void reloadFileModel(); void currentEditorChanged(LiteApi::IEditor*); void aboutToShowContextMenu(QMenu* menu,LiteApi::FILESYSTEM_CONTEXT_FLAG flag,const QFileInfo &fileInfo); protected slots: void setFolderToRoot(); void cdUp(); void openFolderInNewWindow(); void addToFolders(); void executeFile(); void debugFile(); void enterKeyPressedFolderView(const QModelIndex &index); void doubleClickedFolderView(const QModelIndex &index); protected: void addFolderToRoot(const QString &path); protected: LiteApi::IApplication *m_liteApp; QWidget *m_widget; FolderView *m_folderView; QComboBox *m_rootCombo; //QComboBox *m_filterCombo; //QToolBar *m_filterToolBar; QToolBar *m_rootToolBar; QAction *m_syncAct; QAction *m_showHideFilesAct; QAction *m_showDetailsAct; QAction *m_reloadAct; QMenu *m_filterMenu; protected: QAction *m_toolWindowAct; QAction *m_cdupAct; QAction *m_setRootAct; QAction *m_openExplorerAct; QAction *m_openFolderInNewWindowAct; QAction *m_addToFoldersAct; QAction *m_executeFileAct; QAction *m_debugFileAct; }; #endif // FILEBROWSER_H ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowser.pro ================================================ TARGET = filebrowser TEMPLATE = lib include(../../liteideplugin.pri) include(../../utils/fileutil/fileutil.pri) include(../../utils/folderview/folderview.pri) include(../../utils/symboltreeview/symboltreeview.pri) include(../../api/litebuildapi/litebuildapi.pri) include(../../api/golangdocapi/golangdocapi.pri) DEFINES += FILEBROWSER_LIBRARY SOURCES += filebrowserplugin.cpp \ filebrowser.cpp \ filebrowseroptionfactory.cpp \ filebrowseroption.cpp \ HEADERS += filebrowserplugin.h\ filebrowser_global.h \ filebrowser.h \ filebrowseroptionfactory.h \ filebrowseroption.h RESOURCES += \ filebrowser.qrc FORMS += \ filebrowseroption.ui ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowser.qrc ================================================ images/sync.png images/cdup.png images/reload.png ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowser_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowser_global.h // Creator: visualfc #ifndef FILEBROWSER_GLOBAL_H #define FILEBROWSER_GLOBAL_H #include #if defined(FILEBROWSER_LIBRARY) # define FILEBROWSERSHARED_EXPORT Q_DECL_EXPORT #else # define FILEBROWSERSHARED_EXPORT Q_DECL_IMPORT #endif #define FILEBROWSER_SHOWHIDDENFILES "FileBrowser/ShowHiddenFiles" #define FILEBROWSER_SHOWDETAILS "FileBrowser/ShowDetails" #endif // FILEBROWSER_GLOBAL_H ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowseroption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowseroption.cpp // Creator: visualfc #include "filebrowseroption.h" #include "ui_filebrowseroption.h" #include "filebrowser.h" #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FileBrowserOption::FileBrowserOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::FileBrowserOption) { ui->setupUi(m_widget); } FileBrowserOption::~FileBrowserOption() { delete m_widget; delete ui; } QWidget *FileBrowserOption::widget() { return m_widget; } QString FileBrowserOption::name() const { return "FileBrowser"; } QString FileBrowserOption::mimeType() const { return "option/filebrowser"; } void FileBrowserOption::load() { } void FileBrowserOption::save() { QString cmd = ui->cmdLineEdit->text().trimmed(); QString args = ui->argsLineEdit->text().trimmed(); m_liteApp->settings()->setValue("filebrowser/shell_cmd",cmd); m_liteApp->settings()->setValue("filebrowser/shell_args",args.split(" ",qtSkipEmptyParts)); } ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowseroption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowseroption.h // Creator: visualfc #ifndef FILEBROWSEROPTION_H #define FILEBROWSEROPTION_H #include "liteapi/liteapi.h" namespace Ui { class FileBrowserOption; } class FileBrowserOption : public LiteApi::IOption { Q_OBJECT public: explicit FileBrowserOption(LiteApi::IApplication *app, QObject *parent = 0); ~FileBrowserOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void load(); virtual void save(); private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::FileBrowserOption *ui; }; #endif // FILEBROWSEROPTION_H ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowseroption.ui ================================================ FileBrowserOption 0 0 400 118 Form Terminal Command: Arguments: Qt::Vertical 20 164 ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowseroptionfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowseroptionfactory.cpp // Creator: visualfc #include "filebrowseroption.h" #include "filebrowseroptionfactory.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FileBrowserOptionFactory::FileBrowserOptionFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IOptionFactory(parent), m_liteApp(app) { } QStringList FileBrowserOptionFactory::mimeTypes() const { return QStringList() << "option/filebrowser"; } LiteApi::IOption *FileBrowserOptionFactory::create(const QString &mimeType) { if (mimeType == "option/filebrowser") { return new FileBrowserOption(m_liteApp,this); } return 0; } ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowseroptionfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowseroptionfactory.h // Creator: visualfc #ifndef FILEBROWSEROPTIONFACTORY_H #define FILEBROWSEROPTIONFACTORY_H #include "liteapi/liteapi.h" class FileBrowserOptionFactory : public LiteApi::IOptionFactory { public: FileBrowserOptionFactory(LiteApi::IApplication *app, QObject *parent); virtual QStringList mimeTypes() const; virtual LiteApi::IOption *create(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; }; #endif // FILEBROWSEROPTIONFACTORY_H ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowserplugin.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowserplugin.cpp // Creator: visualfc #include "filebrowserplugin.h" #include "filebrowser.h" #include "filebrowseroptionfactory.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FileBrowserPlugin::FileBrowserPlugin() : m_browser(0) { } bool FileBrowserPlugin::load(LiteApi::IApplication *app) { m_browser = new FileBrowser(app,this); //app->optionManager()->addFactory(new FileBrowserOptionFactory(app,this)); return true; } #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(PluginFactory,PluginFactory) #endif ================================================ FILE: liteidex/src/plugins/filebrowser/filebrowserplugin.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: filebrowserplugin.h // Creator: visualfc #ifndef FILEBROWSERPLUGIN_H #define FILEBROWSERPLUGIN_H #include "filebrowser_global.h" #include "liteapi/liteapi.h" #include class FileBrowser; class FileBrowserPlugin : public LiteApi::IPlugin { Q_OBJECT public: FileBrowserPlugin(); virtual bool load(LiteApi::IApplication *app); protected: FileBrowser *m_browser; }; class PluginFactory : public LiteApi::PluginFactoryT { Q_OBJECT Q_INTERFACES(LiteApi::IPluginFactory) #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "liteidex.FileBrowserPlugin") #endif public: PluginFactory() { m_info->setId("plugin/filebrowser"); m_info->setName("FileBrowser"); m_info->setAuthor("visualfc"); m_info->setVer("X37.1"); m_info->setInfo("File System Browser"); } }; #endif // FILEBROWSERPLUGIN_H ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebugger.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebugger.cpp // Creator: visualfc #include "gdbdebugger.h" #include "fileutil/fileutil.h" #include "processex/processex.h" #include "gdbdebuggeroption.h" #include "../litedebug/litedebug_global.h" #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static void GdbMiValueToItem(QStandardItem *item, const GdbMiValue &value) { switch (value.type()) { case GdbMiValue::Invalid: item->appendRow(new QStandardItem("Invalid")); break; case GdbMiValue::Const: if (value.name().isEmpty()) { item->appendRow(new QStandardItem(QString(value.data()))); } else { item->appendRow(new QStandardItem(QString(value.name()+"="+value.data()))); } break; case GdbMiValue::List: { QStandardItem *in = new QStandardItem(QString(value.name())); item->appendRow(in); for (int i = 0; i < value.childCount(); i++) { QStandardItem *iv = new QStandardItem(QString("[%1]").arg(i)); in->appendRow(iv); GdbMiValueToItem(iv,value.childAt(i)); } break; } case GdbMiValue::Tuple: { QStandardItem *iv = item; if (!value.name().isEmpty()) { iv = new QStandardItem(QString(value.name())); item->appendRow(iv); } foreach (const GdbMiValue &v, value.children()) { GdbMiValueToItem(iv,v); } break; } } } GdbDebugger::GdbDebugger(LiteApi::IApplication *app, QObject *parent) : LiteApi::IDebugger(parent), m_liteApp(app), m_envManager(0), m_tty(0) { m_process = new QProcess(this); m_asyncModel = new QStandardItemModel(this); m_asyncItem = new QStandardItem; m_asyncModel->appendRow(m_asyncItem); /* m_asyncModel->setHeaderData(0,Qt::Horizontal,"Reason"); m_asyncModel->setHeaderData(1,Qt::Horizontal,"Address"); m_asyncModel->setHeaderData(2,Qt::Horizontal,"Function"); m_asyncModel->setHeaderData(3,Qt::Horizontal,"File"); m_asyncModel->setHeaderData(4,Qt::Horizontal,"Line"); m_asyncModel->setHeaderData(5,Qt::Horizontal,"Thread ID"); m_asyncModel->setHeaderData(6,Qt::Horizontal,"Stoped Threads"); */ m_varsModel = new QStandardItemModel(0,3,this); m_varsModel->setHeaderData(0,Qt::Horizontal,"Name"); m_varsModel->setHeaderData(1,Qt::Horizontal,"Value"); m_varsModel->setHeaderData(2,Qt::Horizontal,"Type"); m_watchModel = new QStandardItemModel(0,3,this); m_watchModel->setHeaderData(0,Qt::Horizontal,"Name"); m_watchModel->setHeaderData(1,Qt::Horizontal,"Value"); m_watchModel->setHeaderData(2,Qt::Horizontal,"Type"); m_framesModel = new QStandardItemModel(0,5,this); m_framesModel->setHeaderData(0,Qt::Horizontal,"Level"); m_framesModel->setHeaderData(1,Qt::Horizontal,"Address"); m_framesModel->setHeaderData(2,Qt::Horizontal,"Function"); m_framesModel->setHeaderData(3,Qt::Horizontal,"File"); m_framesModel->setHeaderData(4,Qt::Horizontal,"Line"); m_libraryModel = new QStandardItemModel(0,2,this); m_libraryModel->setHeaderData(0,Qt::Horizontal,"Id"); m_libraryModel->setHeaderData(1,Qt::Horizontal,"Thread Groups"); m_gdbinit = false; m_gdbexit = false; connect(app,SIGNAL(loaded()),this,SLOT(appLoaded())); connect(m_process,SIGNAL(started()),this,SIGNAL(debugStarted())); connect(m_process,SIGNAL(finished(int)),this,SLOT(finished(int))); connect(m_process,SIGNAL(error(QProcess::ProcessError)),this,SLOT(error(QProcess::ProcessError))); connect(m_process,SIGNAL(readyReadStandardError()),this,SLOT(readStdError())); connect(m_process,SIGNAL(readyReadStandardOutput()),this,SLOT(readStdOutput())); } GdbDebugger::~GdbDebugger() { if (m_process) { delete m_process; } } void GdbDebugger::appLoaded() { m_envManager = LiteApi::findExtensionObject(m_liteApp,"LiteApi.IEnvManager"); } QString GdbDebugger::mimeType() const { return QLatin1String("debugger/gdb"); } QAbstractItemModel *GdbDebugger::debugModel(LiteApi::DEBUG_MODEL_TYPE type) { if (type == LiteApi::ASYNC_MODEL) { return m_asyncModel; } else if (type == LiteApi::VARS_MODEL) { return m_varsModel; } else if (type == LiteApi::WATCHES_MODEL) { return m_watchModel; }else if (type == LiteApi::FRAMES_MODEL) { return m_framesModel; } else if (type == LiteApi::LIBRARY_MODEL) { return m_libraryModel; } return 0; } void GdbDebugger::setWorkingDirectory(const QString &dir) { m_process->setWorkingDirectory(dir); } void GdbDebugger::setEnvironment (const QStringList &environment) { m_process->setEnvironment(environment); } bool GdbDebugger::start(const QString &program, const QString &arguments) { if (!m_envManager) { return false; } QProcessEnvironment env = LiteApi::getGoEnvironment(m_liteApp); QString goroot = env.value("GOROOT"); if (!goroot.isEmpty()) { m_runtimeFilePath = QFileInfo(QDir(goroot),"src/pkg/runtime/").path(); } QStringList argsList; if (isGdbDebuggerUseTty(m_liteApp)) { if (!m_tty) { m_tty = LiteApi::createTty(m_liteApp,this); if (m_tty) { connect(m_tty,SIGNAL(byteDelivery(QByteArray)),this,SLOT(readTty(QByteArray))); } } if (m_tty && m_tty->listen()) { argsList << "--tty="+m_tty->serverName(); } else if (m_tty) { qDebug() << "error" << m_tty->errorString() << m_tty->serverName(); } } QStringList argsListInfo; argsList << "--interpreter=mi"; argsList << "--args " << program; argsListInfo << "--args " << program; if (!arguments.isEmpty()) { argsList << arguments; argsListInfo << arguments; } QString gdb = env.value("LITEIDE_GDB",""); if (gdb.isEmpty()) { #ifdef Q_OS_WIN if (env.value("GOARCH") != "386") { if (FileUtil::lookPath("gdb64",env,true).isEmpty()) { gdb = "gdb"; } } else { gdb = "gdb"; } #else gdb = "gdb"; #endif } m_gdbFilePath = FileUtil::lookPath(gdb,env,true); if (m_gdbFilePath.isEmpty()) { m_liteApp->appendLog("GdbDebugger",gdb+" was not found on system PATH (hint: is GDB installed?)",true); return false; } clear(); #ifdef Q_OS_WIN m_process->setNativeArguments(argsList.join(" ")); m_process->start("\""+m_gdbFilePath+"\""); #else m_process->start(m_gdbFilePath + " " + argsList.join(" ")); #endif QString log = QString("%1 %2 [%3]").arg(m_gdbFilePath).arg(argsList.join(" ")).arg(m_process->workingDirectory()); emit debugLog(LiteApi::DebugRuntimeLog,log); return true; } void GdbDebugger::stop() { command("-gdb-exit"); if (!m_process->waitForFinished(300)) { m_process->kill(); } } bool GdbDebugger::isRunning() { return m_process->state() != QProcess::NotRunning; } void GdbDebugger::continueRun() { command("-exec-continue"); } void GdbDebugger::stepOver() { command("-exec-next"); } void GdbDebugger::stepInto() { command("-exec-step"); } void GdbDebugger::stepOut() { command("-exec-finish"); } void GdbDebugger::runToLine(const QString &fileName, int line) { line++; GdbCmd cmd; QStringList args; args << "-break-insert"; args << "-t"; args << QString("%1:%2").arg(fileName).arg(line); cmd.setCmd(args); command(cmd); command("-exec-continue"); } void GdbDebugger::createWatch(const QString &var) { QString value; if (value.contains(".")) { value = "\'"+var+"\'"; } else { value = var; } createWatchHelp(var,false,true); } void GdbDebugger::removeWatch(const QString &name) { removeWatchHelp(name,true,true); } void GdbDebugger::removeAllWatch() { //removeWatchHelp foreach (QString name, m_watchList) { removeWatchHelp(name,true,true); } } void GdbDebugger::createWatchHelp(const QString &var, bool floating, bool watchModel) { GdbCmd cmd; QStringList args; args << "-var-create"; args << "-"; if (floating) { args << "@"; } else { args << "*"; } args << var; cmd.setCmd(args); cmd.insert("var",var); if (watchModel) { cmd.insert("watchModel",true); } command(cmd); } void GdbDebugger::removeWatchHelp(const QString &value, bool byName, bool children) { QString name; QString var; if (byName) { name = value; var = m_varNameMap.key(name); } else { var = value; name = m_varNameMap.value(var); } QStringList args; args << "-var-delete"; if (children) { args << "-c"; } args << name; GdbCmd cmd; cmd.setCmd(args); cmd.insert("var",var); cmd.insert("name",name); cmd.insert("children",children); command(cmd); } void GdbDebugger::showFrame(QModelIndex index) { QStandardItem* file = m_framesModel->item( index.row(), 3 ); QStandardItem* line = m_framesModel->item( index.row(), 4 ); if( !file || !line ) { return; } QString filename = file->text(); int lineno = line->text().toInt(); if( lineno <= 0 ) { return; } emit gotoLine(filename, lineno - 1 ); } void GdbDebugger::dbclickItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type) { } void GdbDebugger::expandItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type) { QStandardItem *parent = 0; if (type == LiteApi::VARS_MODEL) { parent = m_varsModel->itemFromIndex(index); } else if (type == LiteApi::WATCHES_MODEL) { parent = m_watchModel->itemFromIndex(index); } if (!parent) { return; } if (parent->data(VarExpanded).toInt() == 1) { return; } parent->setData(1,VarExpanded); for (int i = 0; i < parent->rowCount(); i++) { QStandardItem *item = parent->child(i); QString name = item->data(VarNameRole).toString(); int num = item->data(VarNumChildRole).toInt(); if (num > 0) { updateVarListChildren(name); } } } void GdbDebugger::setInitBreakTable(const QMultiMap &bks) { m_initBks = bks; } void GdbDebugger::setInitWatchList(const QStringList &names) { foreach (QString name, names) { createWatch(name); } } void GdbDebugger::insertBreakPoint(const QString &fileName, int line) { line++; QString location = QString("%1:%2").arg(fileName).arg(line); if (m_locationBkMap.contains(location)) { return; } QStringList args; args << "-break-insert"; args << QString("%1:%2").arg(fileName).arg(line); GdbCmd cmd; cmd.setCmd(args); cmd.insert("file",fileName); cmd.insert("line",line); command(cmd); } void GdbDebugger::removeBreakPoint(const QString &fileName, int line) { line++; QString location = QString("%1:%2").arg(fileName).arg(line); QString number = m_locationBkMap.key(location); if (number.isEmpty()) { return; } QStringList args; args << "-break-delete"; args << number; GdbCmd cmd; cmd.setCmd(args); command(cmd); } void GdbDebugger::command_helper(const GdbCmd &cmd, bool emitOut) { m_token++; QByteArray buf = cmd.makeCmd(m_token); if (emitOut) { emit debugLog(LiteApi::DebugConsoleLog,">>> "+QString::fromUtf8(buf)); } #ifdef Q_OS_WIN buf.append("\r\n"); #else buf.append("\n"); #endif m_tokenCookieMap.insert(m_token,cmd.cookie()); m_process->write(buf); } void GdbDebugger::command(const GdbCmd &cmd) { command_helper(cmd,true); } void GdbDebugger::enterAppText(const QString &text) { if (m_tty) { m_tty->write(text.toUtf8()); } else { m_process->write(text.toUtf8()); } } void GdbDebugger::enterDebugText(const QString &text) { command(text); } void GdbDebugger::command(const QByteArray &cmd) { command_helper(GdbCmd(cmd),false); } void GdbDebugger::readStdError() { emit debugLog(LiteApi::DebugErrorLog,QString::fromUtf8(m_process->readAllStandardError())); } static bool isNameChar(char c) { // could be 'stopped' or 'shlibs-added' return (c >= 'a' && c <= 'z') || c == '-'; } /* 27.4.2 gdb/mi Output Syntax The output from gdb/mi consists of zero or more out-of-band records followed, optionally, by a single result record. This result record is for the most recent command. The sequence of output records is terminated by (gdb). If an input command was prefixed with a token then the corresponding output for that command will also be prefixed by that same token. If an input command was prefixed with a token then the corresponding output for that command will also be prefixed by that same token. output -> ( out-of-band-record )* [ result-record ] "(gdb)" nl result-record -> [ token ] "^" result-class ( "," result )* nl out-of-band-record -> async-record | stream-record async-record -> exec-async-output | status-async-output | notify-async-output exec-async-output -> [ token ] "*" async-output status-async-output -> [ token ] "+" async-output notify-async-output -> [ token ] "=" async-output async-output -> async-class ( "," result )* nl result-class -> "done" | "running" | "connected" | "error" | "exit" async-class -> "stopped" | others (where others will be added depending on the needs¡ªthis is still in development). result -> variable "=" value variable -> string value -> const | tuple | list const -> c-string tuple -> "{}" | "{" result ( "," result )* "}" list -> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" stream-record -> console-stream-output | target-stream-output | log-stream-output console-stream-output -> "~" c-string target-stream-output -> "@" c-string log-stream-output -> "&" c-string nl -> CR | CR-LF */ void GdbDebugger::handleResponse(const QByteArray &buff) { if (buff.isEmpty() || buff == "(gdb) ") return; const char *from = buff.constData(); const char *to = from + buff.size(); const char *inner; int token = -1; // Token is a sequence of numbers. for (inner = from; inner != to; ++inner) if (*inner < '0' || *inner > '9') break; if (from != inner) { token = QByteArray(from, inner - from).toInt(); from = inner; } // Next char decides kind of response. const char c = *from++; switch (c) { case '*': case '+': case '=': { QByteArray asyncClass; for (; from != to; ++from) { const char c = *from; if (!isNameChar(c)) break; asyncClass += *from; } GdbMiValue result; while (from != to) { GdbMiValue data; if (*from != ',') { // happens on archer where we get // 23^running *running,thread-id="all" (gdb) result.m_type = GdbMiValue::Tuple; break; } ++from; // skip ',' data.parseResultOrValue(from, to); if (data.isValid()) { //qDebug() << "parsed result:" << data.toString(); result.m_children += data; result.m_type = GdbMiValue::Tuple; } } handleAsyncClass(asyncClass,result); break; } case '~': handleConsoleStream(GdbMiValue::parseCString(from, to)); break; case '@': handleTargetStream(GdbMiValue::parseCString(from, to)); break; case '&': handleLogStream(GdbMiValue::parseCString(from, to)); break; case '^': { GdbResponse response; response.token = token; for (inner = from; inner != to; ++inner) if (*inner < 'a' || *inner > 'z') break; QByteArray resultClass = QByteArray::fromRawData(from, inner - from); if (resultClass == "done") { response.resultClass = GdbResultDone; } else if (resultClass == "running") { response.resultClass = GdbResultRunning; } else if (resultClass == "connected") { response.resultClass = GdbResultConnected; } else if (resultClass == "error") { response.resultClass = GdbResultError; } else if (resultClass == "exit") { response.resultClass = GdbResultExit; } else { response.resultClass = GdbResultUnknown; } from = inner; if (from != to) { if (*from == ',') { ++from; response.data.parseTuple_helper(from, to); response.data.m_type = GdbMiValue::Tuple; response.data.m_name = "data"; } else { // Archer has this. response.data.m_type = GdbMiValue::Tuple; response.data.m_name = "data"; } } if (m_tokenCookieMap.contains(token)) { response.cookie = m_tokenCookieMap.take(token); } handleResultRecord(response); break; } default: { from--; QByteArray out(from,to-from); out.append("\n"); emit debugLog(LiteApi::DebugApplationLog,QString::fromUtf8(out)); break; } } } void GdbDebugger::handleStopped(const GdbMiValue &result) { QByteArray reason = result.findChild("reason").data(); m_handleState.setReason(reason); m_handleState.setStopped(true); if (reason.startsWith("exited")) { m_handleState.setExited(true); m_handleState.setReason(reason); return; } GdbMiValue frame = result.findChild("frame"); if (frame.isValid()) { QString fullname = frame.findChild("fullname").data(); QString file = frame.findChild("file").data(); QString line = frame.findChild("line").data(); if (!fullname.isEmpty()) { emit setCurrentLine(fullname,line.toInt()-1); } else if (!file.isEmpty()) { //fix go build bug, not find fullname //file="C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist308287094/go/src/pkg/fmt/print.go" int i = file.indexOf("/go/src/pkg"); if (i > 0) { QString fullname = LiteApi::getGOROOT(m_liteApp)+file.right(file.length()-i-3); emit setCurrentLine(fullname,line.toInt()-1); } } } } void GdbDebugger::handleLibrary(const GdbMiValue &result) { QString id = result.findChild("id").data(); QString thread_group = result.findChild("thread-group").data(); m_libraryModel->appendRow(QList() << new QStandardItem(id) << new QStandardItem(thread_group) ); } void GdbDebugger::handleAsyncClass(const QByteArray &asyncClass, const GdbMiValue &result) { m_asyncItem->removeRows(0,m_asyncItem->rowCount()); m_asyncItem->setText(asyncClass); //QStandardItem *item = new QStandardItem(QString(asyncClass)); GdbMiValueToItem(m_asyncItem,result); //m_asyncModel->clear(); //m_asyncModel->appendRow(item); if (asyncClass == "stopped") { handleStopped(result); } else if (asyncClass == "library-loaded") { handleLibrary(result); } emit setExpand(LiteApi::ASYNC_MODEL,m_asyncModel->indexFromItem(m_asyncItem),true); } void GdbDebugger::handleConsoleStream(const QByteArray&) { } void GdbDebugger::handleTargetStream(const QByteArray&) { } void GdbDebugger::handleLogStream(const QByteArray&) { } void GdbDebugger::handleResultStackListFrame(const GdbResponse &response, QMap&) { //10000015^done,stack=[frame={level="0",addr="0x0040113f",func="main.main",file="F:/hg/debug_test/hello/main.go",fullname="F:/hg/debug_test/hello/main.go",line="36"},frame={level="1",addr="0x00401f8a",func="runtime.mainstart",file="386/asm.s",fullname="c:/go/src/pkg/runtime/386/asm.s",line="96"},frame={level="2",addr="0x0040bcfe",func="runtime.initdone",file="/go/src/pkg/runtime/proc.c",fullname="c:/go/src/pkg/runtime/proc.c",line="242"},frame={level="3",addr="0x00000000",func="??"}] m_framesModel->removeRows(0,m_framesModel->rowCount()); if (response.resultClass != GdbResultDone) { return; } GdbMiValue stack = response.data.findChild("stack"); if (stack.isList()) { for (int i = 0; i < stack.childCount(); i++) { GdbMiValue child = stack.childAt(i); if (child.isValid() && child.name() == "frame") { QString level = child.findChild("level").data(); QString addr = child.findChild("addr").data(); QString func = child.findChild("func").data(); QString file = child.findChild("file").data(); QString line = child.findChild("line").data(); m_framesModel->appendRow(QList() << new QStandardItem(level) << new QStandardItem(addr) << new QStandardItem(func) << new QStandardItem(file) << new QStandardItem(line) ); } } } } void GdbDebugger::handleResultStackListVariables(const GdbResponse &response, QMap&) { //10000014^done,variables=[{name="v"},{name="x"},{name="pt"},{name="str"},{name="sum1"},{name="y"}] if (response.resultClass != GdbResultDone) { return; } GdbMiValue vars = response.data.findChild("variables"); if (vars.isList()) { foreach (const GdbMiValue &child, vars.m_children) { if (child.isValid()) { QString var = child.findChild("name").data(); if (!m_varNameMap.contains(var)) { createWatchHelp(var,true,false); } } } } } void GdbDebugger::handleResultVarCreate(const GdbResponse &response, QMap &map) { //10000018^done,name="var4",numchild="0",value="4265530",type="int",thread-id="1",has_more="0" //10000019^done,name="var5",numchild="2",value="{...}",type="struct string",thread-id="1",has_more="0" //10000020^done,name="var6",numchild="3",value="0x40bc38",type="struct main.pt *",thread-id="1",has_more="0" if (response.resultClass != GdbResultDone) { return; } QString name = response.data.findChild("name").data(); QString numchild = response.data.findChild("numchild").data(); QString value = response.data.findChild("value").data(); QString type = response.data.findChild("type").data(); QString var = map.value("var").toString(); if (var.isEmpty()) { var = map.value("cmdList").toStringList().last(); } if (m_varNameMap.contains(var)) { var += QString("-%1").arg(response.token); } m_varNameMap.insert(var,name); QStandardItem *item = new QStandardItem(var); item->setData(name,VarNameRole); m_nameItemMap.insert(name,item); if (map.value("watchModel",false).toBool()) { emit watchCreated(name,map.value("var").toString()); m_watchList.append(name); m_watchModel->appendRow(QList() << item << new QStandardItem(value) << new QStandardItem(type) ); } else { m_varsModel->appendRow(QList() << item << new QStandardItem(value) << new QStandardItem(type) ); } int num = numchild.toInt(); item->setData(num,VarNumChildRole); if (num > 0 ){ updateVarListChildren(name); } } void GdbDebugger::handleResultVarListChildren(const GdbResponse &response, QMap &map) { //10000022^done,numchild="2",children=[child={name="var5.str",exp="str",numchild="1",value="0x4115c6 \"\\203\\304\\b\\303d\\213\\r,\"",type="uint8 *",thread-id="1"},child={name="var5.len",exp="len",numchild="0",value="4242460",type="int",thread-id="1"}],has_more="0" if (response.resultClass != GdbResultDone) { return; } GdbMiValue children = response.data.findChild("children"); if (children.isList()) { QString name = map.value("name").toString(); QStandardItem *parent = m_nameItemMap.value(name); if (parent == 0) { return; } int num = response.data.findChild("numchild").data().toInt(); parent->setData(num,VarNumChildRole); for (int i = 0; i < children.childCount(); i++) { GdbMiValue child = children.childAt(i); if (child.name() == "child" && child.isTuple()) { QString name = child.findChild("name").data(); QString exp = child.findChild("exp").data(); QString numchild = response.data.findChild("numchild").data(); QString value = child.findChild("value").data(); QString type = child.findChild("type").data(); QStandardItem *item = new QStandardItem(exp); item->setData(name,VarNameRole); m_nameItemMap.insert(name,item); parent->appendRow(QList() << item << new QStandardItem(value) << new QStandardItem(type) ); int num = numchild.toInt(); item->setData(num,VarNumChildRole); } } } } void GdbDebugger::handleResultVarUpdate(const GdbResponse &response, QMap&) { //10000040^done,changelist=[{name="var2",in_scope="true",type_changed="false",has_more="0"}] if (response.resultClass != GdbResultDone) { return; } GdbMiValue list = response.data.findChild("changelist"); if (list.isList()) { for (int i = 0; i < list.childCount(); i++) { GdbMiValue child = list.childAt(i); if (child.isValid()) { QString name = child.findChild("name").data(); QString in_scope = child.findChild("in_scope").data(); QString type_changed = child.findChild("type_changed").data(); QString var = m_varNameMap.key(name); if (in_scope == "false") { removeWatchHelp(var,false,false); } else { if (type_changed == "true") { //remove watch children removeWatchHelp(var,false,true); //update type updateVarTypeInfo(name); //udpate children updateVarListChildren(name); } //update value updateVarValue(name); } } } } } void GdbDebugger::handleResultVarDelete(const GdbResponse &response, QMap &map) { //10000062^done,ndeleted="1" //10000063^done,ndeleted="0" if (response.resultClass != GdbResultDone) { return; } bool ndeleted = true; if (response.data.findChild("ndeleted").data() == "0") { ndeleted = false; } QString var = map.value("var").toString(); QString name = map.value("name").toString(); QMutableMapIterator i(m_nameItemMap); QString cls = name+"."; while (i.hasNext()) { i.next(); if (i.key().startsWith(cls)) { i.remove(); } } QStandardItemModel *model = m_varsModel; if (m_watchList.contains(name)) { emit watchRemoved(name); m_watchList.removeAll(name); model = m_watchModel; ndeleted = 1; } if (ndeleted) { m_varNameMap.remove(var); m_nameItemMap.remove(name); } for (int i = 0; i < model->rowCount(); i++) { QStandardItem *item = model->item(i,0); if (item->data() == name) { if (ndeleted) { model->removeRow(i); } else { item->removeRows(0,item->rowCount()); item->setData(0,VarExpanded); emit setExpand(LiteApi::VARS_MODEL,model->indexFromItem(item),false); } break; } } } void GdbDebugger::handleResultVarUpdateValue(const GdbResponse &response, QMap &map) { //10000035^done,value="100" if (response.resultClass != GdbResultDone) { return; } QString value = response.data.findChild("value").data(); QString name = map.value("name").toString(); QStandardItem *item = m_nameItemMap.value(name); if (!item) { return; } QStandardItem *parent = item->parent(); QStandardItem *v = 0; if (parent) { v = parent->child(item->row(),1); } else { v = item->model()->item(item->row(),1); } if (v) { v->setData(value,Qt::DisplayRole); #if QT_VERSION >= 0x050000 v->setData(QColor(Qt::red),Qt::TextColorRole); #else v->setData(Qt::red,Qt::TextColorRole); #endif m_varChangedItemList.insert(v); } } void GdbDebugger::handleResultVarUpdateType(const GdbResponse &response, QMap &map) { //10000060^done,type="struct string" if (response.resultClass != GdbResultDone) { return; } QString type = response.data.findChild("type").data(); QString name = map.value("name").toString(); QStandardItem *item = m_nameItemMap.value(name); if (!item) { return; } QStandardItem *parent = item->parent(); QStandardItem *v = 0; if (parent) { v = parent->child(item->row(),2); } else { v = item->model()->item(item->row(),2); } if (v) { v->setData(type,Qt::DisplayRole); #if QT_VERSION >= 0x050000 v->setData(QColor(Qt::red),Qt::TextColorRole); #else v->setData(Qt::red,Qt::TextColorRole); #endif m_varChangedItemList.insert(v); } } void GdbDebugger::handleBreakInsert(const GdbResponse &response, QMap&) { // >>> 10000029-break-insert F:/hg/debug_test/hello/main.go:31 // 10000029^done,bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="0x004010dd",func="main.test",file="F:/hg/debug_test/hello/main.go",fullname="F:/hg/debug_test/hello/main.go",line="31",times="0",original-location="F:/hg/debug_test/hello/main.go:31"} // >>> 10000046-break-insert F:/hg/debug_test/hello/main.go:37 // 10000046^done,bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="0x0040118a",func="main.main",file="F:/hg/debug_test/hello/main.go",fullname="F:/hg/debug_test/hello/main.go",line="37",times="0",original-location="F:/hg/debug_test/hello/main.go:37"} if (response.resultClass != GdbResultDone) { return; } GdbMiValue bkpt = response.data.findChild("bkpt"); if (bkpt.isTuple()) { QString number = bkpt.findChild("number").data(); QString org_location= bkpt.findChild("original-location").data(); m_locationBkMap.insert(number,org_location); } } void GdbDebugger::handleBreakDelete(const GdbResponse &response, QMap &map) { if (response.resultClass != GdbResultDone) { return; } QStringList cmdList = map.value("cmdList").toStringList(); if (cmdList.size() != 2) { return; } QString number = cmdList.at(1); m_locationBkMap.remove(number); } void GdbDebugger::handleResultRecord(const GdbResponse &response) { if (response.cookie.type() != QVariant::Map) { return; } QMap map = response.cookie.toMap(); QString cmd = map.value("cmd").toString(); if (cmd.isEmpty()) { return; } QStringList cmdList = map.value("cmdList").toStringList(); if (cmdList.isEmpty()) { return; } if (cmdList.at(0) == "-stack-list-variables") { handleResultStackListVariables(response,map); } else if (cmdList.at(0) == "-stack-list-frames") { handleResultStackListFrame(response,map); } else if (cmdList.at(0) == "-var-create") { handleResultVarCreate(response,map); } else if (cmdList.at(0) == "-var-list-children") { handleResultVarListChildren(response,map); } else if (cmdList.at(0) == "-var-update") { handleResultVarUpdate(response,map); } else if (cmdList.at(0) == "-var-delete") { handleResultVarDelete(response,map); } else if (cmdList.at(0) == "-var-evaluate-expression") { handleResultVarUpdateValue(response,map); } else if (cmdList.at(0) == "-var-info-type") { handleResultVarUpdateType(response,map); } else if (cmdList.at(0) == "-break-insert") { handleBreakInsert(response,map); } else if (cmdList.at(0) == "-break-delete") { handleBreakDelete(response,map); } } void GdbDebugger::clear() { m_gdbinit = false; m_gdbexit = false; m_busy = false; m_token = 10000000; m_handleState.clear(); m_varNameMap.clear(); m_watchList.clear(); m_nameItemMap.clear(); m_tokenCookieMap.clear(); m_varChangedItemList.clear(); m_inbuffer.clear(); m_locationBkMap.clear(); m_framesModel->removeRows(0,m_framesModel->rowCount()); m_libraryModel->removeRows(0,m_libraryModel->rowCount()); m_varsModel->removeRows(0,m_varsModel->rowCount()); m_watchModel->removeRows(0,m_watchModel->rowCount()); } void GdbDebugger::initGdb() { command("set unwindonsignal on"); command("set overload-resolution off"); command("handle SIGSEGV nopass stop print"); command("set breakpoint pending on"); command("set width 0"); command("set height 0"); command("set auto-solib-add on"); if (!m_runtimeFilePath.isEmpty()) { #ifdef Q_OS_WIN QStringList pathList = LiteApi::getGOPATH(m_liteApp,false); QString paths; foreach(QString path, pathList) { paths += QDir::fromNativeSeparators(path)+"/src"; paths += ";"; } command("-environment-directory "+m_runtimeFilePath.toLatin1()); //command("-environment-directory "+m_runtimeFilePath.toLatin1()+";"+paths.toLatin1()); command("set substitute-path /go/src/pkg/runtime "+m_runtimeFilePath.toLatin1()); #else command("-environment-directory "+m_runtimeFilePath.toUtf8()); command("set substitute-path /go/src/pkg/runtime "+m_runtimeFilePath.toUtf8()); #endif } //command("set "); QMapIterator i(m_initBks); while (i.hasNext()) { i.next(); QString fileName = i.key(); QList lines = m_initBks.values(fileName); foreach(int line, lines) { insertBreakPoint(fileName,line); } } if (m_liteApp->settings()->value(LITEDEBUG_AUTOBREAKMAIN,false).toBool()) { command("-break-insert main.main"); } command("-exec-run"); debugLoaded(); } void GdbDebugger::updateWatch() { foreach(QStandardItem *item, m_varChangedItemList) { #if QT_VERSION >= 0x050000 item->setData(QColor(Qt::black),Qt::TextColorRole); #else item->setData(Qt::black,Qt::TextColorRole); #endif } m_varChangedItemList.clear(); command("-var-update *"); } void GdbDebugger::updateLocals() { command("-stack-list-variables 0"); } void GdbDebugger::updateFrames() { command("-stack-list-frames"); } void GdbDebugger::updateBreaks() { command("-break-info"); } void GdbDebugger::updateVarTypeInfo(const QString &name) { QStringList args; args << "-var-info-type"; args << name; GdbCmd cmd; cmd.setCmd(args); cmd.insert("name",name); command(cmd); } void GdbDebugger::updateVarListChildren(const QString &name) { GdbCmd cmd; QStringList args; args << "-var-list-children"; args << "1"; args << name; cmd.setCmd(args); cmd.insert("name",name); command(cmd); } void GdbDebugger::updateVarValue(const QString &name) { QStringList args; args << "-var-evaluate-expression"; args << name; GdbCmd cmd; cmd.setCmd(args); cmd.insert("name",name); command(cmd); } void GdbDebugger::readStdOutput() { int newstart = 0; int scan = m_inbuffer.size(); m_inbuffer.append(m_process->readAllStandardOutput()); // This can trigger when a dialog starts a nested event loop. if (m_busy) return; while (newstart < m_inbuffer.size()) { int start = newstart; int end = m_inbuffer.indexOf('\n', scan); if (end < 0) { m_inbuffer.remove(0, start); return; } newstart = end + 1; scan = newstart; if (end == start) continue; #ifdef Q_OS_WIN if (m_inbuffer.at(end - 1) == '\r') { --end; if (end == start) continue; } #endif m_busy = true; QByteArray data = QByteArray::fromRawData(m_inbuffer.constData() + start, end - start); handleResponse(data); m_busy = false; } emit debugLog(LiteApi::DebugConsoleLog,QString::fromUtf8(m_inbuffer)); m_inbuffer.clear(); if (!m_gdbinit) { m_gdbinit = true; initGdb(); } if (m_handleState.exited() && !m_gdbexit) { m_gdbexit = true; stop(); } else if (m_handleState.stopped()) { updateWatch(); updateLocals(); updateFrames(); } m_handleState.clear(); } void GdbDebugger::finished(int code) { clear(); if (m_tty) { m_tty->shutdown(); } emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Program exited with code %1").arg(code)); } void GdbDebugger::error(QProcess::ProcessError err) { clear(); if (m_tty) { m_tty->shutdown(); } emit debugStoped(); emit debugLog(LiteApi::DebugRuntimeLog,QString("Error! %1").arg(ProcessEx::processErrorText(err))); } void GdbDebugger::readTty(const QByteArray &data) { emit debugLog(LiteApi::DebugApplationLog,QString::fromUtf8(data)); } ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebugger.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebugger.h // Creator: visualfc #ifndef GDBDEBUGGER_H #define GDBDEBUGGER_H #include "litedebugapi/litedebugapi.h" #include "liteenvapi/liteenvapi.h" #include "litettyapi/litettyapi.h" #include "qtc_gdbmi/gdbmi.h" #include class QProcess; class GdbHandleState { public: GdbHandleState() : m_exited(false),m_stopped(false) {} void clear() { m_reason.clear(); m_exited = false; m_stopped = false; } void setExited(bool b) {m_exited = b;} void setStopped(bool b) {m_stopped = b;} void setReason(const QByteArray &reason) { m_reason = reason; } bool exited() const { return m_exited; } bool stopped() const { return m_stopped; } QByteArray reason() const { return m_reason; } public: bool m_exited; bool m_stopped; QByteArray m_reason; }; class GdbCmd { public: GdbCmd() { } GdbCmd(const QString &cmd) { setCmd(cmd); } GdbCmd(const QStringList &cmd) { setCmd(cmd); } void setCmd(const QString &cmd) { m_cmd = cmd; m_cookie.insert("cmd",m_cmd); m_cookie.insert("cmdList",cmd.split(" ",qtSkipEmptyParts)); } void setCmd(const QStringList &cmd) { m_cmd = cmd.join(" "); m_cookie.insert("cmd",m_cmd); m_cookie.insert("cmdList",cmd); } void insert(const QString &key, const QVariant &value) { m_cookie.insert(key,value); } QByteArray makeCmd(int index) const { #ifdef Q_OS_WIN return QString("%1%2").arg(index,8,10,QLatin1Char('0')).arg(m_cmd).toLatin1(); #else return QString("%1%2").arg(index,8,10,QLatin1Char('0')).arg(m_cmd).toUtf8(); #endif } QMap cookie() const { return m_cookie; } protected: QString m_cmd; QMap m_cookie; }; class QStandardItemModel; class QStandardItem; class GdbDebugger : public LiteApi::IDebugger { Q_OBJECT public: GdbDebugger(LiteApi::IApplication *app, QObject *parent = 0); ~GdbDebugger(); enum VarItemDataRole{ VarNameRole = Qt::UserRole + 1, VarNumChildRole, VarExpanded }; public: virtual QString mimeType() const; virtual QAbstractItemModel *debugModel(LiteApi::DEBUG_MODEL_TYPE type); virtual void setWorkingDirectory(const QString &dir); virtual void setEnvironment (const QStringList &environment); virtual bool start(const QString &program, const QString &arguments); virtual void stop(); virtual bool isRunning(); virtual void stepOver(); virtual void stepInto(); virtual void stepOut(); virtual void continueRun(); virtual void runToLine(const QString &fileName, int line); virtual void command(const QByteArray &cmd); virtual void enterAppText(const QString &text); virtual void enterDebugText(const QString &text); virtual void expandItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type); virtual void setInitBreakTable(const QMultiMap &bks); virtual void setInitWatchList(const QStringList &names); virtual void insertBreakPoint(const QString &fileName, int line); virtual void removeBreakPoint(const QString &fileName, int line); public: virtual void command(const GdbCmd &cmd); virtual void createWatch(const QString &var); virtual void removeWatch(const QString &name); virtual void removeAllWatch(); virtual void dbclickItem(QModelIndex index, LiteApi::DEBUG_MODEL_TYPE type); void showFrame(QModelIndex index); protected: void createWatchHelp(const QString &var, bool floating, bool watchModel); void removeWatchHelp(const QString &var, bool byName, bool children); void removeWatchByNameHelp(const QString &name, bool children); void command_helper(const GdbCmd &cmd, bool emitOut); public slots: void appLoaded(); void readStdError(); void readStdOutput(); void finished(int); void error(QProcess::ProcessError); void readTty(const QByteArray &data); protected: void handleResponse(const QByteArray &buff); void handleStopped(const GdbMiValue &result); void handleLibrary(const GdbMiValue &result); void handleAsyncClass(const QByteArray &asyncClass, const GdbMiValue &result); void handleConsoleStream(const QByteArray &data); void handleTargetStream(const QByteArray &data); void handleLogStream(const QByteArray &data); void handleResultRecord(const GdbResponse &response); void handleResultStackListFrame(const GdbResponse &response, QMap &map); void handleResultStackListVariables(const GdbResponse &response, QMap &map); void handleResultVarCreate(const GdbResponse &response, QMap &map); void handleResultVarListChildren(const GdbResponse &response, QMap &map); void handleResultVarUpdate(const GdbResponse &response, QMap &map); void handleResultVarDelete(const GdbResponse &response, QMap &map); void handleResultVarUpdateValue(const GdbResponse &response, QMap &map); void handleResultVarUpdateType(const GdbResponse &response, QMap &map); void handleBreakInsert(const GdbResponse &response, QMap &map); void handleBreakDelete(const GdbResponse &response, QMap &map); protected: void clear(); void initGdb(); void updateWatch(); void updateLocals(); void updateFrames(); void updateBreaks(); void updateVarTypeInfo(const QString &name); void updateVarListChildren(const QString &name); void updateVarValue(const QString &name); protected: LiteApi::IApplication *m_liteApp; LiteApi::IEnvManager *m_envManager; LiteApi::ITty *m_tty; QProcess *m_process; QStandardItemModel *m_asyncModel; QStandardItemModel *m_varsModel; QStandardItemModel *m_watchModel; QStandardItemModel *m_framesModel; QStandardItemModel *m_libraryModel; QStandardItem *m_asyncItem; QMap m_tokenCookieMap; QMap m_varNameMap; QList m_watchList; QMap m_nameItemMap; QSet m_varChangedItemList; QString m_gdbFilePath; QString m_runtimeFilePath; QByteArray m_inbuffer; GdbHandleState m_handleState; QMultiMap m_initBks; QMap m_locationBkMap; bool m_busy; bool m_gdbinit; bool m_gdbexit; int m_token; }; #endif // GDBDEBUGGER_H ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebugger.pro ================================================ TARGET = gdbdebugger TEMPLATE = lib include(../../liteideplugin.pri) include(../../api/litedebugapi/litedebugapi.pri) include(../../utils/fileutil/fileutil.pri) include(../../utils/processex/processex.pri) include(../../3rdparty/qtc_gdbmi/qtc_gdbmi.pri) DEFINES += GDBDEBUGER_LIBRARY SOURCES += gdbdebuggerplugin.cpp \ gdbdebugger.cpp \ gdbdebuggeroptionfactory.cpp \ gdbdebuggeroption.cpp HEADERS += gdbdebuggerplugin.h\ gdbdebugger_global.h \ gdbdebugger.h \ gdbdebuggeroptionfactory.h \ gdbdebuggeroption.h FORMS += \ gdbdebuggeroption.ui ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebugger_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebugger_global.h // Creator: visualfc #ifndef GDBDEBUGGER_GLOBAL_H #define GDBDEBUGGER_GLOBAL_H #include #if defined(GDBDEBUGER_LIBRARY) # define GDBDEBUGERSHARED_EXPORT Q_DECL_EXPORT #else # define GDBDEBUGERSHARED_EXPORT Q_DECL_IMPORT #endif #define OPTION_GDBDEBUGGER "option/gdbdebugger" #define GDBDEBUGGER_USETTY "gdbdebugger/usetty" #endif // GDBDEBUGGER_GLOBAL_H ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebuggeroption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebuggeroption.cpp // Creator: visualfc #include "gdbdebuggeroption.h" #include "ui_gdbdebuggeroption.h" #include "gdbdebugger_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GdbDebuggerOption::GdbDebuggerOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::GdbDebuggerOption) { ui->setupUi(m_widget); } GdbDebuggerOption::~GdbDebuggerOption() { delete m_widget; delete ui; } QWidget *GdbDebuggerOption::widget() { return m_widget; } QString GdbDebuggerOption::name() const { return "GdbDebugger"; } QString GdbDebuggerOption::mimeType() const { return OPTION_GDBDEBUGGER; } void GdbDebuggerOption::load() { ui->useTtyCheckBox->setChecked(isGdbDebuggerUseTty(m_liteApp)); } void GdbDebuggerOption::save() { m_liteApp->settings()->setValue(GDBDEBUGGER_USETTY,ui->useTtyCheckBox->isChecked()); } bool isGdbDebuggerUseTty(LiteApi::IApplication *app) { #ifdef Q_OS_WIN return app->settings()->value(GDBDEBUGGER_USETTY,true).toBool(); #else return app->settings()->value(GDBDEBUGGER_USETTY,false).toBool(); #endif } ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebuggeroption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebuggeroption.h // Creator: visualfc #ifndef GDBDEBUGGEROPTION_H #define GDBDEBUGGEROPTION_H #include "liteapi/liteapi.h" namespace Ui { class GdbDebuggerOption; } class GdbDebuggerOption : public LiteApi::IOption { Q_OBJECT public: explicit GdbDebuggerOption(LiteApi::IApplication *app, QObject *parent = 0); ~GdbDebuggerOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void load(); virtual void save(); private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::GdbDebuggerOption *ui; }; bool isGdbDebuggerUseTty(LiteApi::IApplication *app); #endif // GDBDEBUGGEROPTION_H ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebuggeroption.ui ================================================ GdbDebuggerOption 0 0 400 72 Form Enable --tty for program being debugged. Qt::Vertical 20 40 ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebuggeroptionfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebuggeroptionfactory.cpp // Creator: visualfc #include "gdbdebuggeroption.h" #include "gdbdebuggeroptionfactory.h" #include "gdbdebugger_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GdbDebuggerOptionFactory::GdbDebuggerOptionFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IOptionFactory(parent), m_liteApp(app) { } QStringList GdbDebuggerOptionFactory::mimeTypes() const { return QStringList() << OPTION_GDBDEBUGGER; } LiteApi::IOption *GdbDebuggerOptionFactory::create(const QString &mimeType) { if (mimeType == OPTION_GDBDEBUGGER) { return new GdbDebuggerOption(m_liteApp,this); } return 0; } ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebuggeroptionfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebuggeroptionfactory.h // Creator: visualfc #ifndef GDBDEBUGGEROPTIONFACTORY_H #define GDBDEBUGGEROPTIONFACTORY_H #include "liteapi/liteapi.h" class GdbDebuggerOptionFactory : public LiteApi::IOptionFactory { public: GdbDebuggerOptionFactory(LiteApi::IApplication *app, QObject *parent); virtual QStringList mimeTypes() const; virtual LiteApi::IOption *create(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; }; #endif // GDBDEBUGGEROPTIONFACTORY_H ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebuggerplugin.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebuggerplugin.cpp // Creator: visualfc #include "gdbdebuggerplugin.h" #include "gdbdebugger.h" #include "gdbdebuggeroptionfactory.h" #include "litedebugapi/litedebugapi.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GdbDebuggerPlugin::GdbDebuggerPlugin() { } bool GdbDebuggerPlugin::load(LiteApi::IApplication *app) { LiteApi::IDebuggerManager *manager = LiteApi::getDebugManager(app); if (!manager) { return false; } GdbDebugger *debug = new GdbDebugger(app); manager->addDebugger(debug); manager->setCurrentDebugger(debug); app->optionManager()->addFactory(new GdbDebuggerOptionFactory(app,this)); return true; } QStringList GdbDebuggerPlugin::dependPluginList() const { return QStringList() << "plugin/litedebug"; } #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(PluginFactory,PluginFactory) #endif ================================================ FILE: liteidex/src/plugins/gdbdebugger/gdbdebuggerplugin.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: gdbdebuggerplugin.h // Creator: visualfc #ifndef GDBDEBUGGERPLUGIN_H #define GDBDEBUGGERPLUGIN_H #include "gdbdebugger_global.h" #include "liteapi/liteapi.h" #include class GdbDebuggerPlugin : public LiteApi::IPlugin { Q_OBJECT public: GdbDebuggerPlugin(); virtual bool load(LiteApi::IApplication *app); virtual QStringList dependPluginList() const; }; class PluginFactory : public LiteApi::PluginFactoryT { Q_OBJECT Q_INTERFACES(LiteApi::IPluginFactory) #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "liteidex.GdbDebuggerPlugin") #endif public: PluginFactory() { m_info->setId("plugin/GdbDebugger"); m_info->setName("GdbDebugger"); m_info->setAuthor("visualfc"); m_info->setVer("X32"); m_info->setInfo("Core Gdb Debugger"); m_info->setMustLoad(true); } }; #endif // GDBDEBUGGERPLUGIN_H ================================================ FILE: liteidex/src/plugins/golangast/astwidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: astwidget.cpp // Creator: visualfc #include "astwidget.h" #include "golangastitem.h" #include "golangasticon.h" #include "golangdocapi/golangdocapi.h" #include "liteenvapi/liteenvapi.h" #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end AstWidget::AstWidget(bool outline, LiteApi::IApplication *app, QWidget *parent) : QWidget(parent), m_bOutline(outline), m_liteApp(app) { m_bFirst = true; QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); layout->setSpacing(0); m_tree = new SymbolTreeView; m_tree->setExpandsOnDoubleClick(false); m_filterEdit = new Utils::FilterLineEdit(200); m_model = new QStandardItemModel(this); proxyModel = new QSortFilterProxyModel(this); proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); proxyModel->setDynamicSortFilter(true); proxyModel->setSourceModel(m_model); layout->addWidget(m_filterEdit); layout->addWidget(m_tree); this->setLayout(layout); m_tree->setModel(proxyModel); //m_tree->setExpandsOnDoubleClick(false); m_tree->setContextMenuPolicy(Qt::CustomContextMenu); m_gotoPosAct = new QAction(tr("Go To Definition"),this); m_importDocAct = new QAction(tr("View Import Document"),this); m_contextMenu = new QMenu(this); m_contextMenu->addAction(m_gotoPosAct); m_contextMenu->addAction(m_importDocAct); m_contextItem = 0; connect(m_tree,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClicked(QModelIndex))); connect(m_tree,SIGNAL(enterKeyPressed(QModelIndex)),this,SLOT(enterKeyPressed(QModelIndex))); connect(m_filterEdit,SIGNAL(filterChanged(QString)),this,SLOT(filterChanged(QString))); connect(m_tree,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(treeContextMenuRequested(QPoint))); connect(m_gotoPosAct,SIGNAL(triggered()),this,SLOT(gotoDefinition())); connect(m_importDocAct,SIGNAL(triggered()),this,SLOT(viewImportDoc())); } void AstWidget::clear() { m_model->clear(); m_filterEdit->clear(); } static QModelIndexList filterModelList(QString filter, QAbstractItemModel *model, QModelIndex parent) { QModelIndexList list; for (int i = 0; i < model->rowCount(parent); i++) { QModelIndex index = model->index(i,0,parent); if (index.data().toString().indexOf(filter,0,Qt::CaseInsensitive) >= 0) { list.append(index); } list.append(filterModelList(filter,model,index)); } return list; } void AstWidget::clearFilter(QModelIndex parent) { for (int i = 0; i < m_model->rowCount(parent); i++) { QModelIndex index = m_model->index(i,0,parent); clearFilter(index); GolangAstItem *item = (GolangAstItem*)m_model->itemFromIndex(index); if (!item) { continue; } if (item->m_tagName.indexOf("+") >= 0) { continue; } QFont font = item->font(); font.setBold(false); item->setFont(font); } } bool AstWidget::filterModel(QString filter, QModelIndex parent, QModelIndex &first) { bool b = false; for (int i = 0; i < proxyModel->rowCount(parent); i++) { QModelIndex index = proxyModel->index(i,0,parent); GolangAstItem *item = astItemFromIndex(index); if (!item) { continue; } if (item->m_tagName.indexOf("+") < 0) { QFont font = item->font(); if (index.data().toString().indexOf(filter,0,Qt::CaseInsensitive) >= 0) { font.setBold(true); if (!b) { b = true; if (!first.isValid()) { first = index; } } } else { font.setBold(false); } item->setFont(font); } if (filterModel(filter,index,first)) { m_tree->expand(index); b = true; } else { //if (!m_bOutline) { m_tree->collapse(index); //} } } return b; } void AstWidget::filterChanged(QString filter) { if (filter.isEmpty()) { clearFilter(m_tree->rootIndex()); m_tree->expandToDepth(0); /* for(int i = 0; i < proxyModel->rowCount(); i++) { QModelIndex index = proxyModel->index(i,0); m_tree->expand(index); if (m_bOutline) { for (int j = 0; j < proxyModel->rowCount(index);j++) { m_tree->expand(proxyModel->index(j,0,index)); } } } */ } else { QModelIndex first; filterModel(filter,m_tree->rootIndex(),first); if (first.isValid()) { m_tree->scrollTo(first); } } } void AstWidget::treeContextMenuRequested(QPoint pt) { QModelIndex index = m_tree->indexAt(pt); if (!index.isValid()) { return; } GolangAstItem *item = astItemFromIndex(index); if (item->isFolder() || item->m_tagFlag == LiteApi::TagPackage) { return; } m_contextItem = item; m_importDocAct->setVisible(item->m_tagFlag == LiteApi::TagImport); m_contextMenu->popup(m_tree->mapToGlobal(pt)); } void AstWidget::gotoDefinition() { gotoItemDefinition(m_contextItem); } void AstWidget::viewImportDoc() { QString pkg = m_contextItem->text(); QString orgPkg = pkg; //check mod and vendor pkg QString gotools = LiteApi::getGotools(m_liteApp); if (!gotools.isEmpty()) { QProcess process(this); process.setEnvironment(LiteApi::getGoEnvironment(m_liteApp).toStringList()); process.setWorkingDirectory(m_workPath); QStringList args; args << "pkgcheck" << "-pkg" << pkg; process.start(gotools,args); if (!process.waitForFinished(3000)) { process.kill(); } QByteArray ar = process.readAllStandardOutput(); QString pkgs = QString::fromUtf8(ar).trimmed(); if (!pkgs.isEmpty()) { QStringList pkgInfo = pkgs.split(","); if (pkgInfo.size() == 2 && !pkgInfo[0].isEmpty()) { pkg = pkgInfo[0]; } } } LiteApi::IGolangDoc *doc = LiteApi::getGolangDoc(m_liteApp); if (!doc) { return; } QUrl url; url.setScheme("pdoc"); url.setPath(pkg); QString addin; if (pkg != orgPkg) { addin = orgPkg; } doc->openUrl(url,addin); doc->activeBrowser(); } void AstWidget::doubleClicked(QModelIndex index) { GolangAstItem *item = astItemFromIndex(index); if (!item) { return; } if (!item->isFolder()) { gotoItemDefinition(item); } else { m_tree->setExpanded(index,!m_tree->isExpanded(index)); } } void AstWidget::enterKeyPressed(const QModelIndex &index) { GolangAstItem *item = astItemFromIndex(index); if (!item) { return; } if (item->isFolder()) { m_tree->setExpanded(index,!m_tree->isExpanded(index)); } else { gotoItemDefinition(item); } } void AstWidget::gotoItemDefinition(GolangAstItem *item) { if (item->m_posList.isEmpty()) { return; } AstItemPos pos = item->m_posList.at(0); QFileInfo info(QDir(m_workPath),pos.fileName); LiteApi::gotoLine(m_liteApp,info.filePath(),pos.line-1,pos.column-1,true,true); return; // LiteApi::IEditor *editor = m_liteApp->fileManager()->openEditor(info.filePath()); // if (!editor) { // return; // } // editor->widget()->setFocus(); // LiteApi::ITextEditor *textEditor = LiteApi::findExtensionObject(editor,"LiteApi.ITextEditor"); // if (!textEditor) { // return; // } // textEditor->gotoLine(pos.line-1,pos.column,true); } GolangAstItem *AstWidget::astItemFromIndex(QModelIndex index) { QModelIndex i = proxyModel->mapToSource(index); if (!i.isValid()) { return 0; } return (GolangAstItem*)m_model->itemFromIndex(i); } /* tools/goastview/packageview.go const ( tag_package = "p" tag_imports_folder = "+m" tag_import = "mm" tag_type = "t" tag_struct = "s" tag_interface = "i" tag_value = "v" tag_const = "c" tag_func = "f" tag_value_folder = "+v" tag_const_folder = "+c" tag_func_folder = "+f" tag_type_method = "tm" tag_type_factor = "tf" tag_type_value = "tv" ) */ static QString tagInfo(const QString &tag) { if (tag == "p") { return "package"; } else if (tag == "+m") { return "imports folder"; } else if (tag == "mm") { return "import"; } else if (tag == "t") { return "type"; } else if (tag == "s") { return "struct"; } else if (tag == "i") { return "interface"; } else if (tag == "v") { return "value"; } else if (tag == "c") { return "const"; } else if (tag == "f") { return "func"; } else if (tag == "+v") { return "values folder"; } else if (tag == "+c") { return "const folder"; } else if (tag == "+f") { return "funcs folder"; } else if (tag == "tm") { return "method"; } else if (tag == "tf") { return "factory"; } else if (tag == "tv") { return "field"; } return QString(); } static LiteApi::ASTTAG_ENUM toTagFlag(const QString &tag) { if (tag == "p") { return LiteApi::TagPackage; } else if (tag == "+m") { return LiteApi::TagImportFolder; } else if (tag == "mm") { return LiteApi::TagImport; } else if (tag == "t") { return LiteApi::TagType; } else if (tag == "s") { return LiteApi::TagStruct; } else if (tag == "i") { return LiteApi::TagInterface; } else if (tag == "v") { return LiteApi::TagValue; } else if (tag == "c") { return LiteApi::TagConst; } else if (tag == "f") { return LiteApi::TagFunc; } else if (tag == "+v") { return LiteApi::TagValueFolder; } else if (tag == "+c") { return LiteApi::TagConstFolder; } else if (tag == "+f") { return LiteApi::TagFuncFolder; } else if (tag == "tm") { return LiteApi::TagTypeMethod; } else if (tag == "tf") { return LiteApi::TagTypeFactor; } else if (tag == "tv") { return LiteApi::TagTypeValue; } else if (tag == "b") { return LiteApi::TagTodo; } else if (tag == "+b") { return LiteApi::TagTodoFolder; } return LiteApi::TagNone; } void AstWidget::parserModel(QStandardItemModel *model, const QByteArray &data, const QByteArray &sep, bool flatMode, bool skipimport) { QList array = QString::fromUtf8(data).split('\n'); QMap items; QStringList indexFiles; bool ok = false; bool bmain = false; QMap level1NameItemMap; foreach (QString line, array) { int pos = line.indexOf('@'); QString tip; if (pos == 0) { indexFiles.append(line.mid(1)); continue; } else if (pos >= 1) { tip = line.mid(pos+1); line = line.left(pos); } line = line.trimmed(); QList info = line.split(sep); if (info.size() < 3) { continue; } int level = info[0].toInt(&ok); if (!ok) { continue; } QString tag = info[1]; QString name = info[2]; if (name.isEmpty() || tag.isEmpty()) { continue; } if (flatMode && tag.startsWith("+")) { continue; } if (level == 0) { level1NameItemMap.clear(); } if (tag == "p") { if (name == "main") { bmain = true; } else { bmain = false; } if (name == "documentation") { continue; } if (flatMode) { continue; } } if (skipimport && tag == "mm") { continue; } GolangAstItem *item = 0; if (level == 1) { item = level1NameItemMap.value(name); if (item != 0) { items[level] = item; continue; } } item = new GolangAstItem; if (level == 1) { level1NameItemMap.insert(name,item); } item->m_tagName = tag; item->m_tagFlag = toTagFlag(tag); item->setText(name); if (!bmain && (name.at(0).isLower() || name.at(0) == '_')) { item->setIcon(GolangAstIcon::instance()->iconFromTag(tag,false)); } else { item->setIcon(GolangAstIcon::instance()->iconFromTag(tag)); } if (!tip.isEmpty()) { item->setToolTip(tip); // todo comment use tip if (tag == "b") { item->setText(tip); item->setToolTip(name); } } else if (tag.at(0) == '+') { item->setToolTip(QString("%1").arg(tagInfo(tag))); } else { item->setToolTip(QString("%1 %2").arg(tagInfo(tag)).arg(name)); } if (info.size() >= 4) { foreach (QString pos, info[3].split(';')) { QList ar = pos.split(':'); if (ar.size() == 3) { bool ok = false; int index = ar[0].toInt(&ok); if (ok && index >= 0 && index < indexFiles.size()) { bool ok1,ok2; int line = ar[1].toInt(&ok1); int col = ar[2].toInt(&ok2); if (ok1 && ok2) { AstItemPos pos = {indexFiles[index],line,col,-1,-1}; item->m_posList.append(pos); } } } else if (ar.size() == 5) { bool ok = false; int index = ar[0].toInt(&ok); if (ok && index >= 0 && index < indexFiles.size()) { bool ok1,ok2,ok3,ok4; int line = ar[1].toInt(&ok1); int col = ar[2].toInt(&ok2); int endLine = ar[3].toInt(&ok3); int endCol = ar[4].toInt(&ok4); if (ok1 && ok2 && ok3 && ok4) { AstItemPos pos = {indexFiles[index],line,col,endLine,endCol}; item->m_posList.append(pos); } } } } } QStandardItem *parent = items.value(level-1,0); if (parent ) { if (flatMode) { if (tag == "tv") { item->setText(parent->text()+"."+item->text()); } model->appendRow(item); } else { parent->appendRow(item); } } else { model->appendRow(item); } items[level] = item; } } bool AstWidget::trySyncIndex(const QString &filePath, int line, int column) { QModelIndexList finds; QFileInfo info(filePath); findModelIndex(QModelIndex(),info.fileName(),line+1,column+1,finds); if (finds.isEmpty()) { return false; } m_tree->setCurrentIndex(finds.last()); m_tree->scrollTo(finds.last()); return true; } void AstWidget::findModelIndex(const QModelIndex &parent, const QString &fileName, int line, int column, QModelIndexList &finds) { for (int i = 0; i < proxyModel->rowCount(parent); i++) { QModelIndex index = proxyModel->index(i,0,parent); GolangAstItem *item = astItemFromIndex(index); if (!item) { continue; } foreach (AstItemPos pos, item->m_posList) { if (pos.fileName == fileName && line >= pos.line && column >= pos.column && line <= pos.endLine) { if (line < pos.endLine || (line == pos.endLine && column <= pos.endColumn) ) { finds.push_back(index); } } } if (item->hasChildItem()) { findModelIndex(index,fileName,line,column,finds); } } } // level,tag,name,pos,@info void AstWidget::updateModel(const QByteArray &data, const QByteArray &sep) { //save state SymbolTreeState state; m_tree->saveState(&state); m_model->clear(); parserModel(m_model,data,sep,false,false); //load state if (!m_tree->isExpanded(m_tree->rootIndex())) { m_tree->expandToDepth(0); } m_tree->loadState(proxyModel,&state); /* if (m_bOutline && m_bFirst) { //m_tree->expandToDepth(1); for(int i = 0; i < proxyModel->rowCount(); i++) { QModelIndex index = proxyModel->index(i,0); m_tree->expand(index); for (int j = 0; j < proxyModel->rowCount(index);j++) { m_tree->expand(proxyModel->index(j,0,index)); } } m_bFirst = false; } */ QString text = m_filterEdit->text().trimmed(); if (!text.isEmpty()) { this->filterChanged(text); } } ================================================ FILE: liteidex/src/plugins/golangast/astwidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: astwidget.h // Creator: visualfc #ifndef ASTWIDGET_H #define ASTWIDGET_H #include "liteapi/liteapi.h" #include "symboltreeview/symboltreeview.h" #include "qtc_editutil/filterlineedit.h" class GolangAstItem; class QStandardItemModel; class QSortFilterProxyModel; class AstWidget : public QWidget { Q_OBJECT public: explicit AstWidget(bool outline, LiteApi::IApplication *app, QWidget *parent = 0); public: void clear(); void updateModel(const QByteArray &data, const QByteArray &sep); void setWorkPath(const QString &path) { m_workPath = path; } QString workPath() const { return m_workPath; } GolangAstItem *astItemFromIndex(QModelIndex index); SymbolTreeView *tree() { return m_tree; } static void parserModel(QStandardItemModel *model, const QByteArray &data, const QByteArray &sep, bool flatMode, bool skipimport); bool trySyncIndex(const QString &filePath, int line, int column); void findModelIndex(const QModelIndex &parent, const QString &fileName, int line, int column, QModelIndexList &finds); public slots: bool filterModel(QString filter, QModelIndex parent, QModelIndex &first); void clearFilter(QModelIndex parent); void filterChanged(QString); void treeContextMenuRequested(QPoint); void gotoDefinition(); void viewImportDoc(); void doubleClicked(QModelIndex); void enterKeyPressed(const QModelIndex &index); protected: void gotoItemDefinition(GolangAstItem *item); bool m_bOutline; bool m_bFirst; SymbolTreeView *m_tree; Utils::FilterLineEdit *m_filterEdit; QStandardItemModel *m_model; QSortFilterProxyModel *proxyModel; LiteApi::IApplication *m_liteApp; QAction *m_gotoPosAct; QAction *m_importDocAct; QMenu *m_contextMenu; GolangAstItem *m_contextItem; QString m_workPath; }; #endif // ASTWIDGET_H ================================================ FILE: liteidex/src/plugins/golangast/golangast.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangast.cpp // Creator: visualfc #include "golangast.h" #include "golangastitem.h" #include "golangasticon.h" #include "astwidget.h" #include "liteenvapi/liteenvapi.h" #include "golangast_global.h" #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangAst::GolangAst(LiteApi::IApplication *app, QObject *parent) : LiteApi::IGolangAst(parent), m_liteApp(app) { m_astviewSep = ",,,"; m_currentEditor = 0; m_currentPlainTextEditor = 0; m_blankWidget = new QLabel(tr("No outline available")); m_blankWidget->setAlignment(Qt::AlignCenter); m_stackedWidget = new QStackedWidget; m_stackedWidget->addWidget(m_blankWidget); m_projectAstWidget = new AstWidget(false,m_liteApp); m_process = new QProcess(this); m_timer = new QTimer(this); m_processFile = new QProcess(this); m_timerFile = new QTimer(this); m_syncClassViewAct = new QAction(QIcon("icon:images/sync.png"),tr("Synchronize with editor"),this); m_syncClassViewAct->setCheckable(true); m_syncOutlineAct = new QAction(QIcon("icon:images/sync.png"),tr("Synchronize with editor"),this); m_syncOutlineAct->setCheckable(true); m_classViewToolAct = m_liteApp->toolWindowManager()->addToolWindow(Qt::LeftDockWidgetArea,m_projectAstWidget,"GoClassView",tr("Go Class View"),false, QList() << m_syncClassViewAct); m_outlineToolAct = m_liteApp->toolWindowManager()->addToolWindow(Qt::LeftDockWidgetArea,m_stackedWidget,"GoOutline",tr("Go Outline"),false, QList() << m_syncOutlineAct); connect(m_classViewToolAct,SIGNAL(toggled(bool)),this,SLOT(astProjectEnable(bool))); connect(m_outlineToolAct,SIGNAL(toggled(bool)),this,SLOT(astFileEnable(bool))); connect(m_liteApp->editorManager(),SIGNAL(editorCreated(LiteApi::IEditor*)),this,SLOT(editorCreated(LiteApi::IEditor*))); connect(m_liteApp->editorManager(),SIGNAL(editorAboutToClose(LiteApi::IEditor*)),this,SLOT(editorAboutToClose(LiteApi::IEditor*))); connect(m_liteApp->projectManager(),SIGNAL(currentProjectChanged(LiteApi::IProject*)),this,SLOT(projectChanged(LiteApi::IProject*))); connect(m_liteApp->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(editorChanged(LiteApi::IEditor*))); connect(m_liteApp->editorManager(),SIGNAL(editorSaved(LiteApi::IEditor*)),this,SLOT(editorSaved(LiteApi::IEditor*))); connect(m_process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedProcess(int,QProcess::ExitStatus))); connect(m_timer,SIGNAL(timeout()),this,SLOT(updateAstNow())); connect(m_processFile,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedProcessFile(int,QProcess::ExitStatus))); connect(m_timerFile,SIGNAL(timeout()),this,SLOT(updateAstNowFile())); connect(m_syncClassViewAct,SIGNAL(triggered(bool)),this,SLOT(syncClassView(bool))); connect(m_syncOutlineAct,SIGNAL(triggered(bool)),this,SLOT(syncOutline(bool))); m_liteApp->extension()->addObject("LiteApi.IGolangAst",this); m_isSyncClassView = m_liteApp->settings()->value(GOLANGAST_CLASSVIEW_SYNCEDITOR,false).toBool(); m_syncClassViewAct->setChecked(m_isSyncClassView); m_isSyncOutline = m_liteApp->settings()->value(GOLANGAST_OUTLINE_SYNCEDITOR,false).toBool(); m_syncOutlineAct->setChecked(m_isSyncOutline); } GolangAst::~GolangAst() { if (m_timer->isActive()) { m_timer->stop(); } delete m_process; if (m_timerFile->isActive()) { m_timerFile->stop(); } delete m_processFile; m_liteApp->toolWindowManager()->removeToolWindow(m_projectAstWidget); m_liteApp->toolWindowManager()->removeToolWindow(m_stackedWidget); delete m_projectAstWidget; delete m_stackedWidget; } QIcon GolangAst::iconFromTag(const QString &tag, bool pub) const { return GolangAstIcon::instance()->iconFromTag(tag,pub); } QIcon GolangAst::iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool pub) const { return GolangAstIcon::instance()->iconFromTagEnum(tag,pub); } void GolangAst::astProjectEnable(bool b) { if (b) { //loadProject(m_liteApp->projectManager()->currentProject()); LiteApi::IEditor *editor = m_liteApp->editorManager()->currentEditor(); if (!editor) { return; } QString fileName = editor->filePath(); if (!fileName.isEmpty()) { QFileInfo info(fileName); loadProjectPath(info.path()); } } } void GolangAst::astFileEnable(bool b) { if (b) { editorChanged(m_liteApp->editorManager()->currentEditor()); } } void GolangAst::setEnable(bool b) { if (b) { m_stackedWidget->setVisible(true); loadProject(m_liteApp->projectManager()->currentProject()); editorChanged(m_liteApp->editorManager()->currentEditor()); updateAst(); } else { //m_stackedWidget->setVisible(false); } } void GolangAst::projectChanged(LiteApi::IProject *project) { return; if (project) { m_projectAstWidget->clear(); } loadProject(project); if (project) { connect(project,SIGNAL(reloaded()),this,SLOT(projectReloaded())); } } void GolangAst::projectReloaded() { LiteApi::IProject *project = (LiteApi::IProject*)sender(); loadProject(project); } void GolangAst::loadProjectPath(const QString &path) { if (m_projectAstWidget->isHidden()) { return; } m_updateFileNames.clear(); m_updateFilePaths.clear(); QDir dir(path); if (!dir.exists()) { return; } foreach (QFileInfo info, dir.entryInfoList(QStringList()<<"*.go",QDir::Files)) { m_updateFileNames.append(info.fileName()); m_updateFilePaths.append(info.filePath()); } m_workPath = path; m_process->setWorkingDirectory(m_workPath); m_projectAstWidget->setWorkPath(m_workPath); updateAst(); /* if (project) { foreach(QString file, project->fileNameList()) { if (QFileInfo(file).suffix() == "go") { m_updateFileNames.append(file); } } foreach(QString file, project->filePathList()) { QFileInfo info(file); if (info.suffix() == "go") { m_updateFilePaths.append(info.filePath()); } } QFileInfo info(project->filePath()); if (info.isDir()) { m_workPath = info.filePath(); } else { m_workPath = info.path(); } m_process->setWorkingDirectory(m_workPath); m_projectAstWidget->setWorkPath(m_workPath); updateAst(); } else { m_projectAstWidget->clear(); } */ } void GolangAst::loadProject(LiteApi::IProject *project) { return; m_updateFileNames.clear(); m_updateFilePaths.clear(); if (project) { foreach(QString file, project->fileNameList()) { if (QFileInfo(file).suffix() == "go") { m_updateFileNames.append(file); } } foreach(QString file, project->filePathList()) { QFileInfo info(file); if (info.suffix() == "go") { m_updateFilePaths.append(info.filePath()); } } QFileInfo info(project->filePath()); if (info.isDir()) { m_workPath = info.filePath(); } else { m_workPath = info.path(); } m_process->setWorkingDirectory(m_workPath); m_projectAstWidget->setWorkPath(m_workPath); updateAst(); } else { m_projectAstWidget->clear(); } } void GolangAst::editorCreated(LiteApi::IEditor *editor) { AstWidget *w = m_editorAstWidgetMap.value(editor); if (w) { return; } if (editor) { QString fileName = editor->filePath(); if (!fileName.isEmpty()) { QFileInfo info(fileName); if (info.suffix() == "go") { AstWidget *w = new AstWidget(true,m_liteApp); w->setWorkPath(info.absolutePath()); m_stackedWidget->addWidget(w); m_editorAstWidgetMap.insert(editor,w); } } } } void GolangAst::editorAboutToClose(LiteApi::IEditor *editor) { AstWidget *w = m_editorAstWidgetMap.value(editor); if (w == 0) { return; } m_stackedWidget->removeWidget(w); m_editorAstWidgetMap.remove(editor); } void GolangAst::editorChanged(LiteApi::IEditor *editor) { m_editorFileName.clear(); m_editorFilePath.clear(); if (m_currentPlainTextEditor) { disconnect(m_currentPlainTextEditor,0,this,0); } m_currentEditor = editor; m_currentPlainTextEditor = LiteApi::getPlainTextEdit(editor); if (m_currentPlainTextEditor) { connect(m_currentPlainTextEditor,SIGNAL(cursorPositionChanged()),this,SLOT(editorPositionChanged())); } AstWidget *w = m_editorAstWidgetMap.value(editor); if (w) { m_stackedWidget->setCurrentWidget(w); } else { m_stackedWidget->setCurrentWidget(m_blankWidget); } if (editor) { QString fileName = editor->filePath(); if (!fileName.isEmpty()) { QFileInfo info(fileName); m_workPath = info.absolutePath(); if (info.suffix() == "go") { m_processFile->setWorkingDirectory(info.absolutePath()); m_editorFileName.append(info.fileName()); m_editorFilePath.append(info.filePath()); loadProjectPath(info.path()); } updateAstFile(); } } } void GolangAst::editorSaved(LiteApi::IEditor *editor) { if (editor) { QString fileName = editor->filePath(); QFileInfo info(fileName); if (!fileName.isEmpty() && info.suffix() == "go") { updateAstFile(); if (m_updateFilePaths.contains(info.filePath())) { updateAst(); } } } } void GolangAst::updateAst() { m_timer->start(1500); } void GolangAst::updateAstNow() { if (m_timer->isActive()) { m_timer->stop(); } if (m_updateFileNames.isEmpty()) { return; } QString cmd = LiteApi::getGotools(m_liteApp); QStringList args; args << "astview" << "-end"; args << "-todo"; args << "-sep" << m_astviewSep; args << "-tp"; args << m_updateFileNames; m_process->setEnvironment(LiteApi::getGoEnvironment(m_liteApp).toStringList()); m_process->start(cmd,args); } void GolangAst::updateAstFile() { m_timerFile->start(1000); } void GolangAst::updateAstNowFile() { if (m_timerFile->isActive()) { m_timerFile->stop(); } if (m_editorFileName.isEmpty()) { return; } QString cmd = LiteApi::getGotools(m_liteApp); QStringList args; args << "astview" << "-end"; args << "-todo"; args << "-outline"; args << "-sep" << m_astviewSep; args << "-tp"; args << m_editorFileName; m_processFile->setEnvironment(LiteApi::getGoEnvironment(m_liteApp).toStringList()); m_processFile->start(cmd,args); } void GolangAst::syncClassView(bool b) { m_isSyncClassView = b; m_liteApp->settings()->setValue(GOLANGAST_CLASSVIEW_SYNCEDITOR,m_isSyncClassView); } void GolangAst::syncOutline(bool b) { m_isSyncOutline = b; m_liteApp->settings()->setValue(GOLANGAST_OUTLINE_SYNCEDITOR,m_isSyncOutline); } void GolangAst::editorPositionChanged() { if (!m_currentEditor || !m_currentPlainTextEditor) { return; } QTextCursor cursor = m_currentPlainTextEditor->textCursor(); if (m_isSyncClassView && m_classViewToolAct->isChecked()) { m_projectAstWidget->trySyncIndex(m_currentEditor->filePath(),cursor.blockNumber(),cursor.positionInBlock()); } if (m_isSyncOutline && m_outlineToolAct->isChecked()) { AstWidget *w = m_editorAstWidgetMap.value(m_currentEditor); if (w) { w->trySyncIndex(m_currentEditor->filePath(),cursor.blockNumber(),cursor.positionInBlock()); } } } void GolangAst::finishedProcess(int code,QProcess::ExitStatus status) { if (code == 0 && status == QProcess::NormalExit) { // if (m_liteApp->projectManager()->currentProject()) { m_projectAstWidget->updateModel(m_process->readAllStandardOutput(),m_astviewSep); if (m_isSyncClassView && m_currentPlainTextEditor) { QTextCursor cursor = m_currentPlainTextEditor->textCursor(); m_projectAstWidget->trySyncIndex(m_currentEditor->filePath(),cursor.blockNumber(),cursor.positionInBlock()); } // } } else { //qDebug() << m_process->readAllStandardError(); } } void GolangAst::finishedProcessFile(int code,QProcess::ExitStatus status) { if (code == 0 && status == QProcess::NormalExit) { if (m_currentEditor) { AstWidget *w = m_editorAstWidgetMap.value(m_currentEditor); if (w) { w->updateModel(m_processFile->readAllStandardOutput(),m_astviewSep); if (m_isSyncOutline && m_currentPlainTextEditor) { QTextCursor cursor = m_currentPlainTextEditor->textCursor(); w->trySyncIndex(m_currentEditor->filePath(),cursor.blockNumber(),cursor.positionInBlock()); } } } } else { //qDebug() << m_process->readAllStandardError(); } } ================================================ FILE: liteidex/src/plugins/golangast/golangast.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangast.h // Creator: visualfc #ifndef GOLANGAST_H #define GOLANGAST_H #include "liteapi/liteapi.h" #include "golangastapi/golangastapi.h" #include "symboltreeview/symboltreeview.h" #include #include #include class QStackedWidget; class AstWidget; class QLabel; class GolangAst : public LiteApi::IGolangAst { Q_OBJECT public: explicit GolangAst(LiteApi::IApplication *app, QObject *parent = 0); ~GolangAst(); virtual QIcon iconFromTag(const QString &tag, bool pub) const; virtual QIcon iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool pub) const; public: void setEnable(bool b); void loadProject(LiteApi::IProject *project); void loadProjectPath(const QString &path); public slots: void astProjectEnable(bool); void astFileEnable(bool); void projectReloaded(); void projectChanged(LiteApi::IProject*); void editorCreated(LiteApi::IEditor*); void editorAboutToClose(LiteApi::IEditor *editor); void editorChanged(LiteApi::IEditor*); void editorSaved(LiteApi::IEditor*); void finishedProcess(int,QProcess::ExitStatus); void finishedProcessFile(int,QProcess::ExitStatus); void updateAst(); void updateAstNow(); void updateAstFile(); void updateAstNowFile(); void syncClassView(bool b); void syncOutline(bool b); void editorPositionChanged(); protected: LiteApi::IApplication *m_liteApp; QTimer *m_timer; QTimer *m_timerFile; QProcess *m_process; QProcess *m_processFile; QStringList m_updateFileNames; QStringList m_updateFilePaths; QString m_editorFileName; QString m_editorFilePath; QString m_workPath; QStackedWidget *m_stackedWidget; QLabel *m_blankWidget; AstWidget *m_projectAstWidget; LiteApi::IEditor *m_currentEditor; QPlainTextEdit *m_currentPlainTextEditor; QMap m_editorAstWidgetMap; QAction *m_syncClassViewAct; QAction *m_syncOutlineAct; bool m_isSyncClassView; bool m_isSyncOutline; QByteArray m_astviewSep; QAction *m_classViewToolAct; QAction *m_outlineToolAct; }; #endif // GOLANGAST_H ================================================ FILE: liteidex/src/plugins/golangast/golangast.pro ================================================ TARGET = golangast TEMPLATE = lib include (../../liteideplugin.pri) include (../../api/golangastapi/golangastapi.pri) include (../../api/quickopenapi/quickopenapi.pri) include (../../api/liteenvapi/liteenvapi.pri) include (../../utils/symboltreeview/symboltreeview.pri) include (../../3rdparty/qtc_editutil/qtc_editutil.pri) DEFINES += GOLANGAST_LIBRARY SOURCES += golangastplugin.cpp \ golangast.cpp \ golangasticon.cpp \ astwidget.cpp \ golangsymbol.cpp \ golangastoption.cpp \ golangastoptionfactory.cpp HEADERS += golangastplugin.h\ golangast_global.h \ golangast.h \ golangasticon.h \ astwidget.h \ golangastitem.h \ golangsymbol.h \ golangastoption.h \ golangastoptionfactory.h RESOURCES += \ golangast.qrc FORMS += \ golangastoption.ui ================================================ FILE: liteidex/src/plugins/golangast/golangast.qrc ================================================ images/const.png images/const_p.png images/consts.png images/file.png images/func.png images/func_p.png images/funcs.png images/gofile.png images/interface.png images/interface_p.png images/makefile.png images/package.png images/project.png images/struct.png images/struct_p.png images/type.png images/type_p.png images/var.png images/var_p.png images/vars.png images/type_method.png images/type_method_p.png images/type_var_p.png images/type_var.png images/import.png images/imports.png images/type_factor.png images/type_factor_p.png images/todo.png images/todos.png ================================================ FILE: liteidex/src/plugins/golangast/golangast_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangast_global.h // Creator: visualfc #ifndef GOLANGAST_GLOBAL_H #define GOLANGAST_GLOBAL_H #include #if defined(GOLANGAST_LIBRARY) # define GOLANGASTSHARED_EXPORT Q_DECL_EXPORT #else # define GOLANGASTSHARED_EXPORT Q_DECL_IMPORT #endif #define OPTION_GOLANGAST "option/golangast" #define GOLANGAST_QUICKOPEN_SYMBOL_MATCHCASE "golangast/quickopensymbolmatchcase" #define GOLANGAST_QUICKOPNE_SYMBOL_IMPORTPATH "golangast/quickopensymbolimportpath" #define GOLANGAST_CLASSVIEW_SYNCEDITOR "golangast/classviewsynceditor" #define GOLANGAST_OUTLINE_SYNCEDITOR "golangast/outlinesynceditor" #endif // GOLANGAST_GLOBAL_H ================================================ FILE: liteidex/src/plugins/golangast/golangasticon.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangasticon.cpp // Creator: visualfc #include "golangasticon.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end /* tools/goastview/packageview.go const ( tag_package = "p" tag_imports_folder = "+m" tag_import = "mm" tag_type = "t" tag_struct = "s" tag_interface = "i" tag_value = "v" tag_const = "c" tag_func = "f" tag_value_folder = "+v" tag_const_folder = "+c" tag_func_folder = "+f" tag_type_method = "tm" tag_type_factor = "tf" tag_type_value = "tv" ) */ GolangAstIconPublic::GolangAstIconPublic() : iconPackage(QIcon("icon:golangast/images/package.png")), iconImport(QIcon("icon:golangast/images/import.png")), iconImports(QIcon("icon:golangast/images/imports.png")), iconType(QIcon("icon:golangast/images/type.png")), iconStruct(QIcon("icon:golangast/images/struct.png")), iconInterface(QIcon("icon:golangast/images/interface.png")), iconFunc(QIcon("icon:golangast/images/func.png")), iconFuncs(QIcon("icon:golangast/images/funcs.png")), iconVar(QIcon("icon:golangast/images/var.png")), iconVars(QIcon("icon:golangast/images/vars.png")), iconConst(QIcon("icon:golangast/images/const.png")), iconConsts(QIcon("icon:golangast/images/consts.png")), iconTypeMethod(QIcon("icon:golangast/images/type_method.png")), iconTypeFactor(QIcon("icon:golangast/images/type_factor.png")), iconTypeVar(QIcon("icon:golangast/images/type_var.png")), iconTodo(QIcon("icon:golangast/images/todo.png")), iconTodos(QIcon("icon:golangast/images/todos.png")), iconGofile(QIcon("icon:golangast/images/gofile.png")), iconMakefile(QIcon("icon:golangast/images/makefile.png")), iconProfile(QIcon("icon:golangast/images/project.png")) { } QIcon GolangAstIconPublic::iconFromTag(const QString &tag) const { if (tag == "p") return iconPackage; else if (tag == "+m") return iconImports; else if (tag == "mm") return iconImport; else if (tag == "t") return iconType; else if (tag == "i") return iconInterface; else if (tag == "s") return iconStruct; else if (tag == "v") return iconVar; else if (tag == "c") return iconConst; else if (tag == "f") return iconFunc; else if (tag == "+v") return iconVars; else if (tag == "+c") return iconConsts; else if (tag == "+f") return iconFuncs; else if (tag == "tm") return iconTypeMethod; else if (tag == "tf") return iconTypeFactor; else if (tag == "tv") return iconTypeVar; else if (tag == "b") return iconTodo; else if (tag == "+b") return iconTodos; return QIcon(); } QIcon GolangAstIconPublic::iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool) const { if (tag == LiteApi::TagPackage) return iconPackage; else if (tag == LiteApi::TagImportFolder) return iconImports; else if (tag == LiteApi::TagImport) return iconImport; else if (tag == LiteApi::TagType) return iconType; else if (tag == LiteApi::TagInterface) return iconInterface; else if (tag == LiteApi::TagStruct) return iconStruct; else if (tag == LiteApi::TagValue) return iconVar; else if (tag == LiteApi::TagConst) return iconConst; else if (tag == LiteApi::TagFunc) return iconFunc; else if (tag == LiteApi::TagValueFolder) return iconVars; else if (tag == LiteApi::TagConstFolder) return iconConsts; else if (tag == LiteApi::TagFuncFolder) return iconFuncs; else if (tag == LiteApi::TagTypeMethod) return iconTypeMethod; else if (tag == LiteApi::TagTypeFactor) return iconTypeFactor; else if (tag == LiteApi::TagTypeValue) return iconTypeVar; else if (tag == LiteApi::TagTodo) return iconTodo; else if (tag == LiteApi::TagTodoFolder) return iconTodos; return QIcon(); } GolangAstIconPrivate::GolangAstIconPrivate() : iconPackage(QIcon("icon:golangast/images/package.png")), iconImport(QIcon("icon:golangast/images/import.png")), iconImports(QIcon("icon:golangast/images/imports.png")), iconType(QIcon("icon:golangast/images/type_p.png")), iconStruct(QIcon("icon:golangast/images/struct_p.png")), iconInterface(QIcon("icon:golangast/images/interface_p.png")), iconFunc(QIcon("icon:golangast/images/func_p.png")), iconFuncs(QIcon("icon:golangast/images/funcs.png")), iconVar(QIcon("icon:golangast/images/var_p.png")), iconVars(QIcon("icon:golangast/images/vars.png")), iconConst(QIcon("icon:golangast/images/const_p.png")), iconConsts(QIcon("icon:golangast/images/consts.png")), iconTypeMethod(QIcon("icon:golangast/images/type_method_p.png")), iconTypeFactor(QIcon("icon:golangast/images/type_factor_p.png")), iconTypeVar(QIcon("icon:golangast/images/type_var_p.png")), iconTodo(QIcon("icon:golangast/images/todo.png")), iconTodos(QIcon("icon:golangast/images/todos.png")) { } QIcon GolangAstIconPrivate::iconFromTag(const QString &tag) const { if (tag == "p") return iconPackage; else if (tag == "+m") return iconImports; else if (tag == "mm") return iconImport; else if (tag == "t") return iconType; else if (tag == "i") return iconInterface; else if (tag == "s") return iconStruct; else if (tag == "v") return iconVar; else if (tag == "c") return iconConst; else if (tag == "f") return iconFunc; else if (tag == "+v") return iconVars; else if (tag == "+c") return iconConsts; else if (tag == "+f") return iconFuncs; else if (tag == "tm") return iconTypeMethod; else if (tag == "tf") return iconTypeFactor; else if (tag == "tv") return iconTypeVar; else if (tag == "b") return iconTodo; else if (tag == "+b") return iconTodos; return QIcon(); } QIcon GolangAstIconPrivate::iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool) const { if (tag == LiteApi::TagPackage) return iconPackage; else if (tag == LiteApi::TagImportFolder) return iconImports; else if (tag == LiteApi::TagImport) return iconImport; else if (tag == LiteApi::TagType) return iconType; else if (tag == LiteApi::TagInterface) return iconInterface; else if (tag == LiteApi::TagStruct) return iconStruct; else if (tag == LiteApi::TagValue) return iconVar; else if (tag == LiteApi::TagConst) return iconConst; else if (tag == LiteApi::TagFunc) return iconFunc; else if (tag == LiteApi::TagValueFolder) return iconVars; else if (tag == LiteApi::TagConstFolder) return iconConsts; else if (tag == LiteApi::TagFuncFolder) return iconFuncs; else if (tag == LiteApi::TagTypeMethod) return iconTypeMethod; else if (tag == LiteApi::TagTypeFactor) return iconTypeFactor; else if (tag == LiteApi::TagTypeValue) return iconTypeVar; else if (tag == LiteApi::TagTodo) return iconTodo; else if (tag == LiteApi::TagTodoFolder) return iconTodos; return QIcon(); } GolangAstIcon::GolangAstIcon() { } GolangAstIcon *GolangAstIcon::instance() { static GolangAstIcon icons; return &icons; } QIcon GolangAstIcon::iconFromTag(const QString &tag, bool pub) const { if (pub) { return icons.iconFromTag(tag); } return icons_p.iconFromTag(tag); } QIcon GolangAstIcon::iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool pub) const { if (pub) { return icons.iconFromTagEnum(tag); } return icons_p.iconFromTagEnum(tag); } ================================================ FILE: liteidex/src/plugins/golangast/golangasticon.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangasticon.h // Creator: visualfc #ifndef GOLANGASTICON_H #define GOLANGASTICON_H #include #include "golangastapi/golangastapi.h" class GolangAstIconPublic { public: GolangAstIconPublic(); QIcon iconFromTag(const QString &tag) const; QIcon iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool pub = true) const; protected: QIcon iconPackage; QIcon iconImport; QIcon iconImports; QIcon iconType; QIcon iconStruct; QIcon iconInterface; QIcon iconFunc; QIcon iconFuncs; QIcon iconVar; QIcon iconVars; QIcon iconConst; QIcon iconConsts; QIcon iconTypeMethod; QIcon iconTypeFactor; QIcon iconTypeVar; QIcon iconTodo; QIcon iconTodos; public: QIcon iconGofile; QIcon iconMakefile; QIcon iconProfile; }; class GolangAstIconPrivate { public: GolangAstIconPrivate(); QIcon iconFromTag(const QString &tag) const; QIcon iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool pub = true) const; protected: QIcon iconPackage; QIcon iconImport; QIcon iconImports; QIcon iconType; QIcon iconStruct; QIcon iconInterface; QIcon iconFunc; QIcon iconFuncs; QIcon iconVar; QIcon iconVars; QIcon iconConst; QIcon iconConsts; QIcon iconTypeMethod; QIcon iconTypeFactor; QIcon iconTypeVar; QIcon iconTodo; QIcon iconTodos; }; class GolangAstIcon { public: static GolangAstIcon *instance(); QIcon iconFromTag(const QString &tag, bool pub = true) const; QIcon iconFromTagEnum(LiteApi::ASTTAG_ENUM tag, bool pub = true) const; protected: GolangAstIcon(); GolangAstIconPrivate icons_p; GolangAstIconPublic icons; }; #endif // GOLANGASTICON_H ================================================ FILE: liteidex/src/plugins/golangast/golangastitem.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastitem.h // Creator: visualfc #ifndef GOLANGASTITEM_H #define GOLANGASTITEM_H #include #include "golangastapi/golangastapi.h" struct AstItemPos { QString fileName; int line; int column; int endLine; int endColumn; }; class GolangAstItem : public QStandardItem { public: QList m_posList; QString m_tagName; QString m_tipInfo; LiteApi::ASTTAG_ENUM m_tagFlag; public: bool hasChildItem() const { switch (m_tagFlag) { case LiteApi::TagPackage: case LiteApi::TagConstFolder: case LiteApi::TagValueFolder: case LiteApi::TagImportFolder: case LiteApi::TagFuncFolder: case LiteApi::TagTodoFolder: case LiteApi::TagStruct: case LiteApi::TagInterface: case LiteApi::TagType: return true; default: return false; } return false; } bool isFolder() const { switch (m_tagFlag) { case LiteApi::TagConstFolder: case LiteApi::TagValueFolder: case LiteApi::TagImportFolder: case LiteApi::TagFuncFolder: case LiteApi::TagTodoFolder: return true; default: return false; } return false; } }; #endif // GOLANGASTITEM_H ================================================ FILE: liteidex/src/plugins/golangast/golangastoption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastoption.cpp // Creator: visualfc #include "golangastoption.h" #include "ui_golangastoption.h" #include "golangast_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangAstOption::GolangAstOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::GolangAstOption) { ui->setupUi(m_widget); } GolangAstOption::~GolangAstOption() { delete m_widget; delete ui; } QWidget *GolangAstOption::widget() { return m_widget; } QString GolangAstOption::name() const { return "GolangAst"; } QString GolangAstOption::mimeType() const { return OPTION_GOLANGAST; } void GolangAstOption::load() { ui->checkQuickSymbolImportPath->setChecked(m_liteApp->settings()->value(GOLANGAST_QUICKOPNE_SYMBOL_IMPORTPATH,true).toBool()); ui->checkQuickSymbolMatchCase->setChecked(m_liteApp->settings()->value(GOLANGAST_QUICKOPEN_SYMBOL_MATCHCASE,false).toBool()); } void GolangAstOption::save() { m_liteApp->settings()->setValue(GOLANGAST_QUICKOPNE_SYMBOL_IMPORTPATH,ui->checkQuickSymbolImportPath->isChecked()); m_liteApp->settings()->setValue(GOLANGAST_QUICKOPEN_SYMBOL_MATCHCASE,ui->checkQuickSymbolMatchCase->isChecked()); } ================================================ FILE: liteidex/src/plugins/golangast/golangastoption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastoption.h // Creator: visualfc #ifndef GOLANGASTOPTION_H #define GOLANGASTOPTION_H #include "liteapi/liteapi.h" namespace Ui { class GolangAstOption; } class GolangAstOption : public LiteApi::IOption { Q_OBJECT public: explicit GolangAstOption(LiteApi::IApplication *app, QObject *parent = 0); ~GolangAstOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void load(); virtual void save(); private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::GolangAstOption *ui; }; #endif // GOLANGASTOPTION_H ================================================ FILE: liteidex/src/plugins/golangast/golangastoption.ui ================================================ GolangAstOption 0 0 400 121 Form QuickOpenSymbol Show import path Match case sensitive Qt::Vertical 20 24 ================================================ FILE: liteidex/src/plugins/golangast/golangastoptionfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastoptionfactory.cpp // Creator: visualfc #include "golangastoption.h" #include "golangastoptionfactory.h" #include "golangast_global.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangAstOptionFactory::GolangAstOptionFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IOptionFactory(parent), m_liteApp(app) { } QStringList GolangAstOptionFactory::mimeTypes() const { return QStringList() << OPTION_GOLANGAST; } LiteApi::IOption *GolangAstOptionFactory::create(const QString &mimeType) { if (mimeType == OPTION_GOLANGAST) { return new GolangAstOption(m_liteApp,this); } return 0; } ================================================ FILE: liteidex/src/plugins/golangast/golangastoptionfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastoptionfactory.h // Creator: visualfc #ifndef GOLANGASTOPTIONFACTORY_H #define GOLANGASTOPTIONFACTORY_H #include "liteapi/liteapi.h" class GolangAstOptionFactory : public LiteApi::IOptionFactory { public: GolangAstOptionFactory(LiteApi::IApplication *app, QObject *parent); virtual QStringList mimeTypes() const; virtual LiteApi::IOption *create(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; }; #endif // GOLANGASTOPTIONFACTORY_H ================================================ FILE: liteidex/src/plugins/golangast/golangastplugin.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastplugin.cpp // Creator: visualfc #include "golangastplugin.h" #include "golangsymbol.h" #include "golangastoptionfactory.h" #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangAstPlugin::GolangAstPlugin() { } bool GolangAstPlugin::load(LiteApi::IApplication *app) { new GolangAst(app,this); LiteApi::IQuickOpenManager *mgr = LiteApi::getQuickOpenManager(app); if (mgr) { LiteApi::IQuickOpenMimeType *symbol = mgr->registerQuickOpenMimeType("@"); if (symbol) { symbol->addAdapter(new GolangSymbolFactory(app,this)); } } app->optionManager()->addFactory(new GolangAstOptionFactory(app,this)); return true; } #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(PluginFactory,PluginFactory) #endif ================================================ FILE: liteidex/src/plugins/golangast/golangastplugin.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangastplugin.h // Creator: visualfc #ifndef GOLANGASTPLUGIN_H #define GOLANGASTPLUGIN_H #include "golangast_global.h" #include "liteapi/liteapi.h" #include "golangast.h" #include class GolangAstPlugin : public LiteApi::IPlugin { Q_OBJECT public: GolangAstPlugin(); virtual bool load(LiteApi::IApplication *app); }; class PluginFactory : public LiteApi::PluginFactoryT { Q_OBJECT Q_INTERFACES(LiteApi::IPluginFactory) #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "liteidex.GolangAstPlugin") #endif public: PluginFactory() { m_info->setId("plugin/golangast"); m_info->setName("GolangAst"); m_info->setAuthor("visualfc"); m_info->setVer("X35"); m_info->setInfo("Golang Ast View"); m_info->appendDepend("plugin/quickopen"); m_info->appendDepend("plugin/liteenv"); } }; #endif // GOLANGASTPLUGIN_H ================================================ FILE: liteidex/src/plugins/golangast/golangsymbol.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangsymbol.cpp // Creator: visualfc #include "golangsymbol.h" #include "astwidget.h" #include "golangastitem.h" #include "golangast_global.h" #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangSymbol::GolangSymbol(LiteApi::IApplication *app, QObject *parent) : LiteApi::IQuickOpen(parent), m_liteApp(app) { m_model = new QStandardItemModel(this); m_proxy = new QSortFilterProxyModel(this); m_proxy->setSourceModel(m_model); m_process = new QProcess(this); connect(m_process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finished(int,QProcess::ExitStatus))); m_matchCase = Qt::CaseInsensitive; m_importPath = true; m_astviewSep = ",,,"; } QString GolangSymbol::id() const { return "quickopen/golangsymbol"; } QString GolangSymbol::info() const { return tr("Quick Open Symbol by Name"); } QString GolangSymbol::placeholderText() const { return QString(); } void GolangSymbol::activate() { // m_liteApp->editorManager()->addNavigationHistory(); } QAbstractItemModel *GolangSymbol::model() const { return m_proxy; } QModelIndex GolangSymbol::rootIndex() const { return QModelIndex(); } void GolangSymbol::updateModel() { m_matchCase = m_liteApp->settings()->value(GOLANGAST_QUICKOPEN_SYMBOL_MATCHCASE,false).toBool()?Qt::CaseSensitive:Qt::CaseInsensitive; m_importPath = m_liteApp->settings()->value(GOLANGAST_QUICKOPNE_SYMBOL_IMPORTPATH,true).toBool(); m_model->clear(); m_proxy->setFilterCaseSensitivity(m_matchCase); LiteApi::IEditor *editor = m_liteApp->editorManager()->currentEditor(); if (!editor) { return; } QString filePath = editor->filePath(); if (filePath.isEmpty()) { return; } QFileInfo info(filePath); QString cmd = LiteApi::getGotools(m_liteApp); QStringList args; args << "astview"; args << "-outline"; args << "-sep" << m_astviewSep; args << "-tp"; args << info.fileName(); m_process->setWorkingDirectory(info.path()); m_process->setEnvironment(LiteApi::getGoEnvironment(m_liteApp).toStringList()); m_process->start(cmd,args); } QModelIndex GolangSymbol::filterChanged(const QString &text) { m_proxy->setFilterFixedString(text); for (int i = 0; i < m_proxy->rowCount(); i++) { QModelIndex index = m_proxy->index(i,0); if (index.data().toString().startsWith(text,m_matchCase)) { gotoIndex(index,false); return index; } } return m_proxy->index(0,0); } bool GolangSymbol::gotoIndex(const QModelIndex &index,bool saveHistroy) { QModelIndex i = m_proxy->mapToSource(index); if (!i.isValid()) { return false; } GolangAstItem* item = (GolangAstItem*)m_model->itemFromIndex(i); if (item->m_posList.isEmpty()) { return false; } AstItemPos pos = item->m_posList.at(0); QFileInfo info(QDir(m_process->workingDirectory()),pos.fileName); LiteApi::gotoLine(m_liteApp,info.filePath(),pos.line-1,pos.column-1,true,saveHistroy); return true; } void GolangSymbol::indexChanged(const QModelIndex &index) { gotoIndex(index,false); } bool GolangSymbol::selected(const QString &/*text*/, const QModelIndex &index) { return gotoIndex(index,false); } void GolangSymbol::cancel() { } void GolangSymbol::finished(int code, QProcess::ExitStatus status) { if (code == 0 && status == QProcess::NormalExit) { QByteArray ar = m_process->readAll(); AstWidget::parserModel(m_model,ar,m_astviewSep,true,!m_importPath); LiteApi::IQuickOpenManager *mgr = LiteApi::getQuickOpenManager(m_liteApp); if (mgr) { mgr->modelView()->expandAll(); } } } GolangSymbolFactory::GolangSymbolFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IQuickOpenAdapter(parent), m_liteApp(app) { m_symbol = new GolangSymbol(app,this); } QStringList GolangSymbolFactory::mimeTypes() const { return QStringList() << "text/x-gosrc"; } LiteApi::IQuickOpen *GolangSymbolFactory::load(const QString &mimeType) { if (mimeType == "text/x-gosrc") { return m_symbol; } return 0; } ================================================ FILE: liteidex/src/plugins/golangast/golangsymbol.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangsymbol.h // Creator: visualfc #ifndef GOLANGSYMBOL_H #define GOLANGSYMBOL_H #include #include class QStandardItemModel; class QSortFilterProxyModel; class QProcess; class GolangSymbol : public LiteApi::IQuickOpen { Q_OBJECT public: GolangSymbol(LiteApi::IApplication *app, QObject *parent = 0); virtual QString id() const; virtual QString info() const; virtual QString placeholderText() const; virtual void activate(); virtual QAbstractItemModel *model() const; virtual QModelIndex rootIndex() const; virtual void updateModel(); virtual QModelIndex filterChanged(const QString &text); virtual void indexChanged(const QModelIndex &index); virtual bool selected(const QString &text, const QModelIndex &index); virtual void cancel(); bool gotoIndex(const QModelIndex &index, bool saveHistroy); public slots: void finished(int code,QProcess::ExitStatus status); protected: LiteApi::IApplication *m_liteApp; QStandardItemModel *m_model; QSortFilterProxyModel *m_proxy; QProcess *m_process; Qt::CaseSensitivity m_matchCase; QByteArray m_astviewSep; bool m_importPath; }; class GolangSymbolFactory : public LiteApi::IQuickOpenAdapter { public: GolangSymbolFactory(LiteApi::IApplication *app, QObject *parent = 0); virtual QStringList mimeTypes() const; virtual LiteApi::IQuickOpen *load(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; GolangSymbol *m_symbol; }; #endif // GOLANGSYMBOL_H ================================================ FILE: liteidex/src/plugins/golangcode/golangcode.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcode.cpp // Creator: visualfc #include "golangcode.h" #include "golangcode_global.h" #include "fileutil/fileutil.h" #include "processex/processex.h" #include "../liteeditor/faketooltip.h" #include #include #include #include #include #include #include #include #include #include #include //#define GOCODE_CHECKGOPATH //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end int GolangCode::g_gocodeInstCount = 0; GolangCode::GolangCode(LiteApi::IApplication *app, QObject *parent) : QObject(parent), m_liteApp(app), m_editor(0), m_completer(0), m_closeOnExit(true), m_allImportHint(true) { g_gocodeInstCount++; m_gocodeProcess = new Process(this); m_gocodeSetProcess = new Process(this); m_gocodeImportProcess = new Process(this); // m_importProcess = new Process(this); m_gocodeProcess->setWorkingDirectory(m_liteApp->applicationPath()); m_gocodeSetProcess->setWorkingDirectory(m_liteApp->applicationPath()); m_gocodeImportProcess->setWorkingDirectory(m_liteApp->applicationPath()); connect(m_gocodeProcess,SIGNAL(started()),this,SLOT(started())); connect(m_gocodeProcess,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finished(int,QProcess::ExitStatus))); connect(m_gocodeImportProcess,SIGNAL(started()),this,SLOT(gocodeImportStarted())); connect(m_gocodeImportProcess,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(gocodeImportFinished(int,QProcess::ExitStatus))); // connect(m_importProcess,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(importFinished(int,QProcess::ExitStatus))); m_envManager = LiteApi::getEnvManager(m_liteApp); if (m_envManager) { connect(m_envManager,SIGNAL(currentEnvChanged(LiteApi::IEnv*)),this,SLOT(currentEnvChanged(LiteApi::IEnv*))); } m_golangAst = LiteApi::findExtensionObject(m_liteApp,"LiteApi.IGolangAst"); m_pkgImportTip = new ImportPkgTip(m_liteApp,this); connect(m_pkgImportTip,SIGNAL(import(QString,int)),this,SLOT(import(QString,int))); connect(m_liteApp->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*))); connect(m_liteApp->optionManager(),SIGNAL(applyOption(QString)),this,SLOT(applyOption(QString))); connect(m_liteApp,SIGNAL(loaded()),this,SLOT(appLoaded())); //applyOption("option/golangcode"); } void GolangCode::applyOption(QString /*id*/) { // if (id != "option/golangcode") return; // m_closeOnExit = m_liteApp->settings()->value(GOLANGCODE_EXITCLOSE,true).toBool(); // m_allImportHint = m_liteApp->settings()->value(GOLANGCODE_IMPORTHINT_GOPATH,true).toBool(); } void GolangCode::appLoaded() { loadPkgList(); #ifdef GOCODE_CHECKGOPATH LiteApi::IGoEnvManger *goEnv = LiteApi::getGoEnvManager(m_liteApp); if (goEnv) { connect(goEnv,SIGNAL(customGOPATHChanged(QString)),this,SLOT(customGOPATHChanged(QString))); connect(goEnv,SIGNAL(globalGOPATHChanged()),this,SLOT(globalGOPATHChanged())); } #endif } void GolangCode::import(const QString &import, int startPos) { QPlainTextEdit *ed = LiteApi::getPlainTextEdit(m_editor); if (!ed) { return; } QTextBlock block = ed->document()->firstBlock(); int pos1 = -1; int pos2 = -1; int pos3 = -1; int pos4 = -1; int offset = 0; while (block.isValid()) { QString text = block.text(); if (text.startsWith("/*")) { block = block.next(); while(block.isValid()) { if (block.text().endsWith("*/")) { break; } block = block.next(); } if (!block.isValid()) { break; } } else if (text.startsWith("var")) { break; } else if (text.startsWith("func")) { break; } else if (text.startsWith("package ")) { pos1 = block.position()+block.length(); } else if (pos1 != -1 && text.startsWith("import (")) { pos2 = block.position()+block.length(); break; } else if (pos1 != -1 && text.startsWith("import ")) { QString path = text.right(text.length()-7).trimmed(); if (!path.startsWith("\"C\"")) { pos3 = block.position()+ 7; pos4 = block.position()+block.length(); break; } } block = block.next(); } if (pos1 < 0) { return; } QString text = "\t\""+import+"\"\n"; QTextCursor cur = ed->textCursor(); int orgPos = cur.position(); cur.beginEditBlock(); if (pos2 < 0) { if (pos3 < 0) { pos2 = pos1; text = "\nimport (\n\t\""+import+"\"\n)\n"; } else { cur.setPosition(pos3); cur.insertText("(\n\t"); pos2 = pos4+3; offset += 3; text = "\t\""+import+"\"\n)\n"; } } cur.setPosition(pos2); cur.insertText(text); cur.setPosition(orgPos+text.length()+offset); cur.endEditBlock(); ed->setTextCursor(cur); if (orgPos == startPos) { prefixChanged(cur,m_lastPrefix,true); } } bool check_import(const QString &path, const QString &id) { int start = path.indexOf("\""); if (start >= 0) { int end = path.indexOf("\"",start+1); if (end > 0) { QString name = path.left(start).trimmed(); if (!name.isEmpty()) { if (name == id) { return true; } } else { QString tmp = path.mid(start+1,end-start-1); if (tmp == id) { return true; } if (tmp.endsWith("/"+id)) { return true; } } } } return false; } bool GolangCode::findImport(const QString &id) { QPlainTextEdit *ed = LiteApi::getPlainTextEdit(m_editor); if (!ed) { return false; } QTextBlock block = ed->document()->firstBlock(); int pos1 = -1; while (block.isValid()) { QString text = block.text().trimmed(); if (text.startsWith("/*")) { block = block.next(); while(block.isValid()) { if (block.text().endsWith("*/")) { break; } block = block.next(); } if (!block.isValid()) { break; } } else if (text.startsWith("var")) { break; } else if (text.startsWith("func")) { break; } else if (text.startsWith("package ")) { pos1 = block.position()+block.length(); } else if (pos1 != -1 && text.startsWith("import (")) { block = block.next(); while(block.isValid()) { QString text = block.text().trimmed(); if (text.startsWith(")")) { break; } //skip if (text.startsWith("/*")) { block = block.next(); while(block.isValid()) { if (block.text().endsWith("*/")) { break; } block = block.next(); } if (!block.isValid()) { break; } } if (text.startsWith("//")) { block = block.next(); continue; } if (check_import(text,id)) { return true; } block = block.next(); } } else if (pos1 != -1 && text.startsWith("import ")) { QString path = text.right(text.length()-7); if (check_import(path,id)) { return true; } } block = block.next(); } return false; } void GolangCode::updateEditorGOPATH() { if (m_gocodeCmd.isEmpty()) { return; } #ifdef GOCODE_CHECKGOPATH QProcessEnvironment env = LiteApi::getCustomGoEnvironment(m_liteApp,m_liteApp->editorManager()->currentEditor()); QString gopathenv = env.value("GOPATH"); if (gopathenv != m_lastGopathEnv) { m_lastGopathEnv = gopathenv; gocodeUpdataLibpath(env); loadImportsList(env); m_liteApp->appendLog("GolangCode",QString("gocode set lib-path \"%1\"").arg(gopathenv),false); } #else QProcessEnvironment env = LiteApi::getGoEnvironment(m_liteApp); #endif if (!m_gocodeImportProcess->isStop()) { m_gocodeImportProcess->stop(10); } QStringList args; args << "-f" << "csv" << "autocomplete" << "main.go" << "21"; m_gocodeImportProcess->setProcessEnvironment(env); m_gocodeImportProcess->setWorkingDirectory(m_fileInfo.absolutePath()); m_gocodeImportProcess->startEx(m_gocodeCmd,args); } void GolangCode::customGOPATHChanged(const QString &/*buildPath*/) { updateEditorGOPATH(); } void GolangCode::globalGOPATHChanged() { updateEditorGOPATH(); } void GolangCode::broadcast(QString /*module*/,QString /*id*/,QString) { // if (module == "golangpackage" && id == "reloadgopath") { // resetGocode(); // } } GolangCode::~GolangCode() { delete m_gocodeProcess; delete m_gocodeSetProcess; // delete m_importProcess; delete m_gocodeImportProcess; g_gocodeInstCount--; if (g_gocodeInstCount == 0 && m_closeOnExit && !m_gocodeCmd.isEmpty()) { ProcessEx::startDetachedExAndHide(m_gocodeCmd,QStringList() << "close"); } } void GolangCode::gocodeUpdataLibpath(const QProcessEnvironment &env) { if (m_gocodeCmd.isEmpty()) { return; } m_gocodeProcess->setProcessEnvironment(env); m_gocodeSetProcess->setProcessEnvironment(env); if (!m_gocodeSetProcess->isStop()) { m_gocodeSetProcess->stopAndWait(100,1000); } m_gocodeSetProcess->startEx(m_gocodeCmd,QStringList() << "set" << "lib-path" << env.value("GOPATH")); } void GolangCode::gocodeReset(const QProcessEnvironment &env) { if (m_gocodeCmd.isEmpty()) { return; } m_gocodeProcess->setProcessEnvironment(env); m_gocodeSetProcess->setProcessEnvironment(env); if (g_gocodeInstCount > 1) { if (!m_gocodeSetProcess->isStop()) { m_gocodeSetProcess->stopAndWait(100,1000); } m_gocodeSetProcess->startEx(m_gocodeCmd,QStringList() << "close"); } } void GolangCode::cgoComplete() { QStandardItem *root= m_completer->findRoot(m_preWord); QStringList types; types << "int" << "uint" << "short" << "ushort" << "char" << "schar" << "uchar" << "long" << "ulong" << "longlong" << "ulonglong" << "float" << "double" << "complexfloat" << "complexdouble"; QIcon icon = m_golangAst->iconFromTagEnum(LiteApi::TagType,true); foreach(QString item, types) { m_completer->appendChildItem(root,item,"type","",icon,true); } icon = m_golangAst->iconFromTagEnum(LiteApi::TagFunc,true); m_completer->appendChildItem(root,"CString","func","func(string) *C.char",icon,true); m_completer->appendChildItem(root,"GoString","func","func(*C.char) string",icon,true); m_completer->appendChildItem(root,"GoStringN","func","func(*C.char, C.int) string",icon,true); m_completer->appendChildItem(root,"GoBytes","func","func(unsafe.Pointer, C.int) []byte",icon,true); m_completer->appendChildItem(root,"CBytes","func","func([]byte) unsafe.Pointer",icon,true); QStringList all = parserCgoInEditor(1024); icon = QIcon("icon:liteeditor/images/findword.png"); foreach (QString s, all) { m_completer->appendChildItem(root,s,"","",icon,false); } m_completer->updateCompleterModel(); m_completer->showPopup(); } QStringList GolangCode::parserCgoInEditor(int nmax) { QTextCursor tc = m_editor->textCursor(); QTextDocument *doc = m_editor->document(); int maxNumber = tc.blockNumber(); int blockNumber = tc.blockNumber(); QTextBlock block = doc->firstBlock(); int first = maxNumber-nmax; if (first > 0) { block = doc->findBlockByNumber(first); } maxNumber += nmax; QStringList all; QRegExp rx("C\\.([\\w\\-\\_]+)"); while (block.isValid()) { if (block.blockNumber() >= maxNumber) { break; } if (block.blockNumber() == blockNumber) { block = block.next(); continue; } QString line = block.text().trimmed(); if (!line.isEmpty()) { int pos = 0; while ((pos = rx.indexIn(line, pos)) != -1) { QString cap = rx.cap(1); all.push_back(cap); pos += rx.matchedLength(); } } block = block.next(); } all.removeDuplicates(); return all; } void GolangCode::loadPkgList() { QString path = m_liteApp->resourcePath()+("/packages/go/pkglist"); QFile file(path); if (file.open(QFile::ReadOnly)) { QByteArray data = file.readAll(); QString ar = QString::fromUtf8(data); ar.replace("\r\n","\n"); foreach(QString line, ar.split("\n")) { line = line.trimmed(); if (line.isEmpty()) { continue; } QStringList pathList = line.split("/"); m_pkgListMap.insert(pathList.last(),line); m_importList.append(line); } } m_importList.removeDuplicates(); m_importList << "github.com/" << "golang.org/x/"; m_allImportList = m_importList; } //void GolangCode::loadImportsList(const QProcessEnvironment &env) //{ // if (!m_importProcess->isStop()) { // m_importProcess->stopAndWait(100,1000); // } // QString cmd = LiteApi::getGotools(m_liteApp); // if (cmd.isEmpty()) { // return; // } // QStringList args; // args << "pkgs" << "-list" << "-pkg" << "-skip_goroot"; // m_importProcess->setProcessEnvironment(env); // m_importProcess->startEx(cmd,args); //} void GolangCode::currentEnvChanged(LiteApi::IEnv*) { QProcessEnvironment env = LiteApi::getGoEnvironment(m_liteApp); // if (!LiteApi::hasGoEnv(env)) { // return; // } m_liteApp->appendLog("GolangCode","go environment changed"); m_gobinCmd = FileUtil::lookupGoBin("go",m_liteApp,env,false); m_gocodeCmd = FileUtil::lookupGoBin("gocode",m_liteApp,env,true); if (m_gocodeCmd.isEmpty()) { m_liteApp->appendLog("GolangCode","gocode was not found on system PATH (hint: is gocode installed? \"go install github.com/visualfc/gocode@latest\")",true); } else { m_liteApp->appendLog("GolangCode",QString("Found gocode at %1").arg(m_gocodeCmd)); } m_gocodeProcess->setProcessEnvironment(env); // m_importProcess->setProcessEnvironment(env); m_gocodeSetProcess->setProcessEnvironment(env); gocodeReset(env); currentEditorChanged(m_liteApp->editorManager()->currentEditor()); } void GolangCode::currentEditorChanged(LiteApi::IEditor *editor) { if (!editor) { this->setCompleter(0); return; } if (editor->mimeType() == "text/x-gosrc") { LiteApi::ICompleter *completer = LiteApi::findExtensionObject(editor,"LiteApi.ICompleter"); this->setCompleter(completer); } else if (editor->mimeType() == "browser/goplay") { LiteApi::IEditor* pedit = LiteApi::findExtensionObject(m_liteApp->extension(),"LiteApi.Goplay.IEditor"); if (pedit && pedit->mimeType() == "text/x-gosrc") { editor = pedit; LiteApi::ICompleter *completer = LiteApi::findExtensionObject(editor,"LiteApi.ICompleter"); this->setCompleter(completer); } } else { this->setCompleter(0); return; } m_editor = LiteApi::getTextEditor(editor); if (!m_editor) { return; } m_pkgImportTip->setWidget(editor->widget()); QString filePath = m_editor->filePath(); if (filePath.isEmpty()) { return; } m_fileInfo.setFile(filePath); m_gocodeProcess->setWorkingDirectory(m_fileInfo.absolutePath()); updateEditorGOPATH(); } void GolangCode::setCompleter(LiteApi::ICompleter *completer) { if (m_completer) { disconnect(m_completer,0,this,0); } m_completer = completer; if (m_completer) { m_completer->setImportList(m_allImportList); if (!m_gocodeCmd.isEmpty()) { m_completer->setSearchSeparator(false); m_completer->setExternalMode(true); connect(m_completer,SIGNAL(prefixChanged(QTextCursor,QString,bool)),this,SLOT(prefixChanged(QTextCursor,QString,bool))); connect(m_completer,SIGNAL(wordCompleted(QString,QString,QString)),this,SLOT(wordCompleted(QString,QString,QString))); } else { m_completer->setSearchSeparator(true); m_completer->setExternalMode(false); } } } void GolangCode::prefixChanged(QTextCursor cur,QString pre,bool force) { if (m_completer->completionContext() != LiteApi::CompleterCodeContext) { return; } if (m_gocodeCmd.isEmpty()) { return; } // if (m_completer->completer()->completionPrefix().startsWith(pre)) { // // qDebug() << pre << m_completer->completer()->completionPrefix(); // // return; // } if (!m_gocodeProcess->isStop()) { m_gocodeProcess->stopAndWait(30,100); } int offset = -1; if (pre.endsWith('.')) { m_preWord = pre; offset = 0; } else if (pre.length() == m_completer->prefixMin()) { m_preWord.clear(); } else { if (!force) { return; } m_preWord.clear(); int index = pre.lastIndexOf("."); if (index != -1) { m_preWord = pre.left(index); } } m_prefix = pre; m_lastPrefix = m_prefix; if (!m_preWord.isEmpty()) { m_completer->clearItemChilds(m_preWord); } if (m_preWord == "C.") { cgoComplete(); return; } if (m_preWord.endsWith(".")) { bool testDigit = true; for (int i = 0; i < m_preWord.size()-1; i++) { if (!m_preWord.at(i).isDigit()) { testDigit = false; break; } } if (testDigit) { return; } } if (m_prefix.lastIndexOf("..") > 0) { m_pkgImportTip->hide(); return; } QString src = cur.document()->toPlainText(); src = src.replace("\r\n","\n"); m_writeData = src.left(cur.position()).toUtf8(); QStringList args; args << "-f" << "csv" << "autocomplete" << m_fileInfo.fileName() << QString::number(m_writeData.length()+offset); m_writeData = src.toUtf8(); m_gocodeProcess->setWorkingDirectory(m_fileInfo.absolutePath()); m_gocodeProcess->startEx(m_gocodeCmd,args); } void GolangCode::wordCompleted(QString,QString,QString) { m_prefix.clear(); } void GolangCode::started() { if (m_writeData.isEmpty()) { m_gocodeProcess->closeWriteChannel(); return; } m_gocodeProcess->write(m_writeData); m_gocodeProcess->closeWriteChannel(); m_writeData.clear(); } void GolangCode::finished(int code,QProcess::ExitStatus) { if (code != 0) { return; } if (m_prefix.isEmpty()) { return; } if (m_prefix != m_lastPrefix) { m_prefix.clear(); return; } QByteArray read = m_gocodeProcess->readAllStandardOutput(); QList all = read.split('\n'); //func,,Fprint,,func(w io.Writer, a ...interface{}) (n int, error os.Error) //type,,Formatter,,interface //const,,ModeExclusive,, //var,,Args,,[]string int n = 0; QIcon icon; QStandardItem *root= m_completer->findRoot(m_preWord); foreach (QByteArray bs, all) { QStringList word = QString::fromUtf8(bs,bs.size()).split(",,"); //nsf/gocode count=3 //mdempsky/gocode count = 4 // ("var", "s4", "string", "") // ("func", "Errorf", "func(format string, a ...interface{}) error", "fmt") if (word.count() < 3) { continue; } if (word.at(0) == "PANIC") { continue; } LiteApi::ASTTAG_ENUM tag = LiteApi::TagNone; QString kind = word.at(0); QString info = word.at(2); if (kind == "package") { tag = LiteApi::TagPackage; } else if (kind == "func") { tag = LiteApi::TagFunc; } else if (kind == "var") { tag = LiteApi::TagValue; } else if (kind == "const") { tag = LiteApi::TagConst; } else if (kind == "type") { if (info == "interface") { tag = LiteApi::TagInterface; } else if (info == "struct") { tag = LiteApi::TagStruct; } else { tag = LiteApi::TagType; } } if (m_golangAst) { icon = m_golangAst->iconFromTagEnum(tag,true); } //m_completer->appendItemEx(m_preWord+word.at(1),kind,info,icon,true); m_completer->appendChildItem(root,word.at(1),kind,info,icon,true); n++; } m_lastPrefix = m_prefix; m_prefix.clear(); if (n >= 1) { m_completer->updateCompleterModel(); m_completer->showPopup(); } if (n == 0 && m_lastPrefix.endsWith(".")) { QString id = m_lastPrefix.left(m_lastPrefix.length()-1); if (id.length() < 2) { return; } QStringList pkgs = m_pkgListMap.values(id); pkgs.sort(); if (m_allImportHint) { QStringList extras = m_extraPkgListMap.values(id); extras.sort(); pkgs << extras; } if (!pkgs.isEmpty() && !findImport(id)) { QPlainTextEdit *ed = LiteApi::getPlainTextEdit(m_editor); if (ed) { int pos = ed->textCursor().position(); m_pkgImportTip->showPkgHint(pos,pkgs,ed); } } } } void GolangCode::gocodeImportStarted() { m_gocodeImportProcess->write("package main\nimport \"\""); m_gocodeImportProcess->closeWriteChannel(); } void GolangCode::gocodeImportFinished(int code, QProcess::ExitStatus) { if (code != 0) { return; } QByteArray data = m_gocodeImportProcess->readAllStandardOutput(); QList lines = QString::fromUtf8(data).split('\n'); QStringList importList; m_extraPkgListMap.clear(); foreach (QString line, lines) { QStringList ar = line.split(",,"); if (ar.count() < 3) { continue; } if (ar.at(0) == "PANIC") { continue; } if (ar[0] != "import") { continue; } if (m_importList.contains(ar[1])) { continue; } QString pkg = ar[1]; importList.append(pkg); QStringList pathList = pkg.split("/"); m_extraPkgListMap.insert(pathList.last(),pkg); } if (m_completer) { m_completer->setImportList(QStringList() << m_importList << importList); } } //void GolangCode::importFinished(int code,QProcess::ExitStatus) //{ // if (code != 0) { // return; // } // return; // QByteArray read = m_importProcess->readAllStandardOutput(); // QString data = QString::fromUtf8(read); // QStringList importList = data.split('\n'); // importList.removeDuplicates(); // importList.sort(); // m_extraPkgListMap.clear(); // foreach (QString line, importList) { // QStringList pathList = line.split("/"); // m_extraPkgListMap.insert(pathList.last(),line); // } // m_allImportList = m_importList; // m_allImportList.append(importList); // m_allImportList.removeDuplicates(); // if (m_completer) { // m_completer->setImportList(m_allImportList); // } //} ImportPkgTip::ImportPkgTip(LiteApi::IApplication *app, QObject *parent) : QObject(parent), m_liteApp(app) { m_editWidget = 0; m_startPos = 0; m_pkgIndex = 0; m_escapePressed = false; m_enterPressed = false; m_popup = new FakeToolTip(); //m_popup->setFocusPolicy(Qt::NoFocus); m_infoLabel = new QLabel; m_pkgLabel = new QLabel; QHBoxLayout *layout = new QHBoxLayout; layout->setMargin(0); layout->addWidget(m_infoLabel); layout->addWidget(m_pkgLabel); m_popup->setLayout(layout); qApp->installEventFilter(this); } ImportPkgTip::~ImportPkgTip() { delete m_popup; } void ImportPkgTip::showPkgHint(int startpos, const QStringList &pkg, QPlainTextEdit *ed) { const QDesktopWidget *desktop = QApplication::desktop(); #ifdef Q_WS_MAC const QRect screen = desktop->availableGeometry(desktop->screenNumber(ed)); #else const QRect screen = desktop->screenGeometry(desktop->screenNumber(ed)); #endif m_pkg = pkg; m_startPos = startpos; m_enterPressed = false; m_escapePressed = false; m_pkgIndex = 0; const QSize sz = m_popup->minimumSizeHint(); QTextCursor cur = ed->textCursor(); cur.setPosition(startpos); QPoint pos = ed->cursorRect(cur).topLeft(); pos.setY(pos.y() - sz.height() - 1); pos = ed->mapToGlobal(pos); if (pos.x() + sz.width() > screen.right()) pos.setX(screen.right() - sz.width()); m_infoLabel->setText(tr("warning, pkg not find, please enter to import :")); if (m_pkg.size() == 1) { m_pkgLabel->setText(m_pkg[0]); } else { m_pkgLabel->setText(QString("[%1/%2] \"%3\"").arg(m_pkgIndex+1).arg(m_pkg.size()).arg(m_pkg[m_pkgIndex])); } m_popup->move(pos); if (!m_popup->isVisible()) { m_popup->show(); } } void ImportPkgTip::hide() { m_popup->hide(); } void ImportPkgTip::setWidget(QWidget *widget) { hide(); m_editWidget = widget; } bool ImportPkgTip::eventFilter(QObject *obj, QEvent *e) { if (!m_popup->isVisible()) { return QObject::eventFilter(obj,e); } switch (e->type()) { case QEvent::ShortcutOverride: if (m_popup->isVisible() && static_cast(e)->key() == Qt::Key_Escape) { m_escapePressed = true; e->accept(); } else if (static_cast(e)->modifiers() & Qt::ControlModifier) { m_popup->hide(); } break; case QEvent::KeyPress: { QKeyEvent *ke = static_cast(e); if (ke->key() == Qt::Key_Escape) { m_escapePressed = true; } else if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) { m_enterPressed = true; e->accept(); return true; } else if (ke->key() == Qt::Key_Up) { if (m_pkg.size() > 1) { e->accept(); m_pkgIndex--; if (m_pkgIndex < 0) { m_pkgIndex = m_pkg.size()-1; } m_pkgLabel->setText(QString("[%1/%2] \"%3\"").arg(m_pkgIndex+1).arg(m_pkg.size()).arg(m_pkg[m_pkgIndex])); } return true; } else if (ke->key() == Qt::Key_Down) { if (m_pkg.size() > 1) { e->accept(); m_pkgIndex++; if (m_pkgIndex >= m_pkg.size()) { m_pkgIndex = 0; } m_pkgLabel->setText(QString("[%1/%2] \"%3\"").arg(m_pkgIndex+1).arg(m_pkg.size()).arg(m_pkg[m_pkgIndex])); } return true; } } break; case QEvent::KeyRelease: { QKeyEvent *ke = static_cast(e); if (ke->key() == Qt::Key_Escape && m_escapePressed) { hide(); } else if ( (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) && m_enterPressed) { e->accept(); m_enterPressed = false; hide(); emit import(m_pkg[m_pkgIndex],m_startPos); } else if (ke->key() == Qt::Key_Up) { return true; } else if (ke->key() == Qt::Key_Down) { return true; } else if (ke->text() != "."){ hide(); } } break; case QEvent::FocusOut: case QEvent::WindowDeactivate: case QEvent::Resize: if (obj != m_editWidget) break; hide(); break; case QEvent::Move: if (obj != m_liteApp->mainWindow()) break; hide(); break; case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::Wheel: { hide(); } break; default: break; } return false; } ================================================ FILE: liteidex/src/plugins/golangcode/golangcode.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcode.h // Creator: visualfc #ifndef GOLANGCODE_H #define GOLANGCODE_H #include "liteapi/liteapi.h" #include "liteeditorapi/liteeditorapi.h" #include "liteenvapi/liteenvapi.h" #include "golangastapi/golangastapi.h" #include "processex/processex.h" class QProcess; class QLabel; class ImportPkgTip : public QObject { Q_OBJECT public: explicit ImportPkgTip(LiteApi::IApplication *app, QObject *parent = 0); ~ImportPkgTip(); void showPkgHint(int startpos, const QStringList &pkg, QPlainTextEdit *ed); void setWidget(QWidget *widget); void hide(); signals: void import(QString,int); protected: bool eventFilter(QObject *obj, QEvent *e); LiteApi::IApplication *m_liteApp; QWidget *m_editWidget; QWidget *m_popup; QLabel *m_infoLabel; QLabel *m_pkgLabel; QStringList m_pkg; int m_startPos; int m_pkgIndex; bool m_escapePressed; bool m_enterPressed; }; class GolangCode : public QObject { Q_OBJECT public: explicit GolangCode(LiteApi::IApplication *app, QObject *parent = 0); ~GolangCode(); void setCompleter(LiteApi::ICompleter *completer); void gocodeUpdataLibpath(const QProcessEnvironment &env); void gocodeReset(const QProcessEnvironment &env); void cgoComplete(); void loadPkgList(); // void loadImportsList(const QProcessEnvironment &env); public slots: void currentEditorChanged(LiteApi::IEditor*); void currentEnvChanged(LiteApi::IEnv*); void prefixChanged(QTextCursor,QString,bool froce); void wordCompleted(QString,QString,QString); void started(); void finished(int,QProcess::ExitStatus); void gocodeImportStarted(); void gocodeImportFinished(int,QProcess::ExitStatus); // void importFinished(int,QProcess::ExitStatus); void broadcast(QString,QString,QString); void applyOption(QString); void appLoaded(); void import(const QString &import, int startPos); bool findImport(const QString &id); void customGOPATHChanged(const QString &buildPath); void globalGOPATHChanged(); protected: QStringList parserCgoInEditor(int nmax = 1024); void updateEditorGOPATH(); static int g_gocodeInstCount; LiteApi::IApplication *m_liteApp; LiteApi::ITextEditor *m_editor; LiteApi::ICompleter *m_completer; QWidget *m_pkgWidget; ImportPkgTip *m_pkgImportTip; QMultiMap m_pkgListMap; QStringList m_importList; QStringList m_allImportList; QMultiMap m_extraPkgListMap; QString m_gobinCmd; QString m_preWord; QString m_prefix; QString m_lastPrefix; QFileInfo m_fileInfo; Process *m_gocodeProcess; Process *m_gocodeSetProcess; Process *m_gocodeImportProcess; // Process *m_importProcess; QByteArray m_writeData; LiteApi::IEnvManager *m_envManager; LiteApi::IGolangAst *m_golangAst; QString m_gocodeCmd; QString m_lastGopathEnv; bool m_closeOnExit; bool m_allImportHint; }; #endif // GOLANGCODE_H ================================================ FILE: liteidex/src/plugins/golangcode/golangcode.pro ================================================ TARGET = golangcode TEMPLATE = lib include(../../liteideplugin.pri) include (../../api/liteenvapi/liteenvapi.pri) include(../../api/golangastapi/golangastapi.pri) include(../../utils/fileutil/fileutil.pri) include(../../utils/processex/processex.pri) DEFINES += GOLANGCODE_LIBRARY SOURCES += golangcodeplugin.cpp \ golangcode.cpp \ golangcodeoptionfactory.cpp \ golangcodeoption.cpp \ ../liteeditor/faketooltip.cpp HEADERS += golangcodeplugin.h\ golangcode_global.h \ golangcode.h \ golangcodeoptionfactory.h \ golangcodeoption.h \ ../liteeditor/faketooltip.h FORMS += \ golangcodeoption.ui ================================================ FILE: liteidex/src/plugins/golangcode/golangcode_global.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcode_global.h // Creator: visualfc #ifndef GOLANGCODE_GLOBAL_H #define GOLANGCODE_GLOBAL_H #include #if defined(GOLANGCODE_LIBRARY) # define GOLANGCODESHARED_EXPORT Q_DECL_EXPORT #else # define GOLANGCODESHARED_EXPORT Q_DECL_IMPORT #endif #define GOLANGCODE_EXITCLOSE "golangcode/exitclose" #define GOLANGCODE_AUTOBUILD "golangcode/gocodeautobuild" #define GOLANGCODE_IMPORTHINT_GOPATH "golangcode/importhintgopath" #endif // GOLANGCODE_GLOBAL_H ================================================ FILE: liteidex/src/plugins/golangcode/golangcodeoption.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcodeoption.cpp // Creator: Nik-U #include "golangcodeoption.h" #include "golangcode_global.h" #include "ui_golangcodeoption.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangCodeOption::GolangCodeOption(LiteApi::IApplication *app,QObject *parent) : LiteApi::IOption(parent), m_liteApp(app), m_widget(new QWidget), ui(new Ui::GolangCodeOption) { ui->setupUi(m_widget); } GolangCodeOption::~GolangCodeOption() { delete m_widget; delete ui; } QWidget *GolangCodeOption::widget() { return m_widget; } QString GolangCodeOption::name() const { return "GolangCode"; } QString GolangCodeOption::mimeType() const { return "option/golangcode"; } void GolangCodeOption::load() { bool close = m_liteApp->settings()->value(GOLANGCODE_EXITCLOSE,true).toBool(); bool allpkg = m_liteApp->settings()->value(GOLANGCODE_IMPORTHINT_GOPATH,true).toBool(); ui->exitCloseCheckBox->setChecked(close); ui->pkgHintGopathRadioButton->setChecked(allpkg); ui->pkgHintStdRadioButton->setChecked(!allpkg); } void GolangCodeOption::save() { bool close = ui->exitCloseCheckBox->isChecked(); bool allpkg = ui->pkgHintGopathRadioButton->isChecked(); m_liteApp->settings()->setValue(GOLANGCODE_EXITCLOSE,close); m_liteApp->settings()->setValue(GOLANGCODE_IMPORTHINT_GOPATH,allpkg); } ================================================ FILE: liteidex/src/plugins/golangcode/golangcodeoption.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcodeoption.h // Creator: Nik-U #ifndef GOLANGCODEOPTION_H #define GOLANGCODEOPTION_H #include "liteapi/liteapi.h" namespace Ui { class GolangCodeOption; } class GolangCodeOption : public LiteApi::IOption { Q_OBJECT public: explicit GolangCodeOption(LiteApi::IApplication *app, QObject *parent = 0); ~GolangCodeOption(); virtual QWidget *widget(); virtual QString name() const; virtual QString mimeType() const; virtual void load(); virtual void save(); private: LiteApi::IApplication *m_liteApp; QWidget *m_widget; Ui::GolangCodeOption *ui; }; #endif // GOLANGCODEOPTION_H ================================================ FILE: liteidex/src/plugins/golangcode/golangcodeoption.ui ================================================ GolangCodeOption 0 0 678 242 Form PKG automitic import prompt PKG automatic import hints for all packages (Module/GOPATH) PKG automatic import hints for standard package Gocode Close gocode when exiting Qt::Vertical 20 40 ================================================ FILE: liteidex/src/plugins/golangcode/golangcodeoptionfactory.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcodeoptionfactory.cpp // Creator: Nik-U #include "golangcodeoption.h" #include "golangcodeoptionfactory.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangCodeOptionFactory::GolangCodeOptionFactory(LiteApi::IApplication *app, QObject *parent) : LiteApi::IOptionFactory(parent), m_liteApp(app) { } QStringList GolangCodeOptionFactory::mimeTypes() const { return QStringList() << "option/golangcode"; } LiteApi::IOption *GolangCodeOptionFactory::create(const QString &mimeType) { if (mimeType == "option/golangcode") { return new GolangCodeOption(m_liteApp,this); } return 0; } ================================================ FILE: liteidex/src/plugins/golangcode/golangcodeoptionfactory.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcodeoptionfactory.h // Creator: Nik-U #ifndef GOLANGCODEOPTIONFACTORY_H #define GOLANGCODEOPTIONFACTORY_H #include "liteapi/liteapi.h" class GolangCodeOptionFactory : public LiteApi::IOptionFactory { public: GolangCodeOptionFactory(LiteApi::IApplication *app, QObject *parent); virtual QStringList mimeTypes() const; virtual LiteApi::IOption *create(const QString &mimeType); protected: LiteApi::IApplication *m_liteApp; }; #endif // GOLANGCODEOPTIONFACTORY_H ================================================ FILE: liteidex/src/plugins/golangcode/golangcodeplugin.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcodeplugin.cpp // Creator: visualfc #include "golangcodeplugin.h" #include "liteeditorapi/liteeditorapi.h" #include "qtc_editutil/uncommentselection.h" #include "golangcode.h" #include "golangcodeoptionfactory.h" #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end GolangCodePlugin::GolangCodePlugin() { } bool GolangCodePlugin::load(LiteApi::IApplication *app) { m_liteApp = app; m_code = new GolangCode(app,this); //app->optionManager()->addFactory(new GolangCodeOptionFactory(app,this)); connect(app->editorManager(),SIGNAL(editorCreated(LiteApi::IEditor*)),this,SLOT(editorCreated(LiteApi::IEditor*))); //connect(app->editorManager(),SIGNAL(currentEditorChanged(LiteApi::IEditor*)),this,SLOT(currentEditorChanged(LiteApi::IEditor*))); connect(app,SIGNAL(loaded()),this,SLOT(appLoaded())); return true; } QStringList GolangCodePlugin::dependPluginList() const { return QStringList() << "plugin/liteenv" << "plugin/golangast"; } void GolangCodePlugin::appLoaded() { } void GolangCodePlugin::editorCreated(LiteApi::IEditor *editor) { if (!editor) { return; } if (editor->mimeType() != "text/x-gosrc") { return; } LiteApi::ILiteEditor *liteEdit = LiteApi::getLiteEditor(editor); if (liteEdit) { liteEdit->setSpellCheckZoneDontComplete(true); } } void GolangCodePlugin::currentEditorChanged(LiteApi::IEditor *editor) { if (editor) { if (editor->mimeType() == "text/x-gosrc") { LiteApi::ICompleter *completer = LiteApi::findExtensionObject(editor,"LiteApi.ICompleter"); m_code->setCompleter(completer); return; } else if (editor->mimeType() == "browser/goplay") { LiteApi::IEditor* editor = LiteApi::findExtensionObject(m_liteApp->extension(),"LiteApi.Goplay.IEditor"); if (editor && editor->mimeType() == "text/x-gosrc") { LiteApi::ICompleter *completer = LiteApi::findExtensionObject(editor,"LiteApi.ICompleter"); m_code->setCompleter(completer); return; } } } m_code->setCompleter(0); } #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(PluginFactory,PluginFactory) #endif ================================================ FILE: liteidex/src/plugins/golangcode/golangcodeplugin.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangcodeplugin.h // Creator: visualfc #ifndef GOLANGCODEPLUGIN_H #define GOLANGCODEPLUGIN_H #include "golangcode_global.h" #include "liteapi/liteapi.h" #include class GolangCode; class GolangCodePlugin : public LiteApi::IPlugin { Q_OBJECT public: GolangCodePlugin(); virtual bool load(LiteApi::IApplication *app); virtual QStringList dependPluginList() const; protected slots: void appLoaded(); void editorCreated(LiteApi::IEditor*); void currentEditorChanged(LiteApi::IEditor*); protected: LiteApi::IApplication *m_liteApp; GolangCode *m_code; }; class PluginFactory : public LiteApi::PluginFactoryT { Q_OBJECT Q_INTERFACES(LiteApi::IPluginFactory) #if QT_VERSION >= 0x050000 Q_PLUGIN_METADATA(IID "liteidex.GolangCodePlugin") #endif public: PluginFactory() { m_info->setId("plugin/golangcode"); m_info->appendDepend("plugin/golangast"); m_info->setName("GolangCode"); m_info->setAuthor("visualfc"); m_info->setVer("X38.1"); m_info->setInfo("Golang Gocode Support"); m_info->appendDepend("plugin/liteenv"); } }; #endif // GOLANGCODEPLUGIN_H ================================================ FILE: liteidex/src/plugins/golangdoc/findapiwidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: findapiwidget.cpp // Creator: visualfc #include "findapiwidget.h" #include "liteenvapi/liteenvapi.h" #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end FindApiThread::FindApiThread(QObject *parent) : QThread(parent) { m_bMatchCase = true; } FindApiThread::~FindApiThread() { stopFind(); } void FindApiThread::setRootPath(const QString &rootPath) { m_rootPath = rootPath; } void FindApiThread::findApi(const QString &text) { if (this->isRunning()) { this->terminate(); } m_text = text; this->start(); } void FindApiThread::stopFind() { this->terminate(); } void FindApiThread::setMatchCase(bool b) { m_bMatchCase = b; } void FindApiThread::findInFile(const QString &filePath, const QString &baseName) { QFile f(filePath); if (!f.open(QFile::ReadOnly)) { return; } QTextStream *stream = new QTextStream(&f); QRegExp reg("^pkg\\s([\\w\\-\\.\\/]+)(\\s\\(([\\w\\-]+)\\))?,\\s(\\w+)"); QRegExp regm("\\(\\*?([\\w\\-]+)\\)\\s*(\\w+)"); while (!stream->atEnd()) { QString line = stream->readLine(); int pos = reg.indexIn(line); if (pos < 0) { continue; } // 1 pkgname // 2 ? (system) // 3 ? system // 4 const|func|method|var|type QString pkgName = reg.cap(1); // if (!reg.cap(3).isEmpty()) { // pkg = reg.cap(2)+"."+pkg; // } // if (!lastPkg || lastPkg->name != pkgName) { // lastPkg = m_pkgs.findPackage(pkgName); // if (!lastPkg) { // lastPkg = new Package(pkgName); // m_pkgs.pkgList.append(lastPkg); // lastType = 0; // } // } QString right = line.mid(reg.cap().length()).trimmed(); QString findText; QStringList findUrl; QString flag = reg.cap(4); if (flag == "var") { ///pkg archive/tar, var ErrFieldTooLong error int pos = right.indexOf(" "); QString name = right.left(pos); if (pos != -1) { findText = pkgName+"."+name+" "+right.mid(pos+1); findUrl << pkgName+"#variables"<< name; } //if (pos != -1 && lastPkg->findValue(name) == 0) { // lastPkg->valueList.append(new Value(VarApi,name,right.mid(pos+1))); //} } else if (flag == "const") { //pkg syscall (windows-amd64), const ECOMM Errno int pos = right.indexOf(" "); QString name = right.left(pos); if (pos != -1) { QString exp = right.mid(pos+1); findText = pkgName+"."+name+" "+exp; //if (exp.startsWith("ideal-") || exp == "uint16") { findUrl << pkgName+"#constants" << name; // } else { // findUrl << pkgName+"."+name; // } } // if (pos != -1 && lastPkg->findValue(name) == 0) { // lastPkg->valueList.append(new Value(ConstApi,name,right.mid(pos+1))); // } } else if (flag == "func") { //pkg bytes, func FieldsFunc([]byte, func(rune) bool) [][]byte int pos = right.indexOf("("); QString name = right.left(pos); if (pos != -1) { findText = pkgName+"."+name+" "+right.mid(pos); findUrl << pkgName+"#"+name; } // if (pos != -1 && lastPkg->findValue(name) == 0) { // lastPkg->valueList.append(new Value(FuncApi,name,right.mid(pos))); // } } else if (flag == "method") { //pkg archive/tar, method (*Reader) Next() (*Header, error) //pkg archive/zip, method (*File) Open() (io.ReadCloser, error) //pkg bufio, method (ReadWriter) Available() int int pos = regm.indexIn(right); if (pos != -1) { QString typeName = regm.cap(1); QString name = regm.cap(2); QString exp = right.mid(regm.cap().length()).trimmed(); findText = pkgName+"."+typeName+"."+name+" "+exp; findUrl << pkgName+"#"+typeName+"."+name; // if (lastType == 0 || lastType->name != typeName || lastType->typ == StructApi) { // lastType = lastPkg->findType(typeName); // if (!lastType) { // lastType = new Type(StructApi,typeName,"struct"); // lastPkg->typeList.append(lastType); // } // } // if (lastType->findValue(name) == 0) { // lastType->valueList.append(new Value(TypeMethodApi,name,exp)); // } } } else if (flag == "type") { //pkg go/ast, type ObjKind int //pkg archive/tar, type Header struct //pkg archive/tar, type Header struct, AccessTime time.Time //pkg container/heap, type Interface interface { Len, Less, Pop, Push, Swap } //pkg container/heap, type Interface interface, Len() int int pos = right.indexOf(" "); if (pos != -1) { QString typeName = right.left(pos); QString exp = right.mid(pos+1); if (exp == "struct") { findText = pkgName+"."+typeName+" "+exp; findUrl << pkgName+"#"+typeName; // lastType = lastPkg->findType(typeName); // if (!lastType) { // lastType = new Type(StructApi,typeName,exp); // lastPkg->typeList.append(lastType); // } } else if (exp.startsWith("struct,")) { QString last = exp.mid(7).trimmed(); int pos2 = last.indexOf(" "); if (pos2 != -1) { findText = pkgName+"."+typeName; // if (lastType == 0 || lastType->name != typeName || lastType->typ == StructApi) { // lastType = lastPkg->findType(typeName); // if (!lastType) { // lastType = new Type(StructApi,typeName,"struct"); // lastPkg->typeList.append(lastType); // } // } QString name = last.left(pos2); if (name == "embedded") { QString emName = last.mid(pos2+1); findText = pkgName+"."+typeName+"."+emName; findUrl << pkgName+"#"+typeName << emName; // if (!lastType->embeddedList.contains(emName)) { // lastType->embeddedList.append(emName); // } } else { findText = pkgName+"."+typeName+"."+name+" "+last.mid(pos2+1); findUrl << pkgName+"#"+typeName << name; } /*else if (lastType->findValue(name) == 0){ lastType->valueList.append(new Value(TypeVarApi,name,last.mid(pos2+1))); }*/ } } else if (exp.startsWith("interface {")) { findText = pkgName+"."+typeName+" "+exp; findUrl << pkgName+"#"+typeName; // lastType = lastPkg->findType(typeName); // if (!lastType) { // lastType = new Type(InterfaceApi,typeName,exp); // lastPkg->typeList.append(lastType); // } } else if (exp.startsWith("interface,")) { QString last = exp.mid(10).trimmed(); int pos2 = last.indexOf("("); if (pos2 != -1) { // if (lastType == 0 || lastType->name != typeName || lastType->typ == StructApi) { // lastType = lastPkg->findType(typeName); // if (!lastType) { // lastType = new Type(InterfaceApi,typeName,"struct"); // lastPkg->typeList.append(lastType); // } // } QString name = last.left(pos2); //if (lastType->findValue(name) == 0) { findText = pkgName+"."+typeName+"."+name+" "+last.mid(pos2); findUrl << pkgName+"#"+typeName+"."+name; //lastType->valueList.append(new Value(TypeMethodApi,name,last.mid(pos2))); //} } } else { findText = pkgName+"."+typeName+" "+exp; findUrl << pkgName+"#"+typeName; // lastType = lastPkg->findType(typeName); // if (!lastType) { // lastType = new Type(TypeApi,typeName,exp); // lastPkg->typeList.append(lastType); // } } } } if (findText.indexOf(m_text,0,m_bMatchCase?Qt::CaseSensitive:Qt::CaseInsensitive) >= 0) { emit findApiOut(line,baseName,line,findUrl); } } } void FindApiThread::run() { QDir dir(m_rootPath); if (!dir.exists()) { return; } QStringList names; names << "next.txt" << "except.txt" << "go*.txt"; foreach(QFileInfo info,dir.entryInfoList(names)) { findInFile(info.filePath(),info.completeBaseName()); } } FindApiWidget::FindApiWidget(LiteApi::IApplication *app, QWidget *parent) : QWidget(parent), m_liteApp(app) { m_findEdit = new FindApiEdit; m_findEdit->setPlaceholderText(tr("Search")); m_chaseWidget = new ChaseWidget; m_chaseWidget->setMinimumSize(QSize(16,16)); m_chaseWidget->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred); m_apiView = new QTreeView; m_model = new QStandardItemModel(this); m_model->setColumnCount(2); m_apiView->setModel(m_model); m_apiView->setEditTriggers(QTreeView::NoEditTriggers); m_apiView->setHeaderHidden(true); //#if QT_VERSION >= 0x050000 // m_apiView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); //#else // m_apiView->header()->setResizeMode(QHeaderView::ResizeToContents); //#endif m_apiView->header()->setStretchLastSection(true); QToolButton *findBtn = new QToolButton; findBtn->setPopupMode(QToolButton::MenuButtonPopup); findBtn->setText(tr("Find")); QHBoxLayout *findLayout = new QHBoxLayout; findLayout->setMargin(2); findLayout->addWidget(m_findEdit); findLayout->addWidget(findBtn); findLayout->addWidget(m_chaseWidget); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->setMargin(1); mainLayout->setSpacing(1); mainLayout->addLayout(findLayout); mainLayout->addWidget(m_apiView); this->setLayout(mainLayout); m_findThread = new FindApiThread(this); connect(m_findThread,SIGNAL(findApiOut(QString,QString,QString,QStringList)),this,SLOT(findApiOut(QString,QString,QString,QStringList))); connect(m_findThread,SIGNAL(finished()),this,SLOT(findApiFinished())); //connect(m_findThread,SIGNAL(terminated()),this,SLOT(findApiTerminated())); //connect(findBtn,SIGNAL(clicked()),this,SLOT(findApi())); connect(m_findEdit,SIGNAL(returnPressed()),this,SLOT(findApi())); //connect(m_findEdit,SIGNAL(rightButtonClicked()),m_findThread,SLOT(terminate())); connect(m_apiView,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedApi(QModelIndex))); //m_rebuildThread = new ProcessEx(this); m_findAct = new QAction("Search",this); m_caseCheckAct = new QAction("Match case",this); m_caseCheckAct->setCheckable(true); //m_rebuildAct = new QAction(tr("Rebuild database"),this); QMenu *menu = new QMenu(tr("Find"),findBtn); menu->addAction(m_caseCheckAct); menu->addSeparator(); //menu->addAction(m_rebuildAct); findBtn->setMenu(menu); findBtn->setDefaultAction(m_findAct); connect(m_findAct,SIGNAL(triggered()),this,SLOT(findApi())); //connect(m_rebuildAct,SIGNAL(triggered()),this,SLOT(rebuildApiData())); m_caseCheckAct->setChecked(m_liteApp->settings()->value("goapisearch/match_case",true).toBool()); } FindApiWidget::~FindApiWidget() { m_liteApp->settings()->setValue("goapisearch/match_case",m_caseCheckAct->isChecked()); // if (m_rebuildThread->isRunning()) { // if (!m_rebuildThread->waitForFinished(10000)) { // m_rebuildThread->terminate(); // } // } } void FindApiWidget::findApi() { QString text = m_findEdit->text().trimmed(); if (text.length() <= 1) { return; } m_model->clear(); m_chaseWidget->setAnimated(true); m_findEdit->showStopButton(true); QString goroot = LiteApi::getGOROOT(m_liteApp); m_findThread->setRootPath(QFileInfo(goroot,"api").filePath()); m_findThread->setMatchCase(m_caseCheckAct->isChecked()); m_findThread->findApi(text); } void FindApiWidget::findApiOut(const QString &text, const QString &baseName, const QString &tipInfo, const QStringList &url) { QStandardItem *fitem = new QStandardItem(baseName); fitem->setData(url,Qt::UserRole+1); QStandardItem *item = new QStandardItem(text); item->setToolTip(tipInfo); //item->setData(url,Qt::UserRole+1); m_model->appendRow(QList() << fitem << item); } void FindApiWidget::findApiFinished() { m_chaseWidget->setAnimated(false); m_findEdit->showStopButton(false); } void FindApiWidget::doubleClickedApi(QModelIndex index) { if (!index.isValid()) { return; } emit openApiUrl(index.sibling(index.row(),0).data(Qt::UserRole+1).toStringList()); } //void FindApiWidget::rebuildApiData() //{ // if (m_rebuildThread->isRunning()) { // return; // } // m_rebuildThread->setEnvironment(LiteApi::getGoEnvironment(m_liteApp).toStringList()); // QString cmd = LiteApi::getGotools(m_liteApp); // m_rebuildThread->setWorkingDirectory(m_liteApp->storagePath()); // QStringList args; // args << "goapi" << "-o" << "golangapi.txt" << "all"; // m_rebuildThread->start(cmd,args); //} //QString FindApiWidget::apiDataFile() const //{ // return m_liteApp->storagePath()+"/golangapi.txt"; //} ================================================ FILE: liteidex/src/plugins/golangdoc/findapiwidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: findapiwidget.h // Creator: visualfc #ifndef FINDAPIWIDGET_H #define FINDAPIWIDGET_H #include "liteapi/liteapi.h" #include "qtc_editutil/fancylineedit.h" #include "qt_browser/chasewidget.h" #include "processex/processex.h" #include #include #include #include class QListView; class QTreeView; class QStandardItemModel; class FindApiThread : public QThread { Q_OBJECT public: FindApiThread(QObject *parent); ~FindApiThread(); signals: void findApiOut(const QString &text, const QString &baseName, const QString &tipInfo, const QStringList &url); public: void setRootPath(const QString &rootPath); void findApi(const QString &text); void stopFind(); void setMatchCase(bool b); void findInFile(const QString &filePath, const QString &baseName); protected: virtual void run (); QString m_text; QString m_rootPath; bool m_bMatchCase; }; class FindApiEdit : public Utils::FancyLineEdit { Q_OBJECT public: FindApiEdit(QWidget *parent = 0) : Utils::FancyLineEdit(parent) { QIcon icon = QIcon::fromTheme(layoutDirection() == Qt::LeftToRight ? QLatin1String("edit-clear-locationbar-rtl") : QLatin1String("edit-clear-locationbar-ltr"), QIcon::fromTheme(QLatin1String("edit-clear"), QIcon(QLatin1String("icon:images/editclear.png")))); setButtonPixmap(Right, icon.pixmap(16)); setPlaceholderText(tr("Search")); setButtonToolTip(Right, tr("Stop Search")); } void showStopButton(bool b) { this->setButtonVisible(Right,b); } }; class FindApiWidget : public QWidget { Q_OBJECT public: explicit FindApiWidget(LiteApi::IApplication *app,QWidget *parent = 0); ~FindApiWidget(); signals: void openApiUrl(QStringList); public slots: void findApi(); void findApiOut(const QString &text, const QString &baseName, const QString &tipInfo, const QStringList &url); void findApiFinished(); void doubleClickedApi(QModelIndex); // void rebuildApiData(); //QString apiDataFile() const; protected: FindApiThread *m_findThread; LiteApi::IApplication *m_liteApp; FindApiEdit *m_findEdit; ChaseWidget *m_chaseWidget; QTreeView *m_apiView; QStandardItemModel *m_model; //ProcessEx *m_rebuildThread; QAction *m_findAct; QAction *m_caseCheckAct; //QAction *m_rebuildAct; }; #endif // FINDAPIWIDGET_H ================================================ FILE: liteidex/src/plugins/golangdoc/finddocwidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: finddocwidget.cpp // Creator: visualfc #include "finddocwidget.h" #include "liteenvapi/liteenvapi.h" #include "golangdoc_global.h" #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static char help[] = "Search Format" "
"
"fmt.\n"
"    Extracts all fmt pkg symbol document\n"
"fmt.Println or fmt Println\n"
"    Extracts fmt.Println document\n"
"fmt.Print or fmt Print\n"
"    Extracts fmt.Print fmt.Printf fmt.Println etc\n"
"Println\n"
"    Extracts fmt.Println log.Println log.Logger.Println etc"
"
" "Search Option" "
"
"Match Word.\n"
"    Match whole world only\n"
"Match Case\n"
"    Match case sensitive\n"
"Use Regexp\n"
"    Use regexp for search\n"
"    example fmt p.*\n"
"
" ; class SearchEdit : public Utils::FancyLineEdit { Q_DECLARE_TR_FUNCTIONS(SearchEdit) public: SearchEdit(QWidget *parent = 0) : Utils::FancyLineEdit(parent) { QIcon icon = QIcon::fromTheme(layoutDirection() == Qt::LeftToRight ? QLatin1String("edit-clear-locationbar-rtl") : QLatin1String("edit-clear-locationbar-ltr"), QIcon::fromTheme(QLatin1String("edit-clear"), QIcon(QLatin1String("icon:images/editclear.png")))); setButtonPixmap(Right, icon.pixmap(16)); setPlaceholderText(tr("Search")); setButtonToolTip(Right, tr("Stop Search")); } void showStopButton(bool b) { this->setButtonVisible(Right,b); } }; FindDocWidget::FindDocWidget(LiteApi::IApplication *app, QWidget *parent) : QWidget(parent), m_liteApp(app) { m_findEdit = new SearchEdit; m_findEdit->setPlaceholderText(tr("Search")); m_chaseWidget = new ChaseWidget; m_chaseWidget->setMinimumSize(QSize(16,16)); m_chaseWidget->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred); QToolButton *findBtn = new QToolButton; findBtn->setPopupMode(QToolButton::InstantPopup); findBtn->setText(tr("Find")); QHBoxLayout *findLayout = new QHBoxLayout; findLayout->setMargin(2); findLayout->addWidget(m_findEdit); findLayout->addWidget(findBtn); findLayout->addWidget(m_chaseWidget); m_browser = m_liteApp->htmlWidgetManager()->createByName(this,"QTextBrowser"); QStringList paths; paths << m_liteApp->resourcePath()+"/packages/go/godoc"; m_browser->setSearchPaths(paths); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->setMargin(1); mainLayout->setSpacing(1); mainLayout->addLayout(findLayout); mainLayout->addWidget(m_browser->widget()); QAction *findAll = new QAction(tr("Find All"),this); QAction *findConst = new QAction(tr("Find const"),this); findConst->setData("const"); QAction *findFunc = new QAction(tr("Find func"),this); findFunc->setData("func"); QAction *findInterface = new QAction(tr("Find interface"),this); findInterface->setData("interface"); QAction *findPkg = new QAction(tr("Find pkg"),this); findPkg->setData("pkg"); QAction *findStruct = new QAction(tr("Find struct"),this); findStruct->setData("struct"); QAction *findType = new QAction(tr("Find type"),this); findType->setData("type"); QAction *findVar = new QAction(tr("Find var"),this); findVar->setData("var"); m_useRegexpCheckAct = new QAction(tr("Use Regexp"),this); m_useRegexpCheckAct->setCheckable(true); m_matchCaseCheckAct = new QAction(tr("Match Case"),this); m_matchCaseCheckAct->setCheckable(true); m_matchWordCheckAct = new QAction(tr("Match Word"),this); m_matchWordCheckAct->setCheckable(true); m_useRegexpCheckAct->setChecked(m_liteApp->settings()->value(GODOCFIND_USEREGEXP,false).toBool()); m_matchCaseCheckAct->setChecked(m_liteApp->settings()->value(GODOCFIND_MATCHCASE,true).toBool()); m_matchWordCheckAct->setChecked(m_liteApp->settings()->value(GODOCFIND_MATCHWORD,false).toBool()); QMenu *menu = new QMenu(findBtn); menu->addActions(QList() << findAll //<< findPkg ); menu->addSeparator(); menu->addActions(QList() << findInterface << findStruct << findType << findFunc << findConst << findVar ); menu->addSeparator(); menu->addAction(m_matchWordCheckAct); menu->addAction(m_matchCaseCheckAct); menu->addAction(m_useRegexpCheckAct); findBtn->setMenu(menu); QAction *helpAct = new QAction(tr("Help"),this); menu->addSeparator(); menu->addAction(helpAct); connect(helpAct,SIGNAL(triggered()),this,SLOT(showHelp())); this->setLayout(mainLayout); connect(findAll,SIGNAL(triggered()),this,SLOT(findDoc())); connect(findConst,SIGNAL(triggered()),this,SLOT(findDoc())); connect(findFunc,SIGNAL(triggered()),this,SLOT(findDoc())); connect(findInterface,SIGNAL(triggered()),this,SLOT(findDoc())); connect(findPkg,SIGNAL(triggered()),this,SLOT(findDoc())); connect(findStruct,SIGNAL(triggered()),this,SLOT(findDoc())); connect(findType,SIGNAL(triggered()),this,SLOT(findDoc())); connect(findVar,SIGNAL(triggered()),this,SLOT(findDoc())); m_process = new ProcessEx(this); connect(m_process,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(stateChanged(QProcess::ProcessState))); connect(m_process,SIGNAL(extOutput(QByteArray,bool)),this,SLOT(extOutput(QByteArray,bool))); connect(m_process,SIGNAL(extFinish(bool,int,QString)),this,SLOT(extFinish(bool,int,QString))); connect(m_findEdit,SIGNAL(returnPressed()),findAll,SIGNAL(triggered())); connect(m_findEdit,SIGNAL(rightButtonClicked()),this,SLOT(abortFind())); connect(m_browser,SIGNAL(linkClicked(QUrl)),this,SLOT(openUrl(QUrl))); QString path = m_liteApp->resourcePath()+"/packages/go/godoc/finddoc.html"; QFile file(path); if (file.open(QIODevice::ReadOnly)) { m_templateData = file.readAll(); file.close(); } //QFont font = m_browser->widget()->font(); //font.setPointSize(12); //m_browser->widget()->setFont(font); showHelp(); } FindDocWidget::~FindDocWidget() { m_liteApp->settings()->setValue(GODOCFIND_MATCHCASE,m_matchCaseCheckAct->isChecked()); m_liteApp->settings()->setValue(GODOCFIND_MATCHWORD,m_matchWordCheckAct->isChecked()); m_liteApp->settings()->setValue(GODOCFIND_USEREGEXP,m_useRegexpCheckAct->isChecked()); abortFind(); delete m_process; } void FindDocWidget::findDoc() { QAction *act = (QAction*)sender(); QString text = m_findEdit->text().trimmed(); if (text.isEmpty()) { return; } QString findFlag = act->data().toString(); abortFind(); QStringList args; args << "finddoc" << "-urltag" << ""; if (m_matchWordCheckAct->isChecked()) { args << "-word"; } if (m_matchCaseCheckAct->isChecked()) { args << "-case"; } if (m_useRegexpCheckAct->isChecked()) { args << "-r"; } if (!findFlag.isEmpty()) { args << "-"+findFlag; } args << text.split(" "); m_browser->clear(); m_findFlag = findFlag; m_htmlData.clear(); QString cmd = LiteApi::getGotools(m_liteApp); m_process->setEnvironment(LiteApi::getGoEnvironment(m_liteApp).toStringList()); m_process->start(cmd,args); } struct doc_comment { QString url; QString file; QStringList comment; }; void FindDocWidget::extOutput(QByteArray data, bool error) { if (error) { m_liteApp->appendLog("FindDoc",QString::fromUtf8(data),false); return; } /* http://golang.org/pkg\fmt\#Println c:\go\src\pkg\log\log.go:169: // Println calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Println. func (l *Logger) Println(v ...interface{}) http://godoc.org\code.google.com\p\go.tools\cmd\vet\#Println F:\vfc\liteide-git\liteidex\src\code.google.com\p\go.tools\cmd\vet\main.go:375: // Println is fmt.Println guarded by -v. func Println(args ...interface{}) */ QList dc_array; doc_comment dc; int flag = 0; foreach (QString line, QString::fromUtf8(data).split("\n")) { if (line.startsWith("")) { flag = 1; if (!dc.url.isEmpty()) { dc_array.push_back(dc); } dc.url = line.mid(13); dc.file.clear(); dc.comment.clear(); continue; } if (flag == 1) { dc.file = line; flag = 2; continue; } if (flag == 2) { dc.comment.push_back(line); } } if (!dc.url.isEmpty()) { dc_array.push_back(dc); } QStringList array; foreach (doc_comment dc, dc_array) { array.append(docToHtml(dc.url,dc.file,dc.comment)); } // qDebug() << array.join("\n"); // if (m_findFlag == "pkg") { // array = parserPkgDoc(QString::fromUtf8(data)); // } else { // array = parserDoc(QString::fromUtf8(data)); // } m_htmlData.append(array.join("\n")); QString html = m_templateData; html.replace("{content}",m_htmlData); int pos = m_browser->scrollBarValue(Qt::Vertical); m_browser->setHtml(html,QUrl()); m_browser->setScrollBarValue(Qt::Vertical,pos); } void FindDocWidget::extFinish(bool, int, QString) { if (m_htmlData.isEmpty()) { QString html = m_templateData; html.replace("{content}","Not found!"); m_browser->setHtml(html,QUrl()); } m_htmlData.clear(); } void FindDocWidget::abortFind() { m_process->stop(100); } void FindDocWidget::stateChanged(QProcess::ProcessState state) { m_chaseWidget->setAnimated(state == QProcess::Running); m_findEdit->showStopButton(state == QProcess::Running); } void FindDocWidget::openUrl(QUrl url) { if (!url.isLocalFile()) { return; } QString text = url.toLocalFile(); QRegExp rep("(\\w?\\:?[\\w\\d\\_\\-\\\\/\\.]+):(\\d+):"); int index = rep.indexIn(text); if (index < 0) return; QStringList capList = rep.capturedTexts(); if (capList.count() < 3) return; QString fileName = capList[1]; QString fileLine = capList[2]; bool ok = false; int line = fileLine.toInt(&ok); if (!ok) return; LiteApi::IEditor *editor = m_liteApp->fileManager()->openEditor(fileName,true); if (editor) { LiteApi::ITextEditor *textEditor = LiteApi::getTextEditor(editor); if (textEditor) { textEditor->gotoLine(line-1,0,true); } } } void FindDocWidget::showHelp() { QString data = m_templateData; data.replace("{content}",help); m_browser->setHtml(data,QUrl()); } static QString escape(const QString &text) { #if QT_VERSION >= 0x050000 return QString(text).toHtmlEscaped(); #else return Qt::escape(text); #endif } QStringList FindDocWidget::docToHtml(const QString &url, const QString &file, const QStringList &comment) { QString sz; QString pkgName; QString findName; if (url.startsWith("http://golang.org/pkg")) { sz = url.mid(21); } else if (url.startsWith("http://golang.org/cmd")) { sz = url.mid(21); } else if (url.startsWith("http://godoc.org")) { sz = url.mid(16); } //\code.google.com\p\go.tools\cmd\vet\#Println int pos = sz.indexOf("#"); if (pos != -1) { pkgName = QDir::fromNativeSeparators(sz.left(pos)); if (pkgName.startsWith("/")) { pkgName = pkgName.mid(1); } if (pkgName.endsWith("/")) { pkgName = pkgName.left(pkgName.length()-1); } findName = sz.mid(pos+1); } QStringList array; array.push_back(QString("

%2  %3

") .arg(QDir::fromNativeSeparators(escape(file))).arg(pkgName).arg(findName)); if (!comment.isEmpty() && ( comment.first().startsWith("const (") || comment.first().startsWith("var (")) ) { array.push_back("
");
        QString head = "const ";
        if (comment.first().startsWith("var (")) {
            head = "var ";
        }
        QStringList incmd;
        foreach (QString sz, comment) {
            if (sz.trimmed().startsWith("//")) {
                incmd.push_back(escape(sz.trimmed()));
            } else if (sz.indexOf(findName) >= 0) {
                array.append(incmd);
                array.push_back(escape(head+sz.replace("\t"," ").trimmed()));
            } else {
                incmd.clear();
            }
        }
        array.push_back("
"); return array; } int flag = 0; QString lastTag; foreach (QString sz, comment) { if (sz.startsWith("//")) { if (flag != 1) { if (!lastTag.isEmpty()) array.push_back(lastTag); array.push_back("

"); lastTag = "

"; } flag = 1; if (sz.mid(2).trimmed().isEmpty()) { array.push_back("

"); } else { array.push_back(escape(sz.mid(2))); } } else { if (sz.trimmed().isEmpty()) { continue; } if (flag != 3) { if (!lastTag.isEmpty()) array.push_back(lastTag); array.push_back("

");
                lastTag = "
"; } flag = 3; array.push_back(escape(sz.replace("\t"," "))); } } if (!lastTag.isEmpty()) array.push_back(lastTag); array.push_back("

"); return array; } QStringList FindDocWidget::parserDoc(QString findText) { QStringList array; int lastFlag = 0; QString findName; QString findPos; QString findComment; foreach (QString sz, findText.split('\n')) { int flag = 0; if (sz.startsWith("http://golang.org/pkg")) { flag = 1; sz = sz.mid(21); } else if (sz.startsWith("http://golang.org/cmd")) { flag = 1; sz = sz.mid(21); } else if (sz.startsWith("http://godoc.org")) { flag = 1; sz = sz.mid(16); } else if (sz.startsWith("//")) { flag = 2; sz = sz.mid(2); } else if (sz.isEmpty()) { flag = 4; } else { flag = 3; } if (flag == 1) { //\code.google.com\p\go.tools\cmd\vet\#Println int pos = sz.indexOf("#"); if (pos != -1) { QString pkg = sz.left(pos); pkg = QDir::fromNativeSeparators(pkg); if (pkg.startsWith("/")) { pkg = pkg.mid(1); } if (pkg.endsWith("/")) { pkg = pkg.left(pkg.length()-1); } sz = pkg+sz.mid(pos); findName = sz; } else { QString pkg = sz; pkg = QDir::fromNativeSeparators(pkg); if (pkg.startsWith("/")) { pkg = pkg.mid(1); } if (pkg.endsWith("/")) { pkg = pkg.left(pkg.length()-1); } findName = pkg; } } else if (flag == 3) { if (lastFlag == 1) { findPos = "file:"+sz; array.push_back(QString("

%2

").arg(findPos).arg(findName)); } else { array.push_back(QString("%1").arg(sz)); if (!findComment.isEmpty()) { array.push_back(QString("

%1

").arg(findComment)); } findComment.clear(); } } else if (flag == 2) { findComment += sz.trimmed(); } else if (flag == 4) { } lastFlag = flag; } return array; } QStringList FindDocWidget::parserPkgDoc(QString findText) { QStringList array; int lastFlag = 0; QString findName; QString findPos; QString findComment; bool bHead = false; foreach (QString sz, findText.split('\n')) { int flag = 0; if (sz.startsWith("http://golang.org/pkg")) { flag = 1; sz = sz.mid(21); } else if (sz.startsWith("http://golang.org/cmd")) { flag = 1; sz = sz.mid(21); } else if (sz.startsWith("http://godoc.org")) { flag = 1; sz = sz.mid(16); } else { flag = 3; } if (flag == 1) { bHead = false; } if (bHead) { // findComment.append(sz+"\n"); if (sz.startsWith("\t\t")) { flag = 5; } else if (sz.trimmed().isEmpty()){ flag = 6; } else { flag = 7; } sz.replace("\t"," "); if (lastFlag != flag && !findComment.isEmpty()) { if (lastFlag == 5) { array.push_back(QString("
%1
").arg(findComment)); } else { array.push_back(QString("

%1

").arg(findComment)); } findComment.clear(); } if (flag == 5) { findComment += sz.trimmed()+"\n"; } else { findComment += sz.trimmed(); } lastFlag = flag; continue; } if (flag == 1) { //\code.google.com\p\go.tools\cmd\vet\#Println int pos = sz.indexOf("#"); if (pos != -1) { QString pkg = sz.left(pos); pkg = QDir::fromNativeSeparators(pkg); if (pkg.startsWith("/")) { pkg = pkg.mid(1); } if (pkg.endsWith("/")) { pkg = pkg.left(pkg.length()-1); } sz = pkg+sz.mid(pos); findName = sz; } else { QString pkg = sz; pkg = QDir::fromNativeSeparators(pkg); if (pkg.startsWith("/")) { pkg = pkg.mid(1); } if (pkg.endsWith("/")) { pkg = pkg.left(pkg.length()-1); } findName = pkg; } } else if (flag == 3) { if (lastFlag == 1) { findPos = "file:"+sz; array.push_back(QString("

%2

").arg(findPos).arg(findName)); bHead = true; } } else if (flag == 2) { findComment += sz.trimmed(); } lastFlag = flag; } if (!findComment.isEmpty()) { if (lastFlag == 5) { array.push_back(QString("
%1
").arg(findComment)); } else { array.push_back(QString("

%1

").arg(findComment)); } } return array; } ================================================ FILE: liteidex/src/plugins/golangdoc/finddocwidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: finddocwidget.h // Creator: visualfc #ifndef FINDDOCWIDGET_H #define FINDDOCWIDGET_H #include "liteapi/liteapi.h" #include "qtc_editutil/filterlineedit.h" #include "qtc_editutil/fancylineedit.h" #include "qt_browser/chasewidget.h" #include "processex/processex.h" class SearchEdit; class QTextBrowser; class FindDocWidget : public QWidget { Q_OBJECT public: explicit FindDocWidget(LiteApi::IApplication *app, QWidget *parent = 0); ~FindDocWidget(); protected slots: void findDoc(); void extOutput(QByteArray,bool); void extFinish(bool,int,QString); void abortFind(); void stateChanged(QProcess::ProcessState); void openUrl(QUrl); void showHelp(); protected: QStringList docToHtml(const QString &url,const QString &file,const QStringList &comment); QStringList parserDoc(QString findText); QStringList parserPkgDoc(QString findText); LiteApi::IApplication *m_liteApp; SearchEdit *m_findEdit; ChaseWidget *m_chaseWidget; QAction* m_matchWordCheckAct; QAction* m_matchCaseCheckAct; QAction* m_useRegexpCheckAct; ProcessEx *m_process; LiteApi::IHtmlWidget *m_browser; QString m_findFlag; QString m_templateData; QString m_htmlData; }; #endif // FINDDOCWIDGET_H ================================================ FILE: liteidex/src/plugins/golangdoc/golangdoc.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: golangdoc.cpp // Creator: visualfc #include "golangdoc.h" #include "litebuildapi/litebuildapi.h" #include "processex/processex.h" #include "fileutil/fileutil.h" #include "htmlutil/htmlutil.h" #include "golangapi/golangapi.h" #include "documentbrowser/documentbrowser.h" #include "qjson/include/QJson/Parser" #include "finddocwidget.h" #include "findapiwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end void ListViewEx::currentChanged(const QModelIndex ¤t, const QModelIndex&) { emit currentIndexChanged(current); } GolangDoc::GolangDoc(LiteApi::IApplication *app, QObject *parent) : LiteApi::IGolangDoc(parent), m_liteApp(app) { m_findProcess = new ProcessEx(this); m_godocProcess = new ProcessEx(this); m_findDocWidget = new FindDocWidget(m_liteApp); m_docSearchWindowAct = m_liteApp->toolWindowManager()->addToolWindow(Qt::BottomDockWidgetArea,m_findDocWidget,"GoDocSearch",tr("Go Doc Search"),true); m_findApiWidget = new FindApiWidget(m_liteApp); m_apiSearchWindowAct = m_liteApp->toolWindowManager()->addToolWindow(Qt::BottomDockWidgetArea,m_findApiWidget,"GoApiIndex",tr("Go Api Index"),true); connect(m_findApiWidget,SIGNAL(openApiUrl(QStringList)),this,SLOT(openApiUrl(QStringList))); m_docBrowser = new DocumentBrowser(m_liteApp,this); m_docBrowser->setName(tr("Godoc Search")); QStringList paths; paths << m_liteApp->resourcePath()+"/packages/go/godoc"; m_docBrowser->setSearchPaths(paths); m_godocFindComboBox = new QComboBox; m_godocFindComboBox->setMinimumWidth(100); m_godocFindComboBox->setEditable(true); //m_godocFindComboBox->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); m_docBrowser->toolBar()->addSeparator(); m_docBrowser->toolBar()->addWidget(new QLabel(tr("Find Package:"))); m_docBrowser->toolBar()->addWidget(m_godocFindComboBox); m_browserAct = m_liteApp->editorManager()->registerBrowser(m_docBrowser); m_liteApp->actionManager()->insertViewMenu(LiteApi::ViewMenuBrowserPos,m_browserAct); connect(m_apiSearchWindowAct,SIGNAL(toggled(bool)),this,SLOT(toggledApiSearchWindow(bool))); connect(m_docSearchWindowAct,SIGNAL(toggled(bool)),this,SLOT(toggledDocSearchWindow(bool))); connect(m_docBrowser,SIGNAL(requestUrl(QUrl)),this,SLOT(openUrl(QUrl))); connect(m_docBrowser,SIGNAL(linkHovered(QUrl)),this,SLOT(highlighted(QUrl))); connect(m_docBrowser,SIGNAL(documentLoaded()),this,SLOT(documentLoaded())); connect(m_docBrowser,SIGNAL(anchorChanged(QString)),this,SLOT(anchorChanged(QString))); connect(m_godocFindComboBox,SIGNAL(activated(QString)),this,SLOT(godocFindPackage(QString))); connect(m_godocProcess,SIGNAL(extOutput(QByteArray,bool)),this,SLOT(godocOutput(QByteArray,bool))); connect(m_godocProcess,SIGNAL(extFinish(bool,int,QString)),this,SLOT(godocFinish(bool,int,QString))); connect(m_findProcess,SIGNAL(extOutput(QByteArray,bool)),this,SLOT(findOutput(QByteArray,bool))); connect(m_findProcess,SIGNAL(extFinish(bool,int,QString)),this,SLOT(findFinish(bool,int,QString))); connect(m_liteApp,SIGNAL(loaded()),this,SLOT(appLoaded())); m_envManager = LiteApi::findExtensionObject(m_liteApp,"LiteApi.IEnvManager"); if (m_envManager) { connect(m_envManager,SIGNAL(currentEnvChanged(LiteApi::IEnv*)),this,SLOT(currentEnvChanged(LiteApi::IEnv*))); } m_liteApp->extension()->addObject("LiteApi.IGolangDoc",this); //m_liteApp->extension()->addObject("LiteApi.IGolangApi",m_golangApiThread); QString path = m_liteApp->resourcePath()+"/packages/go/godoc/godoc.html"; QFile file(path); if (file.open(QIODevice::ReadOnly)) { m_templateData = file.readAll(); file.close(); } QString about = m_liteApp->resourcePath()+"/packages/go/godoc/about.html"; QFileInfo info(about); if(info.exists()) { m_templateData.replace("{about}",info.filePath()); } QUrl url; url.setScheme("file"); url.setPath(info.filePath()); openUrl(url); } GolangDoc::~GolangDoc() { m_liteApp->settings()->setValue("golangdoc/goroot",m_goroot); if (m_docBrowser) { delete m_docBrowser; } delete m_findDocWidget; delete m_findApiWidget; } void GolangDoc::currentEnvChanged(LiteApi::IEnv*) { loadEnv(); // if (!m_bApiLoaded) { // return; // } //loadApi(); } void GolangDoc::loadEnv() { QProcessEnvironment env = LiteApi::getGoEnvironment(m_liteApp);//m_envManager->currentEnvironment(); // if (!LiteApi::hasGoEnv(env)) { // return; // } // m_godocCmd = FileUtil::lookupGoBin("godoc",m_liteApp,env,false); // m_findProcess->setEnvironment(env.toStringList()); // m_godocProcess->setEnvironment(env.toStringList()); // if (!m_godocCmd.isEmpty()) { // m_liteApp->appendLog("GolangDoc",QString("Found godoc at %1").arg(m_godocCmd),false); // } else { // m_liteApp->appendLog("GolangDoc",QString("Could not find godoc, (hint: is godoc installed?)"),true); // } m_pathFileMap.clear(); loadGoroot(); } void GolangDoc::loadGoroot() { m_goroot = LiteApi::getGOROOT(m_liteApp); if (m_goroot.isEmpty()) { return; } QDir dir(m_goroot); if (dir.exists() && dir.cd("doc")) { foreach(QFileInfo info, dir.entryInfoList(QStringList()<<"*.html",QDir::Files)) { QFile f(info.filePath()); if (f.open(QFile::ReadOnly)) { QByteArray line = f.read(1024); int start = line.indexOf(""); if (end > start) { QByteArray jsonData = line.mid(start+4,end-start-4); QJson::Parser parser; bool ok = false; QVariant json = parser.parse(jsonData, &ok).toMap(); if (ok) { QVariantMap jsonMap = json.toMap(); if (jsonMap.contains("Path")) { m_pathFileMap.insert(jsonMap.value("Path").toString(),info.filePath()); } } } } } } } } void GolangDoc::activeBrowser() { m_liteApp->editorManager()->activeBrowser(m_docBrowser); } //void GolangDoc::rebuildApiData() //{ // if (!m_liteApp->globalCookie().value("golangdoc.goapi.rebuild").toBool()) { // QFileInfo info(m_findApiWidget->apiDataFile()); // if (!info.exists()) { // m_findApiWidget->rebuildApiData(); // } // QDateTime dt = info.lastModified(); // if (dt.toLocalTime().date() < QDate::currentDate()) { // m_findApiWidget->rebuildApiData(); // } // m_liteApp->globalCookie().value("golangdoc.goapi.rebuild",true); // } //} void GolangDoc::listPkg() { QString cmd = LiteApi::getGotools(m_liteApp); QStringList args; args << "docview" << "-mode=lite" << "-list=pkg"; m_findData.clear(); m_findProcess->start(cmd,args); } void GolangDoc::listCmd() { QString cmd = LiteApi::getGotools(m_liteApp); QStringList args; args << "docview" << "-mode" << "lite" << "-list"<<"cmd"; m_findData.clear(); m_findProcess->start(cmd,args); } void GolangDoc::godocFindPackage(QString pkgname) { if (pkgname.isEmpty()) { pkgname = m_godocFindComboBox->currentText(); } if (pkgname.isEmpty()) { return; } QUrl url; url.setScheme("find"); url.setPath(pkgname); openUrl(url); } //void GolangDoc::findPackage(QString pkgname) //{ // if (pkgname.isEmpty()) { // pkgname = m_findDocEdit->text(); // } // if (pkgname.isEmpty()) { // return; // } // QString cmd = LiteApi::liteide_stub_cmd(m_liteApp); // QStringList args; // args << "docview" << "-mode=lite" << "-find" << pkgname; // m_findData.clear(); // m_findProcess->start(cmd,args); //} void GolangDoc::findOutput(QByteArray data,bool bStderr) { if (bStderr) { return; } m_findData.append(data); } void GolangDoc::findFinish(bool error,int code,QString /*msg*/) { if (!error && code == 0) { QStringList array = QString(m_findData.trimmed()).split(','); if (array.size() >= 2 && array.at(0) == "$find") { array.removeFirst(); QString best = array.at(0); if (best.isEmpty()) { array.removeFirst(); } else { activeBrowser(); QUrl url; url.setScheme("pdoc"); url.setPath(best); openUrl(url); } // if (array.isEmpty()) { // m_findResultModel->setStringList(QStringList() << ""); // } else { // m_findResultModel->setStringList(array); // } }/* else if (array.size() >= 1 && array.at(0) == "$list") { //array.removeFirst(); m_findResultModel->setStringList(array); }*/ } /*else { m_findResultModel->setStringList(QStringList() << ""); }*/ } void GolangDoc::godocOutput(QByteArray data,bool bStderr) { if (bStderr) { QTextCodec *codec = QTextCodec::codecForName("utf8"); m_liteApp->appendLog("GolangDoc",codec->toUnicode(data),false); return; } m_godocData.append(data); } void GolangDoc::godocFinish(bool error,int code,QString /*msg*/) { if (!error && code == 0 && m_docBrowser != 0) { bool nav = true; QString header; if (m_openUrl.scheme() == "list") { nav = false; header = "Package List"; } else if (m_openUrl.scheme() == "find") { nav = false; header = "Find Package "+m_openUrl.path(); } else if (m_openUrl.scheme() == "pdoc") { nav = false; header = "Package "+m_openUrl.path(); } if (m_godocData.indexOf(" */ QString HtmlUtil::findTitle(const QString &data) { QRegExp reg(""); int n = reg.indexIn(data); if (n < 0) { return QString(); } QRegExp reg1("Title[\"\\s:]*([\\w\\s]*)[\\s\"]*"); n = reg1.indexIn(reg.cap(1)); if (n < 0) { return QString(); } return reg1.cap(1); } QString HtmlUtil::docToNavdoc(const QString &data, QString &header, QString &nav) { QDomDocument doc; QStringList srcLines = data.split("\n"); QStringList navLines; QStringList dstLines; navLines.append("
"); int index = 0; if (srcLines.length() >= 1) { header = findTitle(data); if (header.isEmpty()) { // QString line = srcLines.at(0); QRegExp reg(""); if (reg.indexIn(line) >= 0) { header = reg.cap(1).trimmed(); } } } foreach(QString source, srcLines) { QString line = source.trimmed(); index++; if (line.length() >= 10) { if (line.left(3) == "[Top] QDomElement span = doc.createElement("span"); span.setAttribute("class","navtop"); QDomElement a = doc.createElement("a"); a.setAttribute("href","#top"); QDomText top = doc.createTextNode("[Top]"); a.appendChild(top); span.appendChild(a); e.appendChild(span); source = doc.toString(); navLines << QString("
%2
").arg(id).arg(text); } } } else if (line.left(3) == "%2").arg(id).arg(text); } } } } dstLines.append(source); } navLines.append("
"); nav = navLines.join(""); return dstLines.join("\n"); } ================================================ FILE: liteidex/src/utils/htmlutil/htmlutil.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: htmlutil.h // Creator: visualfc #ifndef HTMLUTIL_H #define HTMLUTIL_H #include class HtmlUtil { public: HtmlUtil(); static QString docToNavdoc(const QString &data, QString &header, QString &nav); static QString findTitle(const QString &data); }; #endif // HTMLUTIL_H ================================================ FILE: liteidex/src/utils/htmlutil/htmlutil.pri ================================================ LIBS *= -l$$qtLibraryName(htmlutil) ================================================ FILE: liteidex/src/utils/htmlutil/htmlutil.pro ================================================ TARGET = htmlutil TEMPLATE = lib CONFIG += staticlib QT += xml include (../../liteideutils.pri) SOURCES += htmlutil.cpp HEADERS += htmlutil.h ================================================ FILE: liteidex/src/utils/iconutil/iconutil.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: iconutil.cpp // Creator: visualfc #include "iconutil.h" //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ================================================ FILE: liteidex/src/utils/iconutil/iconutil.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2017 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: iconutil.h // Creator: visualfc #ifndef ICONUTIL_H #define ICONUTIL_H #include #include inline QIcon loadIcon(const QString &fileName) { QIcon icon(fileName); if (icon.availableSizes().isEmpty()) { qDebug() << "warning empty icon" << fileName; return QIcon(); } return icon; } #endif // ICONUTIL_H ================================================ FILE: liteidex/src/utils/iconutil/iconutil.pri ================================================ LIBS *= -l$$qtLibraryName(iconutil) ================================================ FILE: liteidex/src/utils/iconutil/iconutil.pro ================================================ TARGET = iconutil TEMPLATE = lib CONFIG += staticlib include (../../liteideutils.pri) SOURCES += iconutil.cpp HEADERS += iconutil.h ================================================ FILE: liteidex/src/utils/mimetype/mimetype.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: mimetype.cpp // Creator: visualfc #include "mimetype.h" #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end QString MimeType::package() const { return m_package; } QString MimeType::type() const { return m_type; } QString MimeType::scheme() const { return m_scheme; } QString MimeType::comment() const { return m_comment.join("/"); } QString MimeType::codec() const { return m_codec; } bool MimeType::tabToSpace() const { return m_tabToSpace; } int MimeType::tabWidth() const { return m_tabWidth; } QStringList MimeType::globPatterns() const { return m_globPatterns; } QStringList MimeType::subClassesOf() const { return m_subClassesOf; } void MimeType::merge(const IMimeType *mimeType) { if (m_type != mimeType->type()) { return; } m_subClassesOf.append(mimeType->subClassesOf()); m_globPatterns.append(mimeType->globPatterns()); m_customPatterns.append(mimeType->customPatterns()); m_comment.append(mimeType->comment()); if (!mimeType->codec().isEmpty()) { m_codec = mimeType->codec(); } if (!mimeType->scheme().isEmpty()) { m_scheme = mimeType->scheme(); } if (!mimeType->package().isEmpty()) { m_package = mimeType->package(); } if (mimeType->tabToSpace()) { m_tabToSpace = mimeType->tabToSpace(); } if (mimeType->tabWidth() != -1) { m_tabWidth = mimeType->tabWidth(); } m_subClassesOf.removeDuplicates(); m_globPatterns.removeDuplicates(); m_customPatterns.removeDuplicates(); m_comment.removeDuplicates(); } void MimeType::setCustomPatterns(const QStringList &custom) { m_customPatterns = custom; } QStringList MimeType::customPatterns() const { return m_customPatterns; } QStringList MimeType::allPatterns() const { QStringList all; all << m_globPatterns; all << m_customPatterns; all.removeDuplicates(); return all; } void MimeType::setPackage(const QString &package) { m_package = package; } void MimeType::setType(const QString &type) { m_type = type; } void MimeType::setScheme(const QString &scheme) { m_scheme = scheme; } void MimeType::setCodec(const QString &codec) { m_codec = codec; } void MimeType::setTabToSpace(const QString &s) { if (s == "true" || s == "1") { m_tabToSpace = true; } } void MimeType::setTabWidth(const QString &s) { bool ok = false; int n = s.toInt(&ok); if (ok) { m_tabWidth = n; } } void MimeType::setComment(const QString &comment) { m_comment.append(comment); } void MimeType::appendLocalComment(const QString &local, const QString &comment) { if (!local.isEmpty() && !comment.isEmpty()) { m_localCommentMap.insert(local,comment); } } void MimeType::appendGlobPatterns(const QString &globPattern) { if (globPattern.isEmpty()) { return; } m_globPatterns.append(globPattern); } void MimeType::appendSubClassesOf(const QString &subClassOf) { if (subClassOf.isEmpty()) { return; } m_subClassesOf.append(subClassOf); } bool MimeType::isEmpty() const { return m_type.isEmpty(); } bool MimeType::loadMimeTypes(LiteApi::IMimeTypeManager *manager, const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) { return false; } return MimeType::loadMimeTypes(manager,&file,fileName); } bool MimeType::loadMimeTypes(LiteApi::IMimeTypeManager *manager, QIODevice *dev, const QString &/*fileName*/) { QXmlStreamReader reader(dev); QXmlStreamAttributes attrs; MimeType *mimeType = 0; while (!reader.atEnd()) { switch (reader.readNext()) { case QXmlStreamReader::StartElement: attrs = reader.attributes(); if (reader.name() == "mime-type" && mimeType == 0) { mimeType = new MimeType; mimeType->setType(attrs.value("type").toString()); mimeType->setPackage(attrs.value("package").toString()); mimeType->setCodec(attrs.value("codec").toString()); mimeType->setScheme(attrs.value("scheme").toString()); mimeType->setTabToSpace(attrs.value("tabtospace").toString()); mimeType->setTabWidth(attrs.value("tabwidth").toString()); } else if (reader.name() == "sub-class-of" && mimeType) { mimeType->appendSubClassesOf(attrs.value("type").toString()); } else if (reader.name() == "comment" && mimeType) { QString locale = attrs.value("xml:lang").toString(); const QString comment = QCoreApplication::translate("MimeType", reader.readElementText().toLatin1()); if (locale.isEmpty()) { mimeType->setComment(comment); } else { mimeType->appendLocalComment(locale,comment); } } else if (reader.name() == "glob" && mimeType) { mimeType->appendGlobPatterns(attrs.value("pattern").toString()); } break; case QXmlStreamReader::EndElement: if (reader.name() == "mime-type") { bool b = false; if (mimeType && !mimeType->isEmpty()) { if (manager->addMimeType(mimeType)) { b = true; } } if (!b) { delete mimeType; } mimeType = 0; } break; default: break; } } return true; } ================================================ FILE: liteidex/src/utils/mimetype/mimetype.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: mimetype.h // Creator: visualfc #ifndef LITEAPI_MIMETYPE_H #define LITEAPI_MIMETYPE_H #include "liteapi/liteapi.h" class MimeType : public LiteApi::IMimeType { public: MimeType(): m_tabToSpace(false), m_tabWidth(4) { } virtual QString package() const; virtual QString type() const; virtual QString scheme() const; virtual QString comment() const; virtual QString codec() const; virtual bool tabToSpace() const; virtual int tabWidth() const; virtual QStringList globPatterns() const; virtual QStringList subClassesOf() const; virtual void merge(const IMimeType *mimeType); virtual void setCustomPatterns(const QStringList &custom); virtual QStringList customPatterns() const; virtual QStringList allPatterns() const; void setPackage(const QString &package); void setType(const QString &type); void setScheme(const QString &scheme); void setCodec(const QString &codec); void setTabToSpace(const QString &s); void setTabWidth(const QString &s); void setComment(const QString &comment); void appendGlobPatterns(const QString &globPattern); void appendSubClassesOf(const QString &subClassOf); void appendLocalComment(const QString &local, const QString &commnet); bool isEmpty() const; public: static bool loadMimeTypes(LiteApi::IMimeTypeManager *manager, const QString &fileName); static bool loadMimeTypes(LiteApi::IMimeTypeManager *manager, QIODevice *dev, const QString &fileName); protected: bool m_tabToSpace; // default false int m_tabWidth; //default 4 QString m_package; QString m_type; QString m_scheme; QString m_codec; QStringList m_comment; QStringList m_globPatterns; QStringList m_subClassesOf; QStringList m_customPatterns; QMap m_localCommentMap; }; #endif // LITEAPI_MIMETYPE_H ================================================ FILE: liteidex/src/utils/mimetype/mimetype.pri ================================================ LIBS *= -l$$qtLibraryName(mimetype) ================================================ FILE: liteidex/src/utils/mimetype/mimetype.pro ================================================ TARGET = mimetype TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += mimetype.h SOURCES += mimetype.cpp ================================================ FILE: liteidex/src/utils/modelproject/modelfileimpl.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: modelfileimpl.cpp // Creator: visualfc #include "modelfileimpl.h" #include "fileutil/fileutil.h" #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ModelFileImpl::ModelFileImpl(LiteApi::IApplication *app, QObject *parent) : LiteApi::IFile(parent), m_liteApp(app) { m_model = new QStandardItemModel(this); m_bReadOnly = false; } bool ModelFileImpl::loadText(const QString &fileName, const QString &mimeType, QString &/*outText*/) { m_mimeType = mimeType; if (!loadFile(fileName)) { return false; } m_fileName = fileName; m_rootPath = QFileInfo(m_fileName).absolutePath(); return true; } bool ModelFileImpl::reloadText(QString &outText) { if (m_fileName.isEmpty()) { return false; } return loadText(m_fileName,m_mimeType,outText); } bool ModelFileImpl::isReadOnly() const { return m_bReadOnly; } bool ModelFileImpl::isBinary() const { return false; } bool ModelFileImpl::saveText(const QString &/*fileName*/, const QString &/*text*/) { return false; } QString ModelFileImpl::filePath() const { return m_fileName; } QString ModelFileImpl::mimeType() const { return m_mimeType; } QStandardItemModel *ModelFileImpl::model() const { return m_model; } QString ModelFileImpl::value(const QString &key) const { QStringList val = m_context.value(key); if (!val.isEmpty()) { return val.at(0); } return QString(); } QStringList ModelFileImpl::values(const QString &key) const { return m_context.value(key); } QStringList ModelFileImpl::fileNameList() const { return m_fileNameList; } QStringList ModelFileImpl::filePathList() const { return m_filePathList; } QString ModelFileImpl::fileNameToFullPath(const QString &fileName) { QString fullPath = m_rootPath; fullPath += QLatin1Char('/'); fullPath += fileName; return fullPath; } QString ModelFileImpl::workPath() const { return QFileInfo(m_fileName).absolutePath(); } ================================================ FILE: liteidex/src/utils/modelproject/modelfileimpl.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: modelfileimpl.h // Creator: visualfc #ifndef MODELFILEIMPL_H #define MODELFILEIMPL_H #include "liteapi/liteapi.h" class QStandardItemModel; class ModelFileImpl : public LiteApi::IFile { Q_OBJECT public: ModelFileImpl(LiteApi::IApplication *app, QObject *parent); enum ITEM_TYPE{ ItemRoot = 1, ItemFolder, ItemProFile, ItemFile }; public: virtual bool loadText(const QString &filePath, const QString &mimeType, QString &outText); virtual bool reloadText(QString &outText); virtual bool saveText(const QString &filePath, const QString &text); virtual bool isReadOnly() const; virtual bool isBinary() const; virtual QString filePath() const; virtual QString mimeType() const; public: virtual void updateModel() = 0; protected: virtual bool loadFile(const QString &filePath) = 0; public: virtual QString target() const = 0; virtual QString targetPath() const = 0; virtual QString workPath() const; virtual QMap targetInfo() const = 0; QStandardItemModel *model() const; QString value(const QString &key) const; QStringList values(const QString &key) const; QStringList fileNameList() const; QStringList filePathList() const; QString fileNameToFullPath(const QString &filePath); protected: LiteApi::IApplication *m_liteApp; QStandardItemModel *m_model; QString m_rootPath; QMap m_context; QStringList m_fileNameList; QStringList m_filePathList; QString m_mimeType; QString m_fileName; bool m_bReadOnly; }; #endif // MODELFILEIMPL_H ================================================ FILE: liteidex/src/utils/modelproject/modelproject.pri ================================================ LIBS *= -l$$qtLibraryName(modelproject) ================================================ FILE: liteidex/src/utils/modelproject/modelproject.pro ================================================ TARGET = modelproject TEMPLATE = lib CONFIG += staticlib include (../../liteideutils.pri) include (../fileutil/fileutil.pri) HEADERS += \ modelprojectimpl.h \ modelfileimpl.h SOURCES += \ modelprojectimpl.cpp \ modelfileimpl.cpp ================================================ FILE: liteidex/src/utils/modelproject/modelprojectimpl.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: modelprojectimpl.cpp // Creator: visualfc #include "modelprojectimpl.h" #include "modelfileimpl.h" #include "fileutil/fileutil.h" #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end ModelProjectImpl::ModelProjectImpl(LiteApi::IApplication *app) : m_liteApp(app) { m_widget = new QWidget(m_liteApp->mainWindow()); m_tree = new QTreeView; m_tree->setEditTriggers(QAbstractItemView::NoEditTriggers); m_tree->setHeaderHidden(true); m_tree->setContextMenuPolicy(Qt::CustomContextMenu); QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); layout->addWidget(m_tree); m_widget->setLayout(layout); connect(m_tree,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedTree(QModelIndex))); connect(m_liteApp->editorManager(),SIGNAL(editorSaved(LiteApi::IEditor*)),this,SLOT(editorSaved(LiteApi::IEditor*))); } ModelProjectImpl::~ModelProjectImpl() { if (m_widget) { delete m_widget; } // m_liteApp->dockManager()->removeDock(m_widget); } void ModelProjectImpl::load() { //m_liteApp->dockManager()->addDock(m_widget,tr("Project - ")+displayName()); } QWidget *ModelProjectImpl::widget() { return m_widget; } QString ModelProjectImpl::name() const { return QFileInfo(m_file->filePath()).fileName(); } QIcon ModelProjectImpl::icon() const { return QIcon(); } LiteApi::IFile *ModelProjectImpl::file() { return m_file; } QString ModelProjectImpl::filePath() const { if (m_file) { return m_file->filePath(); } return QString(); } QString ModelProjectImpl::mimeType() const { if (m_file) { return m_file->mimeType(); } return QString(); } void ModelProjectImpl::setModelFile(ModelFileImpl *file) { if (m_file == file) { return; } m_file = file; m_tree->setModel(m_file->model()); } bool ModelProjectImpl::open(const QString &fileName, const QString &mimeType) { QString outText; bool success = m_file->loadText(fileName,mimeType,outText); if (success) { m_file->updateModel(); m_tree->expandAll(); } return success; } QStringList ModelProjectImpl::folderList() const { QFileInfo info(m_file->filePath()); return QStringList() << info.path(); } QStringList ModelProjectImpl::fileNameList() const { return m_file->fileNameList(); } QStringList ModelProjectImpl::filePathList() const { return m_file->filePathList(); } QString ModelProjectImpl::fileNameToFullPath(const QString &fileName) { return m_file->fileNameToFullPath(fileName); } QMap ModelProjectImpl::targetInfo() const { return m_file->targetInfo(); } void ModelProjectImpl::editorSaved(LiteApi::IEditor *editor) { if (!editor) { return; } if (FileUtil::compareFile(editor->filePath(),m_file->filePath())) { QString outText; bool success = m_file->reloadText(outText); if (success) { m_file->updateModel(); m_tree->expandAll(); emit reloaded(); } } } void ModelProjectImpl::doubleClickedTree(QModelIndex index) { if (!index.isValid()) { return; } QStandardItem *item = m_file->model()->itemFromIndex(index); if (!item) { return; } bool ok; int itemType = item->data().toInt(&ok); if (ok && ( itemType == ModelFileImpl::ItemFile || itemType == ModelFileImpl::ItemProFile ) ) { QString fileName = m_file->fileNameToFullPath(item->text()); if (!fileName.isEmpty()) { m_liteApp->fileManager()->openEditor(fileName); } } } ================================================ FILE: liteidex/src/utils/modelproject/modelprojectimpl.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: modelprojectimpl.h // Creator: visualfc #ifndef MODELPROJECTIMPL_H #define MODELPROJECTIMPL_H #include "liteapi/liteapi.h" #include #include class QTreeView; class QStandardItemModel; class ModelFileImpl; class ModelProjectImpl : public LiteApi::IProject { Q_OBJECT public: ModelProjectImpl(LiteApi::IApplication *app); virtual ~ModelProjectImpl(); public: virtual QWidget *widget(); virtual QString name() const; virtual QIcon icon() const; public: virtual LiteApi::IFile *file(); virtual QString filePath() const; virtual QString mimeType() const; virtual QStringList folderList() const; virtual QStringList fileNameList() const; virtual QStringList filePathList() const; virtual QString fileNameToFullPath(const QString &filePath); virtual QMap targetInfo() const; virtual void load(); public: virtual bool open(const QString &filePath, const QString &mimeType); void setModelFile(ModelFileImpl *file); protected slots: virtual void doubleClickedTree(QModelIndex index); virtual void editorSaved(LiteApi::IEditor*); protected: LiteApi::IApplication *m_liteApp; QPointer m_file; QWidget *m_widget; QTreeView *m_tree; QStandardItemModel *m_model; }; #endif // MODELPROJECTIMPL_H ================================================ FILE: liteidex/src/utils/navigate/navigate.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: navigate.cpp // Creator: visualfc #include "navigate.h" #include "quickopenapi/quickopenapi.h" #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static QString escaped(const QString &text) { #if QT_VERSION >= 0x050000 return text.toHtmlEscaped(); #else return Qt::escape(text); #endif } NavigateBar::NavigateBar(LiteApi::IApplication *app, QObject *parent) : QObject(parent), m_liteApp(app), m_toolBar(0) { } NavigateBar::~NavigateBar() { } QToolBar *NavigateBar::createToolBar(const QString &title, QWidget *parent) { if (m_toolBar) { return m_toolBar; } m_toolBar = new QToolBar(title,parent); m_toolBar->setIconSize(LiteApi::getToolBarIconSize(m_liteApp)); return m_toolBar; } void NavigateBar::LoadPath(const QString &path) { m_filePath = path; QFileInfo info(path); if (!info.filePath().startsWith("//")) { QStringList paths = QDir::fromNativeSeparators(info.filePath()).split("/"); if (paths.size() >= 2) { QString head = ""; //m_editNavHeadAct = m_editNavBar->addSeparator(); QString last; #ifdef Q_OS_WIN last = paths[0]; #endif for (int i = 1; i < paths.size(); i++) { QString name = paths[i]; #ifdef Q_OS_WIN if (i == 1) { name = paths[0]+"\\"+paths[1]; } #endif QString path = last+"/"+paths[i]; last = path; if (i != paths.size()-1) { name += ">"; } QString text = QString("%2").arg(escaped(path)).arg(escaped(name)); QLabel *lbl = new QLabel; lbl->setText(head+text); m_toolBar->addWidget(lbl); connect(lbl,SIGNAL(linkActivated(QString)),this,SLOT(pathLinkActivated(QString))); } m_navHeadAct = m_toolBar->actions().first(); } } QAction *emptyAct = new QAction(this); m_toolBar->addAction(emptyAct); } QToolBar *NavigateBar::createNavToolBar(QWidget *parent) { QFileInfo info(m_filePath); QStringList paths = QDir::fromNativeSeparators(info.filePath()).split("/"); if (paths.size() < 2) { return 0; } QString head = ""; QToolBar *toolBar = new QToolBar(parent); toolBar->setIconSize(LiteApi::getToolBarIconSize(m_liteApp)); QString last; #ifdef Q_OS_WIN last = paths[0]; #endif for (int i = 1; i < paths.size(); i++) { QString name = paths[i]; #ifdef Q_OS_WIN if (i == 1) { name = paths[0]+"\\"+paths[1]; } #endif QString path = last+"/"+paths[i]; last = path; if (i != paths.size()-1) { name += ">"; } QString text = QString("%2").arg(escaped(path)).arg(escaped(name)); QLabel *lbl = new QLabel; lbl->setText(head+text); toolBar->addWidget(lbl); connect(lbl,SIGNAL(linkActivated(QString)),this,SLOT(quickPathLinkActivated(QString))); } QAction *empytAct = new QAction(toolBar); toolBar->addAction(empytAct); return toolBar; } void NavigateBar::pathLinkActivated(const QString &path) { QString dirpath = QFileInfo(path).absolutePath(); LiteApi::IQuickOpenManager *mgr = LiteApi::getQuickOpenManager(m_liteApp); if (mgr) { LiteApi::IQuickOpenFileSystem *fileSystem = LiteApi::getQuickOpenFileSystem(mgr); if (fileSystem) { fileSystem->setRootPath(dirpath); fileSystem->setPlaceholderText(QString(tr("Browser Files in %1").arg(QDir::toNativeSeparators(dirpath)))); mgr->setCurrentFilter(fileSystem); mgr->modelView()->setRootIndex(fileSystem->rootIndex()); QModelIndex index = fileSystem->indexForPath(path); mgr->modelView()->setCurrentIndex(index); mgr->setTempToolBar(this->createNavToolBar(mgr->widget())); QRect rc = m_toolBar->actionGeometry(m_navHeadAct); QPoint pt = m_toolBar->mapToGlobal(rc.topLeft()); mgr->showPopup(&pt); mgr->modelView()->scrollTo(index); return; } } } void NavigateBar::quickPathLinkActivated(const QString &path) { QString dirpath = QFileInfo(path).absolutePath(); LiteApi::IQuickOpenManager *mgr = LiteApi::getQuickOpenManager(m_liteApp); if (mgr) { LiteApi::IQuickOpenFileSystem *fileSystem = LiteApi::getQuickOpenFileSystem(mgr); if (fileSystem) { fileSystem->setRootPath(dirpath); fileSystem->setPlaceholderText(QString(tr("Browser Files in %1").arg(QDir::toNativeSeparators(dirpath)))); mgr->setCurrentFilter(fileSystem); mgr->modelView()->setRootIndex(fileSystem->rootIndex()); QModelIndex index = fileSystem->indexForPath(path); mgr->modelView()->setCurrentIndex(index); } } } ================================================ FILE: liteidex/src/utils/navigate/navigate.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: navigate.h // Creator: visualfc #ifndef NAVIGATE_H #define NAVIGATE_H #include "liteapi/liteapi.h" class NavigateBar : public QObject { Q_OBJECT public: NavigateBar(LiteApi::IApplication *app, QObject *parent); virtual ~NavigateBar(); QToolBar* createToolBar(const QString &title, QWidget *parent); void LoadPath(const QString &path); QToolBar *toolBar() const { return m_toolBar; } public slots: void pathLinkActivated(const QString &path); void quickPathLinkActivated(const QString &path); protected: QToolBar *createNavToolBar(QWidget *parent); protected: LiteApi::IApplication *m_liteApp; QToolBar *m_toolBar; QAction *m_navHeadAct; QString m_filePath; }; #endif // NAVIGATE_H ================================================ FILE: liteidex/src/utils/navigate/navigate.pri ================================================ LIBS *= -l$$qtLibraryName(navigate) ================================================ FILE: liteidex/src/utils/navigate/navigate.pro ================================================ TARGET = navigate TEMPLATE = lib CONFIG += staticlib include (../../liteideutils.pri) SOURCES += navigate.cpp HEADERS += navigate.h ================================================ FILE: liteidex/src/utils/processex/processex.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: processex.cpp // Creator: visualfc #include "processex.h" #include #ifndef Q_OS_WIN #include #endif #ifdef Q_OS_WIN #include #include #endif //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end QString ProcessEx::exitStatusText(int code, QProcess::ExitStatus status) { static QString text; switch (status) { case QProcess::NormalExit: text = tr("process exited with code %1").arg(code); break; case QProcess::CrashExit: text = tr("process crashed or was terminated"); break; default: text = tr("process exited with an unknown status"); } return text; } QString ProcessEx::processErrorText(QProcess::ProcessError code) { static QString text; switch (code) { case QProcess::FailedToStart: text = tr("process failed to start"); break; case QProcess::Crashed: text = tr("process crashed or was terminated while running"); break; case QProcess::Timedout: text = tr("timed out waiting for process"); break; case QProcess::ReadError: text = tr("couldn't read from the process"); break; case QProcess::WriteError: text = tr("couldn't write to the process"); break; case QProcess::UnknownError: default: text = tr("an unknown error occurred"); } return text; } ProcessEx::ProcessEx(QObject *parent) : Process(parent), m_suppressFinish(false) { connect(this,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(slotStateChanged(QProcess::ProcessState))); connect(this,SIGNAL(readyReadStandardOutput()),this,SLOT(slotReadOutput())); connect(this,SIGNAL(readyReadStandardError()),this,SLOT(slotReadError())); connect(this,SIGNAL(error(QProcess::ProcessError)),this,SLOT(slotError(QProcess::ProcessError))); connect(this,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotFinished(int,QProcess::ExitStatus))); } void ProcessEx::slotStateChanged(QProcess::ProcessState newState) { if (newState == QProcess::Starting) { m_suppressFinish = false; } } void ProcessEx::slotError(QProcess::ProcessError error) { switch (error) { // Suppress only if the process has stopped default: case QProcess::UnknownError: if (this->isRunning()) break; // Fall through // Always suppress case QProcess::FailedToStart: case QProcess::Crashed: m_suppressFinish = true; emit extFinish(true,-1,this->processErrorText(error)); break; // Never suppress case QProcess::Timedout: case QProcess::WriteError: case QProcess::ReadError: break; } } void ProcessEx::slotFinished(int code,QProcess::ExitStatus status) { if (!m_suppressFinish) { emit extFinish(false,code,this->exitStatusText(code,status)); } } void ProcessEx::slotReadOutput() { emit extOutput(this->readAllStandardOutput(),false); } void ProcessEx::slotReadError() { emit extOutput(this->readAllStandardError(),true); } Process::Process(QObject *parent) : QProcess(parent) { } Process::~Process() { stop(1); } bool Process::isRunning() const { return this->state() == QProcess::Running; } bool Process::isStop() const { return this->state() == QProcess::NotRunning; } void Process::stop(int ms) { if (isStop()) { return; } terminate(); closeReadChannel(QProcess::StandardOutput); closeReadChannel(QProcess::StandardError); if (!waitForFinished(ms)) { kill(); } } void Process::stopAndWait(int termMs, int finishMs) { stop(termMs); waitForFinished(finishMs); } void Process::startEx(const QString &cmd, const QStringList &args) { this->startEx(cmd,args.join(" ")); } void Process::startEx(const QString &cmd, const QString &args) { #ifdef Q_OS_WIN this->setNativeArguments(args); if (cmd.contains(' ')) { this->start("\""+cmd+"\""); } else { this->start(cmd); } #else if (cmd.contains(' ')) { this->start("\""+cmd+"\" "+args); } else { this->start(cmd+" "+args); } #endif } bool Process::startDetachedExAndHide(const QString &cmd, const QStringList &args) { #ifdef Q_OS_WIN return (intptr_t)ShellExecuteW(NULL, NULL, (LPCWSTR)cmd.toStdWString().data(), (LPCWSTR)args.join(" ").toStdWString().data(), NULL, SW_HIDE) > 32; #else return QProcess::startDetached(cmd, args); #endif } bool Process::startDetachedEx(const QString &cmd, const QStringList &args, const QString &workDir) { #ifdef Q_OS_WIN return (intptr_t)ShellExecuteW(NULL, L"open", (LPCWSTR)cmd.toStdWString().data(), (LPCWSTR)args.join(" ").toStdWString().data(), (LPCWSTR)workDir.toStdWString().data(), SW_SHOW) > 32; #else return QProcess::startDetached(cmd, args, workDir); #endif } void Process::setUserData(int id, const QVariant &data) { m_idVarMap.insert(id,data); } QVariant Process::userData(int id) const { return m_idVarMap.value(id); } #ifdef Q_OS_WIN void SendProcessCtrlC(QProcess */*process*/) { } #else void SendProcessCtrlC(QProcess *process) { if (process->pid() <= 0) { return; } kill(process->pid(),SIGINT); } #endif LiteProcess::LiteProcess(LiteApi::IApplication *app, QObject *parent) : QProcess(parent), m_liteApp(app), m_useCtrlC(false) { } void LiteProcess::setUseCtrlC(bool use) { m_useCtrlC = use; } void LiteProcess::startEx(const QString &cmd, const QString &args) { #ifdef Q_OS_WIN if (m_useCtrlC) { QString stub = m_liteApp->applicationPath()+"/liteide_ctrlc_stub.exe"; QString stubArg = cmd+" "+args; this->setNativeArguments(stubArg); this->start("\""+stub+"\""); } else { this->setNativeArguments(args); this->start(cmd); } #else this->start(cmd+" "+args); #endif } #ifdef Q_OS_WIN static BOOL sendMessage(UINT message, HWND hwnd, LPARAM lParam) { DWORD dwProcessID; GetWindowThreadProcessId(hwnd, &dwProcessID); if ((DWORD)lParam == dwProcessID) { SendNotifyMessage(hwnd, message, 0, 0); return FALSE; } return TRUE; } BOOL CALLBACK sendShutDownMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam) { static UINT uiShutDownMessage = RegisterWindowMessage(L"liteide_ctrlcstub_shutdown"); return sendMessage(uiShutDownMessage, hwnd, lParam); } BOOL CALLBACK sendInterruptMessageToAllWindowsOfProcess_enumWnd(HWND hwnd, LPARAM lParam) { static UINT uiInterruptMessage = RegisterWindowMessage(L"liteide_ctrlcstub_interrupt"); return sendMessage(uiInterruptMessage, hwnd, lParam); } #endif void LiteProcess::interrupt() { if (m_useCtrlC) { Q_PID processId = this->pid(); #ifdef Q_OS_WIN if (processId) { EnumWindows(sendInterruptMessageToAllWindowsOfProcess_enumWnd, processId->dwProcessId); } #else if (processId > 0) { ::kill(processId,SIGINT); } #endif } } void LiteProcess::terminate() { if (m_useCtrlC) { Q_PID processId = this->pid(); #ifdef Q_OS_WIN if (processId) { EnumWindows(sendShutDownMessageToAllWindowsOfProcess_enumWnd, processId->dwProcessId); } #else if (processId > 0) { ::kill(processId,SIGINT); } #endif } else { QProcess::terminate(); } } bool LiteProcess::isStop() const { return this->state() == QProcess::NotRunning; } ================================================ FILE: liteidex/src/utils/processex/processex.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: processex.h // Creator: visualfc #ifndef LITEAPI_PROCESSEX_H #define LITEAPI_PROCESSEX_H #include #include #include "liteapi/liteapi.h" class Process : public QProcess { Q_OBJECT public: Process(QObject *parent); virtual ~Process(); bool isRunning() const; bool isStop() const; void stop(int ms); void stopAndWait(int termMs, int finishMs); void startEx(const QString &cmd, const QStringList &args); void startEx(const QString &cmd, const QString &args); static bool startDetachedExAndHide(const QString& cmd, const QStringList &args); static bool startDetachedEx(const QString &cmd, const QStringList &args, const QString &workDir); public: void setUserData(int id, const QVariant &data); QVariant userData(int id) const; protected: QMap m_idVarMap; }; class ProcessEx : public Process { Q_OBJECT public: ProcessEx(QObject *parent); signals: void extOutput(const QByteArray &data,bool bError); void extFinish(bool error,int code, QString msg); protected slots: void slotStateChanged(QProcess::ProcessState); void slotError(QProcess::ProcessError); void slotFinished(int,QProcess::ExitStatus); void slotReadOutput(); void slotReadError(); public: static QString exitStatusText(int code,QProcess::ExitStatus status); static QString processErrorText(QProcess::ProcessError code); private: bool m_suppressFinish; }; void SendProcessCtrlC(QProcess *); class LiteProcess : public QProcess { public: LiteProcess(LiteApi::IApplication *app, QObject *parent); void setUseCtrlC(bool use); void startEx(const QString &cmd, const QString &args); void interrupt(); void terminate(); bool isStop() const; protected: LiteApi::IApplication *m_liteApp; bool m_useCtrlC; }; #endif // LITEAPI_PROCESSEX_H ================================================ FILE: liteidex/src/utils/processex/processex.pri ================================================ LIBS *= -l$$qtLibraryName(processex) win32 { LIBS += -luser32 -lshell32 } ================================================ FILE: liteidex/src/utils/processex/processex.pro ================================================ TARGET = processex TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += processex.h SOURCES += processex.cpp ================================================ FILE: liteidex/src/utils/symboltreeview/symboltreeview.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: symboltreeview.cpp // Creator: visualfc #include "symboltreeview.h" #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static QStringList stringListFromIndex(const QModelIndex &index) { QStringList list; if (!index.isValid()) return list; list.append(stringListFromIndex(index.parent())); list.append(index.data().toString()); return list; } static QModelIndex indexFromStringList(QAbstractItemModel *model, QStringList &list, const QModelIndex & parent = QModelIndex()) { if (list.isEmpty()) return QModelIndex(); QString text = list.front(); for (int i = 0; i < model->rowCount(parent); i++) { QModelIndex child = model->index(i,0,parent); if (child.data().toString() == text) { list.pop_front(); if (list.isEmpty()) { return child; } else { QModelIndex next = indexFromStringList(model,list,child); if (next.isValid()) return next; else return child; } } } return QModelIndex(); } SymbolTreeView::SymbolTreeView(QWidget *parent) : QTreeView(parent) { init(true); } SymbolTreeView::SymbolTreeView(bool bResizeToContents, QWidget *parent) : QTreeView(parent) { init(bResizeToContents); } void SymbolTreeView::init(bool bResizeToContents) { m_bClickedItem = false; m_hsbPos = 0; setEditTriggers(QAbstractItemView::NoEditTriggers); // setFrameStyle(QFrame::NoFrame); setIndentation(indentation() * 9/10); { this->setHeaderHidden(true); if (bResizeToContents) { #if QT_VERSION >= 0x050000 this->header()->setSectionResizeMode(QHeaderView::ResizeToContents); #else this->header()->setResizeMode(QHeaderView::ResizeToContents); #endif this->header()->setStretchLastSection(false); } this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); } setContextMenuPolicy(Qt::CustomContextMenu); setUniformRowHeights(true); setTextElideMode(Qt::ElideNone); // setExpandsOnDoubleClick(false); setAttribute(Qt::WA_MacShowFocusRect, false); connect(this,SIGNAL(clicked(QModelIndex)),this,SLOT(clickedItem(QModelIndex))); connect(this->horizontalScrollBar(),SIGNAL(valueChanged(int)),this,SLOT(hsbValueChanged(int))); } void SymbolTreeView::focusInEvent(QFocusEvent *event) { if (event->reason() != Qt::PopupFocusReason) QTreeView::focusInEvent(event); } void SymbolTreeView::focusOutEvent(QFocusEvent *event) { if (event->reason() != Qt::PopupFocusReason) QTreeView::focusOutEvent(event); } QModelIndex SymbolTreeView::topViewIndex() { return indexAt(QPoint(1,1)); } void SymbolTreeView::reset() { QTreeView::reset(); //setRootIndex(model()->index(0,0)); //this->setRootIndex(QModelIndex()); } void SymbolTreeView::getTreeExpands(const QModelIndex &parent, QList &list) const { for (int i = 0; i < this->model()->rowCount(parent); i++) { QModelIndex index = this->model()->index(i,0,parent); if (this->isExpanded(index)) { list.append(index); getTreeExpands(index,list); } } } void SymbolTreeView::clickedItem(QModelIndex) { this->m_bClickedItem = true; this->m_hsbPos = this->horizontalScrollBar()->sliderPosition(); } void SymbolTreeView::hsbValueChanged(int) { if (this->m_bClickedItem) { this->m_bClickedItem = false; this->horizontalScrollBar()->setValue(this->m_hsbPos); } } QList SymbolTreeView::expandIndexs() const { QList expands; getTreeExpands(QModelIndex(),expands); return expands; } void SymbolTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { QTreeView::currentChanged(current,previous); emit currentIndexChanged(current, previous); } void SymbolTreeView::saveState(SymbolTreeState *state) { if (!state) { return; } state->expands.clear(); foreach (QModelIndex index, this->expandIndexs()) { state->expands.append(stringListFromIndex(index)); } state->cur = stringListFromIndex(this->currentIndex()); state->vbar = verticalScrollBar()->value(); state->hbar = horizontalScrollBar()->value(); } void SymbolTreeView::loadState(QAbstractItemModel *model,SymbolTreeState *state) { //load state //this->expandToDepth(0) QListIterator ie(state->expands); while (ie.hasNext()) { QStringList expandPath = ie.next(); QModelIndex expandIndex = indexFromStringList(model,expandPath); if (expandIndex.isValid()) { this->setExpanded(expandIndex,true); } } QModelIndex curIndex = indexFromStringList(model,state->cur); if (curIndex.isValid()) { this->setCurrentIndex(curIndex); } if (state->vbar != -1) { verticalScrollBar()->setValue(state->vbar); } if (state->hbar != -1) { horizontalScrollBar()->setValue(state->hbar); } } void SymbolTreeView::keyPressEvent(QKeyEvent *event) { // Note: This always eats the event // whereas QAbstractItemView never eats it if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && event->modifiers() == 0 && QTreeView::currentIndex().isValid() && QTreeView::state() != QAbstractItemView::EditingState) { emit QTreeView::activated(QTreeView::currentIndex()); emit enterKeyPressed(QTreeView::currentIndex()); return; } QTreeView::keyPressEvent(event); } ================================================ FILE: liteidex/src/utils/symboltreeview/symboltreeview.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: symboltreeview.h // Creator: visualfc #ifndef SYMBOLTREEVIEW_H #define SYMBOLTREEVIEW_H #include struct SymbolTreeState { SymbolTreeState() : vbar(-1),hbar(-1) { } QList expands; QStringList cur; int vbar; int hbar; }; class SymbolTreeView : public QTreeView { Q_OBJECT public: SymbolTreeView(QWidget *parent = 0); SymbolTreeView(bool bResizeToContents, QWidget *parent = 0); protected: void init(bool bResizeToContents); public: QModelIndex topViewIndex(); QList expandIndexs() const; virtual void reset(); void saveState(SymbolTreeState *state); void loadState(QAbstractItemModel *model,SymbolTreeState *state); signals: void currentIndexChanged(const QModelIndex ¤t, const QModelIndex &previous); void enterKeyPressed(QModelIndex); protected: void focusInEvent(QFocusEvent *event); void focusOutEvent(QFocusEvent *event); void keyPressEvent(QKeyEvent *event); void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); void getTreeExpands(const QModelIndex &parent, QList &list) const; protected slots: void clickedItem(QModelIndex); void hsbValueChanged(int); protected: bool m_bClickedItem; int m_hsbPos; }; #endif //SYMBOLTREEVIEW_H ================================================ FILE: liteidex/src/utils/symboltreeview/symboltreeview.pri ================================================ LIBS *= -l$$qtLibraryName(symboltreeview) ================================================ FILE: liteidex/src/utils/symboltreeview/symboltreeview.pro ================================================ TARGET = symboltreeview TEMPLATE = lib CONFIG += staticlib include(../../liteideutils.pri) HEADERS += symboltreeview.h SOURCES += symboltreeview.cpp ================================================ FILE: liteidex/src/utils/tabwidget/litetabwidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: litetabwidget.cpp // Creator: visualfc #include "litetabwidget.h" #include "liteapi/liteapi.h" #include #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end LiteTabWidget::LiteTabWidget(QSize iconSize, QObject *parent) : QObject(parent) { m_tabBar = new TabBar; m_tabBar->setExpanding(false); m_tabBar->setDocumentMode(true); m_tabBar->setDrawBase(false); m_tabBar->setUsesScrollButtons(true); m_tabBar->setMovable(true); m_tabBar->setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); m_tabBarWidget = new QWidget; m_addTabAct = new QAction(QIcon("icon:images/addpage.png"),tr("Open a new tab"),this); m_listButton = new QToolButton; m_listButton->setToolTip(tr("List All Tabs")); m_listButton->setIcon(QIcon("icon:images/listpage.png")); m_listButton->setPopupMode(QToolButton::InstantPopup); m_listButton->setStyleSheet( "QToolButton::menu-indicator{image:none;}"); m_closeTabAct = new QAction(QIcon("icon:images/closepage.png"),tr("Close Tab"),this); // m_closeButton = new QToolButton; // m_closeButton->setDefaultAction(m_closeTabAct); QHBoxLayout *layout = new QHBoxLayout; layout->setMargin(0); layout->setSpacing(0); m_tabBar->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); m_tabToolBar = new QToolBar; m_tabToolBar->setObjectName("toolbar.tabs"); m_tabToolBar->setIconSize(iconSize); m_tabToolBar->addWidget(m_tabBar); //QWidget *dump = new QWidget; //dump->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Preferred); // m_tabToolBar->addWidget(dump); m_tabToolBar->addWidget(m_listButton); m_tabToolBar->addAction(m_closeTabAct); layout->addWidget(m_tabToolBar); m_tabBarWidget->setLayout(layout); m_stackedWidget = new QStackedWidget; connect(m_tabBar,SIGNAL(currentChanged(int)),this,SLOT(tabCurrentChanged(int))); connect(m_tabBar,SIGNAL(tabCloseRequested(int)),this,SIGNAL(tabCloseRequested(int))); connect(m_tabBar,SIGNAL(tabMoved(int,int)),this,SLOT(tabMoved(int,int))); connect(m_closeTabAct,SIGNAL(triggered()),this,SLOT(closeCurrentTab())); connect(m_addTabAct,SIGNAL(triggered()),this,SIGNAL(tabAddRequest())); m_listButton->setEnabled(false); } LiteTabWidget::~LiteTabWidget() { delete m_tabBarWidget; } void LiteTabWidget::closeCurrentTab() { int index = m_tabBar->currentIndex(); if (index < 0) { return; } emit tabCloseRequested(index); } int LiteTabWidget::addTab(QWidget *w,const QString & label, const QString &tip) { return addTab(w,QIcon(),label,tip); } int LiteTabWidget::addTab(QWidget *w,const QIcon & icon, const QString & label, const QString &tip) { if (!w) { return -1; } if (m_widgetList.size() == 0) { m_listButton->setEnabled(true); } int index = m_tabBar->addTab(icon,label); if (!tip.isEmpty()) { m_tabBar->setTabToolTip(index,tip); } m_stackedWidget->addWidget(w); m_widgetList.append(w); return index; } void LiteTabWidget::removeTab(int index) { if (index < 0) return; QWidget *w = widget(index); if (w) { m_stackedWidget->removeWidget(w); m_widgetList.removeAt(index); } if (m_widgetList.size() == 0) { m_listButton->setEnabled(false); } m_tabBar->removeTab(index); } QWidget *LiteTabWidget::currentWidget() { return m_stackedWidget->currentWidget(); } TabBar *LiteTabWidget::tabBar() { return m_tabBar; } int LiteTabWidget::count() const { return m_tabBar->count(); } int LiteTabWidget::currentIndex() const { return m_tabBar->currentIndex(); } QList LiteTabWidget::widgetList() const { return m_widgetList; } QWidget *LiteTabWidget::stackedWidget() { return m_stackedWidget; } QWidget *LiteTabWidget::tabBarWidget() { return m_tabBarWidget; } void LiteTabWidget::setListMenu(QMenu *menu) { m_listButton->setMenu(menu); } void LiteTabWidget::setTabText(int index, const QString & text) { m_tabBar->setTabText(index,text); } QString LiteTabWidget::tabText(int index) const { return m_tabBar->tabText(index); } void LiteTabWidget::setTabToolTip(int index, const QString &tip) { m_tabBar->setTabToolTip(index,tip); } void LiteTabWidget::setTabData(int index, const QVariant &data) { m_tabBar->setTabData(index,data); } QVariant LiteTabWidget::tabData(int index) const { return m_tabBar->tabData(index); } int LiteTabWidget::indexOf(QWidget *w) { return m_widgetList.indexOf(w); } QWidget *LiteTabWidget::widget(int index) { return m_widgetList.value(index); } void LiteTabWidget::setCurrentWidget(QWidget *w) { int index = indexOf(w); if (index < 0) return; setCurrentIndex(index); } void LiteTabWidget::tabCurrentChanged(int index) { QWidget *w = m_widgetList.value(index); if (w) { m_stackedWidget->setCurrentWidget(w); } emit currentChanged(index); } void LiteTabWidget::setCurrentIndex(int index) { m_tabBar->setCurrentIndex(index); } void LiteTabWidget::tabMoved(int from, int to) { m_widgetList.swap(from,to); } ================================================ FILE: liteidex/src/utils/tabwidget/litetabwidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: litetabwidget.h // Creator: visualfc #ifndef LITETABWIDGET_H #define LITETABWIDGET_H #include #include #include #include class QMenu; class QTabBar; class QHBoxLayout; class QStackedLayout; class QStackedWidget; class QToolButton; class QToolBar; class QAction; class QActionGroup; //header : headerWidget //body: stackedWidget class TabBar : public QTabBar { Q_OBJECT public: TabBar(QWidget *parent = 0) : QTabBar(parent) { m_enableWheel = true; } void wheelEvent(QWheelEvent *event) { if (!m_enableWheel) { return; } QTabBar::wheelEvent(event); } void setEnableWheel(bool b) { m_enableWheel = b; } bool enableWheel() const { return m_enableWheel; } protected: bool m_enableWheel; }; class LiteTabWidget : public QObject { Q_OBJECT public: explicit LiteTabWidget(QSize iconSize, QObject *parent = 0); virtual ~LiteTabWidget(); int addTab(QWidget *w,const QString & label, const QString &tip = QString()); int addTab(QWidget *w,const QIcon & icon, const QString & label,const QString &tip); void removeTab(int index); int indexOf(QWidget *w); QWidget *widget(int index); QWidget *currentWidget(); TabBar *tabBar(); int count() const; int currentIndex() const; void setTabText(int index, const QString & text); QString tabText(int index) const; void setTabToolTip(int index, const QString &tip); void setTabData(int index, const QVariant &data); QVariant tabData(int index) const; QList widgetList() const; QWidget *stackedWidget(); QWidget *tabBarWidget(); void setListMenu(QMenu *menu); signals: void currentChanged(int index); void tabCloseRequested(int index); void tabAddRequest(); public slots: void setCurrentWidget(QWidget *w); void setCurrentIndex(int index); void tabMoved(int,int); public slots: void closeCurrentTab(); void tabCurrentChanged(int); protected: QToolBar *m_tabToolBar; QWidget *m_tabBarWidget; TabBar *m_tabBar; QToolButton *m_listButton; QToolButton *m_closeButton; QStackedWidget *m_stackedWidget; QList m_widgetList; QAction *m_closeTabAct; QAction *m_addTabAct; QPointer m_currentWidget; }; #endif // LITETABWIDGET_H ================================================ FILE: liteidex/src/utils/tabwidget/tabwidget.pri ================================================ LIBS *= -l$$qtLibraryName(tabwidget) ================================================ FILE: liteidex/src/utils/tabwidget/tabwidget.pro ================================================ TARGET = tabwidget TEMPLATE = lib CONFIG += staticlib include (../../liteideutils.pri) SOURCES += litetabwidget.cpp HEADERS += litetabwidget.h ================================================ FILE: liteidex/src/utils/textoutput/terminaledit.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: terminaledit.cpp // Creator: visualfc #include "terminaledit.h" #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end TerminalEdit::TerminalEdit(QWidget *parent) : QPlainTextEdit(parent) { this->setCursorWidth(4); this->setAcceptDrops(false); //this->setWordWrapMode(QTextOption::NoWrap); m_contextMenu = new QMenu(this); m_contextRoMenu = new QMenu(this); m_bAutoPosCursor = true; m_bFilterTermColor = false; m_bTerminalInput = false; m_lastInputPostion = 0; m_lastPosition = 0; m_lastKey = -1; this->setContextMenuPolicy(Qt::CustomContextMenu); m_cut = new QAction(tr("Cut"),this); m_cut->setShortcut(QKeySequence::Cut); m_cut->setShortcutContext(Qt::WidgetShortcut); m_copy = new QAction(tr("Copy"),this); m_copy->setShortcut(QKeySequence::Copy); m_copy->setShortcutContext(Qt::WidgetShortcut); m_paste = new QAction(tr("Paste"),this); m_paste->setShortcut(QKeySequence::Paste); m_paste->setShortcutContext(Qt::WidgetShortcut); m_selectAll = new QAction(tr("Select All"),this); m_selectAll->setShortcut(QKeySequence::SelectAll); m_selectAll->setShortcutContext(Qt::WidgetShortcut); m_clear = new QAction(tr("Clear All"),this); m_contextMenu->addAction(m_cut); m_contextMenu->addAction(m_copy); m_contextMenu->addAction(m_paste); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_selectAll); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_clear); m_contextRoMenu->addAction(m_copy); m_contextRoMenu->addSeparator(); m_contextRoMenu->addAction(m_selectAll); m_contextRoMenu->addSeparator(); m_contextRoMenu->addAction(m_clear); connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuRequested(QPoint))); connect(this,SIGNAL(cursorPositionChanged()),this,SLOT(cursorPositionChanged())); connect(this,SIGNAL(selectionChanged()),this,SLOT(cursorPositionChanged())); connect(m_cut,SIGNAL(triggered()),this,SLOT(cut())); connect(m_copy,SIGNAL(triggered()),this,SLOT(copy())); connect(m_paste,SIGNAL(triggered()),this,SLOT(paste())); connect(m_selectAll,SIGNAL(triggered()),this,SLOT(selectAll())); connect(m_clear,SIGNAL(triggered()),this,SLOT(clear())); } void TerminalEdit::setFilterTermColor(bool filter) { m_bFilterTermColor = filter; } void TerminalEdit::setTerminalInput(bool term) { m_bTerminalInput = term; } void TerminalEdit::append(const QString &text, QTextCharFormat *fmt) { QString str = text; if (m_bFilterTermColor) { static QRegExp rx("\033\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]"); str.remove(rx); } if (str.isEmpty()) { return; } setUndoRedoEnabled(false); QTextCursor cur = this->textCursor(); cur.movePosition(QTextCursor::End); if (m_bTerminalInput && m_lastKey != -1) { cur.setPosition(m_lastInputPostion,QTextCursor::KeepAnchor); } if (fmt) { cur.setCharFormat(*fmt); } cur.insertText(str); this->setTextCursor(cur); setUndoRedoEnabled(true); m_lastPosition = this->textCursor().position(); if (str.contains("\n") || m_lastKey == -1) { m_lastInputPostion = m_lastPosition; } m_lastKey = -1; } void TerminalEdit::clear() { m_lastPosition = 0; m_lastInputPostion = 0; m_lastKey = -1; QPlainTextEdit::clear(); } void TerminalEdit::keyPressEvent(QKeyEvent *ke) { QTextCursor cur = this->textCursor(); int pos = cur.position(); int end = cur.position(); if (cur.hasSelection()) { pos = cur.selectionStart(); end = cur.selectionEnd(); } bool bReadOnly = pos < m_lastInputPostion; if (bReadOnly && ( ke == QKeySequence::Paste || ke == QKeySequence::Cut || ke == QKeySequence::DeleteEndOfWord || ke == QKeySequence::DeleteStartOfWord)) { return; } if (ke == QKeySequence::DeleteStartOfWord) { if (!cur.hasSelection()) { cur.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); if (cur.selectionStart() < m_lastPosition) { cur.movePosition(QTextCursor::Right,QTextCursor::KeepAnchor,m_lastPosition-cur.selectionStart()); } } cur.removeSelectedText(); return; } m_lastKey = ke->key(); if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier || ke->modifiers() == Qt::KeypadModifier) { if (ke->key() < Qt::Key_Escape) { if (bReadOnly) { return; } } else { if (ke->key() == Qt::Key_Backspace) { if (cur.hasSelection()) { if (bReadOnly) { return; } } else if (pos <= m_lastInputPostion) { return; } } else if (bReadOnly && ( ke->key() == Qt::Key_Delete || ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab || ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)) { return; } if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) { cur.setPosition(end,QTextCursor::MoveAnchor); cur.setPosition(m_lastPosition,QTextCursor::KeepAnchor); #ifdef Q_OS_WIN emit enterText(cur.selectedText()+"\r\n"); #else emit enterText(cur.selectedText()+"\n"); #endif QPlainTextEdit::keyPressEvent(ke); QTextCursor cur = this->textCursor(); cur.movePosition(QTextCursor::End); return; } else if (ke->key() == Qt::Key_Tab){ cur.setPosition(end,QTextCursor::MoveAnchor); cur.setPosition(m_lastPosition,QTextCursor::KeepAnchor); emit tabText(cur.selectedText()+"\t"); return; } else if (ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down) { emit keyUpdown(ke->key()); return; } } } QPlainTextEdit::keyPressEvent(ke); } void TerminalEdit::mouseDoubleClickEvent(QMouseEvent *e) { QPlainTextEdit::mouseDoubleClickEvent(e); QTextCursor cur = cursorForPosition(e->pos()); emit dbclickEvent(cur); } void TerminalEdit::mousePressEvent(QMouseEvent *e) { QPlainTextEdit::mousePressEvent(e); if (!m_bAutoPosCursor) { return; } if (!this->isReadOnly() && m_bFocusOut) { m_bFocusOut = false; QTextCursor cur = this->textCursor(); if (!cur.hasSelection()) { cur.movePosition(QTextCursor::End); this->setTextCursor(cur); } } } void TerminalEdit::focusOutEvent(QFocusEvent *e) { QPlainTextEdit::focusOutEvent(e); m_bFocusOut = true; } void TerminalEdit::focusInEvent(QFocusEvent *e) { QPlainTextEdit::focusInEvent(e); if (!this->isReadOnly()) { QTextCursor cur = this->textCursor(); if (!cur.hasSelection()) { cur.movePosition(QTextCursor::End); this->setTextCursor(cur); } } } void TerminalEdit::contextMenuRequested(const QPoint &pt) { QPoint globalPos = this->mapToGlobal(pt); if (isReadOnly()) { m_contextRoMenu->popup(globalPos); } else { m_contextMenu->popup(globalPos); } } void TerminalEdit::cursorPositionChanged() { QTextCursor cur = this->textCursor(); int pos = cur.position(); if (cur.hasSelection()) { pos = cur.selectionStart(); m_copy->setEnabled(true); if (pos < m_lastPosition) { m_cut->setEnabled(false); } else { m_cut->setEnabled(!this->isReadOnly()); } } else { m_copy->setEnabled(false); m_cut->setEnabled(false); } if (pos < m_lastPosition) { m_paste->setEnabled(false); } else { QClipboard *clipboard = QApplication::clipboard(); if (clipboard->mimeData()->hasText() || clipboard->mimeData()->hasHtml()){ m_paste->setEnabled(true); } else { m_paste->setEnabled(false); } } } ================================================ FILE: liteidex/src/utils/textoutput/terminaledit.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: terminaledit.h // Creator: visualfc #ifndef TERMINALEDIT_H #define TERMINALEDIT_H #include class TerminalEdit : public QPlainTextEdit { Q_OBJECT public: explicit TerminalEdit(QWidget *parent = 0); void setFilterTermColor(bool filter); void setTerminalInput(bool term); signals: void enterText(const QString &text); void tabText(const QString &text); void keyUpdown(int key); void dbclickEvent(const QTextCursor &cur); public slots: void append(const QString &text, QTextCharFormat *fmt = 0); void clear(); void contextMenuRequested(const QPoint &pt); void cursorPositionChanged(); public: void setAutoPosCursor(bool b) { m_bAutoPosCursor = b; } bool isAutoMoveToLast() const { return m_bAutoPosCursor; } protected: virtual void keyPressEvent(QKeyEvent *e); virtual void mouseDoubleClickEvent(QMouseEvent *e); virtual void mousePressEvent(QMouseEvent *e); virtual void focusOutEvent(QFocusEvent *e); virtual void focusInEvent(QFocusEvent *e); int m_lastPosition; int m_lastInputPostion; int m_lastKey; QMenu *m_contextMenu; QMenu *m_contextRoMenu; QAction *m_cut; QAction *m_copy; QAction *m_paste; QAction *m_selectAll; QAction *m_clear; bool m_bFocusOut; bool m_bAutoPosCursor; bool m_bFilterTermColor; bool m_bTerminalInput; }; #endif // TERMINALEDIT_H ================================================ FILE: liteidex/src/utils/textoutput/textoutput.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: textoutput.cpp // Creator: visualfc #include "textoutput.h" #include "colorstyle/colorstyle.h" #include "../liteapp/liteapp_global.h" #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end static void fadeText(QTextCursor& cur) { QTextCharFormat f(cur.charFormat()); QColor color(f.foreground().color()); color.setAlpha(160); f.setForeground(color); cur.setCharFormat(f); } TextOutput::TextOutput(LiteApi::IApplication *app, bool readOnly, QWidget *parent) : TerminalEdit(parent), m_liteApp(app) { this->setReadOnly(readOnly); m_fmt = this->currentCharFormat(); m_defPalette = this->palette(); m_clrText = m_defPalette.foreground().color(); m_clrTag = Qt::darkBlue; m_clrError = Qt::red; m_existsTimer.start(); connect(m_liteApp->editorManager(),SIGNAL(colorStyleSchemeChanged()),this,SLOT(loadColorStyleScheme())); connect(m_liteApp->optionManager(),SIGNAL(applyOption(QString)),this,SLOT(applyOption(QString))); this->applyOption(OPTION_LITEOUTPUT); } void TextOutput::append(const QString &text) { append(text, m_clrText); } void TextOutput::append(const QString &text,const QBrush &foreground) { QTextCharFormat f = m_fmt; f.setForeground(foreground); appendAndReset(text, f); } void TextOutput::appendTag(const QString &text, bool error, bool time) { QTextCharFormat f = m_fmt; f.setFontWeight(QFont::Bold); if (error) { f.setForeground(m_clrError); } else { f.setForeground(m_clrTag); } if (time) { appendAndReset(QTime::currentTime().toString("hh:mm:ss: ")+text, f); } else { appendAndReset(text, f); } } void TextOutput::appendAndReset(const QString &text, QTextCharFormat& f) { TerminalEdit::append(text, &f); m_existsTimer.restart(); } void TextOutput::updateExistsTextColor(bool force) { if (!m_existsTimer.hasExpired(2500) && !force) return; QTextDocument* doc = document(); for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) { QTextCursor cur(it); cur.select(QTextCursor::BlockUnderCursor); fadeText(cur); } } void TextOutput::setMaxLine(int max) { this->setMaximumBlockCount(max);; } void TextOutput::setLineWrap(bool b) { this->setLineWrapMode(b ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap); } bool TextOutput::isLineWrap() const { return this->lineWrapMode() != QPlainTextEdit::NoWrap; } void TextOutput::loadColorStyleScheme() { bool useColorShceme = m_liteApp->settings()->value(OUTPUT_USECOLORSCHEME,true).toBool(); const ColorStyleScheme *colorScheme = m_liteApp->editorManager()->colorStyleScheme(); const ColorStyle *text = colorScheme->findStyle("Text"); const ColorStyle *selection = colorScheme->findStyle("Selection"); const ColorStyle *keyword = colorScheme->findStyle("Keyword"); const ColorStyle *error = colorScheme->findStyle("Error"); QPalette p = this->m_defPalette; if (useColorShceme && text) { if (text->foregound().isValid()) { p.setColor(QPalette::Text,text->foregound()); p.setColor(QPalette::Foreground, text->foregound()); } if (text->background().isValid()) { p.setColor(QPalette::Base, text->background()); } } if (useColorShceme && selection) { if (selection->foregound().isValid()) { p.setColor(QPalette::HighlightedText, selection->foregound()); } if (selection->background().isValid()) { p.setColor(QPalette::Highlight, selection->background()); } p.setBrush(QPalette::Inactive, QPalette::Highlight, p.highlight()); p.setBrush(QPalette::Inactive, QPalette::HighlightedText, p.highlightedText()); } QString sheet = QString("QPlainTextEdit{color:%1;background-color:%2;selection-color:%3;selection-background-color:%4;}") .arg(p.text().color().name()) .arg(p.base().color().name()) .arg(p.highlightedText().color().name()) .arg(p.highlight().color().name()); this->setPalette(p); this->setStyleSheet(sheet); m_clrText = p.text().color(); m_fmt.setForeground(p.text().color()); m_fmt.setBackground(p.base().color()); if (useColorShceme && keyword && keyword->foregound().isValid()) { m_clrTag = keyword->foregound(); } else { m_clrTag = Qt::darkBlue; } if (useColorShceme && error && error->foregound().isValid()) { m_clrError = error->foregound(); } else { m_clrError = Qt::red; } QTextCursor cur(document()); cur.select(QTextCursor::Document); cur.setCharFormat(m_fmt); fadeText(cur); } void TextOutput::applyOption(QString opt) { if (opt != OPTION_LITEOUTPUT) { return; } QString fontFamily = m_liteApp->settings()->value(OUTPUT_FAMILY).toString(); int fontSize = m_liteApp->settings()->value(OUTPUT_FONTSIZE,12).toInt(); int fontZoom = m_liteApp->settings()->value(OUTPUT_FONTZOOM,100).toInt(); bool antialias = m_liteApp->settings()->value(OUTPUT_ANTIALIAS,true).toBool(); int maxLines = m_liteApp->settings()->value(OUTPUT_MAXLINES,5000).toInt(); QFont font = this->font(); if (!fontFamily.isEmpty()) { font.setFamily(fontFamily); } font.setPointSize(fontSize*fontZoom/100.0); if (antialias) { font.setStyleStrategy(QFont::PreferAntialias); } else { font.setStyleStrategy(QFont::NoAntialias); } this->setFont(font); this->setMaxLine(maxLines); this->loadColorStyleScheme(); } ================================================ FILE: liteidex/src/utils/textoutput/textoutput.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2019 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: textoutput.h // Creator: visualfc #ifndef TEXTOUTPUT_H #define TEXTOUTPUT_H #include "terminaledit.h" #include "liteapi/liteapi.h" #include class TextOutput : public TerminalEdit { Q_OBJECT public: explicit TextOutput(LiteApi::IApplication *app, bool readOnly = true, QWidget *parent = 0); void append(const QString &text); void append(const QString &text,const QBrush &foreground); void appendTag(const QString &text, bool error = false, bool time = false); void updateExistsTextColor(bool force = false); void setMaxLine(int max); void setLineWrap(bool b); bool isLineWrap() const; public slots: void loadColorStyleScheme(); void applyOption(QString); protected: void appendAndReset(const QString &text, QTextCharFormat& f); LiteApi::IApplication *m_liteApp; QPalette m_defPalette; QTextCharFormat m_fmt; QColor m_clrTag; QColor m_clrError; QColor m_clrText; QElapsedTimer m_existsTimer; }; #endif // TEXTOUTPUT_H ================================================ FILE: liteidex/src/utils/textoutput/textoutput.pri ================================================ LIBS *= -l$$qtLibraryName(textoutput) ================================================ FILE: liteidex/src/utils/textoutput/textoutput.pro ================================================ TARGET = textoutput TEMPLATE = lib CONFIG += staticlib include (../../liteideutils.pri) include (../colorstyle/colorstyle.pri) HEADERS += textoutput.h \ terminaledit.h SOURCES += textoutput.cpp \ terminaledit.cpp ================================================ FILE: liteidex/src/utils/utils.pro ================================================ # USE .subdir AND .depends ! # OTHERWISE PLUGINS WILL BUILD IN WRONG ORDER (DIRECTORIES ARE COMPILED IN PARALLEL) TEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ fileutil \ mimetype \ extension \ textoutput \ symboltreeview \ modelproject \ processex \ colorstyle \ documentbrowser \ htmlutil \ golangapi \ filesystem \ editorutil \ folderview \ iconutil \ dlvclient \ navigate \ tabwidget \ vterm ================================================ FILE: liteidex/src/utils/vterm/vterm.pri ================================================ LIBS *= -l$$qtLibraryName(vtermwidget) LIBS *= -l$$qtLibraryName(libvterm) LIBS *= -l$$qtLibraryName(ptyqt) ================================================ FILE: liteidex/src/utils/vterm/vterm.pro ================================================ TARGET = vtermwidget TEMPLATE = lib CONFIG += staticlib QT += xml include (../../liteideutils.pri) include (../../3rdparty/libvterm/libvterm.pri) include (../../3rdparty/ptyqt/ptyqt.pri) win32 { QT += network } HEADERS += \ vtermcolor.h \ vtermwidget.h \ vtermwidgetbase.h SOURCES += \ vtermwidget.cpp \ vtermwidgetbase.cpp ================================================ FILE: liteidex/src/utils/vterm/vtermcolor.h ================================================ #ifndef VTERMCOLOR_H #define VTERMCOLOR_H #include #include enum TERM_COLOR { TERM_COLOR_DEFAULT = -1, TERM_COLOR_BLACK = 0, TERM_COLOR_RED = 1, TERM_COLOR_GREEN = 2, TERM_COLOR_YELLOW = 3, TERM_COLOR_BLUE = 4, TERM_COLOR_PURPLE = 5, TERM_COLOR_CYAN = 6, TERM_COLOR_WHITE = 7, }; enum TERM_ATTR { TERM_ATTR_NORMAL = 0, TERM_ATTR_BOLD = 0x00000001, TERM_ATTR_NOBOLD = 0x00000002, TERM_ATTR_ITALIC = 0x00000004, TERM_ATTR_NOITALIC = 0x00000008, TERM_ATTR_UNDERLINE = 0x00000010, TERM_ATTR_NOUNDERLINE = 0x000020, TERM_ATTR_BLINK = 0x00000040, TERM_ATTR_NOBLINK = 0x00000080, TERM_ATTR_REVERSE = 0x00000100, TERM_ATTR_NOREVERSE = 0x00000200, TERM_ATTR_HALF = 0x00000400, TERM_ATTR_NOHALF = TERM_ATTR_NOBOLD, TERM_ATTR_LIGHT = TERM_ATTR_BOLD, TERM_ATTR_NOLIGHT = TERM_ATTR_NOBOLD, TERM_ATTR_HIDE = 0x00000800, }; inline QString term_color(const QString &text, TERM_COLOR fg = TERM_COLOR_DEFAULT, TERM_COLOR bg = TERM_COLOR_DEFAULT, int attr = TERM_ATTR_NORMAL, bool endResetDefault = true) { if (fg == TERM_COLOR_DEFAULT && bg == TERM_COLOR_DEFAULT && attr == TERM_ATTR_NORMAL) { return text; } QStringList attrs; if (fg != TERM_COLOR_DEFAULT) { attrs << QString("3%1").arg(fg); } if (bg != TERM_COLOR_DEFAULT) { attrs << QString("4%1").arg(bg); } if ((attr & TERM_ATTR_BOLD) == TERM_ATTR_BOLD) { attrs << "1"; } if ((attr & TERM_ATTR_HALF) == TERM_ATTR_HALF) { attrs << "2"; } if ((attr & TERM_ATTR_NOBOLD) == TERM_ATTR_NOBOLD) { attrs << "22"; } if ((attr & TERM_ATTR_ITALIC) == TERM_ATTR_ITALIC) { attrs << "3"; } if ((attr & TERM_ATTR_NOITALIC) == TERM_ATTR_NOITALIC) { attrs << "23"; } if ((attr & TERM_ATTR_UNDERLINE) == TERM_ATTR_UNDERLINE) { attrs << "4"; } if ((attr & TERM_ATTR_NOUNDERLINE) == TERM_ATTR_NOUNDERLINE) { attrs << "24"; } if ((attr & TERM_ATTR_BLINK) == TERM_ATTR_BLINK) { attrs << "5"; } if ((attr & TERM_ATTR_NOBLINK) == TERM_ATTR_NOBLINK) { attrs << "25"; } if ((attr & TERM_ATTR_REVERSE) == TERM_ATTR_REVERSE) { attrs << "7"; } if ((attr & TERM_ATTR_NOREVERSE) == TERM_ATTR_NOREVERSE) { attrs << "27"; } if (endResetDefault) { return QString("\033[%1m%2\033[0m").arg(attrs.join(";")).arg(text); } return QString("\033[%1m%2").arg(attrs.join(";")).arg(text); } inline QString term_bold(const QString &text, int attr = TERM_ATTR_BOLD) { return term_color(text,TERM_COLOR_DEFAULT,TERM_COLOR_DEFAULT,attr,true); } #endif // VTERMCOLOR_H ================================================ FILE: liteidex/src/utils/vterm/vtermwidget.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2020 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: vtermwidget.cpp // Creator: visualfc #include "vtermwidget.h" #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end #if defined(Q_OS_MAC) # define TermControlModifier Qt::MetaModifier #else # define TermControlModifier Qt::ControlModifier #endif VTermWidget::VTermWidget(LiteApi::IApplication *app, const QFont &font, QWidget *parent) : VTermWidgetBase(app,24,80,font,parent),m_liteApp(app) { this->setContextMenuPolicy(Qt::CustomContextMenu); m_process = PtyQt::createPtyProcess(IPtyProcess::AutoPty); m_contextMenu = new QMenu(this); m_bStarted = false; m_copy = new QAction(tr("Copy"),this); m_copy->setShortcut(QKeySequence::Copy); m_copy->setShortcutContext(Qt::WidgetShortcut); m_paste = new QAction(tr("Paste"),this); m_paste->setShortcut(QKeySequence::Paste); m_paste->setShortcutContext(Qt::WidgetShortcut); m_selectAll = new QAction(tr("Select All"),this); m_selectAll->setShortcut(QKeySequence::SelectAll); m_selectAll->setShortcutContext(Qt::WidgetShortcut); m_contextMenu->addAction(m_copy); m_contextMenu->addAction(m_paste); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_selectAll); connect(m_process,SIGNAL(started()),this,SIGNAL(started())); connect(m_process,SIGNAL(exited()),this,SIGNAL(exited())); connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuRequested(QPoint))); connect(m_copy,SIGNAL(triggered()),this,SLOT(copy())); connect(m_paste,SIGNAL(triggered()),this,SLOT(paste())); connect(m_selectAll,SIGNAL(triggered()),this,SLOT(selectAll())); } VTermWidget::~VTermWidget() { delete m_process; } bool VTermWidget::isAvailable() const { return m_process->isAvailable(); } void VTermWidget::start(const QString &program, const QStringList &arguments, const QString &workingDirectory, QStringList env) { m_bStarted = false; if (!m_process->isAvailable()) { qDebug() << "pty process invalid"; return; } bool b = m_process->startProcess(program,arguments,workingDirectory,env,qint16(m_cols),qint16(m_rows)); if (!b) { qDebug() << m_process->lastError(); return; } m_bStarted = true; connect(m_process->notifier(),SIGNAL(readyRead()),this,SLOT(readyRead())); connect(this,SIGNAL(sizeChanged(int,int)),this,SLOT(resizePty(int,int))); } bool VTermWidget::isStarted() const { return m_bStarted; } IPtyProcess *VTermWidget::process() const { return m_process; } void VTermWidget::copy() { QString text = selectedText(); if (!text.isEmpty()) { qApp->clipboard()->setText(text); } } void VTermWidget::paste() { QString text = qApp->clipboard()->text(); if (!text.isEmpty()) { m_process->write(text.toUtf8()); } } void VTermWidget::readyRead() { QByteArray data = m_process->readAll(); if (data.isEmpty()) { return; } this->inputWrite(data); } void VTermWidget::resizeEvent(QResizeEvent *e) { VTermWidgetBase::resizeEvent(e); } void VTermWidget::keyPressEvent(QKeyEvent *e) { if (!m_bStarted) { return; } //#ifdef Q_OS_WIN // WINDOWS copy & clear selection if (hasSelection() && (e == QKeySequence::Copy || e->key() == Qt::Key_Return)) { QString text = selectedText(); if (!text.isEmpty()) { qApp->clipboard()->setText(text); clearSelection(); return; } } //#else // if (e == QKeySequence::Copy) { // QString text = selectedText(); // if (!text.isEmpty()) { // qApp->clipboard()->setText(text); // } // return; // } //#endif else if (e == QKeySequence::Paste) { QString text = qApp->clipboard()->text(); if (!text.isEmpty()) { m_process->write(text.toUtf8()); } return; } else if (e == QKeySequence::SelectAll) { selectAll(); return; } if ((e->modifiers() & TermControlModifier) ) { QChar c(e->key()); char asciiVal = c.toUpper().toLatin1(); QByteArray array; if (asciiVal >= 0x41 && asciiVal <= 0x5f) { array.push_back(asciiVal-0x40); m_process->write(array); return; } } VTermWidgetBase::keyPressEvent(e); } void VTermWidget::resizePty(int rows, int cols) { if (!m_bStarted) { return; } m_process->resize(cols,rows); } void VTermWidget::contextMenuRequested(const QPoint &pt) { m_copy->setEnabled(this->hasSelection()); m_paste->setEnabled(!qApp->clipboard()->text().isEmpty()); QPoint globalPos = this->mapToGlobal(pt); m_contextMenu->popup(globalPos); } void VTermWidget::write_data(const char *buf, int len) { if (!m_bStarted) { return; } m_process->write(QByteArray(buf,len)); } ================================================ FILE: liteidex/src/utils/vterm/vtermwidget.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2020 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: vtermwidget.h // Creator: visualfc #ifndef VTERMWIDGET_H #define VTERMWIDGET_H #include "liteapi/liteapi.h" #include "vtermwidgetbase.h" #include "ptyqt/core/ptyqt.h" class QProcess; class QMenu; class QAction; class VTermWidget : public VTermWidgetBase { Q_OBJECT public: explicit VTermWidget(LiteApi::IApplication *app, const QFont &font, QWidget *parent); virtual ~VTermWidget(); bool isAvailable() const; void start(const QString &program, const QStringList &arguments, const QString &workingDirectory, QStringList env); bool isStarted() const; IPtyProcess *process() const; signals: void started(); void exited(); public slots: void copy(); void paste(); void readyRead(); void resizePty(int rows,int cols); void contextMenuRequested(const QPoint &pt); protected: virtual void write_data(const char *buf, int len); virtual void resizeEvent(QResizeEvent *e); virtual void keyPressEvent(QKeyEvent *e); protected: IPtyProcess *m_process; QMenu *m_contextMenu; bool m_bStarted; LiteApi::IApplication *m_liteApp; QAction *m_copy; QAction *m_paste; QAction *m_selectAll; }; #endif // VTERMWIDGET_H ================================================ FILE: liteidex/src/utils/vterm/vtermwidgetbase.cpp ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2020 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: vtermwidgetbase.cpp // Creator: visualfc #include "vtermwidgetbase.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //lite_memory_check_begin #if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) #define _CRTDBG_MAP_ALLOC #include #include #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #define new DEBUG_NEW #endif //lite_memory_check_end QColor toQColor(VTermColor *c, int alpha = 255) { return QColor(c->rgb.red, c->rgb.green, c->rgb.blue,alpha); }; bool attrs_is_equal(VTermScreenCellAttrs *a, VTermScreenCellAttrs *b) { return a->bold == b->bold && a->italic == b->italic && a->strike == b->strike && a->underline == b->underline; } int vterm_damage(VTermRect rect, void *user) { return static_cast(user)->vterm_damage(rect); } int vterm_moverect(VTermRect dest, VTermRect src, void *user) { return static_cast(user)->vterm_moverect(dest,src); } int vterm_movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user) { return static_cast(user)->vterm_movecursor(pos,oldpos,visible); } int vterm_settermprop(VTermProp prop, VTermValue *val, void *user) { return static_cast(user)->vterm_settermprop(prop,val); } int vterm_bell(void *user) { return static_cast(user)->vterm_bell(); } int vterm_resize(int rows, int cols, void *user) { return static_cast(user)->vterm_resize(rows,cols); } int vterm_sb_pushline(int cols, const VTermScreenCell *cells, void *user) { return static_cast(user)->vterm_sb_pushline(cols,cells); } int vterm_sb_popline(int cols, VTermScreenCell *cells, void *user) { return static_cast(user)->vterm_sb_popline(cols,cells); } static VTermScreenCallbacks vterm_screen_callbacks = { vterm_damage, vterm_moverect, vterm_movecursor, vterm_settermprop, vterm_bell, vterm_resize, vterm_sb_pushline, vterm_sb_popline, }; VTermWidgetBase::VTermWidgetBase(LiteApi::IApplication *app, int rows, int cols, const QFont &font, QWidget *parent) : QAbstractScrollArea(parent), m_liteApp(app) { this->setAttribute(Qt::WA_InputMethodEnabled,true); this->setFont(font); m_sbListCapacity = 10000; m_rows = rows; m_cols = cols; m_lineBuf.resize(m_cols); m_cursor.row = -1; m_cursor.col = -1; m_cursor.visible = false; m_ignoreScroll = false; m_darkMode = false; m_leftButtonPress = false; m_vt = vterm_new(rows,cols); m_screen = vterm_obtain_screen(m_vt); m_state = vterm_obtain_state(m_vt); vterm_screen_set_callbacks(m_screen,&vterm_screen_callbacks,this); vterm_set_utf8(m_vt,1); vterm_screen_set_damage_merge(m_screen, VTERM_DAMAGE_SCROLL); vterm_screen_enable_altscreen(m_screen,1); // static QColor colorTable[] = { // QColor(0x00,0x00,0x00), QColor(0xB2,0x18,0x18), // Black, Red // QColor(0x18,0xB2,0x18), QColor(0xB2,0x68,0x18), // Green, Yellow // QColor(0x18,0x18,0xB2), QColor(0xB2,0x18,0xB2), // Blue, Magenta // QColor(0x18,0xB2,0xB2), QColor(0xB2,0xB2,0xB2), // Cyan, White // QColor(0x68,0x68,0x68), QColor(0xFF,0x54,0x54), // QColor(0x54,0xFF,0x54), QColor(0xFF,0xFF,0x54), // QColor(0x54,0x54,0xFF), QColor(0xFF,0x54,0xFF), // QColor(0x54,0xFF,0xFF), QColor(0xFF,0xFF,0xFF), // }; // for (int i = 0; i < 16; i++) { // QColor c = colorTable[i]; // setPaletteColor(i,c.red(),c.green(),c.blue()); // } memset(&m_empytCell,0,sizeof (VTermScreenCell)); m_empytCell.chars[0] = '\0'; m_empytCell.width = 1; setDarkMode(false); vterm_screen_reset(m_screen, 1); this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); m_ptOffset = QPoint(4,2); connect(this,SIGNAL(selectionChanged()),viewport(),SLOT(update())); } void VTermWidgetBase::setPaletteColor(int index, uint8_t r, uint8_t g, uint8_t b) { VTermColor col; vterm_color_rgb(&col, r, g, b); vterm_state_set_palette_color(m_state, index, &col); } VTermWidgetBase::~VTermWidgetBase() { for (int i = 0; i < m_sbList.size(); ++i) { delete m_sbList[i]; } m_sbList.clear(); vterm_free(m_vt); } int VTermWidgetBase::vterm_damage(VTermRect rect) { // QRect rc = mapVTermRectToRect(rect); // qDebug() << "vterm_damage1"<< rect.start_row << rect.end_row << rect.start_col << rect.end_col; // rect = mapRectToVTermRect(rc); // qDebug() << "vterm_damage2"<< rect.start_row << rect.end_row << rect.start_col << rect.end_col; this->clearSelection(); viewport()->update(mapVTermRectToRect(rect)); return 1; } QRect VTermWidgetBase::mapVTermRectToRect(VTermRect rect) { QPoint topLeft = QPoint( rect.start_col * m_cellSize.width(), rect.start_row * m_cellSize.height()); QPoint bottomRight = QPoint( (rect.end_col+1) * m_cellSize.width(), (rect.end_row+1) * m_cellSize.height()); topLeft += m_ptOffset; bottomRight += m_ptOffset; return QRect(topLeft,bottomRight); } VTermRect VTermWidgetBase::mapRectToVTermRect(QRect rect) { VTermRect rc; rect.translate(-m_ptOffset); rc.start_row = rect.top() /m_cellSize.height(); rc.end_row = rect.bottom()/m_cellSize.height()-1; rc.start_col = rect.left()/m_cellSize.width(); rc.end_col = rect.right()/m_cellSize.width()-1; return rc; } QPoint VTermWidgetBase::mapPointToCell(QPoint pt) { int row = (pt.y()-m_ptOffset.y())/m_cellSize.height(); int col = (pt.x()-m_ptOffset.x())/m_cellSize.width(); return QPoint(col,row+topVisibleRow()); } int VTermWidgetBase::scrollbackRowSize() const { return m_sbList.size(); } int VTermWidgetBase::termRows() const { return m_rows; } int VTermWidgetBase::termCols() const { return m_cols; } int VTermWidgetBase::topVisibleRow() const { return this->verticalScrollBar()->value()-m_sbList.size(); } int VTermWidgetBase::allRowSize() const { return m_sbList.size()+m_rows; } int VTermWidgetBase::startRow() const { return -scrollbackRowSize(); } int VTermWidgetBase::endRow() const { return m_rows; } QString VTermWidgetBase::getLineText(int row, int start_col, int end_col) const { VTermRect rc; rc.start_row = row; rc.end_row = row+1; rc.start_col = start_col; rc.end_col = end_col; size_t len = end_col-start_col; size_t n = _get_chars(m_screen,0, (void*)(&m_lineBuf[0]),len,rc); return QString::fromUcs4(&m_lineBuf[0],n); } QString VTermWidgetBase::selectedText() const { if (m_selection.isNull()) { return QString(); } if (m_selection.height() == 1) { return getLineText(m_selection.top(),m_selection.left(),m_selection.right()); } int start_row = m_selection.top(); int end_row = m_selection.bottom(); QStringList lines; lines.append(getLineText(start_row,m_selection.left(),m_cols)); for (int row = start_row+1; row < end_row; row++) { lines.append(getLineText(row,0,m_cols)); } lines.append(getLineText(end_row,0,m_selection.right())); #ifdef Q_OS_WIN QString sep = "\r\n"; #else QString sep = "\n"; #endif return lines.join(sep); } QRect VTermWidgetBase::selectedRect() const { return m_selection; } int VTermWidgetBase::vterm_moverect(VTermRect dest, VTermRect src) { // qDebug() << "vterm_moverect" << dest.start_row << dest.end_row << src.start_row << src.end_row; //viewport()->update(); QRegion re; re += mapVTermRectToRect(dest); re += mapVTermRectToRect(src); viewport()->update(re); return 1; } int VTermWidgetBase::vterm_movecursor(VTermPos pos, VTermPos oldpos, int visible) { // qDebug() << "vterm_movecursor" << pos.row << pos.col << oldpos.row << oldpos.col+1; m_cursor.row = pos.row; m_cursor.col = pos.col; m_cursor.visible = visible; QRegion re; VTermRect rc1 = {pos.row,pos.row,pos.col,pos.col+1}; re += mapVTermRectToRect(rc1); VTermRect rc2 = {oldpos.row,oldpos.row,oldpos.col,oldpos.col+1}; re += mapVTermRectToRect(rc2); viewport()->update(re); return 1; } /* VTERM_PROP_CURSORVISIBLE = 1, // bool VTERM_PROP_CURSORBLINK, // bool VTERM_PROP_ALTSCREEN, // bool VTERM_PROP_TITLE, // string VTERM_PROP_ICONNAME, // string VTERM_PROP_REVERSE, // bool VTERM_PROP_CURSORSHAPE, // number VTERM_PROP_MOUSE, // number */ int VTermWidgetBase::vterm_settermprop(VTermProp prop, VTermValue *val) { //qDebug() << "vterm_settermprop" << prop << val->number; switch (prop) { case VTERM_PROP_CURSORVISIBLE: m_cursor.visible = val->boolean; break; case VTERM_PROP_CURSORBLINK: m_cursor.blink = val->boolean; break; case VTERM_PROP_ALTSCREEN: m_altScreen = val->boolean; this->verticalScrollBar()->setEnabled(!m_altScreen); //this->verticalScrollBar()->setRange(0,m_altScreen ? 0 : m_sbList.size()); break; case VTERM_PROP_TITLE: emit titleChanged(QString::fromUtf8(val->string)); break; case VTERM_PROP_ICONNAME: emit iconNameChanged(QString::fromUtf8(val->string)); break; case VTERM_PROP_REVERSE: // qDebug() << "VTERM_PROP_REVERSE" << val->number; break; case VTERM_PROP_CURSORSHAPE: m_cursor.shape = val->number; break; case VTERM_PROP_MOUSE: m_propMouse = val->number; break; default: break; } //this->viewport()->update(); return 1; } int VTermWidgetBase::vterm_bell() { return 1; } int VTermWidgetBase::vterm_resize(int rows, int cols) { m_rows = rows; m_cols = cols; m_lineBuf.resize(m_cols); //qDebug() << "vterm_resize" << rows << cols << m_cellWidth << m_cellHeight; emit sizeChanged(m_rows,m_cols); return 1; } int VTermWidgetBase::vterm_sb_pushline(int cols, const VTermScreenCell *cells) { // qDebug() << "vterm_sb_pushline" << cols; ScrollbackLine *sb = new ScrollbackLine; sb->cols = cols; sb->cells.resize(cols); memcpy(&sb->cells[0],cells,sizeof(cells[0])*size_t(cols)); m_sbList.push_front(sb); while (m_sbList.size() > m_sbListCapacity) { m_sbList.pop_back(); } this->verticalScrollBar()->setRange(0,m_sbList.size()); this->verticalScrollBar()->setValue(this->verticalScrollBar()->maximum()); return 1; } int VTermWidgetBase::vterm_sb_popline(int cols, VTermScreenCell *cells) { // qDebug() << "vterm_sb_popline" << cols; if (m_sbList.isEmpty()) { return 0; } ScrollbackLine *sb = m_sbList.front(); int ncells = sb->cols; if (ncells > cols) { ncells = cols; } memcpy(cells, &sb->cells[0], sizeof(cells[0]) * size_t(ncells)); if (cols > ncells) { memset(&cells[ncells],0,sizeof(cells[0])*size_t(cols-ncells)); } for (int i = ncells; i < cols; ++i) { cells[i].width = 1; cells[i].fg = m_defaultFg; cells[i].bg = m_defaultBg; } m_sbList.pop_front(); delete sb; this->verticalScrollBar()->setRange(0,m_sbList.size()); return 1; } bool VTermWidgetBase::fetchCell(int row, int col, VTermScreenCell *cell) const { if (row < 0) { if (m_sbList.isEmpty()) { *cell = m_empytCell; return false; } ScrollbackLine *sb = m_sbList.at(-row-1); if (col < sb->cols) { *cell = sb->cells[col]; } else { *cell = m_empytCell; return false; } } else { vterm_screen_get_cell(m_screen,VTermPos{row,col},cell); } vterm_screen_convert_color_to_rgb(m_screen, &cell->fg); vterm_screen_convert_color_to_rgb(m_screen, &cell->bg); return true; } bool VTermWidgetBase::event(QEvent *e) { if (e->type() == QEvent::KeyPress) { QKeyEvent *ke = static_cast(e); if (ke->key() == Qt::Key_Tab) { keyPressEvent(ke); return true; } } return QAbstractScrollArea::event(e); } void VTermWidgetBase::setFont(const QFont &fnt) { QFontMetrics fm(fnt); #ifdef Q_OS_WIN m_cellSize.setWidth(fm.averageCharWidth()); #else m_cellSize.setWidth(fm.maxWidth()); #endif m_cellSize.setHeight(fm.height()); QAbstractScrollArea::setFont(fnt); } void VTermWidgetBase::setTermSize(int rows, int cols) { m_ignoreScroll = true; vterm_set_size(m_vt,rows,cols); vterm_screen_flush_damage(m_screen); m_ignoreScroll = false; int width = rows*m_cellSize.width(); int height = cols*m_cellSize.height(); this->viewport()->setMinimumSize(width,height); } void VTermWidgetBase::inputWrite(const QByteArray &data) { vterm_input_write(m_vt,data.data(),size_t(data.length())); vterm_screen_flush_damage(m_screen); //this->viewport()->update(); } void VTermWidgetBase::inputKey(Qt::Key _key, Qt::KeyboardModifier _mod) { VTermModifier mod = qt_to_vtermModifier(_mod); VTermKey key = qt_to_vtermKey(_key,_mod & Qt::KeypadModifier); if (key != VTERM_KEY_NONE) { if (key == VTERM_KEY_ESCAPE) mod = VTERM_MOD_NONE; vterm_keyboard_key(m_vt, key, mod); } flushOutput(); } void VTermWidgetBase::setDarkMode(bool b) { m_darkMode = b; if (m_darkMode) { vterm_color_rgb(&m_defaultBg,30,30,30); vterm_color_rgb(&m_defaultFg,200,200,200); m_clrSelect = QColor(86,86,84); } else { vterm_color_rgb(&m_defaultBg,255,255,255); vterm_color_rgb(&m_defaultFg,0,0,0); m_clrSelect = QColor(179,215,253); } m_clrCursor = toQColor(&m_defaultFg,128); vterm_state_set_default_colors(m_state,&m_defaultFg,&m_defaultBg); m_empytCell.bg = m_defaultBg; m_empytCell.fg = m_defaultFg; vterm_screen_reset(m_screen, 1); } bool VTermWidgetBase::isDarkMode() const { return m_darkMode; } void VTermWidgetBase::paintEvent(QPaintEvent *e) { QPainter p(viewport()); p.fillRect(this->rect(),toQColor(&m_defaultBg)); // qDebug() << e->region().rectCount(); // for (QRegion::const_iterator it=e->region().begin(); it != e->region().end(); it++) { // //p.fillRect(*it,toQColor(&m_defaultBg)); // //p.setClipRect(*it); // VTermRect rc = qrect_to_vtermrect(*it); // if (rc.end_row == rc.start_row) { // rc.end_row++; // } // qDebug() << "update" << rc.start_row << rc.end_row << rc.start_col << rc.end_col << "-" << m_rows << m_cols; // drawScreenCell(p,rc); // } // return; // //qDebug() << "check" << this->verticalScrollBar()->value()-m_sbList.size(); VTermRect rect; rect.start_row = topVisibleRow(); rect.end_row = rect.start_row+m_rows; rect.start_col = 0; rect.end_col = m_cols; //qDebug() << "drawScreenCell" << rect.start_row << rect.end_row << rect.start_col << rect.end_col; drawScreenCell(p,rect); } void VTermWidgetBase::drawScreenCell(QPainter &p, VTermRect rect) { QFont fnt = this->font(); QFontMetrics fm(fnt); p.setPen(toQColor(&m_defaultFg)); p.setBrush(toQColor(&m_defaultBg)); VTermScreenCell cell; int xoff = m_ptOffset.x();//(this->width()-this->verticalScrollBar()->sizeHint().width() -m_cellSize.width()*m_cols)/2; int yoff = 1-fm.descent()+m_ptOffset.y(); QRect cursorRect; QPen oldPen = p.pen(); QBrush oldBrush = p.brush(); for (int row = rect.start_row; row < rect.end_row; row++) { int x = xoff; int y = yoff+(row-rect.start_row)*m_cellSize.height(); QString text; VTermColor last_bg = m_defaultBg; VTermColor last_fg = m_defaultFg; VTermScreenCellAttrs last_attr = m_empytCell.attrs; QTextLayout::FormatRange lastFR; QFont lastFnt = this->font(); p.setPen(oldPen); p.setBrush(oldBrush); p.setFont(this->font()); for (int col = rect.start_col; col < rect.end_col; col++) { bool b = fetchCell(row,col,&cell); VTermColor *bg = &cell.bg; VTermColor *fg = &cell.fg; if (cell.attrs.reverse) { qSwap(bg,fg); } last_fg = *fg; last_bg = *bg; QString c; if (!b || !cell.chars[0]) { text += ' '; cell.width = 1; c = ' '; } else { c = QString::fromUcs4(cell.chars); text += c; } QRect rc(x+col*m_cellSize.width(),y+fm.descent(),m_cellSize.width()*cell.width,m_cellSize.height()); if (m_cursor.visible && m_cursor.row == row && m_cursor.col == col) { cursorRect = rc; } if (!attrs_is_equal(&last_attr,&cell.attrs)) { QFont fnt = this->font(); if (cell.attrs.bold) { fnt.setWeight(QFont::Bold); } if (cell.attrs.italic) { fnt.setItalic(true); } if (cell.attrs.strike) { fnt.setStrikeOut(true); } if (cell.attrs.underline) { fnt.setUnderline(true); } p.setFont(fnt); } last_attr = cell.attrs; if (!vterm_color_is_equal(&m_defaultBg,bg)) { p.fillRect(rc,toQColor(bg)); } if (!vterm_color_is_equal(&m_defaultFg,fg)) { p.setPen(toQColor(fg)); } else { p.setPen(oldPen); } if (isSelection(row,col)) { p.fillRect(rc,m_clrSelect); } p.drawText(x+col*m_cellSize.width(),y+m_cellSize.height(),c); if (cell.width > 1) { col += cell.width-1; } } } if (cursorRect.isEmpty()) { return; } // VTERM_PROP_CURSORSHAPE_BLOCK = 1, // VTERM_PROP_CURSORSHAPE_UNDERLINE, // VTERM_PROP_CURSORSHAPE_BAR_LEFT, switch (m_cursor.shape) { case VTERM_PROP_CURSORSHAPE_BLOCK: break; case VTERM_PROP_CURSORSHAPE_UNDERLINE: cursorRect.setTop(cursorRect.bottom()-2); break; case VTERM_PROP_CURSORSHAPE_BAR_LEFT: cursorRect.setRight(cursorRect.left()+2); break; } //p.fillRect(cursorRect,QColor(40,40,40,128)); if (this->hasFocus()) { p.fillRect(cursorRect,m_clrCursor); } else { p.setPen(m_clrCursor); p.drawRect(cursorRect); } } void VTermWidgetBase::keyPressEvent(QKeyEvent *e) { VTermModifier mod = qt_to_vtermModifier(e->modifiers()); VTermKey key = qt_to_vtermKey(e->key(),e->modifiers() & Qt::KeypadModifier); if (key != VTERM_KEY_NONE) { if (key == VTERM_KEY_ESCAPE) mod = VTERM_MOD_NONE; vterm_keyboard_key(m_vt, key, mod); } else if (e->text().length()) { vterm_keyboard_unichar( m_vt, e->text().toUcs4()[0], mod); } flushOutput(); } void VTermWidgetBase::mouseMoveEvent(QMouseEvent *e) { // vterm_mouse_move(m_vt,row,col,qt_to_vtermModifier(e->modifiers())); // this->viewport()->update(); if (m_leftButtonPress) { updateSelection(e->pos()); viewport()->update(); } } void VTermWidgetBase::mousePressEvent(QMouseEvent *e) { // vterm_mouse_button(m_vt,e->button(),true,qt_to_vtermModifier(e->modifiers())); // this->viewport()->update(); if (e->button() == Qt::LeftButton) { if (m_trippleClickTimer.isActive() && ( (e->pos() - m_trippleClickPoint).manhattanLength() < QApplication::startDragDistance())) { QPoint cell = mapPointToCell(e->pos()); setSelectionByRow(cell.y()); m_trippleClickTimer.stop(); } else { this->clearSelection(); } m_ptOrg = e->pos(); m_leftButtonPress = true; } } void VTermWidgetBase::updateSelection(QPoint scenePos) { QPoint start = mapPointToCell(m_ptOrg); QPoint end = mapPointToCell(scenePos); if (start != end) { setSelection(start, end); } } void VTermWidgetBase::mouseReleaseEvent(QMouseEvent *e) { // vterm_mouse_button(m_vt,e->button(),false,qt_to_vtermModifier(e->modifiers())); // this->viewport()->update(); if (e->button() == Qt::LeftButton) { this->updateSelection(e->pos()); m_leftButtonPress = false; } } void VTermWidgetBase::mouseDoubleClickEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { m_trippleClickPoint = e->pos(); m_trippleClickTimer.start(QApplication::doubleClickInterval(),this); QPoint cell = mapPointToCell(e->pos()); setSelectionUnderWord(cell.y(),cell.x()); } } void VTermWidgetBase::timerEvent(QTimerEvent *e) { if (e->timerId() == m_trippleClickTimer.timerId()) { m_trippleClickTimer.stop(); } } void VTermWidgetBase::inputMethodEvent(QInputMethodEvent *e) { QVector str = e->commitString().toUcs4(); foreach(uint c, str) { vterm_keyboard_unichar(m_vt,c,VTERM_MOD_NONE); } flushOutput(); viewport()->update(); } void VTermWidgetBase::resizeEvent(QResizeEvent *e) { e->accept(); // save scroll int rows = (e->size().height()-m_ptOffset.y()*2) /m_cellSize.height(); int cols = (e->size().width()-this->verticalScrollBar()->sizeHint().width() - m_ptOffset.x()*2) /m_cellSize.width(); int oldMax = this->verticalScrollBar()->maximum(); int oldValue = this->verticalScrollBar()->value(); m_ignoreScroll = true; vterm_set_size(m_vt,rows,cols); vterm_screen_flush_damage(m_screen); m_ignoreScroll = false; // restore scroll int newMax = this->verticalScrollBar()->maximum(); if (newMax!=0 && oldMax!=0) { int newValue = oldValue*newMax/oldMax; this->verticalScrollBar()->setValue(newValue); } QAbstractScrollArea::resizeEvent(e); } void VTermWidgetBase::focusInEvent(QFocusEvent *e) { e->accept(); viewport()->update(); } void VTermWidgetBase::focusOutEvent(QFocusEvent *e) { e->accept(); viewport()->update(); } void VTermWidgetBase::flushOutput() { size_t len = vterm_output_read(m_vt, textbuf, sizeof(textbuf)); if (len > 0) { this->write_data(textbuf,int(len)); } } void VTermWidgetBase::write_data(const char *buf, int len) { qDebug() << "output" << QString::fromUtf8(buf,int(len)); } void VTermWidgetBase::setSelection(QPoint cellStart, QPoint cellEnd) { if (cellStart.y() > cellEnd.y()) qSwap(cellStart, cellEnd); if (cellStart.y() == cellEnd.y() && cellStart.x() > cellEnd.x()) qSwap(cellStart, cellEnd); if (cellStart.x() < 0) cellStart.rx() = 0; if (cellStart.y() < startRow()) cellStart.ry() = startRow(); if (cellEnd.x() > m_cols) cellEnd.rx() = m_cols; if (cellEnd.y() > endRow()) cellEnd.ry() = endRow(); if (cellStart.y() >= m_rows) { m_selection = QRect(); } else { m_selection = QRect(cellStart, cellEnd); } m_selected.start_row = cellStart.y()+topVisibleRow(); m_selected.start_col = cellStart.x(); m_selected.end_col = cellStart.y(); m_selected.end_row = cellEnd.y()+topVisibleRow(); emit selectionChanged(); } void VTermWidgetBase::setSelectionByRow(int row) { if (row < startRow() || row >= endRow()) { clearSelection(); return; } m_selection = QRect(0,row,m_cols+1,1); emit selectionChanged(); } bool VTermWidgetBase::adjustFetchCell(int row, int *col, VTermScreenCell *cell) { bool b = this->fetchCell(row,*col,cell); if (!b) { return false; } if (cell->chars[0] == uint32_t(-1)) { bool b = this->fetchCell(row,*col-1,cell); if (b) { *col = *col-1; return true; } } return b; } void VTermWidgetBase::setSelectionUnderWord(int row, int col) { if (row < startRow() || row >= endRow() || col < 0 || col >= m_cols) { clearSelection(); return; } VTermScreenCell cell; this->adjustFetchCell(row,&col,&cell); if (!cell.chars[0]) { int ncol = col+1; for (; ncol < m_cols; ++ncol) { this->fetchCell(row,ncol,&cell); if (cell.chars[0]) { break; } } int pcol = col-1; for (;pcol >= 0;--pcol) { this->fetchCell(row,pcol,&cell); if (cell.chars[0]) { break; } } setSelection(QPoint(pcol+1,row),QPoint(ncol,row)); } else { bool isSpace = QString::fromUcs4(cell.chars)[0].isSpace(); int width = cell.width; int ncol = col+width; for (; ncol < m_cols;) { this->fetchCell(row,ncol,&cell); if (!cell.chars[0]) { break; } QChar c = QString::fromUcs4(cell.chars)[0]; if (isSpace && !c.isSpace()) { break; } else if (!isSpace && c.isSpace()) { break; } ncol += cell.width; } int pcol = col-1; for (; pcol >= 0;--pcol) { this->adjustFetchCell(row,&pcol,&cell); if (!cell.chars[0]) { break; } QChar c = QString::fromUcs4(cell.chars)[0]; if (isSpace && !c.isSpace()) { break; } else if (!isSpace && c.isSpace()) { break; } } setSelection(QPoint(pcol+cell.width,row),QPoint(ncol,row)); } } void VTermWidgetBase::selectAll() { m_selection = QRect(0,-scrollbackRowSize(),m_cols+1,allRowSize()); emit selectionChanged(); } void VTermWidgetBase::clearSelection() { if (m_selection.isNull()) return; m_selection = QRect(); emit selectionChanged(); } bool VTermWidgetBase::hasSelection() const { return !m_selection.isNull(); } bool VTermWidgetBase::isSelection(int row, int col) const { if (m_selection.isNull()) { return false; } if (m_selection.height() == 1) { if (row == m_selection.top() && col >= m_selection.left() && col < m_selection.right()) { return true; } } else { if (m_selection.top() == row) { if (col >= m_selection.left()) { return true; } } else if (m_selection.bottom() == row) { if (col < m_selection.right()) { return true; } } else if (row > m_selection.top() && row < m_selection.bottom()) { return true; } } return false; } VTermModifier qt_to_vtermModifier(Qt::KeyboardModifiers mod) { int ret = VTERM_MOD_NONE; if (mod & Qt::SHIFT) ret |= VTERM_MOD_SHIFT; if (mod & Qt::ALT) ret |= VTERM_MOD_ALT; if (mod & Qt::CTRL) ret |= VTERM_MOD_CTRL; return static_cast(ret); } VTermKey qt_to_vtermKey(int key, bool keypad) { if (key >= Qt::Key_F1 && key <= Qt::Key_F35) return static_cast(VTERM_KEY_FUNCTION_0 + key - Qt::Key_F1 + 1); switch (key) { case Qt::Key_Return: return VTERM_KEY_ENTER; case Qt::Key_Tab: return VTERM_KEY_TAB; case Qt::Key_Backspace: return VTERM_KEY_BACKSPACE; case Qt::Key_Escape: return VTERM_KEY_ESCAPE; case Qt::Key_Up: return VTERM_KEY_UP; case Qt::Key_Down: return VTERM_KEY_DOWN; case Qt::Key_Left: return VTERM_KEY_LEFT; case Qt::Key_Right: return VTERM_KEY_RIGHT; case Qt::Key_Insert: return VTERM_KEY_INS; case Qt::Key_Delete: return VTERM_KEY_DEL; case Qt::Key_Home: return VTERM_KEY_HOME; case Qt::Key_End: return VTERM_KEY_END; case Qt::Key_PageUp: return VTERM_KEY_PAGEUP; case Qt::Key_PageDown: return VTERM_KEY_PAGEDOWN; case Qt::Key_multiply: return keypad ? VTERM_KEY_KP_MULT : VTERM_KEY_NONE; case Qt::Key_Plus: return keypad ? VTERM_KEY_KP_PLUS : VTERM_KEY_NONE; case Qt::Key_Comma: return keypad ? VTERM_KEY_KP_COMMA : VTERM_KEY_NONE; case Qt::Key_Minus: return keypad ? VTERM_KEY_KP_MINUS : VTERM_KEY_NONE; case Qt::Key_Period: return keypad ? VTERM_KEY_KP_PERIOD : VTERM_KEY_NONE; case Qt::Key_Slash: return keypad ? VTERM_KEY_KP_DIVIDE : VTERM_KEY_NONE; case Qt::Key_Enter: return keypad ? VTERM_KEY_KP_ENTER : VTERM_KEY_NONE; case Qt::Key_Equal: return keypad ? VTERM_KEY_KP_EQUAL : VTERM_KEY_NONE; default: return VTERM_KEY_NONE; } } #define UNICODE_TAB '\t' #define UNICODE_SPACE 0x20 #define UNICODE_LINEFEED 0x0a static inline unsigned int utf8_seqlen(long codepoint) { if(codepoint < 0x0000080) return 1; if(codepoint < 0x0000800) return 2; if(codepoint < 0x0010000) return 3; if(codepoint < 0x0200000) return 4; if(codepoint < 0x4000000) return 5; return 6; } /* Does NOT NUL-terminate the buffer */ static int fill_utf8(long codepoint, char *str) { int nbytes = utf8_seqlen(codepoint); // This is easier done backwards int b = nbytes; while(b > 1) { b--; str[b] = 0x80 | (codepoint & 0x3f); codepoint >>= 6; } switch(nbytes) { case 1: str[0] = (codepoint & 0x7f); break; case 2: str[0] = 0xc0 | (codepoint & 0x1f); break; case 3: str[0] = 0xe0 | (codepoint & 0x0f); break; case 4: str[0] = 0xf0 | (codepoint & 0x07); break; case 5: str[0] = 0xf8 | (codepoint & 0x03); break; case 6: str[0] = 0xfc | (codepoint & 0x01); break; } return nbytes; } size_t VTermWidgetBase::_get_chars(const VTermScreen *screen, const int utf8, void *buffer, size_t len, const VTermRect rect) const { size_t outpos = 0; int padding = 0; #define PUT(c) \ if(utf8) { \ size_t thislen = utf8_seqlen(c); \ if(buffer && outpos + thislen <= len) \ outpos += fill_utf8((c), (char *)buffer + outpos); \ else \ outpos += thislen; \ } \ else { \ if(buffer && outpos + 1 <= len) \ ((uint32_t*)buffer)[outpos++] = (c); \ else \ outpos++; \ } int row,col,i; for(row = rect.start_row; row < rect.end_row; row++) { for(col = rect.start_col; col < rect.end_col; col++) { VTermScreenCell cell; fetchCell(row, col,&cell); if(cell.chars[0] == 0) // Erased cell, might need a space padding++; else if(cell.chars[0] == (uint32_t)-1) // Gap behind a double-width char, do nothing ; else { while(padding > 0) { PUT(UNICODE_TAB); padding-=8; } padding = 0; for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell.chars[i]; i++) { PUT(cell.chars[i]); } } } if(row < rect.end_row - 1) { PUT(UNICODE_LINEFEED); padding = 0; } } return outpos; } ================================================ FILE: liteidex/src/utils/vterm/vtermwidgetbase.h ================================================ /************************************************************************** ** This file is part of LiteIDE ** ** Copyright (c) 2011-2020 LiteIDE. All rights reserved. ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** In addition, as a special exception, that plugins developed for LiteIDE, ** are allowed to remain closed sourced and can be distributed under any license . ** These rights are included in the file LGPL_EXCEPTION.txt in this package. ** **************************************************************************/ // Module: vtermwidgetbase.h // Creator: visualfc #ifndef VTERMWIDGETBASE_H #define VTERMWIDGETBASE_H extern "C" { #include "libvterm/include/vterm.h" } #include "liteapi/liteapi.h" #include #include #include typedef struct { int row; int col; bool visible; bool blink; int shape; } QVTermCursor; typedef struct { int cols; QVector cells; QString text; } ScrollbackLine; class VTermWidgetBase : public QAbstractScrollArea { Q_OBJECT public: VTermWidgetBase(LiteApi::IApplication *app,int rows, int cols, const QFont &font, QWidget *parent); virtual ~VTermWidgetBase(); void setFont(const QFont &fnt); void setTermSize(int rows, int cols); void inputWrite(const QByteArray &data); void inputKey(Qt::Key key, Qt::KeyboardModifier mod); void setDarkMode(bool b); bool isDarkMode() const; public: int vterm_damage(VTermRect rect); int vterm_moverect(VTermRect dest, VTermRect src); int vterm_movecursor(VTermPos pos, VTermPos oldpos, int visible); int vterm_settermprop(VTermProp prop, VTermValue *val); int vterm_bell(); int vterm_resize(int rows, int cols); int vterm_sb_pushline(int cols, const VTermScreenCell *cells); int vterm_sb_popline(int cols, VTermScreenCell *cells); void setPaletteColor(int index, uint8_t r, uint8_t g, uint8_t b); QRect mapVTermRectToRect(VTermRect rect); VTermRect mapRectToVTermRect(QRect rect); public: QPoint mapPointToCell(QPoint pt); int allRowSize() const; int startRow() const; int endRow() const; int topVisibleRow() const; int scrollbackRowSize() const; int termRows() const; int termCols() const; QString selectedText() const; QRect selectedRect() const; void setSelection(QPoint cellStart, QPoint cellEnd); void setSelectionByRow(int row); void setSelectionUnderWord(int row, int col); bool hasSelection() const; bool isSelection(int row, int col) const; bool adjustFetchCell(int row, int *col, VTermScreenCell *cell); QString getLineText(int row, int start_col, int end_col) const; size_t _get_chars(const VTermScreen *screen, const int utf8, void *buffer, size_t len, const VTermRect rect) const; public slots: void selectAll(); void clearSelection(); protected: void updateSelection(QPoint scenePos); protected: bool fetchCell(int row, int col, VTermScreenCell *cell) const; bool event(QEvent *e); void paintEvent(QPaintEvent *e); void keyPressEvent(QKeyEvent *e); void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); void mouseDoubleClickEvent(QMouseEvent *e); void timerEvent(QTimerEvent *e); void inputMethodEvent(QInputMethodEvent *e); void resizeEvent(QResizeEvent *e); void focusInEvent(QFocusEvent *e); void focusOutEvent(QFocusEvent *e); void flushOutput(); virtual void write_data(const char *buf, int len); void drawScreenCell(QPainter &p, VTermRect rect); signals: void iconNameChanged(QString); void titleChanged(QString); void sizeChanged(int rows, int cols); void output(char *buf, int len); void selectionChanged(); protected: LiteApi::IApplication *m_liteApp; int m_rows; int m_cols; int m_propMouse; int m_sbListCapacity; bool m_altScreen; bool m_ignoreScroll; bool m_darkMode; bool m_leftButtonPress; char textbuf[0x1fff]; std::vector m_lineBuf; VTerm *m_vt; VTermScreen *m_screen; VTermState *m_state; VTermColor m_defaultFg; VTermColor m_defaultBg; QColor m_clrSelect; QColor m_clrCursor; QSize m_cellSize; QVTermCursor m_cursor; QList m_sbList; VTermScreenCell m_empytCell; VTermRect m_selected; QRect m_selection; QPoint m_ptOrg; QPoint m_ptOffset; QBasicTimer m_trippleClickTimer; QPoint m_trippleClickPoint; }; VTermModifier qt_to_vtermModifier(Qt::KeyboardModifiers mod); VTermKey qt_to_vtermKey(int key, bool keypad); #endif // VTERMWIDGETBASE_H ================================================ FILE: liteidex/windows_deploy.cmd ================================================ @echo on copy LICENSE.LGPL liteide copy LGPL_EXCEPTION.TXT liteide copy ..\README.md liteide copy bin\gocode.exe liteide\bin copy bin\gotools.exe liteide\bin copy bin\gomodifytags.exe liteide\bin xcopy deploy liteide\share\liteide /e /y /i xcopy os_deploy\windows liteide\share\liteide /e /y /i