diff --git a/SciTE4AutoHotkey.sln b/SciTE4AutoHotkey.sln new file mode 100644 index 0000000..e7be725 --- /dev/null +++ b/SciTE4AutoHotkey.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SciTE", "scite\SciTE.vcxproj", "{2DC33974-65FD-4DAF-B522-ACA7A7AC9721}" + ProjectSection(ProjectDependencies) = postProject + {8FBDA743-F364-430E-BC7E-207D7469215A} = {8FBDA743-F364-430E-BC7E-207D7469215A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scintilla", "Scintilla\Scintilla.vcxproj", "{8FBDA743-F364-430E-BC7E-207D7469215A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Debug|Win32.ActiveCfg = Debug|Win32 + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Debug|Win32.Build.0 = Debug|Win32 + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Debug|x64.ActiveCfg = Debug|x64 + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Debug|x64.Build.0 = Debug|x64 + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Release|Win32.ActiveCfg = Release|Win32 + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Release|Win32.Build.0 = Release|Win32 + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Release|x64.ActiveCfg = Release|x64 + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721}.Release|x64.Build.0 = Release|x64 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Debug|Win32.Build.0 = Debug|Win32 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Debug|x64.ActiveCfg = Debug|x64 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Debug|x64.Build.0 = Debug|x64 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Release|Win32.ActiveCfg = Release|Win32 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Release|Win32.Build.0 = Release|Win32 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Release|x64.ActiveCfg = Release|x64 + {8FBDA743-F364-430E-BC7E-207D7469215A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/scintilla/Scintilla.vcxproj b/scintilla/Scintilla.vcxproj new file mode 100644 index 0000000..385734f --- /dev/null +++ b/scintilla/Scintilla.vcxproj @@ -0,0 +1,369 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8FBDA743-F364-430E-BC7E-207D7469215A} + Win32Proj + Scintilla + $(VCTargetsPath11) + + + + DynamicLibrary + true + Unicode + v110_xp + + + DynamicLibrary + true + Unicode + v110_xp + + + DynamicLibrary + false + true + Unicode + v110_xp + + + DynamicLibrary + false + true + Unicode + v110_xp + + + + + + + + + + + + + + + + + + + true + + + + true + $(SolutionDir)debug\x64\ + $(SolutionDir)debug\x64\temp\Scintilla\ + SciLexer + $(ProjectDir)include;$(ProjectDir)src;$(ProjectDir)lexlib;$(IncludePath) + + + + false + $(ProjectDir)include;$(ProjectDir)src;$(ProjectDir)lexlib;$(IncludePath) + + + $(SolutionDir)bin\x86\ + $(SolutionDir)obj\x86\Scintilla\ + SciLexer + + + false + $(ProjectDir)include;$(ProjectDir)src;$(ProjectDir)lexlib;$(IncludePath) + + + $(SolutionDir)bin\x64\ + $(SolutionDir)obj\x64\Scintilla\ + SciLexer + $(VCInstallDir)..\Common7\IDE;$(ExecutablePath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SCINTILLA_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;SCI_LEXER;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + Windows + true + imm32.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;SCI_LEXER;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + false + true + NoExtensions + + + Windows + false + true + true + imm32.lib;%(AdditionalDependencies) + false + false + + + + + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;SCI_LEXER;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + false + true + + + Windows + false + true + true + imm32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scintilla/Scintilla.vcxproj.filters b/scintilla/Scintilla.vcxproj.filters new file mode 100644 index 0000000..8266563 --- /dev/null +++ b/scintilla/Scintilla.vcxproj.filters @@ -0,0 +1,562 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h index 18cdb98..2d742cb 100644 --- a/scintilla/include/SciLexer.h +++ b/scintilla/include/SciLexer.h @@ -1649,4 +1649,28 @@ #define SCE_STTXT_PRAGMAS 18 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ +#define SCLEX_AHK1 200 +#define SCLEX_AHK2 201 +#define SCE_AHK_DEFAULT 0 +#define SCE_AHK_COMMENTLINE 1 +#define SCE_AHK_COMMENTBLOCK 2 +#define SCE_AHK_ESCAPE 3 +#define SCE_AHK_SYNOPERATOR 4 +#define SCE_AHK_EXPOPERATOR 5 +#define SCE_AHK_STRING 6 +#define SCE_AHK_NUMBER 7 +#define SCE_AHK_IDENTIFIER 8 +#define SCE_AHK_VARREF 9 +#define SCE_AHK_LABEL 10 +#define SCE_AHK_WORD_CF 11 +#define SCE_AHK_WORD_CMD 12 +#define SCE_AHK_WORD_FN 13 +#define SCE_AHK_WORD_DIR 14 +#define SCE_AHK_WORD_KB 15 +#define SCE_AHK_WORD_VAR 16 +#define SCE_AHK_WORD_SP 17 +#define SCE_AHK_WORD_UD 18 +#define SCE_AHK_VARREFKW 19 +#define SCE_AHK_ERROR 20 + #endif diff --git a/scintilla/lexers/LexAHK1.cxx b/scintilla/lexers/LexAHK1.cxx new file mode 100644 index 0000000..b002e3f --- /dev/null +++ b/scintilla/lexers/LexAHK1.cxx @@ -0,0 +1,510 @@ +// Scintilla source code edit control +/** @file LexAHK1.cxx + ** Lexer for AutoHotkey, simplified version + ** Written by Philippe Lhoste (PhiLho) + ** Some hacks by fincs to: + ** - Support object syntax + ** - Support ternary operators (? :) + ** - Fix folding + ** - Fix expression lines starting with ( as being misdetected as continuation sections + ** - Add ;{ and ;} section folding support + **/ +// Copyright 1998-2012 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + + +static inline bool IsAWordChar(const int ch) { + return ch >= 0x80 || (isascii(ch) && isalnum(ch)) || + ch == '_' || ch == '$' || //ch == '[' || ch == ']' || // fincs-edit + ch == '#' || ch == '@'; //|| ch == '?'; // fincs-edit +} + +// Expression operator +// ( ) + - * ** / // ! ~ ^ & << >> . < > <= >= = == != <> && || [ ] ? : +static inline bool IsExpOperator(const int ch) { + if (ch >= 0x80 || (isascii(ch) && isalnum(ch))) // Fast exit + return false; + return ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '(' || ch == ')' || ch == '.' || + ch == '=' || ch == '<' || ch == '>' || + ch == '&' || ch == '|' || ch == '^' || ch == '~' || ch == '!' || + ch == '[' || ch == ']' || ch == '?' || ch == ':'; // fincs-edit +} + +static void HighlightKeyword( + char currentWord[], + StyleContext &sc, + WordList *keywordlists[], + Accessor &styler) { + + WordList &controlFlow = *keywordlists[0]; + WordList &commands = *keywordlists[1]; + WordList &functions = *keywordlists[2]; + WordList &directives = *keywordlists[3]; + WordList &keysButtons = *keywordlists[4]; + WordList &variables = *keywordlists[5]; + WordList &specialParams = *keywordlists[6]; + WordList &userDefined = *keywordlists[7]; + + if (controlFlow.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_CF); + } else if (commands.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_CMD); + } else if (functions.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_FN); + } else if (currentWord[0] == '#' && directives.InList(currentWord + 1)) { + sc.ChangeState(SCE_AHK_WORD_DIR); + } else if (keysButtons.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_KB); + } else if (variables.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_VAR); + } else if (specialParams.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_SP); + } else if (userDefined.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_UD); + } else { + sc.ChangeState(SCE_AHK_DEFAULT); + } +} + +static bool LineHasChar(Accessor &styler, int pos, int ch) +{ + for (;;) + { + int c = styler.SafeGetCharAt(pos++, 0); + if (c == 0 || c == '\r' || c == '\n') + return false; + if (c == ch) + return true; + } +} + +static void ColouriseAHK1Doc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keysButtons = *keywordlists[4]; + WordList &variables = *keywordlists[5]; + char currentWord[256]; + + // Do not leak onto next line + if (initStyle != SCE_AHK_COMMENTBLOCK && + initStyle != SCE_AHK_STRING) { + initStyle = SCE_AHK_DEFAULT; + } + int currentState = initStyle; + int nextState = -1; + + /* The AutoHotkey syntax is heavily context-dependent. + For example, for each command, the lexer knows if parameter #n + is a string, a variable, a number, an expression, etc. + I won't go this far, but I will try to handle most regular cases. + */ + // True if in a continuation section + bool bContinuationSection = (initStyle == SCE_AHK_STRING); + // Indicate if the lexer has seen only spaces since the start of the line + bool bOnlySpaces = (!bContinuationSection); + // Indicate if since the start of the line, lexer met only legal label chars + bool bIsLabel = false; + // Distinguish hotkeys from hotstring + bool bIsHotkey = false; + bool bIsHotstring = false; + // In an expression + bool bInExpression = false; + // A quoted string in an expression (share state with continuation section string) + bool bInExprString = false; + // To accept A-F chars in a number + bool bInHexNumber = false; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (nextState >= 0) { + // I need to reset a state before checking new char + sc.SetState(nextState); + nextState = -1; + } + if (sc.state == SCE_AHK_SYNOPERATOR) { + // Only one char (if two detected, we move Forward() anyway) + sc.SetState(SCE_AHK_DEFAULT); + } + if (sc.atLineEnd && (bIsHotkey || bIsHotstring)) { + // I make the hotkeys and hotstrings more visible + // by changing the line end to LABEL style (if style uses eolfilled) + bIsHotkey = bIsHotstring = false; + sc.SetState(SCE_AHK_LABEL); + } + if (sc.atLineStart) { + if (sc.state != SCE_AHK_COMMENTBLOCK && + !bContinuationSection) { + // Prevent some styles from leaking back to previous line + sc.SetState(SCE_AHK_DEFAULT); + } + bOnlySpaces = true; + bIsLabel = false; + bInExpression = false; // I don't manage multiline expressions yet! + bInHexNumber = false; + } + + // Manage cases occuring in (almost) all states (not in comments) + if (sc.state != SCE_AHK_COMMENTLINE && + sc.state != SCE_AHK_COMMENTBLOCK && + !IsASpace(sc.ch)) { + if (sc.ch == '`') { + // Backtick, escape sequence + currentState = sc.state; + sc.SetState(SCE_AHK_ESCAPE); + sc.Forward(); + nextState = currentState; + continue; + } + if (sc.ch == '%' && !bIsHotstring && !bInExprString && + sc.state != SCE_AHK_VARREF && + sc.state != SCE_AHK_VARREFKW && + sc.state != SCE_AHK_ERROR) { + if (IsASpace(sc.chNext)) { + if (sc.state == SCE_AHK_STRING) { + // Illegal unquoted character! + sc.SetState(SCE_AHK_ERROR); + } else { + // % followed by a space is expression start + bInExpression = true; + } + } else { + // Variable reference + currentState = sc.state; + sc.SetState(SCE_AHK_SYNOPERATOR); + nextState = SCE_AHK_VARREF; + continue; + } + } + if (sc.state != SCE_AHK_STRING && !bInExpression) { + // Management of labels, hotkeys, hotstrings and remapping + + // Check if the starting string is a label candidate + if (bOnlySpaces && + sc.ch != ',' && sc.ch != ';' && sc.ch != ':' && + sc.ch != '%' && sc.ch != '`') { + // A label cannot start with one of the above chars + bIsLabel = true; + } + + // The current state can be IDENTIFIER or DEFAULT, + // depending if the label starts with a word char or not + if (bIsLabel && sc.ch == ':' && + (IsASpace(sc.chNext) || sc.atLineEnd)) { + // ?l/a|b\e^l!: + // Only ; comment should be allowed after + sc.ChangeState(SCE_AHK_LABEL); + sc.SetState(SCE_AHK_SYNOPERATOR); + nextState = SCE_AHK_DEFAULT; + continue; + } else if (sc.Match(':', ':')) { + if (bOnlySpaces) { + // Hotstring ::aa::Foo + bIsHotstring = true; + sc.SetState(SCE_AHK_SYNOPERATOR); + sc.Forward(); + nextState = SCE_AHK_LABEL; + continue; + } + // Hotkey F2:: or remapping a::b + bIsHotkey = true; + // Check if it is a known key + sc.GetCurrentLowered(currentWord, sizeof(currentWord)); + if (keysButtons.InList(currentWord)) { + sc.ChangeState(SCE_AHK_WORD_KB); + } + sc.SetState(SCE_AHK_SYNOPERATOR); + sc.Forward(); + if (bIsHotstring) { + nextState = SCE_AHK_STRING; + } + continue; + } + } + } + // Check if the current string is still a label candidate + // Labels are much more permissive than regular identifiers... + if (bIsLabel && + (sc.ch == ',' || sc.ch == '%' || sc.ch == '`' || IsASpace(sc.ch))) { + // Illegal character in a label + bIsLabel = false; + } + + // Determine if the current state should terminate. + if (sc.state == SCE_AHK_COMMENTLINE) { + if (sc.atLineEnd) { + sc.SetState(SCE_AHK_DEFAULT); + } + } else if (sc.state == SCE_AHK_COMMENTBLOCK) { + if (bOnlySpaces && sc.Match('*', '/')) { + // End of comment at start of line (skipping white space) + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } + } else if (sc.state == SCE_AHK_EXPOPERATOR) { + if (!IsExpOperator(sc.ch)) { + sc.SetState(SCE_AHK_DEFAULT); + } + } else if (sc.state == SCE_AHK_STRING) { + if (bContinuationSection) { + if (bOnlySpaces && sc.ch == ')') { + // End of continuation section + bContinuationSection = false; + sc.SetState(SCE_AHK_SYNOPERATOR); + } + } else if (bInExprString) { + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + // In expression string, double quotes are doubled to escape them + sc.Forward(); // Skip it + } else { + bInExprString = false; + sc.ForwardSetState(SCE_AHK_DEFAULT); + } + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_AHK_ERROR); + } + } else { + if (sc.ch == ';' && IsASpace(sc.chPrev)) { + // Line comments after code must be preceded by a space + sc.SetState(SCE_AHK_COMMENTLINE); + } + } + } else if (sc.state == SCE_AHK_NUMBER) { + if (bInHexNumber) { + if (!IsADigit(sc.ch, 16)) { + bInHexNumber = false; + sc.SetState(SCE_AHK_DEFAULT); + } + } else if (!(IsADigit(sc.ch) || sc.ch == '.')) { + sc.SetState(SCE_AHK_DEFAULT); + } + } else if (sc.state == SCE_AHK_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + sc.GetCurrentLowered(currentWord, sizeof(currentWord)); + HighlightKeyword(currentWord, sc, keywordlists, styler); + if (strcmp(currentWord, "if") == 0) { + bInExpression = true; + } + sc.SetState(SCE_AHK_DEFAULT); + } + } else if (sc.state == SCE_AHK_VARREF) { + if (sc.ch == '%') { + // End of variable reference + sc.GetCurrentLowered(currentWord, sizeof(currentWord)); + if (variables.InList(currentWord)) { + sc.ChangeState(SCE_AHK_VARREFKW); + } + sc.SetState(SCE_AHK_SYNOPERATOR); + nextState = currentState; + continue; + } else if (!IsAWordChar(sc.ch)) { + // Oops! Probably no terminating % + sc.ChangeState(SCE_AHK_ERROR); + } + } else if (sc.state == SCE_AHK_LABEL) { + // Hotstring -- modifier or trigger string :*:aa::Foo or ::aa::Foo + if (sc.ch == ':') { + sc.SetState(SCE_AHK_SYNOPERATOR); + if (sc.chNext == ':') { + sc.Forward(); + } + nextState = SCE_AHK_LABEL; + continue; + } + } + + // Determine if a new state should be entered + if (sc.state == SCE_AHK_DEFAULT) { + if (sc.ch == ';' && + (bOnlySpaces || IsASpace(sc.chPrev))) { + // Line comments are alone on the line or are preceded by a space + sc.SetState(SCE_AHK_COMMENTLINE); + } else if (bOnlySpaces && sc.Match('/', '*')) { + // Comment at start of line (skipping white space) + sc.SetState(SCE_AHK_COMMENTBLOCK); + sc.Forward(); + } else if (sc.ch == '{' || sc.ch == '}') { + // Code block or special key {Enter} + sc.SetState(SCE_AHK_SYNOPERATOR); + } else if (bOnlySpaces && sc.ch == '(' && !LineHasChar(styler, sc.currentPos, ')')) { + // Continuation section + bContinuationSection = true; + sc.SetState(SCE_AHK_SYNOPERATOR); + nextState = SCE_AHK_STRING; // !!! Can be an expression! + } else if (sc.Match(':', '=') || + sc.Match('+', '=') || + sc.Match('-', '=') || + sc.Match('/', '=') || + sc.Match('*', '=')) { + // Expression assignment + bInExpression = true; + sc.SetState(SCE_AHK_SYNOPERATOR); + sc.Forward(); + nextState = SCE_AHK_DEFAULT; + } else if (IsExpOperator(sc.ch)) { + sc.SetState(SCE_AHK_EXPOPERATOR); + } else if (sc.ch == '\"') { + bInExprString = true; + sc.SetState(SCE_AHK_STRING); + } else if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) { + // Hexa, skip forward as we don't accept any other alpha char (beside A-F) inside + bInHexNumber = true; + sc.SetState(SCE_AHK_NUMBER); + sc.Forward(2); + } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { + sc.SetState(SCE_AHK_NUMBER); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(SCE_AHK_IDENTIFIER); + } else if (sc.ch == ',') { + sc.SetState(SCE_AHK_SYNOPERATOR); + nextState = SCE_AHK_DEFAULT; + } else if (sc.ch == ':') { + if (bOnlySpaces) { + // Start of hotstring :*:foo::Stuff or ::btw::Stuff + bIsHotstring = true; + sc.SetState(SCE_AHK_SYNOPERATOR); + if (sc.chNext == ':') { + sc.Forward(); + } + nextState = SCE_AHK_LABEL; + } + } else if (IsAWordChar(sc.ch)) { + sc.SetState(SCE_AHK_IDENTIFIER); + } + } + if (!IsASpace(sc.ch)) { + bOnlySpaces = false; + } + } + // End of file: complete any pending changeState + if (sc.state == SCE_AHK_IDENTIFIER) { + sc.GetCurrentLowered(currentWord, sizeof(currentWord)); + HighlightKeyword(currentWord, sc, keywordlists, styler); + } else if (sc.state == SCE_AHK_STRING && bInExprString) { + sc.ChangeState(SCE_AHK_ERROR); + } else if (sc.state == SCE_AHK_VARREF) { + sc.ChangeState(SCE_AHK_ERROR); + } + sc.Complete(); +} + +static void FoldAHK1Doc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + bool bOnlySpaces = true; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) { + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; + } + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && style == SCE_AHK_COMMENTBLOCK) { + if (stylePrev != SCE_AHK_COMMENTBLOCK) { + levelNext++; + } else if ((styleNext != SCE_AHK_COMMENTBLOCK) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (foldComment && style == SCE_AHK_COMMENTLINE) { + if (ch == ';') { + if (chNext == '{') { + levelNext ++; + } else if (chNext == '}') { + levelNext --; + } + } + } + if (style == SCE_AHK_SYNOPERATOR) { + if (ch == '(' || ch == '{') { + levelNext++; + } else if (ch == ')' || ch == '}') { + levelNext--; + } + } + if (atEOL || (i == endPos-1)) { + int level = levelCurrent | (levelNext << 16); + if (bOnlySpaces && foldCompact) { + // Empty line + level |= SC_FOLDLEVELWHITEFLAG; + } + if (levelCurrent < levelNext) { + level |= SC_FOLDLEVELHEADERFLAG; + } + if (level != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, level); + } + lineCurrent++; + levelCurrent = levelNext; + if (atEOL && (i == static_cast(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + bOnlySpaces = true; + } + if (!isspacechar(ch)) { + bOnlySpaces = false; + } + } +} + +static const char * const ahkWordListDesc[] = { + "Flow of control", + "Commands", + "Functions", + "Directives", + "Keys & buttons", + "Variables", + "Special Parameters (keywords)", + "User defined", + 0 +}; + +LexerModule lmAHK1(SCLEX_AHK1, ColouriseAHK1Doc, "ahk1", FoldAHK1Doc, ahkWordListDesc); diff --git a/scintilla/lexers/LexAHK2.cxx b/scintilla/lexers/LexAHK2.cxx new file mode 100644 index 0000000..2ed789e --- /dev/null +++ b/scintilla/lexers/LexAHK2.cxx @@ -0,0 +1,876 @@ +// Scintilla source code edit control +/** @file LexAHK2.cxx + ** Lexer for AutoHotkey v2-alpha + ** Written by fincs + **/ +// Copyright 1998-2011 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SparseState.h" + +struct OptionsAHK2 +{ + bool Fold; + bool FoldComment; + bool FoldCompact; + + OptionsAHK2() { } +}; + +static const char* const ahk2WordListDesc[] = +{ + //"Flow of control", + //"Built-in functions", // includes commands + "Built-in variables", + //"Directives", + //"Special Parameters (keywords)", + //"User defined", + NULL +}; + +static const char* ahk2FlowOfControl = "if else loop while until for try catch throw return class break continue exit exitapp gosub goto static global local var"; +static const char* ahk2SpecialWords = "and or is contains in extends new"; + +struct OptionSetAHK2 : public OptionSet +{ + OptionSetAHK2() + { + DefineWordListSets(ahk2WordListDesc); + + DefineProperty("fold", &OptionsAHK2::Fold); + + DefineProperty("fold.compact", &OptionsAHK2::FoldCompact); + + DefineProperty("fold.comment", &OptionsAHK2::FoldComment, + "This option enables folding multi-line comments and explicit fold points when using the AHK v2 lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} " + "at the end of a section that should fold."); + } +}; + +typedef enum +{ + LINE_NODATA, + LINE_BLANK, LINE_MLCOMMENT, LINE_COMMAND, LINE_EXPR, LINE_CONTSECT, LINE_SYNTAX, LINE_LABELANDOTHER, LINE_DIRECTIVE +} AhkLineType; + +struct AhkLineInfo +{ + AhkLineType type; + AhkLineType context; + // These are used in continuation sections + bool bAdmitsComments, bNoLiteralQuote, bLiteralPercent, bNoLiteralComma, bLiteralEscape; + + AhkLineInfo() + { + init(); + } + + void init() + { + type = LINE_NODATA; + context = LINE_BLANK; + bAdmitsComments = false; + bNoLiteralQuote = false; + bLiteralPercent = false; + bNoLiteralComma = false; + bLiteralEscape = false; + } + + void initcontext(const AhkLineInfo& base) + { + type = base.type; + context = base.context; + bAdmitsComments = base.bAdmitsComments; + bNoLiteralQuote = base.bNoLiteralQuote; + bLiteralPercent = base.bLiteralPercent; + bNoLiteralComma = base.bNoLiteralComma; + bLiteralEscape = base.bLiteralEscape; + } +}; + +class AhkProvideLineInfo +{ + std::vector st; +public: + AhkLineInfo& get(int line) + { + assert (line >= 0); + if ((size_t) line >= st.size()) + { + st.resize(line+1); + st[line] = AhkLineInfo(); + return st[line]; + }else + return st[line]; + } +}; + +class LexerAHK2 : public ILexer +{ + OptionsAHK2 options; + OptionSetAHK2 opSet; + WordList /*bifList,*/ bivList/*, directiveList*/; + WordList flowOfControl, specialWords; + AhkProvideLineInfo linfos; + + LexerAHK2() + { + flowOfControl.Set(ahk2FlowOfControl); + specialWords.Set(ahk2SpecialWords); + } + ~LexerAHK2() { } + +public: + + virtual int SCI_METHOD Version() const { return lvOriginal; } + virtual void SCI_METHOD Release() { delete this; } + virtual const char* SCI_METHOD PropertyNames() { return opSet.PropertyNames(); } + virtual int SCI_METHOD PropertyType(const char* name) { return opSet.PropertyType(name); } + virtual const char* SCI_METHOD DescribeProperty(const char* name) { return opSet.DescribeProperty(name); } + virtual int SCI_METHOD PropertySet(const char* key, const char* val); + virtual const char* SCI_METHOD DescribeWordListSets() { return opSet.DescribeWordListSets(); } + virtual int SCI_METHOD WordListSet(int n, const char* wl); + virtual void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument* pAccess); + virtual void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument* pAccess); + virtual void* SCI_METHOD PrivateCall(int operation, void* pointer) { return NULL; } + + static ILexer* LexerFactoryAHK2() + { + try { return new LexerAHK2(); } + catch(...) { return NULL; } + } +}; + +int SCI_METHOD LexerAHK2::PropertySet(const char* key, const char* val) +{ + return opSet.PropertySet(&options, key, val) ? 0 : -1; +} + +int SCI_METHOD LexerAHK2::WordListSet(int n, const char* wl) +{ + if (n != 0) return -1; + bivList.Set(wl); + return 0; + /* + WordList* pWl = NULL; + switch(n) + { + case 0: pWl = &bifList; break; + case 1: pWl = &bivList; break; + case 2: pWl = &directiveList; break; + default: return -1; + } + pWl->Set(wl); + return 0; + */ +} + +LexerModule lmAHK2(SCLEX_AHK2, LexerAHK2::LexerFactoryAHK2, "ahk2", ahk2WordListDesc); + +// +// End of boilerplate +// + +static inline bool isWhitespace(int c) +{ + return c == ' ' || c == '\t'; +} + +static inline bool isNumeric(int c, bool allowHex = false) +{ + return (c >= '0' && c <= '9') || (allowHex && ((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))); +} + +static inline bool isIdChar(int c, bool allowNumeric = true) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (allowNumeric && isNumeric(c)) || c == '_' || c > 0x7F; +} + +static inline bool isExprOp(int c) +{ + return c == '+' || c == '-' || c == '*' || c == '/' || c == '.' || c == '(' || c == ')' || c == '=' || c == '[' || c == ']' + || c == '!' || c == '<' || c == '>' || c == '&' || c == '|' || c == '^' || c == '~' || c == '?' || c == ':' || c == ','; +} + +static inline void chopcr(char* buf) +{ + size_t pos = strlen(buf) - 1; + if (buf[pos] == '\r') buf[pos] = 0; +} + +class Backtrack +{ + LexAccessor& styler; + StyleContext& sc; + int pos; + char mask; +public: + + Backtrack(LexAccessor& _styler, StyleContext& _sc, int _pos, char chMask=31) + : styler(_styler), sc(_sc), pos(_pos), mask(chMask) + { + styler.Flush(); + styler.StartAt(pos, mask); + styler.StartSegment(pos); + } + + void StyleChars(int len, int style) + { + if (len != 0) + styler.ColourTo((pos += len) - 1, style); + } + + ~Backtrack() + { + styler.Flush(); + styler.StartAt(sc.currentPos, mask); + styler.StartSegment(sc.currentPos); + } + + static void Colour(LexAccessor& _styler, StyleContext& _sc, int pos, int size, int style) + { + Backtrack b(_styler, _sc, pos); + b.StyleChars(size, style); + } +}; + +void SCI_METHOD LexerAHK2::Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument* pAccess) +{ + if (initStyle != SCE_AHK_COMMENTBLOCK) + initStyle = SCE_AHK_DEFAULT; + + LexAccessor styler(pAccess); + StyleContext sc(startPos, lengthDoc, initStyle, styler); + + int curLine = styler.GetLine(startPos); + AhkLineInfo prevInfo = curLine > 0 ? linfos.get(curLine - 1) : AhkLineInfo(); // make copy + AhkLineInfo* curInfo = &linfos.get(curLine); + curInfo->initcontext(prevInfo); + curInfo->type = LINE_BLANK; + + bool bNewLine = true, bInitialWS = true, bBegOfLine = true, bPhysBegOfLine = true, bKnowType = false, bIsHex = false; + int backtrackStart = -1, backtrackSize = 0; + + char wordbuf[256]; + + for(; sc.More(); sc.Forward()) + { + int ch = sc.ch; + if (bNewLine) + { + bNewLine = false; + bInitialWS = true; + bKnowType = false; + } + + _loopHead: + + bBegOfLine = bInitialWS; + if (!bBegOfLine) bPhysBegOfLine = false; + + if (ch == '\r' && sc.chNext == '\n') + { + sc.Forward(); + goto _doNewLine; + } + + if (ch == '\n') + { + _doNewLine: + if (bKnowType && curInfo->type == LINE_EXPR && sc.state == SCE_AHK_STRING) + sc.ChangeState(SCE_AHK_ERROR); + + if (sc.state == SCE_AHK_IDENTIFIER) + { + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + chopcr(wordbuf); + if (bivList.InList(wordbuf)) + sc.ChangeState(SCE_AHK_WORD_VAR); + } else if (sc.state == SCE_AHK_VARREF) + { + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + chopcr(wordbuf); + if (bivList.InList(wordbuf+1)) // skip initial '%' + sc.ChangeState(SCE_AHK_VARREFKW); + } + + // New line will be reached + bNewLine = true; + bPhysBegOfLine = true; + prevInfo.initcontext(*curInfo); + curInfo = &linfos.get(++ curLine); + curInfo->initcontext(prevInfo); + curInfo->type = LINE_BLANK; + if (sc.state != SCE_AHK_COMMENTBLOCK) + sc.SetState(SCE_AHK_DEFAULT); + else + curInfo->type = LINE_MLCOMMENT; + continue; + } + + if (bInitialWS) + { + if(!isWhitespace(ch)) + bInitialWS = false; + else + continue; + } + + if (sc.state == SCE_AHK_COMMENTBLOCK) + { + if (bPhysBegOfLine && sc.Match('*', '/')) + { + // Fake new line + curInfo->type = LINE_BLANK; //curInfo->context; + prevInfo.initcontext(*curInfo); + bInitialWS = true; + bKnowType = false; + bPhysBegOfLine = false; + sc.Forward(2); + sc.SetState(SCE_AHK_DEFAULT); + ch = sc.ch; + goto _loopHead; + } + continue; + } + + if (sc.state == SCE_AHK_COMMENTLINE || sc.state == SCE_AHK_LABEL || sc.state == SCE_AHK_ERROR) + continue; + + if (ch == ';' && (bBegOfLine || isWhitespace(sc.chPrev))) + { + if (bKnowType && curInfo->type == LINE_EXPR && sc.state == SCE_AHK_STRING) + sc.ChangeState(SCE_AHK_ERROR); + sc.SetState(SCE_AHK_COMMENTLINE); + continue; + } + + if (bPhysBegOfLine && sc.Match('/', '*')) + { + curInfo->type = LINE_MLCOMMENT; + sc.SetState(SCE_AHK_COMMENTBLOCK); + continue; + } + + if (bBegOfLine && (ch == '{' || ch == '}')) + { + sc.SetState(SCE_AHK_EXPOPERATOR); + // Fake new line + curInfo->context = LINE_BLANK; + bInitialWS = true; + bKnowType = false; + bPhysBegOfLine = false; + sc.Forward(); + sc.SetState(SCE_AHK_DEFAULT); + ch = sc.ch; + goto _loopHead; + } + + if (bBegOfLine && ch == ':' && sc.chNext != '=') + { + // Hotstring + curInfo->type = LINE_LABELANDOTHER; + curInfo->context = LINE_LABELANDOTHER; + sc.SetState(SCE_AHK_LABEL); + continue; + } + + if (bBegOfLine && ch == '#') + { + // Directive + bKnowType = true; + curInfo->type = LINE_DIRECTIVE; + curInfo->context = LINE_DIRECTIVE; + sc.SetState(SCE_AHK_WORD_DIR); + continue; + } + + if (bBegOfLine && isExprOp(ch)) + { + bKnowType = true; + if (sc.Match('+', '+') || sc.Match('-', '-')) + { + // Expression + sc.SetState(SCE_AHK_EXPOPERATOR); + sc.Forward(); + curInfo->type = LINE_EXPR; + curInfo->context = LINE_EXPR; + continue; + } + switch(curInfo->context) + { + case LINE_LABELANDOTHER: + curInfo->type = LINE_LABELANDOTHER; + sc.SetState(SCE_AHK_LABEL); + continue; + case LINE_COMMAND: + curInfo->type = LINE_COMMAND; + sc.SetState(ch != ',' ? SCE_AHK_STRING : SCE_AHK_EXPOPERATOR); + continue; + case LINE_EXPR: + curInfo->type = LINE_EXPR; + sc.SetState(SCE_AHK_EXPOPERATOR); + continue; + default: + //assert(false); + sc.SetState(SCE_AHK_ERROR); + curInfo->type = LINE_BLANK; + curInfo->context = LINE_BLANK; + continue; + } + } + + if (!bKnowType) + { + if (bBegOfLine) + { + if (!isIdChar(ch, false)) + { + sc.SetState(SCE_AHK_ERROR); + curInfo->type = LINE_BLANK; + curInfo->context = LINE_BLANK; + continue; + } + + curInfo->type = LINE_COMMAND; // for now + curInfo->context = LINE_COMMAND; + sc.SetState(SCE_AHK_WORD_CMD); + backtrackStart = sc.currentPos; + backtrackSize = 0; + continue; + } + + if (sc.state != SCE_AHK_DEFAULT) + { + if (isIdChar(ch)) continue; + + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + backtrackSize = sc.currentPos - backtrackStart; + + if (ch == ',') + { + // Definitely command + bKnowType = true; + + bool bIsFOC = flowOfControl.InList(wordbuf); + if (bIsFOC) + sc.ChangeState(SCE_AHK_WORD_CF); + + sc.SetState(SCE_AHK_EXPOPERATOR); + + if (bIsFOC) + { + curInfo->type = LINE_EXPR; + curInfo->context = LINE_EXPR; + } + + continue; + } else if (ch == '(') + { + // Function call or definition + bKnowType = true; + curInfo->type = LINE_EXPR; + curInfo->context = LINE_EXPR; + if (strcmp(wordbuf, "if") == 0 || strcmp(wordbuf, "while") == 0) + sc.ChangeState(SCE_AHK_WORD_CF); + else + sc.ChangeState(SCE_AHK_WORD_FN); + sc.SetState(SCE_AHK_EXPOPERATOR); + continue; + } else if (ch == '.') + { + // Object syntax + bKnowType = true; + curInfo->type = LINE_EXPR; + curInfo->context = LINE_EXPR; + sc.ChangeState(bivList.InList(wordbuf) ? SCE_AHK_WORD_VAR : SCE_AHK_IDENTIFIER); + sc.SetState(SCE_AHK_EXPOPERATOR); + continue; + } else if (!isWhitespace(ch)) + { + // Error + sc.SetState(SCE_AHK_ERROR); + curInfo->type = LINE_BLANK; + curInfo->context = LINE_BLANK; + continue; + } + + // For now, change the sym type if needed + if (flowOfControl.InList(wordbuf)) + sc.ChangeState(SCE_AHK_WORD_CF); + + // Search more + sc.SetState(SCE_AHK_DEFAULT); + continue; + } + + if (isWhitespace(ch)) continue; + + if (sc.Match(':', '=') || sc.Match('+', '=') || sc.Match('-', '=') || sc.Match('*', '=') || sc.Match('/', '=') + || sc.Match("//=") || sc.Match('.', '=') || sc.Match('|', '=') || sc.Match('&', '=') || sc.Match('^', '=') + || sc.Match(">>=") || sc.Match("<<=")) + { + // Assignment + // Need backtrack to highlight previous word as identifier... + Backtrack::Colour(styler, sc, backtrackStart, backtrackSize, bivList.InList(wordbuf) ? SCE_AHK_WORD_VAR : SCE_AHK_IDENTIFIER); + bKnowType = true; + curInfo->type = LINE_EXPR; + curInfo->context = LINE_EXPR; + sc.SetState(SCE_AHK_EXPOPERATOR); + sc.Forward(); + if (sc.Match('/', '=') || sc.Match('>', '=') || sc.Match('<', '=')) + sc.Forward(); + continue; + }else if (flowOfControl.InList(wordbuf)) + { + // Flow of control + bKnowType = true; + curInfo->type = LINE_EXPR; + curInfo->context = LINE_EXPR; + // fall down + sc.SetState(SCE_AHK_DEFAULT); + }else + { + // Definitely command + bKnowType = true; + if (ch == ',') + { + sc.SetState(SCE_AHK_EXPOPERATOR); + continue; + } + // else fall down + sc.SetState(SCE_AHK_STRING); + } + } + + // Catch-all string handler + if (sc.state == SCE_AHK_STRING) + { + if (ch == '`') + { + sc.SetState(SCE_AHK_ESCAPE); + sc.Forward(); + sc.SetState(SCE_AHK_STRING); + continue; + //ch = sc.ch; + //goto _loopHead; + } + + if (ch == '%') + { + sc.SetState(SCE_AHK_VARREF); + continue; + } + }else + + // Catch-all deref handler + if (sc.state == SCE_AHK_VARREF) + { + if (isIdChar(ch, sc.LengthCurrent() != 1)) + continue; + // else let section below handle it + }else + + // Catch-all escape handler + if (sc.state == SCE_AHK_ESCAPE) + sc.SetState(SCE_AHK_STRING); + else + + // Catch-all identifier handler + if (sc.state == SCE_AHK_IDENTIFIER) + { + if (isIdChar(ch)) + continue; + + if (ch == '(') + sc.ChangeState(SCE_AHK_WORD_FN); + else + { + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + if (bivList.InList(wordbuf)) + sc.ChangeState(SCE_AHK_WORD_VAR); + if (specialWords.InList(wordbuf)) + sc.ChangeState(SCE_AHK_WORD_SP); + } + + // Let it fall down + sc.SetState(SCE_AHK_DEFAULT); + }else + + // Catch-all number handler + if (sc.state == SCE_AHK_NUMBER) + { + if (isNumeric(ch, bIsHex) || (bIsHex && sc.LengthCurrent() == 1 && ch == 'x')) + continue; + + // Let it fall down + sc.SetState(SCE_AHK_DEFAULT); + }else + + // End operator state + if (sc.state == SCE_AHK_EXPOPERATOR) + sc.SetState(SCE_AHK_DEFAULT); + + switch(curInfo->type) + { + case LINE_COMMAND: + if (sc.state == SCE_AHK_VARREF) + { + if (ch == ',') + { + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + if (bivList.InList(wordbuf+1)) // skip initial '%' + sc.ChangeState(SCE_AHK_VARREFKW); + + sc.SetState(SCE_AHK_EXPOPERATOR); + continue; + } + + if (ch == '%' || isWhitespace(ch)) + { + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + if (bivList.InList(wordbuf+1)) // skip initial '%' + sc.ChangeState(SCE_AHK_VARREFKW); + + if (ch == '%') + { + sc.Forward(); + ch = sc.ch; + } + sc.SetState(SCE_AHK_STRING); + // Reprocess character + goto _loopHead; + //continue; + } + + sc.SetState(SCE_AHK_ERROR); + curInfo->type = LINE_BLANK; + curInfo->context = LINE_BLANK; + continue; + } + + if (ch == ',') + { + sc.SetState(SCE_AHK_EXPOPERATOR); + continue; + } + + if (sc.state == SCE_AHK_DEFAULT) + sc.ChangeState(SCE_AHK_STRING); + break; + + case LINE_EXPR: + { + bool bTokBegin = sc.state == SCE_AHK_DEFAULT; + + switch (sc.state) + { + // Token begin + case SCE_AHK_DEFAULT: + if (isWhitespace(ch)) + continue; + + if (isNumeric(ch)) + { + sc.SetState(SCE_AHK_NUMBER); + bIsHex = sc.Match('0', 'x'); + continue; + } + + if (isIdChar(ch, false)) + { + sc.SetState(SCE_AHK_IDENTIFIER); + continue; + } + + if (isExprOp(ch) || ch == '{' || ch == '}') + { + sc.SetState(SCE_AHK_EXPOPERATOR); + continue; + } + + if (ch == '"') + { + sc.SetState(SCE_AHK_STRING); + continue; + } + + sc.SetState(SCE_AHK_ERROR); + curInfo->type = LINE_BLANK; + curInfo->context = LINE_BLANK; + break; + + // String + case SCE_AHK_STRING: + _strMiddle: + if (ch == '"') + { + sc.Forward(); + sc.SetState(SCE_AHK_DEFAULT); + ch = sc.ch; + //goto _beginTok; + goto _loopHead; + } + break; + + // Var ref end + case SCE_AHK_VARREF: + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + if (bivList.InList(wordbuf+1)) // skip initial '%' + sc.ChangeState(SCE_AHK_VARREFKW); + if (ch == '%') + { + sc.Forward(); + ch = sc.ch; + } + sc.SetState(SCE_AHK_STRING); + goto _strMiddle; + } + break; + } + case LINE_DIRECTIVE: + if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) continue; + + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + bool bShouldBeExpr = strcmp(wordbuf, "#if") == 0; + sc.SetState(SCE_AHK_DEFAULT); + + if (ch == ',' || isWhitespace(ch)) + { + curInfo->type = bShouldBeExpr ? LINE_EXPR : LINE_COMMAND; + curInfo->context = curInfo->type; + goto _loopHead; + } + + curInfo->type = LINE_BLANK; + curInfo->context = LINE_BLANK; + sc.SetState(SCE_AHK_ERROR); + break; + } + } + + if (!bNewLine) + { + if (bKnowType && curInfo->type == LINE_EXPR && sc.state == SCE_AHK_STRING) + sc.ChangeState(SCE_AHK_ERROR); + + if (sc.state == SCE_AHK_IDENTIFIER) + { + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + chopcr(wordbuf); + if (bivList.InList(wordbuf)) + sc.ChangeState(SCE_AHK_WORD_VAR); + } else if (sc.state == SCE_AHK_VARREF) + { + sc.GetCurrentLowered(wordbuf, _countof(wordbuf)); + chopcr(wordbuf); + if (bivList.InList(wordbuf+1)) // skip initial '%' + sc.ChangeState(SCE_AHK_VARREFKW); + } + } + + sc.Complete(); +} + +void SCI_METHOD LexerAHK2::Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument* pAccess) +{ + if (!options.Fold) return; + + bool bFoldComment = options.FoldComment; + bool bFoldCompact = options.FoldCompact; + + LexAccessor styler(pAccess); + unsigned int endPos = startPos + lengthDoc; + bool bOnlySpaces = true; + + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; + + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + for (unsigned int i = startPos; i < endPos; i ++) + { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (bFoldComment && style == SCE_AHK_COMMENTBLOCK) + { + if (stylePrev != SCE_AHK_COMMENTBLOCK) + levelNext ++; + else if ((styleNext != SCE_AHK_COMMENTBLOCK) && !atEOL) + // Comments don't end at end of line and the next character may be unstyled. + levelNext --; + } + + if (bFoldComment && style == SCE_AHK_COMMENTLINE) + { + if (ch == ';') + { + if (chNext == '{') + levelNext ++; + else if (chNext == '}') + levelNext --; + } + } + + if (style == SCE_AHK_EXPOPERATOR) + { + if (ch == '(' || ch == '{' || ch == '[') + levelNext ++; + else if (ch == ')' || ch == '}' || ch == ']') + levelNext --; + } + if (atEOL || (i == endPos-1)) + { + int level = levelCurrent | (levelNext << 16); + if (bOnlySpaces && bFoldCompact) + // Empty line + level |= SC_FOLDLEVELWHITEFLAG; + if (levelCurrent < levelNext) + level |= SC_FOLDLEVELHEADERFLAG; + if (level != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, level); + lineCurrent ++; + levelCurrent = levelNext; + if (atEOL && (i == static_cast(styler.Length()-1))) + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + bOnlySpaces = true; + } + if (!isWhitespace(ch)) + bOnlySpaces = false; + } +} diff --git a/scintilla/src/Catalogue.cxx b/scintilla/src/Catalogue.cxx index 1a56304..1439eb8 100644 --- a/scintilla/src/Catalogue.cxx +++ b/scintilla/src/Catalogue.cxx @@ -84,6 +84,8 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmA68k); LINK_LEXER(lmAbaqus); LINK_LEXER(lmAda); + LINK_LEXER(lmAHK1); + LINK_LEXER(lmAHK2); LINK_LEXER(lmAPDL); LINK_LEXER(lmAsm); LINK_LEXER(lmAsn1); diff --git a/scintilla/win32/ScintRes.rc b/scintilla/win32/ScintRes.rc index cb3c982..fb438a9 100644 --- a/scintilla/win32/ScintRes.rc +++ b/scintilla/win32/ScintRes.rc @@ -25,11 +25,11 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Neil Hodgson neilh@scintilla.org\0" - VALUE "FileDescription", "Scintilla.DLL - a Source Editing Component\0" + VALUE "FileDescription", "Scintilla.dll (with AHK support) - a Source Editing Component\0" VALUE "FileVersion", VERSION_SCINTILLA "\0" VALUE "InternalName", "Scintilla\0" - VALUE "LegalCopyright", "Copyright 1998-2012 by Neil Hodgson\0" - VALUE "OriginalFilename", "Scintilla.DLL\0" + VALUE "LegalCopyright", "Copyright 1998-2013 by Neil Hodgson\0" + VALUE "OriginalFilename", "Scintilla.dll\0" VALUE "ProductName", "Scintilla\0" VALUE "ProductVersion", VERSION_SCINTILLA "\0" END diff --git a/scintilla/win32/deps.mak b/scintilla/win32/deps.mak index a9466cd..9f3b619 100644 --- a/scintilla/win32/deps.mak +++ b/scintilla/win32/deps.mak @@ -115,6 +115,10 @@ LexAbaqus.o: ../lexers/LexAbaqus.cxx ../include/ILexer.h \ ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \ ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ ../lexlib/CharacterSet.h ../lexlib/LexerModule.h +LexAHK1.o: ../lexers/LexAda.cxx ../include/ILexer.h ../include/Scintilla.h \ + ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \ + ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \ + ../lexlib/CharacterSet.h ../lexlib/LexerModule.h LexAda.o: ../lexers/LexAda.cxx ../include/ILexer.h ../include/Scintilla.h \ ../include/SciLexer.h ../lexlib/WordList.h ../lexlib/LexAccessor.h \ ../lexlib/Accessor.h ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \ diff --git a/scite/SciTE.vcxproj b/scite/SciTE.vcxproj new file mode 100644 index 0000000..acdbe54 --- /dev/null +++ b/scite/SciTE.vcxproj @@ -0,0 +1,299 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {2DC33974-65FD-4DAF-B522-ACA7A7AC9721} + Win32Proj + SciTE + $(VCTargetsPath11) + + + + Application + true + Unicode + v110_xp + + + Application + true + Unicode + v110_xp + + + Application + false + true + Unicode + v110_xp + + + Application + false + true + Unicode + v110_xp + + + + + + + + + + + + + + + + + + + true + + + + true + $(SolutionDir)debug\x64\ + $(SolutionDir)debug\x64\temp\SciTE\ + SciTE + $(SolutionDir)scintilla\include;$(SolutionDir)scintilla\win32;$(ProjectDir)src;$(ProjectDir)lua\include;$(IncludePath) + false + + + + false + $(SolutionDir)scintilla\include;$(SolutionDir)scintilla\win32;$(ProjectDir)src;$(ProjectDir)lua\include;$(IncludePath) + $(SolutionDir)bin\x86\ + $(SolutionDir)obj\x86\scite\ + SciTE + + + false + false + + + false + $(SolutionDir)scintilla\include;$(SolutionDir)scintilla\win32;$(ProjectDir)src;$(ProjectDir)lua\include;$(IncludePath) + $(SolutionDir)bin\x64\ + $(SolutionDir)obj\x64\scite\ + SciTE + + + false + $(VCInstallDir)..\Common7\IDE;$(ExecutablePath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;LUA_USER_H="scite_lua_win.h";%(PreprocessorDefinitions) + + + Windows + true + comctl32.lib;imm32.lib;uxtheme.lib;shlwapi.lib;%(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;LUA_USER_H="scite_lua_win.h";%(PreprocessorDefinitions) + true + true + MultiThreaded + false + NoExtensions + + + Windows + false + true + true + comctl32.lib;Msimg32.lib;uxtheme.lib;shlwapi.lib;%(AdditionalDependencies) + false + false + + + + + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;LUA_USER_H="scite_lua_win.h";%(PreprocessorDefinitions) + true + true + MultiThreaded + false + + + Windows + false + true + true + comctl32.lib;Msimg32.lib;imm32.lib;uxtheme.lib;shlwapi.lib;msimg32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scite/SciTE.vcxproj.filters b/scite/SciTE.vcxproj.filters new file mode 100644 index 0000000..6709b29 --- /dev/null +++ b/scite/SciTE.vcxproj.filters @@ -0,0 +1,332 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/scite/src/Credits.cxx b/scite/src/Credits.cxx index d9a6e93..a45384e 100644 --- a/scite/src/Credits.cxx +++ b/scite/src/Credits.cxx @@ -396,7 +396,11 @@ void SciTEBase::SetAboutMessage(GUI::ScintillaWindow &wsci, const char *appTitle wsci.Send(SCI_STYLESETSIZE, 0, fontSize); wsci.Send(SCI_STYLESETBACK, 0, ColourRGB(0, 0, 0x80)); AddStyledText(wsci, appTitle, 0); - AddStyledText(wsci, "\n", 0); +#ifndef _WIN64 // fincs-edit + AddStyledText(wsci, "\n", 1 /* fincs-edit */); +#else // fincs-edit + AddStyledText(wsci, " (64-bit)\n", 1); +#endif SetAboutStyle(wsci, 1, ColourRGB(0, 0, 0)); int trsSty = 5; // define the stylenumber to assign font for translators. SString translator = GetTranslationToAbout("TranslationCredit", false); @@ -416,16 +420,18 @@ void SciTEBase::SetAboutMessage(GUI::ScintillaWindow &wsci, const char *appTitle } #endif AddStyledText(wsci, GetTranslationToAbout("Version").c_str(), trsSty); - AddStyledText(wsci, " " VERSION_SCITE "\n", 1); + AddStyledText(wsci, " " VERSION_SCITE " - Based on SciTE " VERSION_ORGSCITE "\n", 1); AddStyledText(wsci, " " __DATE__ " " __TIME__ "\n", 1); SetAboutStyle(wsci, 2, ColourRGB(0, 0, 0)); wsci.Send(SCI_STYLESETITALIC, 2, 1); AddStyledText(wsci, GetTranslationToAbout("by").c_str(), trsSty); - AddStyledText(wsci, " Neil Hodgson.\n", 2); + AddStyledText(wsci, " fincs", 2); + AddStyledText(wsci, " - Original SciTE by ", trsSty); + AddStyledText(wsci, "Neil Hodgson\n", 2); SetAboutStyle(wsci, 3, ColourRGB(0, 0, 0)); - AddStyledText(wsci, COPYRIGHT_DATES ".\n", 3); + AddStyledText(wsci, "SciTE: " COPYRIGHT_DATES " Neil Hodgson.\nSciTE4AutoHotkey: 2007-2013 fincs.\n", 3); SetAboutStyle(wsci, 4, ColourRGB(0, 0x7f, 0x7f)); - AddStyledText(wsci, "http://www.scintilla.org\n", 4); + AddStyledText(wsci, "http://www.autohotkey.com, http://www.scintilla.org\n", 4); AddStyledText(wsci, "Lua scripting language by TeCGraf, PUC-Rio\n", 3); AddStyledText(wsci, " http://www.lua.org\n", 4); if (translator.length()) { diff --git a/scite/src/Extender.h b/scite/src/Extender.h index c44fb49..733833b 100644 --- a/scite/src/Extender.h +++ b/scite/src/Extender.h @@ -66,7 +66,7 @@ public: } virtual bool OnDoubleClick() { return false; } virtual bool OnUpdateUI() { return false; } - virtual bool OnMarginClick() { return false; } + virtual bool OnMarginClick(int, int) { return false; } // fincs-edit virtual bool OnMacro(const char *, const char *) { return false; } virtual bool OnUserListSelection(int, const char *) { return false; } diff --git a/scite/src/IFaceTable.cxx b/scite/src/IFaceTable.cxx index 48aaf79..944f5b9 100644 --- a/scite/src/IFaceTable.cxx +++ b/scite/src/IFaceTable.cxx @@ -402,6 +402,27 @@ static IFaceConstant ifaceConstants[] = { {"SCE_ADA_STRING",7}, {"SCE_ADA_STRINGEOL",8}, {"SCE_ADA_WORD",1}, + {"SCE_AHK_COMMENTBLOCK",2}, + {"SCE_AHK_COMMENTLINE",1}, + {"SCE_AHK_DEFAULT",0}, + {"SCE_AHK_ERROR",20}, + {"SCE_AHK_ESCAPE",3}, + {"SCE_AHK_EXPOPERATOR",5}, + {"SCE_AHK_IDENTIFIER",8}, + {"SCE_AHK_LABEL",10}, + {"SCE_AHK_NUMBER",7}, + {"SCE_AHK_STRING",6}, + {"SCE_AHK_SYNOPERATOR",4}, + {"SCE_AHK_VARREF",9}, + {"SCE_AHK_VARREFKW",19}, + {"SCE_AHK_WORD_CF",11}, + {"SCE_AHK_WORD_CMD",12}, + {"SCE_AHK_WORD_DIR",14}, + {"SCE_AHK_WORD_FN",13}, + {"SCE_AHK_WORD_KB",15}, + {"SCE_AHK_WORD_SP",17}, + {"SCE_AHK_WORD_UD",18}, + {"SCE_AHK_WORD_VAR",16}, {"SCE_APDL_ARGUMENT",11}, {"SCE_APDL_COMMAND",8}, {"SCE_APDL_COMMENT",1}, @@ -2248,6 +2269,7 @@ static IFaceConstant ifaceConstants[] = { {"SCLEX_A68K",100}, {"SCLEX_ABAQUS",84}, {"SCLEX_ADA",20}, + {"SCLEX_AHK1",200}, {"SCLEX_APDL",61}, {"SCLEX_ASM",34}, {"SCLEX_ASN1",63}, @@ -3063,7 +3085,7 @@ static IFaceProperty ifaceProperties[] = { enum { ifaceFunctionCount = 281, - ifaceConstantCount = 2427, + ifaceConstantCount = sizeof(ifaceConstants) / sizeof(IFaceConstant), ifacePropertyCount = 210 }; diff --git a/scite/src/LuaExtension.cxx b/scite/src/LuaExtension.cxx index 1ed23f6..a2a9376 100644 --- a/scite/src/LuaExtension.cxx +++ b/scite/src/LuaExtension.cxx @@ -1348,6 +1348,11 @@ static bool InitGlobalScope(bool checkProperties, bool forceReload = false) { // ...register standard libraries luaL_openlibs(luaState); +#ifdef WIN32 + extern int MessagePumpLibInit(lua_State* L); + MessagePumpLibInit(luaState); +#endif + lua_register(luaState, "_ALERT", cf_global_print); // although this is mostly redundant with output:append @@ -2055,8 +2060,8 @@ bool LuaExtension::OnUpdateUI() { return CallNamedFunction("OnUpdateUI"); } -bool LuaExtension::OnMarginClick() { - return CallNamedFunction("OnMarginClick"); +bool LuaExtension::OnMarginClick(int position, int margin) { // fincs-edit + return CallNamedFunction("OnMarginClick", position, margin); // fincs-edit } bool LuaExtension::OnUserListSelection(int listType, const char *selection) { diff --git a/scite/src/LuaExtension.h b/scite/src/LuaExtension.h index 51b0676..9a64432 100644 --- a/scite/src/LuaExtension.h +++ b/scite/src/LuaExtension.h @@ -34,7 +34,7 @@ public: virtual bool OnStyle(unsigned int startPos, int lengthDoc, int initStyle, StyleWriter *styler); virtual bool OnDoubleClick(); virtual bool OnUpdateUI(); - virtual bool OnMarginClick(); + virtual bool OnMarginClick(int position, int margin); // fincs-edit virtual bool OnUserListSelection(int listType, const char *selection); virtual bool OnKey(int keyval, int modifiers); virtual bool OnDwellStart(int pos, const char *word); diff --git a/scite/src/MultiplexExtension.cxx b/scite/src/MultiplexExtension.cxx index 2924ff9..cb99ceb 100644 --- a/scite/src/MultiplexExtension.cxx +++ b/scite/src/MultiplexExtension.cxx @@ -197,10 +197,10 @@ bool MultiplexExtension::OnUpdateUI() { return handled; } -bool MultiplexExtension::OnMarginClick() { +bool MultiplexExtension::OnMarginClick(int p, int q) { // fincs-edit bool handled = false; for (int i = 0; i < extensionCount && !handled; ++i) - if (extensions[i]->OnMarginClick()) + if (extensions[i]->OnMarginClick(p, q)) // fincs-edit handled = true; return handled; } diff --git a/scite/src/MultiplexExtension.h b/scite/src/MultiplexExtension.h index 4886e00..3f3d6eb 100644 --- a/scite/src/MultiplexExtension.h +++ b/scite/src/MultiplexExtension.h @@ -64,7 +64,7 @@ public: virtual bool OnStyle(unsigned int, int, int, StyleWriter *); virtual bool OnDoubleClick(); virtual bool OnUpdateUI(); - virtual bool OnMarginClick(); + virtual bool OnMarginClick(int, int); // fincs-edit virtual bool OnMacro(const char *, const char *); virtual bool OnUserListSelection(int, const char *); diff --git a/scite/src/SciTE.h b/scite/src/SciTE.h index 0c89fe7..5126da3 100644 --- a/scite/src/SciTE.h +++ b/scite/src/SciTE.h @@ -9,9 +9,10 @@ #define SCITE_H // Version numbers and dates -#define VERSION_SCITE "3.3.4" -#define VERSION_WORDS 3, 3, 4, 0 -#define COPYRIGHT_DATES "December 1998-July 2013" +#define VERSION_SCITE "3.0.04" +#define VERSION_ORGSCITE "3.3.4" +#define VERSION_WORDS 3, 0, 4, 0 +#define COPYRIGHT_DATES "December 1998-August 2013" #define COPYRIGHT_YEARS "1998-2013" // Menu IDs. @@ -269,4 +270,8 @@ #define IDBM_BACKSLASH 104 #define IDBM_AROUND 105 #define IDBM_UP 106 +#define IDR_CLOSEFILE_BIG 107 #endif + +// fincs-edit +#define IDI_MAINICON 500 diff --git a/scite/src/SciTEBase.cxx b/scite/src/SciTEBase.cxx index 4b5f665..f1e56fa 100644 --- a/scite/src/SciTEBase.cxx +++ b/scite/src/SciTEBase.cxx @@ -170,6 +170,7 @@ SciTEBase::SciTEBase(Extension *ext) : apis(true), extender(ext) { bracesCheck = true; bracesSloppy = false; bracesStyle = 0; + bracesStyle2 = 0; braceCount = 0; indentationWSVisible = true; @@ -177,6 +178,7 @@ SciTEBase::SciTEBase(Extension *ext) : apis(true), extender(ext) { autoCompleteIgnoreCase = false; callTipUseEscapes = false; callTipIgnoreCase = false; + callTipSkipBareWords = false; autoCCausedByOnlyOne = false; startCalltipWord = 0; currentCallTip = 0; @@ -520,6 +522,7 @@ bool SciTEBase::FindMatchingBracePosition(bool editor, int &braceAtCaret, int &b return false; int bracesStyleCheck = editor ? bracesStyle : 0; + int bracesStyleCheck2 = editor ? bracesStyle2 : 0; int caretPos = win.Call(SCI_GETCURRENTPOS, 0, 0); braceAtCaret = -1; braceOpposite = -1; @@ -536,7 +539,7 @@ bool SciTEBase::FindMatchingBracePosition(bool editor, int &braceAtCaret, int &b } // Priority goes to character before caret if (charBefore && IsBrace(charBefore) && - ((styleBefore == bracesStyleCheck) || (!bracesStyle))) { + (((styleBefore == bracesStyleCheck) || (!bracesStyle)) || ((styleBefore == bracesStyleCheck2) || (!bracesStyle2)))) { braceAtCaret = caretPos - 1; } bool colonMode = false; @@ -552,7 +555,7 @@ bool SciTEBase::FindMatchingBracePosition(bool editor, int &braceAtCaret, int &b if (win.Send(SCI_POSITIONAFTER, caretPos) == (caretPos + 1)) { char charAfter = acc[caretPos]; char styleAfter = static_cast(acc.StyleAt(caretPos) & maskStyle); - if (charAfter && IsBrace(charAfter) && ((styleAfter == bracesStyleCheck) || (!bracesStyle))) { + if (charAfter && IsBrace(charAfter) && (((styleAfter == bracesStyleCheck) || (!bracesStyle)) || ((styleAfter == bracesStyleCheck2) || (!bracesStyle2)))) { braceAtCaret = caretPos; isAfter = false; } @@ -1390,10 +1393,18 @@ void SciTEBase::ToggleOutputVisible() { WindowSetFocus(wEditor); } else { if (previousHeightOutput < 20) { +#ifndef WIN32 if (splitVertical) heightOutput = NormaliseSplit(300); else heightOutput = NormaliseSplit(100); +#else + extern int g_ScreenDPI; + if (splitVertical) + heightOutput = NormaliseSplit(MulDiv(300, g_ScreenDPI, 96)); + else + heightOutput = NormaliseSplit(MulDiv(100, g_ScreenDPI, 96)); +#endif previousHeightOutput = heightOutput; } else { heightOutput = NormaliseSplit(previousHeightOutput); @@ -1469,10 +1480,12 @@ void SciTEBase::Redraw() { } char *SciTEBase::GetNearestWords(const char *wordStart, size_t searchLen, - const char *separators, bool ignoreCase /*=false*/, bool exactLen /*=false*/) { + const char *separators, bool ignoreCase /*=false*/, bool exactLen /*=false*/, + bool separatorIsRequired /*=false*/) { char *words = 0; while (!words && *separators) { - words = apis.GetNearestWords(wordStart, searchLen, ignoreCase, *separators, exactLen); + words = apis.GetNearestWords(wordStart, searchLen, ignoreCase, *separators, exactLen, + separatorIsRequired); separators++; } return words; @@ -1484,7 +1497,7 @@ void SciTEBase::FillFunctionDefinition(int pos /*= -1*/) { } if (apis) { char *words = GetNearestWords(currentCallTipWord.c_str(), currentCallTipWord.length(), - calltipParametersStart.c_str(), callTipIgnoreCase, true); + calltipParametersStart.c_str(), callTipIgnoreCase, true, callTipSkipBareWords); if (!words) return; // Counts how many call tips @@ -1498,7 +1511,7 @@ void SciTEBase::FillFunctionDefinition(int pos /*= -1*/) { // Should get current api definition const char *word = apis.GetNearestWord(currentCallTipWord.c_str(), currentCallTipWord.length(), - callTipIgnoreCase, calltipWordCharacters, currentCallTip); + callTipIgnoreCase, calltipWordCharacters, currentCallTip, callTipSkipBareWords); if (word) { functionDefinition = word; if (maxCallTips > 1) { @@ -1607,7 +1620,7 @@ void SciTEBase::ContinueCallTip() { commas--; // If it reached the end of the argument list it means that the user typed in more // arguments than the ones listed in the calltip - if (calltipParametersEnd.contains(functionDefinition[startHighlight])) + if (functionDefinition[startHighlight] && calltipParametersSeparators.contains(functionDefinition[startHighlight])) commas = 0; else startHighlight++; @@ -1678,7 +1691,8 @@ bool SciTEBase::StartAutoComplete() { SString root = line.substr(startword, current - startword); if (apis) { char *words = GetNearestWords(root.c_str(), root.length(), - calltipParametersStart.c_str(), autoCompleteIgnoreCase); + calltipParametersStart.c_str(), autoCompleteIgnoreCase, + false, false); if (words) { EliminateDuplicateWords(words); wEditor.Call(SCI_AUTOCSETSEPARATOR, ' '); @@ -3999,7 +4013,7 @@ void SciTEBase::Notify(SCNotification *notification) { case SCN_MARGINCLICK: { if (extender) - handled = extender->OnMarginClick(); + handled = extender->OnMarginClick(notification->position, notification->margin); // fincs-edit if (!handled) { if (notification->margin == 2) { MarginClick(notification->position, notification->modifiers); diff --git a/scite/src/SciTEBase.h b/scite/src/SciTEBase.h index f6bc98f..b42e378 100644 --- a/scite/src/SciTEBase.h +++ b/scite/src/SciTEBase.h @@ -214,6 +214,7 @@ public: enum { heightTools = 24, + heightToolsBig = 32, heightTab = 24, heightStatus = 20, statusPosWidth = 256 @@ -471,7 +472,7 @@ protected: bool twoPhaseDraw; bool bracesCheck; bool bracesSloppy; - int bracesStyle; + int bracesStyle, bracesStyle2; int braceCount; bool indentationWSVisible; @@ -485,6 +486,7 @@ protected: SString calltipParametersEnd; SString calltipParametersSeparators; SString calltipEndDefinition; + bool callTipSkipBareWords; SString autoCompleteStartCharacters; SString autoCompleteFillUpCharacters; SString wordCharacters; @@ -738,7 +740,8 @@ protected: void GoMessage(int dir); virtual bool StartCallTip(); char *GetNearestWords(const char *wordStart, size_t searchLen, - const char *separators, bool ignoreCase=false, bool exactLen=false); + const char *separators, bool ignoreCase=false, bool exactLen=false, + bool separatorIsRequired=false); virtual void FillFunctionDefinition(int pos = -1); void ContinueCallTip(); virtual void EliminateDuplicateWords(char *words); diff --git a/scite/src/SciTEBuffers.cxx b/scite/src/SciTEBuffers.cxx index 5864fff..6c0e108 100644 --- a/scite/src/SciTEBuffers.cxx +++ b/scite/src/SciTEBuffers.cxx @@ -823,6 +823,7 @@ void SciTEBase::SetIndentSettings() { int useTabs = props.GetInt("use.tabs", 1); int tabSize = props.GetInt("tabsize"); int indentSize = props.GetInt("indent.size"); + // Either set the settings related to the extension or the default ones SString fileNameForExtension = ExtensionFileName(); SString useTabsChars = props.GetNewExpand("use.tabs.", diff --git a/scite/src/SciTEProps.cxx b/scite/src/SciTEProps.cxx index 68494ac..7f75b5c 100644 --- a/scite/src/SciTEProps.cxx +++ b/scite/src/SciTEProps.cxx @@ -1004,6 +1004,8 @@ void SciTEBase::ReadProperties() { char bracesStyleKey[200]; sprintf(bracesStyleKey, "braces.%s.style", language.c_str()); bracesStyle = props.GetInt(bracesStyleKey, 0); + strcat(bracesStyleKey, "2"); + bracesStyle2 = props.GetInt(bracesStyleKey, 0); char key[200]; SString sval; @@ -1021,6 +1023,9 @@ void SciTEBase::ReadProperties() { calltipEndDefinition = FindLanguageProperty("calltip.*.end.definition"); + sval = FindLanguageProperty("calltip.*.skip.bare.words"); + callTipSkipBareWords = sval == "1"; + sprintf(key, "autocomplete.%s.start.characters", language.c_str()); autoCompleteStartCharacters = props.GetExpanded(key); if (autoCompleteStartCharacters == "") @@ -1488,6 +1493,11 @@ void SciTEBase::SetPropertiesInitial() { foldMargin = foldMarginWidth; if (foldMarginWidth == 0) foldMarginWidth = foldMarginWidthDefault; +#ifdef WIN32 + extern int g_ScreenDPI; + marginWidth = MulDiv(marginWidth, g_ScreenDPI, 96); + foldMarginWidth = MulDiv(foldMarginWidth, g_ScreenDPI, 96); +#endif matchCase = props.GetInt("find.replace.matchcase"); regExp = props.GetInt("find.replace.regexp"); @@ -1572,7 +1582,12 @@ void SciTEBase::ReadPropertiesInitial() { (splitVertical && (sizeHorizontal > 0) && (heightOutput < sizeHorizontal))) { previousHeightOutput = splitVertical ? sizeHorizontal : sizeVertical; if (!hideOutput) { +#ifndef WIN32 heightOutput = NormaliseSplit(previousHeightOutput); +#else + extern int g_ScreenDPI; + heightOutput = NormaliseSplit(MulDiv(previousHeightOutput, g_ScreenDPI, 96)); +#endif SizeSubWindows(); Redraw(); } diff --git a/scite/src/StringList.cxx b/scite/src/StringList.cxx index 4c4f8ab..b48ca0f 100644 --- a/scite/src/StringList.cxx +++ b/scite/src/StringList.cxx @@ -199,7 +199,7 @@ bool StringList::InList(const char *s) { * The length of the word to compare is passed too. * Letter case can be ignored or preserved (default). */ -const char *StringList::GetNearestWord(const char *wordStart, size_t searchLen, bool ignoreCase /*= false*/, SString wordCharacters /*='/0' */, int wordIndex /*= -1 */) { +const char *StringList::GetNearestWord(const char *wordStart, size_t searchLen, bool ignoreCase /*= false*/, SString wordCharacters /*='/0' */, int wordIndex /*= -1 */, bool skipBareWords /*= false*/) { int start = 0; // lower bound of the api array block to search int end = len - 1; // upper bound of the api array block to search int pivot; // index of api array element just being compared @@ -233,6 +233,12 @@ const char *StringList::GetNearestWord(const char *wordStart, size_t searchLen, for (pivot = start; pivot <= end; pivot++) { word = wordsNoCase[pivot]; if (!word[searchLen] || !wordCharacters.contains(word[searchLen])) { + if (skipBareWords) { + unsigned int i; + for (i = searchLen; (i < strlen(word)) && IsASpace(word[i]); i++); + if (!word[i]) + continue; + } if (wordIndex <= 0) // Checks if a specific index was requested return word; // result must not be freed with free() wordIndex--; @@ -271,6 +277,12 @@ const char *StringList::GetNearestWord(const char *wordStart, size_t searchLen, while (pivot <= end) { word = words[pivot]; if (!word[searchLen] || !wordCharacters.contains(word[searchLen])) { + if (skipBareWords) { + unsigned int i; + for (i = searchLen; (i < strlen(word)) && IsASpace(word[i]); i++); + if (!word[i]) + continue; + } if (wordIndex <= 0) // Checks if a specific index was requested return word; // result must not be freed with free() wordIndex--; @@ -294,7 +306,7 @@ const char *StringList::GetNearestWord(const char *wordStart, size_t searchLen, * there may be extra spaces after the identifier that should not be * counted in the length. */ -static unsigned int LengthWord(const char *word, char otherSeparator) { +static unsigned int LengthWord(const char *word, char otherSeparator, bool separatorIsRequired=false) { const char *endWord = 0; // Find an otherSeparator if (otherSeparator) @@ -302,7 +314,7 @@ static unsigned int LengthWord(const char *word, char otherSeparator) { // Find a '('. If that fails go to the end of the string. if (!endWord) endWord = strchr(word, '('); - if (!endWord) + if (!endWord && !separatorIsRequired) endWord = word + strlen(word); // Last case always succeeds so endWord != 0 @@ -332,7 +344,8 @@ char *StringList::GetNearestWords( size_t searchLen, bool ignoreCase /*= false*/, char otherSeparator /*= '\0'*/, - bool exactLen /*=false*/) { + bool exactLen /*=false*/, + bool separatorIsRequired /*=false*/) { unsigned int wordlen; // length of the word part (before the '(' brace) of the api array element SString wordsNear; wordsNear.setsizegrowth(1000); @@ -362,7 +375,7 @@ char *StringList::GetNearestWords( while ((pivot <= end) && (0 == CompareNCaseInsensitive(wordStart, wordsNoCase[pivot], searchLen))) { - wordlen = LengthWord(wordsNoCase[pivot], otherSeparator) + 1; + wordlen = LengthWord(wordsNoCase[pivot], otherSeparator, separatorIsRequired) + 1; ++pivot; if (exactLen && wordlen != LengthWord(wordStart, otherSeparator) + 1) continue; @@ -394,7 +407,7 @@ char *StringList::GetNearestWords( while ((pivot <= end) && (0 == strncmp(wordStart, words[pivot], searchLen))) { - wordlen = LengthWord(words[pivot], otherSeparator) + 1; + wordlen = LengthWord(words[pivot], otherSeparator, separatorIsRequired) + 1; ++pivot; if (exactLen && wordlen != LengthWord(wordStart, otherSeparator) + 1) continue; diff --git a/scite/src/StringList.h b/scite/src/StringList.h index bdab39f..bd4a5ac 100644 --- a/scite/src/StringList.h +++ b/scite/src/StringList.h @@ -29,8 +29,10 @@ public: bool InList(const char *s); //bool InListAbbreviated(const char *s, const char marker); const char *GetNearestWord(const char *wordStart, size_t searchLen, - bool ignoreCase = false, SString wordCharacters="", int wordIndex = -1); + bool ignoreCase = false, SString wordCharacters="", int wordIndex = -1, + bool skipBareWords = false); char *GetNearestWords(const char *wordStart, size_t searchLen, - bool ignoreCase=false, char otherSeparator='\0', bool exactLen=false); + bool ignoreCase=false, char otherSeparator='\0', bool exactLen=false, + bool separatorIsRequired=false); }; diff --git a/scite/win32/MessagePump.cxx b/scite/win32/MessagePump.cxx new file mode 100644 index 0000000..a415252 --- /dev/null +++ b/scite/win32/MessagePump.cxx @@ -0,0 +1,166 @@ +// SciTE4AutoHotkey v3 Lua message pumper + +// Includes +#include +#include +extern "C" +{ +#include "lauxlib.h" +} + +// Some defines +#define RET_OK 1 +#define RET_FAIL 0 +#define MAX_TITLE 255 + +// Global variables +static HWND cWindow = 0, tWindow = 0; +static const char* cWinTitle; // variable pointer to constant char + +// Private callback function to enumerate the windows. +static BOOL CALLBACK _lib_winsearchproc(HWND hWnd, LPARAM lParam) +{ + char wTitle[MAX_TITLE+1]; + // Get window title + GetWindowTextA(hWnd, wTitle, MAX_TITLE); + if (strncmp(wTitle, cWinTitle, lParam) == 0) + { + // Window found. + cWindow = hWnd; + return 0; // Cancel the enumeration + } + return 1; // Continue enumerating the windows +} + +// localizewin(wintitle) -- Localizes the window with the specified window title to +// further send messages to it. True = sucess, false = failure. +static int lib_localizewin(lua_State* L) +{ + // set the global variables + cWinTitle = luaL_checkstring(L, 1); + tWindow = cWindow, cWindow = 0; + + // look for the window + EnumWindows((WNDENUMPROC)_lib_winsearchproc, strlen(cWinTitle)); + if (!cWindow) // no window found? + { + // just restore the old window and return false. + cWindow = tWindow; + lua_pushboolean(L, RET_FAIL); + return 1; + } + // return true. + lua_pushboolean(L, RET_OK); + return 1; +} + +// pumpmsg(msg, wParam, lParam) -- Sends a message to the current window. +static int lib_pumpmsg(lua_State* L) +{ + int result; + + // get the parameters + int iMsg = luaL_checkint(L, 1); + int wParam = luaL_checkint(L, 2); + int lParam = luaL_checkint(L, 3); + + if (!IsWindow(cWindow)) // invalid window? + return luaL_error(L, "Invalid window handle."); + + // just dispatch the message to the window + result = (int) SendMessageA(cWindow, (UINT)iMsg, (WPARAM)wParam, (LPARAM)lParam); + + // return the number that the window gave to us + lua_pushinteger(L, result); + return 1; +} + +// postmsg(msg, wParam, lParam) -- Posts a message to the current window. +static int lib_postmsg(lua_State* L) +{ + int result; + + // get the parameters + int iMsg = luaL_checkint(L, 1); + int wParam = luaL_checkint(L, 2); + int lParam = luaL_checkint(L, 3); + + if (!IsWindow(cWindow)) // invalid window? + return luaL_error(L, "Invalid window handle."); + + // just dispatch the message to the window + result = PostMessageA(cWindow, (UINT)iMsg, (WPARAM)wParam, (LPARAM)lParam); + + // return the return code + lua_pushboolean(L, result); + return 1; +} + +// pumpmsg(msg, wparam, lparam) -- Sends a message in which lParam will be received as a string. +static int lib_pumpmsgstr(lua_State* L) +{ + DWORD pID; + HANDLE hProcess; + void* rlParam; + int result; + + // get the parameters + int iMsg = luaL_checkint(L, 1); + int wParam = luaL_checkint(L, 2); + const char* lParam = luaL_checkstring(L, 3); + // get the string length + size_t lParamSize = strlen(lParam) + 1; + + if (!IsWindow(cWindow)) // invalid window? + return luaL_error(L, "Invalid window handle."); + + // inject the string at the process. + GetWindowThreadProcessId(cWindow, &pID); + hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, pID); + if (!hProcess) + return luaL_error(L, "Couldn't open the memory of the window!"); + rlParam = VirtualAllocEx(hProcess, 0, lParamSize, MEM_COMMIT, PAGE_READWRITE); + if (!rlParam) + return luaL_error(L, "Couldn't allocate the memory at the window!"); + if (!WriteProcessMemory(hProcess, rlParam, lParam, lParamSize, NULL)) + return luaL_error(L, "Couldn't inject the string parameter at the window!"); + + // just dispatch the message to the window + result = (int) SendMessageA(cWindow, (UINT)iMsg, (WPARAM)wParam, (LPARAM)rlParam); + + // free the memory used by the string + if (!VirtualFreeEx(hProcess, rlParam, 0, MEM_RELEASE)) + return luaL_error(L, "Failed to free the memory at the window!"); + if (!CloseHandle(hProcess)) + return luaL_error(L, "Couldn't close the process handle!"); + + // return the number that the window gave to us + lua_pushinteger(L, result); + return 1; +} + +// sleep(time) -- sleeps for the specified amount of time +static int lib_sleep(lua_State* L) +{ + Sleep(luaL_checkint(L, 1)); + return 0; +} + +static const luaL_Reg pumpLib[] = +{ + { "localizewin", lib_localizewin }, + { "pumpmsg", lib_pumpmsg }, + { "pumpmsgstr", lib_pumpmsgstr }, + { "postmsg", lib_postmsg }, + { "sleep", lib_sleep }, + { NULL, NULL } +}; + +int MessagePumpLibInit(lua_State* L) +{ + // register the library's functions in the Lua engine + for (const luaL_Reg* it = pumpLib; it->name; it ++) + lua_register(L, it->name, it->func); + + return 0; +} diff --git a/scite/win32/SciBall.ico b/scite/win32/SciBall.ico index 28b4ff4..bd241a7 100644 Binary files a/scite/win32/SciBall.ico and b/scite/win32/SciBall.ico differ diff --git a/scite/win32/SciTERes.rc b/scite/win32/SciTERes.rc index 66423ed..ac9fb85 100644 --- a/scite/win32/SciTERes.rc +++ b/scite/win32/SciTERes.rc @@ -6,7 +6,9 @@ #include "SciTE.h" -SciTE ICON SciBall.ico +// fincs-edit +//SciTE ICON SciBall.ico +IDI_MAINICON ICON SciBall.ico 1 RT_MANIFEST SciTE.exe.manifest @@ -176,12 +178,11 @@ END POPUP "&Help" BEGIN MENUITEM "&Help\tF1", IDM_HELP + MENUITEM "&SciTE4AutoHotkey Help", IDM_HELP_SCITE #ifdef STATIC_BUILD - MENUITEM "&Sc1 Help", IDM_HELP_SCITE - MENUITEM "&About Sc1", IDM_ABOUT + MENUITEM "&About SciTE4AutoHotkey Lite", IDM_ABOUT #else - MENUITEM "&SciTE Help", IDM_HELP_SCITE - MENUITEM "&About SciTE", IDM_ABOUT + MENUITEM "&About SciTE4AutoHotkey", IDM_ABOUT #endif END @@ -193,7 +194,8 @@ STYLE DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSME FONT 8, "MS Shell Dlg" BEGIN CONTROL "", IDABOUTSCINTILLA, "Scintilla", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 1, 1, 346, 218 - ICON "SciTE", -1, 1, 221, 32, 32, WS_CHILD | WS_VISIBLE + //ICON "SciTE", -1, 1, 221, 32, 32, WS_CHILD | WS_VISIBLE + ICON IDI_MAINICON, -1, 1, 221, 32, 32, WS_CHILD | WS_VISIBLE // fincs-edit DEFPUSHBUTTON "OK", IDOK, 26, 222, 322, 20, WS_TABSTOP END @@ -560,6 +562,7 @@ BEGIN END IDR_CLOSEFILE BITMAP "closefile.bmp" +IDR_CLOSEFILE_BIG BITMAP "closefile_big.bmp" IDBM_WORD BITMAP "word.bmp" IDBM_CASE BITMAP "case.bmp" IDBM_REGEX BITMAP "regex.bmp" @@ -590,13 +593,13 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "CompanyName", "Neil Hodgson neilh@scintilla.org\0" - VALUE "FileDescription", "SciTE - a Scintilla based Text Editor\0" + VALUE "CompanyName", "fincs @ autohotkey.com forum / Original SciTE by Neil Hodgson: neilh@scintilla.org\0" + VALUE "FileDescription", "SciTE4AutoHotkey - a SciTE distribution for AutoHotkey\0" VALUE "FileVersion", VERSION_SCITE "\0" - VALUE "InternalName", "SciTE\0" - VALUE "LegalCopyright", "Copyright " COPYRIGHT_YEARS " by Neil Hodgson\0" - VALUE "OriginalFilename", "SciTE.EXE\0" - VALUE "ProductName", "SciTE\0" + VALUE "InternalName", "SciTE4AutoHotkey\0" + VALUE "LegalCopyright", "SciTE is (c) 1998-2013 by Neil Hodgson, the AutoHotkey distribution is (c) 2007-2013 by fincs\0" + VALUE "OriginalFilename", "SciTE.exe\0" + VALUE "ProductName", "SciTE4AutoHotkey\0" VALUE "ProductVersion", VERSION_SCITE "\0" END END diff --git a/scite/win32/SciTEWin.cxx b/scite/win32/SciTEWin.cxx index d2c9c90..b76483a 100644 --- a/scite/win32/SciTEWin.cxx +++ b/scite/win32/SciTEWin.cxx @@ -53,9 +53,9 @@ #endif #ifdef STATIC_BUILD -const GUI::gui_char appName[] = GUI_TEXT("Sc1"); +const GUI::gui_char appName[] = GUI_TEXT("SciTE4AutoHotkey Lite"); // fincs-edit #else -const GUI::gui_char appName[] = GUI_TEXT("SciTE"); +const GUI::gui_char appName[] = GUI_TEXT("SciTE4AutoHotkey"); // fincs-edit #endif static GUI::gui_string GetErrorMessage(DWORD nRet) { @@ -213,6 +213,11 @@ SciTEWin::SciTEWin(Extension *ext) : SciTEBase(ext) { // System type properties are also stored in the embedded properties. propsEmbed.Set("PLAT_WIN", "1"); propsEmbed.Set("PLAT_WINNT", "1"); +#ifdef _WIN64 + propsEmbed.Set("PLAT_WIN64", "1"); +#else + propsEmbed.Set("PLAT_WIN32", "1"); +#endif HRSRC handProps = ::FindResource(hInstance, TEXT("Embedded"), TEXT("Properties")); if (handProps) { @@ -274,12 +279,14 @@ void SciTEWin::Register(HINSTANCE hInstance_) { // Register the frame window className = TEXT("SciTEWindow"); - wndclass.style = 0; + wndclass.style = CS_DBLCLKS; // fincs-edit wndclass.lpfnWndProc = SciTEWin::TWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = sizeof(SciTEWin*); wndclass.hInstance = hInstance; - wndclass.hIcon = ::LoadIcon(hInstance, resourceName); + // fincs-edit + //wndclass.hIcon = ::LoadIcon(hInstance, resourceName); + wndclass.hIcon = (HICON) ::LoadImage(hInstance, MAKEINTRESOURCE(IDI_MAINICON), IMAGE_ICON, 0, 0, LR_SHARED); wndclass.hCursor = NULL; wndclass.hbrBackground = NULL; wndclass.lpszMenuName = resourceName; @@ -426,10 +433,51 @@ FilePath SciTEWin::GetSciteDefaultHome() { return GetSciTEPath(home); } +// fincs-edit START +bool _IsPortable() +{ + wchar_t aBuf[MAX_PATH+1]; + wchar_t* aBufPtr = aBuf; + + GetModuleFileNameW(NULL, aBuf, MAX_PATH+1); + aBufPtr += wcslen(aBuf); + while(*--aBufPtr != '\\'); + wcscpy(aBufPtr+1, L"$PORTABLE"); + + return GetFileAttributes(aBuf) != INVALID_FILE_ATTRIBUTES; +} +// fincs-edit END + FilePath SciTEWin::GetSciteUserHome() { + bool is_portable = _IsPortable(); // fincs-edit + GUI::gui_char *home = _wgetenv(GUI_TEXT("SciTE_HOME")); if (!home) - home = _wgetenv(GUI_TEXT("USERPROFILE")); + { // fincs-edit START + WCHAR szPath[MAX_PATH+1]; + bool success = false; + + if(!is_portable) + { + if(SUCCEEDED(::SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, 0, szPath))) + { + ::PathAppendW(szPath, GUI_TEXT("AutoHotkey\\SciTE")); + home = szPath; + success = true; + } + }else + { + ::GetModuleFileNameW(NULL, szPath, MAX_PATH+1); + ::PathRemoveFileSpecW(szPath); + ::PathAppendW(szPath, GUI_TEXT("user")); + home = szPath; + success = true; + } + + if(!success) + home = _wgetenv(GUI_TEXT("USERPROFILE")); + } // fincs-edit END + return GetSciTEPath(home); } @@ -588,6 +636,10 @@ HWND SciTEWin::MainHWND() { return HwndOf(wSciTE); } +HWND SciTEWin::ToolHWND() { // fincs-edit + return reinterpret_cast(wToolBar.GetID()); // fincs-edit +} // fincs-edit + void SciTEWin::Command(WPARAM wParam, LPARAM lParam) { int cmdID = ControlIDOfWParam(wParam); if (wParam & 0x10000) { @@ -1466,6 +1518,18 @@ void SciTEWin::Run(const GUI::gui_char *cmdLine) { return; // Don't do anything else } +#ifndef STATIC_BUILD + // fincs-edit + do + { + SString autorun = props.GetExpanded("command.autorun"); + if (autorun.length() == 0) + break; + + ShellExec(autorun, ""); + } while(0); +#endif + // OK, the instance will be displayed SizeSubWindows(); wSciTE.Show(); @@ -1897,6 +1961,10 @@ LRESULT SciTEWin::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { WorkerCommand(static_cast(wParam), reinterpret_cast(lParam)); break; + case WM_LBUTTONDBLCLK: // fincs-edit + ::SendMessage(MainHWND(), WM_COMMAND, IDM_NEW, 0); + return 0; + case WM_NOTIFY: Notify(reinterpret_cast(lParam)); break; @@ -1990,6 +2058,15 @@ LRESULT SciTEWin::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { case WM_COPYDATA: return uniqueInstance.CopyData(reinterpret_cast(lParam)); + case WM_USER: // fincs-edit + SIZE uTSize; // fincs-edit + ::SendMessage(ToolHWND(), TB_GETMAXSIZE, 0, (LPARAM)&uTSize); // fincs-edit + return (LRESULT) uTSize.cx; // fincs-edit + + case WM_USER+1: // fincs-edit + ReloadProperties(); // fincs-edit + return 0l; // fincs-edit + default: return ::DefWindowProcW(MainHWND(), iMessage, wParam, lParam); } @@ -3858,6 +3935,20 @@ uptr_t SciTEWin::EventLoop() { return msg.wParam; } +// fincs-edit START + +static int GetScreenDPI() +{ + HDC hdc = GetDC(NULL); + int dpi = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(NULL, hdc); + return dpi; +} + +int g_ScreenDPI = GetScreenDPI(); + +// fincs-edit END + int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { typedef BOOL (WINAPI *SetDllDirectorySig)(LPCTSTR lpPathName); @@ -3887,13 +3978,12 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { #endif SciTEWin::Register(hInstance); -#ifdef STATIC_BUILD +#ifdef STATIC_BUILD Scintilla_LinkLexers(); Scintilla_RegisterClasses(hInstance); #else - - HMODULE hmod = ::LoadLibrary(TEXT("SciLexer.DLL")); + HMODULE hmod = ::LoadLibrary(TEXT("SciLexer.dll")); if (hmod == NULL) ::MessageBox(NULL, TEXT("The Scintilla DLL could not be loaded. SciTE will now close"), TEXT("Error loading Scintilla"), MB_OK | MB_ICONERROR); diff --git a/scite/win32/SciTEWin.h b/scite/win32/SciTEWin.h index 6e44d17..e871b0e 100644 --- a/scite/win32/SciTEWin.h +++ b/scite/win32/SciTEWin.h @@ -50,12 +50,13 @@ typedef void *HTHEME; #endif #include #include -#include #include #include #include #include +#include // fincs-edit +#include // fincs-edit #ifdef _MSC_VER #include #endif @@ -506,6 +507,7 @@ protected: void FullScreenToggle(); void Command(WPARAM wParam, LPARAM lParam); HWND MainHWND(); + HWND ToolHWND(); // fincs-edit virtual void UserStripShow(const char *description); virtual void UserStripSet(int control, const char *value); diff --git a/scite/win32/SciTEWinBar.cxx b/scite/win32/SciTEWinBar.cxx index 26e1354..1526f4d 100644 --- a/scite/win32/SciTEWinBar.cxx +++ b/scite/win32/SciTEWinBar.cxx @@ -869,6 +869,11 @@ void SciTEWin::Creation() { wOutput.Call(SCI_USEPOPUP, 0); ::DragAcceptFiles(MainHWND(), true); + extern int g_ScreenDPI; + bool bHasHighDPI = g_ScreenDPI >= 120; + int trueHeightTools = bHasHighDPI ? heightToolsBig : heightTools; + int imgSize = bHasHighDPI ? 24 : 16; + HWND hwndToolBar = ::CreateWindowEx( 0, TOOLBARCLASSNAME, @@ -876,7 +881,7 @@ void SciTEWin::Creation() { WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_NORESIZE, 0, 0, - 100, heightTools, + 100, trueHeightTools, MainHWND(), reinterpret_cast(IDM_TOOLWIN), hInstance, @@ -884,10 +889,11 @@ void SciTEWin::Creation() { wToolBar = hwndToolBar; ::SendMessage(hwndToolBar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); - ::SendMessage(hwndToolBar, TB_LOADIMAGES, IDB_STD_SMALL_COLOR, + ::SendMessage(hwndToolBar, TB_SETBITMAPSIZE, 0, MAKELONG(imgSize, imgSize)); + ::SendMessage(hwndToolBar, TB_LOADIMAGES, bHasHighDPI ? IDB_STD_LARGE_COLOR : IDB_STD_SMALL_COLOR, reinterpret_cast(HINST_COMMCTRL)); - TBADDBITMAP addbmp = { hInstance, IDR_CLOSEFILE }; + TBADDBITMAP addbmp = { hInstance, bHasHighDPI ? IDR_CLOSEFILE_BIG : IDR_CLOSEFILE }; ::SendMessage(hwndToolBar, TB_ADDBITMAP, 1, (LPARAM)&addbmp); TBBUTTON tbb[ELEMENTS(bbs)]; @@ -1036,7 +1042,7 @@ void SciTEWin::Creation() { SB_SETPARTS, 1, reinterpret_cast(widths)); - bands.push_back(Band(true, heightTools, false, wToolBar)); + bands.push_back(Band(true, trueHeightTools, false, wToolBar)); bands.push_back(Band(true, heightTab, false, wTabBar)); bands.push_back(Band(true, 100, true, wContent)); bands.push_back(Band(true, userStrip.Height(), false, userStrip)); diff --git a/scite/win32/SciTEWinDlg.cxx b/scite/win32/SciTEWinDlg.cxx index 27383e0..6318061 100644 --- a/scite/win32/SciTEWinDlg.cxx +++ b/scite/win32/SciTEWinDlg.cxx @@ -242,6 +242,11 @@ bool SciTEWin::OpenDialog(FilePath directory, const GUI::gui_char *filter) { if (props.GetInt("open.dialog.in.file.directory")) { ofn.lpstrInitialDir = directory.AsInternal(); } + // fincs-edit START + GUI::gui_string defExt = GUI::StringFromUTF8(props.GetExpanded("default.file.ext").c_str()); + if (defExt.length() > 0) + ofn.lpstrDefExt = defExt.c_str() + 1; + // fincs-edit END ofn.Flags = OFN_HIDEREADONLY; if (buffers.size > 1) { @@ -291,6 +296,11 @@ FilePath SciTEWin::ChooseSaveName(FilePath directory, const char *title, const G ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR; ofn.lpstrFilter = filter; ofn.lpstrInitialDir = directory.AsInternal(); + // fincs-edit START + GUI::gui_string defExt = GUI::StringFromUTF8(props.GetExpanded("default.file.ext").c_str()); + if (defExt.length() > 0) + ofn.lpstrDefExt = defExt.c_str() + 1; + // fincs-edit END dialogsOnScreen++; if (::GetSaveFileNameW(&ofn)) { @@ -1668,7 +1678,7 @@ BOOL SciTEWin::AboutMessage(HWND hDlg, UINT message, WPARAM wParam) { LONG_PTR subclassedProc = ::SetWindowLongPtr(hwndCredits, GWLP_WNDPROC, reinterpret_cast(CreditsWndProc)); ::SetWindowLongPtr(hwndCredits, GWLP_USERDATA, subclassedProc); ss.SetID(hwndCredits); - SetAboutMessage(ss, staticBuild ? "Sc1 " : "SciTE"); + SetAboutMessage(ss, staticBuild ? "SciTE4AutoHotkey Lite" : "SciTE4AutoHotkey"); // fincs-edit } return TRUE; diff --git a/scite/win32/closefile.bmp b/scite/win32/closefile.bmp index 1050a29..2aabd4f 100644 Binary files a/scite/win32/closefile.bmp and b/scite/win32/closefile.bmp differ diff --git a/scite/win32/closefile_big.bmp b/scite/win32/closefile_big.bmp new file mode 100644 index 0000000..37268aa Binary files /dev/null and b/scite/win32/closefile_big.bmp differ