From 1c1c311db981ed200f951328fdb60dfe6868e0d8 Mon Sep 17 00:00:00 2001 From: Skif-off Date: Wed, 30 Mar 2016 11:36:20 +0400 Subject: [PATCH 1/3] Add: AutoIt syntax highlighting --- data/Makefile.am | 3 +- data/filedefs/filetypes.autoit | 98 ++++ data/filetype_extensions.conf | 1 + scintilla/Makefile.am | 1 + scintilla/lexers/LexAU3.cxx | 910 ++++++++++++++++++++++++++++++ scintilla/scintilla_changes.patch | 4 +- scintilla/src/Catalogue.cxx | 1 + src/filetypes.c | 1 + src/filetypes.h | 1 + src/highlighting.c | 9 + src/highlightingmappings.h | 35 ++ 11 files changed, 1061 insertions(+), 3 deletions(-) create mode 100644 data/filedefs/filetypes.autoit create mode 100644 scintilla/lexers/LexAU3.cxx diff --git a/data/Makefile.am b/data/Makefile.am index f9e2a632c7..8184b976a7 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -70,7 +70,8 @@ filetypes = \ filedefs/filetypes.vhdl \ filedefs/filetypes.xml \ filedefs/filetypes.yaml \ - filedefs/filetypes.zephir + filedefs/filetypes.zephir \ + filedefs/filetypes.autoit tagfiles = \ tags/c99.tags \ diff --git a/data/filedefs/filetypes.autoit b/data/filedefs/filetypes.autoit new file mode 100644 index 0000000000..a7107ac6b9 --- /dev/null +++ b/data/filedefs/filetypes.autoit @@ -0,0 +1,98 @@ +# For complete documentation of this file, please see Geany's main documentation +# AutoIt 3.3.14.2 +[styling] +# Edit these in the colorscheme .conf file instead +default=default +comment=comment +commentblock=comment +number=number,bold,italic +function=function,bold,italic +keyword=type +macro=preprocessor,bold +string=string +operator=operator,bold +variable=keyword_2 +sent=0xd77100;;true;false +preprocessor=preprocessor,italic +special=type +expand=default +comobj=keyword_1,italic +udf=class,italic + +# SciTE-like with Default "built-in" color scheme +#default=0x000000;0xffffff;false;false +#comment=0x009933;0xffffff;false;true +#commentblock=0x669900;0xffffff;false;true +#number=0xac00a9;0xffffff;true;true +#function=0x000090;0xffffff;true;true +#keyword=0x0000ff;0xffffff;true;false +#macro=0xff33ff;0xffffff;true;false +#string=0x9999cc;0xffffff;true;false +#operator=0xff0000;0xffffff;true;false +#variable=0xaa0000;0xffffff;true;false +#sent=0xff8800;0xffffff;true;false +#preprocessor=0xf000ff;0xffffff;false;true +#special=0xa00ff0;0xffffff;false;true +#expand=0xff0000;0xffffff;true;false +#comobj=0x0000ff;0xffffff;true;true +#udf=0xdd9900;0xffffff;false;false + +[keywords] +keywords=and byref case const continuecase continueloop default dim do else elseif endfunc endif endselect endswitch endwith enum exit exitloop false for func global if in local next not null or redim return select static step switch then to true until volatile wend while with +functions=abs acos adlibregister adlibunregister asc ascw asin assign atan autoitsetoption autoitwingettitle autoitwinsettitle beep binary binarylen binarymid binarytostring bitand bitnot bitor bitrotate bitshift bitxor blockinput break call cdtray ceiling chr chrw clipget clipput consoleread consolewrite consolewriteerror controlclick controlcommand controldisable controlenable controlfocus controlgetfocus controlgethandle controlgetpos controlgettext controlhide controllistview controlmove controlsend controlsettext controlshow controltreeview cos dec dircopy dircreate dirgetsize dirmove dirremove dllcall dllcalladdress dllcallbackfree dllcallbackgetptr dllcallbackregister dllclose dllopen dllstructcreate dllstructgetdata dllstructgetptr dllstructgetsize dllstructsetdata drivegetdrive drivegetfilesystem drivegetlabel drivegetserial drivegettype drivemapadd drivemapdel drivemapget drivesetlabel drivespacefree drivespacetotal drivestatus envget envset envupdate eval execute exp filechangedir fileclose filecopy filecreatentfslink filecreateshortcut filedelete fileexists filefindfirstfile filefindnextfile fileflush filegetattrib filegetencoding filegetlongname filegetpos filegetshortcut filegetshortname filegetsize filegettime filegetversion fileinstall filemove fileopen fileopendialog fileread filereadline filereadtoarray filerecycle filerecycleempty filesavedialog fileselectfolder filesetattrib filesetend filesetpos filesettime filewrite filewriteline floor ftpsetproxy funcname guicreate guictrlcreateavi guictrlcreatebutton guictrlcreatecheckbox guictrlcreatecombo guictrlcreatecontextmenu guictrlcreatedate guictrlcreatedummy guictrlcreateedit guictrlcreategraphic guictrlcreategroup guictrlcreateicon guictrlcreateinput guictrlcreatelabel guictrlcreatelist guictrlcreatelistview guictrlcreatelistviewitem guictrlcreatemenu guictrlcreatemenuitem guictrlcreatemonthcal guictrlcreateobj guictrlcreatepic guictrlcreateprogress guictrlcreateradio guictrlcreateslider guictrlcreatetab guictrlcreatetabitem guictrlcreatetreeview guictrlcreatetreeviewitem guictrlcreateupdown guictrldelete guictrlgethandle guictrlgetstate guictrlread guictrlrecvmsg guictrlregisterlistviewsort guictrlsendmsg guictrlsendtodummy guictrlsetbkcolor guictrlsetcolor guictrlsetcursor guictrlsetdata guictrlsetdefbkcolor guictrlsetdefcolor guictrlsetfont guictrlsetgraphic guictrlsetimage guictrlsetlimit guictrlsetonevent guictrlsetpos guictrlsetresizing guictrlsetstate guictrlsetstyle guictrlsettip guidelete guigetcursorinfo guigetmsg guigetstyle guiregistermsg guisetaccelerators guisetbkcolor guisetcoord guisetcursor guisetfont guisethelp guiseticon guisetonevent guisetstate guisetstyle guistartgroup guiswitch hex hotkeyset httpsetproxy httpsetuseragent hwnd inetclose inetget inetgetinfo inetgetsize inetread inidelete iniread inireadsection inireadsectionnames inirenamesection iniwrite iniwritesection inputbox int isadmin isarray isbinary isbool isdeclared isdllstruct isfloat isfunc ishwnd isint iskeyword isnumber isobj isptr isstring log memgetstats mod mouseclick mouseclickdrag mousedown mousegetcursor mousegetpos mousemove mouseup mousewheel msgbox number objcreate objcreateinterface objevent objevent objget objname onautoitexitregister onautoitexitunregister opt ping pixelchecksum pixelgetcolor pixelsearch processclose processexists processgetstats processlist processsetpriority processwait processwaitclose progressoff progresson progressset ptr random regdelete regenumkey regenumval regread regwrite round run runas runaswait runwait send sendkeepactive seterror setextended shellexecute shellexecutewait shutdown sin sleep soundplay soundsetwavevolume splashimageon splashoff splashtexton sqrt srandom statusbargettext stderrread stdinwrite stdioclose stdoutread string stringaddcr stringcompare stringformat stringfromasciiarray stringinstr stringisalnum stringisalpha stringisascii stringisdigit stringisfloat stringisint stringislower stringisspace stringisupper stringisxdigit stringleft stringlen stringlower stringmid stringregexp stringregexpreplace stringreplace stringreverse stringright stringsplit stringstripcr stringstripws stringtoasciiarray stringtobinary stringtrimleft stringtrimright stringupper tan tcpaccept tcpclosesocket tcpconnect tcplisten tcpnametoip tcprecv tcpsend tcpshutdown tcpstartup timerdiff timerinit tooltip traycreateitem traycreatemenu traygetmsg trayitemdelete trayitemgethandle trayitemgetstate trayitemgettext trayitemsetonevent trayitemsetstate trayitemsettext traysetclick trayseticon traysetonevent traysetpauseicon traysetstate traysettooltip traytip ubound udpbind udpclosesocket udpopen udprecv udpsend udpshutdown udpstartup vargettype winactivate winactive winclose winexists winflash wingetcaretpos wingetclasslist wingetclientsize wingethandle wingetpos wingetprocess wingetstate wingettext wingettitle winkill winlist winmenuselectitem winminimizeall winminimizeallundo winmove winsetontop winsetstate winsettitle winsettrans winwait winwaitactive winwaitclose winwaitnotactive +macros=@appdatacommondir @appdatadir @autoitexe @autoitpid @autoitversion @autoitx64 @com_eventobj @commonfilesdir @compiled @computername @comspec @cpuarch @cr @crlf @desktopcommondir @desktopdepth @desktopdir @desktopheight @desktoprefresh @desktopwidth @documentscommondir @error @exitcode @exitmethod @extended @favoritescommondir @favoritesdir @gui_ctrlhandle @gui_ctrlid @gui_dragfile @gui_dragid @gui_dropid @gui_winhandle @homedrive @homepath @homeshare @hotkeypressed @hour @ipaddress1 @ipaddress2 @ipaddress3 @ipaddress4 @kblayout @lf @localappdatadir @logondnsdomain @logondomain @logonserver @mday @min @mon @msec @muilang @mydocumentsdir @numparams @osarch @osbuild @oslang @osservicepack @ostype @osversion @programfilesdir @programscommondir @programsdir @scriptdir @scriptfullpath @scriptlinenumber @scriptname @sec @startmenucommondir @startmenudir @startupcommondir @startupdir @sw_disable @sw_enable @sw_hide @sw_lock @sw_maximize @sw_minimize @sw_restore @sw_show @sw_showdefault @sw_showmaximized @sw_showminimized @sw_showminnoactive @sw_showna @sw_shownoactivate @sw_shownormal @sw_unlock @systemdir @tab @tempdir @tray_id @trayiconflashing @trayiconvisible @username @userprofiledir @wday @windowsdir @workingdir @yday @year +sent={!} {#} {^} {{} {}} {+} {alt} {altdown} {altup} {appskey} {asc} {backspace} {break} {browser_back} {browser_favorites} {browser_forward} {browser_home} {browser_refresh} {browser_search} {browser_stop} {bs} {capslock} {ctrldown} {ctrlup} {del} {delete} {down} {end} {enter} {esc} {escape} {f1} {f10} {f11} {f12} {f2} {f3} {f4} {f5} {f6} {f7} {f8} {f9} {home} {ins} {insert} {lalt} {launch_app1} {launch_app2} {launch_mail} {launch_media} {lctrl} {left} {lshift} {lwin} {lwindown} {lwinup} {media_next} {media_play_pause} {media_prev} {media_stop} {numlock} {numpad0} {numpad1} {numpad2} {numpad3} {numpad4} {numpad5} {numpad6} {numpad7} {numpad8} {numpad9} {numpadadd} {numpaddiv} {numpaddot} {numpadenter} {numpadmult} {numpadsub} {oem_102} {pause} {pgdn} {pgup} {printscreen} {ralt} {rctrl} {right} {rshift} {rwin} {rwindown} {rwinup} {scrolllock} {shiftdown} {shiftup} {sleep} {space} {tab} {up} {volume_down} {volume_mute} {volume_up} +preprocessor=#ce #comments-end #comments-start #cs #include #include-once #notrayicon #onautoitstartregister #requireadmin +special=#endregion #forcedef #forceref #ignorefunc #pragma #region +expand= +udf=_arrayadd _arraybinarysearch _arraydelete _arraydisplay + +[lexer_properties] +#settings for folding comment blocks and preprocessor lines +#lexer.au3.fold.comment=1 +#lexer.au3.fold.compact=1 +#lexer.au3.fold.preprocessor=0 + +[settings] +# default extension used when saving files +extension=au3 + +# MIME type + +# which characters should be skipped when moving (or included when deleting) to word boundaries +# should always include space and tab (\s\t) +whitespace_chars=\s\t!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~ +# the following characters are these which a "word" can contains, see documentation +wordchars=_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 + +# single comments, like # in this file +comment_single=; +# multiline comments +comment_open=#cs +comment_close=#ce +# or alternatively +#comment_open=#comments-start +#comment_close=#comments-end + +# set to false if a comment character/string should start at column 0 of a line, true uses any +# indentation of the line, e.g. setting to true causes the following on pressing CTRL+d + #command_example(); +# setting to false would generate this +# command_example(); +# This setting works only for single line comments +comment_use_indent=true + +# context action command (please see Geany's main documentation for details) +context_action_cmd= + +[indentation] +#width=4 +# 0 is spaces, 1 is tabs, 2 is tab & spaces +#type=1 + +[build_settings] +# %f will be replaced by the complete filename +# %e will be replaced by the filename without extension +# (use only one of it at one time) +compiler=C:\program files\autoit3\aut2exe\aut2exe.exe /in "%f" +run_cmd=C:\program files\autoit3\autoit3.exe "%f" diff --git a/data/filetype_extensions.conf b/data/filetype_extensions.conf index cab0b757ea..7c9edc5cf2 100644 --- a/data/filetype_extensions.conf +++ b/data/filetype_extensions.conf @@ -8,6 +8,7 @@ ActionScript=*.as; Ada=*.adb;*.ads; Asciidoc=*.asciidoc;*.adoc; ASM=*.asm;*.asm51;*.a51; +AutoIt=*.au3; Batch=*.bat;*.cmd;*.nt; CAML=*.ml;*.mli; C=*.c;*.h;*.xpm; diff --git a/scintilla/Makefile.am b/scintilla/Makefile.am index 1eab390ed1..f13997d91c 100644 --- a/scintilla/Makefile.am +++ b/scintilla/Makefile.am @@ -9,6 +9,7 @@ LEXER_SRCS= \ lexers/LexAbaqus.cxx \ lexers/LexAda.cxx \ lexers/LexAsm.cxx \ +lexers/LexAU3.cxx \ lexers/LexBash.cxx \ lexers/LexBasic.cxx \ lexers/LexBatch.cxx \ diff --git a/scintilla/lexers/LexAU3.cxx b/scintilla/lexers/LexAU3.cxx new file mode 100644 index 0000000000..c8ab9d7008 --- /dev/null +++ b/scintilla/lexers/LexAU3.cxx @@ -0,0 +1,910 @@ +// Scintilla source code edit control +// @file LexAU3.cxx +// Lexer for AutoIt3 http://www.hiddensoft.com/autoit3 +// by Jos van der Zande, jvdzande@yahoo.com +// +// Changes: +// March 28, 2004 - Added the standard Folding code +// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting +// Fixed Number highlighting +// Changed default isoperator to IsAOperator to have a better match to AutoIt3 +// Fixed "#comments_start" -> "#comments-start" +// Fixed "#comments_end" -> "#comments-end" +// Fixed Sendkeys in Strings when not terminated with } +// Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} +// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. +// Added logic for #include to treat the <> as string +// Added underscore to IsAOperator. +// May 17, 2004 - Changed the folding logic from indent to keyword folding. +// Added Folding logic for blocks of single-commentlines or commentblock. +// triggered by: fold.comment=1 +// Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 +// Added Special for #region - #endregion syntax highlight and folding. +// May 30, 2004 - Fixed issue with continuation lines on If statements. +// June 5, 2004 - Added comma to Operators for better readability. +// Added fold.compact support set with fold.compact=1 +// Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 +// it will now only happen when fold.comment=2. +// Sep 5, 2004 - Added logic to handle colourizing words on the last line. +// Typed Characters now show as "default" till they match any table. +// Oct 10, 2004 - Added logic to show Comments in "Special" directives. +// Nov 1, 2004 - Added better testing for Numbers supporting x and e notation. +// Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting. +// Jan 10, 2005 - Added Abbreviations Keyword used for expansion +// Mar 24, 2005 - Updated Abbreviations Keywords to fix when followed by Operator. +// Apr 18, 2005 - Updated #CE/#Comment-End logic to take a linecomment ";" into account +// - Added folding support for With...EndWith +// - Added support for a DOT in variable names +// - Fixed Underscore in CommentBlock +// May 23, 2005 - Fixed the SentKey lexing in case of a missing } +// Aug 11, 2005 - Fixed possible bug with s_save length > 100. +// Aug 23, 2005 - Added Switch/endswitch support to the folding logic. +// Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys. +// Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions. +// Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF) +// Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color. +// Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL. +// Jul 26, 2007 - Fixed #endregion undetected bug. +// +// Copyright for Scintilla: 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. +// Scintilla source code edit control + +#include +#include +#include +#include +#include +#include + +#include "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" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsTypeCharacter(const int ch) +{ + return ch == '$'; +} +static inline bool IsAWordChar(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) +{ + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); +} + +static inline bool IsAOperator(char ch) { + if (IsASCII(ch) && isalnum(ch)) + return false; + if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || + ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || + ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' ) + return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// GetSendKey() filters the portion before and after a/multiple space(s) +// and return the first portion to be looked-up in the table +// also check if the second portion is valid... (up,down.on.off,toggle or a number) +/////////////////////////////////////////////////////////////////////////////// + +static int GetSendKey(const char *szLine, char *szKey) +{ + int nFlag = 0; + int nStartFound = 0; + int nKeyPos = 0; + int nSpecPos= 0; + int nSpecNum= 1; + int nPos = 0; + char cTemp; + char szSpecial[100]; + + // split the portion of the sendkey in the part before and after the spaces + while ( ( (cTemp = szLine[nPos]) != '\0')) + { + // skip leading Ctrl/Shift/Alt state + if (cTemp == '{') { + nStartFound = 1; + } + // + if (nStartFound == 1) { + if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space + { + nFlag = 1; + // Add } to the end of the first bit for table lookup later. + szKey[nKeyPos++] = '}'; + } + else if (cTemp == ' ') + { + // skip other spaces + } + else if (nFlag == 0) + { + // save first portion into var till space or } is hit + szKey[nKeyPos++] = cTemp; + } + else if ((nFlag == 1) && (cTemp != '}')) + { + // Save second portion into var... + szSpecial[nSpecPos++] = cTemp; + // check if Second portion is all numbers for repeat fuction + if (isdigit(cTemp) == false) {nSpecNum = 0;} + } + } + nPos++; // skip to next char + + } // End While + + + // Check if the second portion is either a number or one of these keywords + szKey[nKeyPos] = '\0'; + szSpecial[nSpecPos] = '\0'; + if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || + strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || + strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) + { + nFlag = 0; + } + else + { + nFlag = 1; + } + return nFlag; // 1 is bad, 0 is good + +} // GetSendKey() + +// +// Routine to check the last "none comment" character on a line to see if its a continuation +// +static bool IsContinuationLine(Sci_PositionU szLine, Accessor &styler) +{ + Sci_Position nsPos = styler.LineStart(szLine); + Sci_Position nePos = styler.LineStart(szLine+1) - 2; + //int stylech = styler.StyleAt(nsPos); + while (nsPos < nePos) + { + //stylech = styler.StyleAt(nePos); + int stylech = styler.StyleAt(nsPos); + if (!(stylech == SCE_AU3_COMMENT)) { + char ch = styler.SafeGetCharAt(nePos); + if (!isspacechar(ch)) { + if (ch == '_') + return true; + else + return false; + } + } + nePos--; // skip to next char + } // End While + return false; +} // IsContinuationLine() + +// +// syntax highlighting logic +static void ColouriseAU3Doc(Sci_PositionU startPos, + Sci_Position length, int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; + WordList &keywords7 = *keywordlists[6]; + WordList &keywords8 = *keywordlists[7]; + // find the first previous line without continuation character at the end + Sci_Position lineCurrent = styler.GetLine(startPos); + Sci_Position s_startPos = startPos; + // When not inside a Block comment: find First line without _ + if (!(initStyle==SCE_AU3_COMMENTBLOCK)) { + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); // get start position + initStyle = 0; // reset the start style to 0 + } + } + // Set the new length to include it from the start and set the start position + length = length + s_startPos - startPos; // correct the total length to process + styler.StartAt(startPos); + + StyleContext sc(startPos, length, initStyle, styler); + char si; // string indicator "=1 '=2 + char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 + char ci; // comment indicator 0=not linecomment(;) + char s_save[100] = ""; + si=0; + ni=0; + ci=0; + //$$$ + for (; sc.More(); sc.Forward()) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + // ********************************************** + // save the total current word for eof processing + if (IsAWordChar(sc.ch) || sc.ch == '}') + { + strcpy(s_save,s); + int tp = static_cast(strlen(s_save)); + if (tp < 99) { + s_save[tp] = static_cast(tolower(sc.ch)); + s_save[tp+1] = '\0'; + } + } + // ********************************************** + // + switch (sc.state) + { + case SCE_AU3_COMMENTBLOCK: + { + //Reset at line end + if (sc.atLineEnd) { + ci=0; + if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) { + if (sc.atLineEnd) + sc.SetState(SCE_AU3_DEFAULT); + else + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + //skip rest of line when a ; is encountered + if (sc.chPrev == ';') { + ci=2; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + // skip rest of the line + if (ci==2) + break; + // check when first character is detected on the line + if (ci==0) { + if (IsAWordStart(static_cast(sc.ch)) || IsAOperator(static_cast(sc.ch))) { + ci=1; + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + break; + } + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) { + if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) + sc.SetState(SCE_AU3_COMMENT); // set to comment line for the rest of the line + else + ci=2; // line doesn't begin with #CE so skip the rest of the line + } + break; + } + case SCE_AU3_COMMENT: + { + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_OPERATOR: + { + // check if its a COMobject + if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_COMOBJ); + } + else { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_SPECIAL: + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_KEYWORD: + { + if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0)))) + { + if (!IsTypeCharacter(sc.ch)) + { + if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + break; + } + else if (keywords.InList(s)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords2.InList(s)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords3.InList(s)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords5.InList(s)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_DEFAULT); + if (strcmp(s, "#include")== 0) + { + si = 3; // use to determine string start for #inlude <> + } + } + else if (keywords6.InList(s)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if ((keywords7.InList(s)) && (!IsAOperator(static_cast(sc.ch)))) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (keywords8.InList(s)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (strcmp(s, "_") == 0) { + sc.ChangeState(SCE_AU3_OPERATOR); + sc.SetState(SCE_AU3_DEFAULT); + } + else if (!IsAWordChar(sc.ch)) { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + } + if (sc.atLineEnd) { + sc.SetState(SCE_AU3_DEFAULT);} + break; + } + case SCE_AU3_NUMBER: + { + // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3 + // + // test for Hex notation + if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0) + { + ni = 2; + break; + } + // test for E notation + if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1) + { + ni = 3; + break; + } + // Allow Hex characters inside hex numeric strings + if ((ni == 2) && + (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' || + sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' )) + { + break; + } + // test for 1 dec point only + if (sc.ch == '.') + { + if (ni==0) + { + ni=1; + } + else + { + ni=9; + } + break; + } + // end of numeric string ? + if (!(IsADigit(sc.ch))) + { + if (ni==9) + { + sc.ChangeState(SCE_AU3_DEFAULT); + } + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_VARIABLE: + { + // Check if its a COMObject + if (sc.ch == '.' && !IsADigit(sc.chNext)) { + sc.SetState(SCE_AU3_OPERATOR); + } + else if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_COMOBJ: + { + if (!(IsAWordChar(sc.ch))) { + sc.SetState(SCE_AU3_DEFAULT); + } + break; + } + case SCE_AU3_STRING: + { + // check for " to end a double qouted string or + // check for ' to end a single qouted string + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) + { + sc.ForwardSetState(SCE_AU3_DEFAULT); + si=0; + break; + } + if (sc.atLineEnd) + { + si=0; + // at line end and not found a continuation char then reset to default + Sci_Position lineCurrent = styler.GetLine(sc.currentPos); + if (!IsContinuationLine(lineCurrent,styler)) + { + sc.SetState(SCE_AU3_DEFAULT); + break; + } + } + // find Sendkeys in a STRING + if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) { + sc.SetState(SCE_AU3_SENT);} + break; + } + + case SCE_AU3_SENT: + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + else + { + // check if the start is a valid SendKey start + Sci_Position nPos = 0; + int nState = 1; + char cTemp; + while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) + { + if (cTemp == '{' && nState == 1) + { + nState = 2; + } + if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' )) + { + nState = 0; + } + nPos++; + } + //Verify characters infront of { ... if not assume regular string + if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + // If invalid character found then assume its a regular string + if (nState == 0) { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_STRING); + } + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + si = 0; // reset string indicator + } + //* check in next characters following a sentkey are again a sent key + // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{} + if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) { + sc.SetState(SCE_AU3_SENT);} + // check to see if the string ended... + // Sendkey string isn't complete but the string ended.... + if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'')) + { + sc.ChangeState(SCE_AU3_STRING); + sc.ForwardSetState(SCE_AU3_DEFAULT); + } + break; + } + } //switch (sc.state) + + // Determine if a new state should be entered: + + if (sc.state == SCE_AU3_DEFAULT) + { + if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} + else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);} + else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} + //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} + else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include + else if (sc.ch == '\"') { + sc.SetState(SCE_AU3_STRING); + si = 1; } + else if (sc.ch == '\'') { + sc.SetState(SCE_AU3_STRING); + si = 2; } + else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) + { + sc.SetState(SCE_AU3_NUMBER); + ni = 0; + } + else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} + else if (IsAOperator(static_cast(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} + else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} + } + } //for (; sc.More(); sc.Forward()) + + //************************************* + // Colourize the last word correctly + //************************************* + if (sc.state == SCE_AU3_KEYWORD) + { + if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 ) + { + sc.ChangeState(SCE_AU3_COMMENTBLOCK); + sc.SetState(SCE_AU3_COMMENTBLOCK); + } + else if (keywords.InList(s_save)) { + sc.ChangeState(SCE_AU3_KEYWORD); + sc.SetState(SCE_AU3_KEYWORD); + } + else if (keywords2.InList(s_save)) { + sc.ChangeState(SCE_AU3_FUNCTION); + sc.SetState(SCE_AU3_FUNCTION); + } + else if (keywords3.InList(s_save)) { + sc.ChangeState(SCE_AU3_MACRO); + sc.SetState(SCE_AU3_MACRO); + } + else if (keywords5.InList(s_save)) { + sc.ChangeState(SCE_AU3_PREPROCESSOR); + sc.SetState(SCE_AU3_PREPROCESSOR); + } + else if (keywords6.InList(s_save)) { + sc.ChangeState(SCE_AU3_SPECIAL); + sc.SetState(SCE_AU3_SPECIAL); + } + else if (keywords7.InList(s_save) && sc.atLineEnd) { + sc.ChangeState(SCE_AU3_EXPAND); + sc.SetState(SCE_AU3_EXPAND); + } + else if (keywords8.InList(s_save)) { + sc.ChangeState(SCE_AU3_UDF); + sc.SetState(SCE_AU3_UDF); + } + else { + sc.ChangeState(SCE_AU3_DEFAULT); + sc.SetState(SCE_AU3_DEFAULT); + } + } + if (sc.state == SCE_AU3_SENT) + { + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') + { + // set color to SENDKEY when valid sendkey .. else set back to regular string + char sk[100]; + // split {111 222} and return {111} and check if 222 is valid. + // if return code = 1 then invalid 222 so must be string + if (GetSendKey(s_save,sk)) + { + sc.ChangeState(SCE_AU3_STRING); + } + // if single char between {?} then its ok as sendkey for a single character + else if (strlen(sk) == 3) + { + sc.ChangeState(SCE_AU3_SENT); + } + // if sendkey {111} is in table then ok as sendkey + else if (keywords4.InList(sk)) + { + sc.ChangeState(SCE_AU3_SENT); + } + else + { + sc.ChangeState(SCE_AU3_STRING); + } + sc.SetState(SCE_AU3_STRING); + } + // check if next portion is again a sendkey + if (sc.atLineEnd) + { + sc.ChangeState(SCE_AU3_STRING); + sc.SetState(SCE_AU3_DEFAULT); + } + } + //************************************* + sc.Complete(); +} + +// +static bool IsStreamCommentStyle(int style) { + return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; +} + +// +// Routine to find first none space on the current line and return its Style +// needed for comment lines not starting on pos 1 +static int GetStyleFirstWord(Sci_PositionU szLine, Accessor &styler) +{ + Sci_Position nsPos = styler.LineStart(szLine); + Sci_Position nePos = styler.LineStart(szLine+1) - 1; + while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) + { + nsPos++; // skip to next char + + } // End While + return styler.StyleAt(nsPos); + +} // GetStyleFirstWord() + + +// +static void FoldAU3Doc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) +{ + Sci_Position endPos = startPos + length; + // get settings from the config files for folding comments and preprocessor lines + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + // Backtrack to previous line in case need to fix its fold status + Sci_Position lineCurrent = styler.GetLine(startPos); + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + // vars for style of previous/current/next lines + int style = GetStyleFirstWord(lineCurrent,styler); + int stylePrev = 0; + // find the first previous line without continuation character at the end + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || + (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + if (lineCurrent > 0) { + stylePrev = GetStyleFirstWord(lineCurrent-1,styler); + } + // vars for getting first word to check for keywords + bool FirstWordStart = false; + bool FirstWordEnd = false; + char szKeyword[11]=""; + int szKeywordlen = 0; + char szThen[5]=""; + int szThenlen = 0; + bool ThenFoundLast = false; + // var for indentlevel + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + // + int visibleChars = 0; + char chNext = styler.SafeGetCharAt(startPos); + char chPrev = ' '; + // + for (Sci_Position i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + if (IsAWordChar(ch)) { + visibleChars++; + } + // get the syle for the current character neede to check in comment + int stylech = styler.StyleAt(i); + // get first word for the line for indent check max 9 characters + if (FirstWordStart && (!(FirstWordEnd))) { + if (!IsAWordChar(ch)) { + FirstWordEnd = true; + szKeyword[szKeywordlen] = '\0'; + } + else { + if (szKeywordlen < 10) { + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + } + // start the capture of the first word + if (!(FirstWordStart)) { + if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { + FirstWordStart = true; + szKeyword[szKeywordlen++] = static_cast(tolower(ch)); + } + } + // only process this logic when not in comment section + if (!(stylech == SCE_AU3_COMMENT)) { + if (ThenFoundLast) { + if (IsAWordChar(ch)) { + ThenFoundLast = false; + } + } + // find out if the word "then" is the last on a "if" line + if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { + if (szThenlen == 4) { + szThen[0] = szThen[1]; + szThen[1] = szThen[2]; + szThen[2] = szThen[3]; + szThen[3] = static_cast(tolower(ch)); + if (strcmp(szThen,"then") == 0 ) { + ThenFoundLast = true; + } + } + else { + szThen[szThenlen++] = static_cast(tolower(ch)); + if (szThenlen == 5) { + szThen[4] = '\0'; + } + } + } + } + // End of Line found so process the information + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { + // ************************** + // Folding logic for Keywords + // ************************** + // if a keyword is found on the current line and the line doesn't end with _ (continuation) + // and we are not inside a commentblock. + if (szKeywordlen > 0 && (!(chPrev == '_')) && + ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { + szKeyword[szKeywordlen] = '\0'; + // only fold "if" last keyword is "then" (else its a one line if) + if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { + levelNext++; + } + // create new fold for these words + if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || + strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| + strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) { + levelNext++; + } + // create double Fold for select&switch because Case will subtract one of the current level + if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) { + levelNext++; + levelNext++; + } + // end the fold for these words before the current line + if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || + strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || + strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){ + levelNext--; + levelCurrent--; + } + // end the fold for these words before the current line and Start new fold + if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || + strcmp(szKeyword,"elseif") == 0 ) { + levelCurrent--; + } + // end the double fold for this word before the current line + if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) { + levelNext--; + levelNext--; + levelCurrent--; + levelCurrent--; + } + // end the fold for these words on the current line + if (strcmp(szKeyword,"#endregion") == 0 ) { + levelNext--; + } + } + // Preprocessor and Comment folding + int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); + // ************************************* + // Folding logic for preprocessor blocks + // ************************************* + // process preprosessor line + if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { + if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { + levelNext--; + } + } + // ********************************* + // Folding logic for Comment blocks + // ********************************* + if (foldComment && IsStreamCommentStyle(style)) { + // Start of a comment block + if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { + levelNext++; + } + // fold till the last line for normal comment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENT) + && stylePrev == SCE_AU3_COMMENT + && style == SCE_AU3_COMMENT) { + levelNext--; + } + // fold till the one but last line for Blockcomment lines + else if (IsStreamCommentStyle(stylePrev) + && !(styleNext == SCE_AU3_COMMENTBLOCK) + && style == SCE_AU3_COMMENTBLOCK) { + levelNext--; + levelCurrent--; + } + } + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + // reset values for the next line + lineCurrent++; + stylePrev = style; + style = styleNext; + levelCurrent = levelNext; + visibleChars = 0; + // if the last character is an Underscore then don't reset since the line continues on the next line. + if (!(chPrev == '_')) { + szKeywordlen = 0; + szThenlen = 0; + FirstWordStart = false; + FirstWordEnd = false; + ThenFoundLast = false; + } + } + // save the last processed character + if (!isspacechar(ch)) { + chPrev = ch; + visibleChars++; + } + } +} + + +// + +static const char * const AU3WordLists[] = { + "#autoit keywords", + "#autoit functions", + "#autoit macros", + "#autoit Sent keys", + "#autoit Pre-processors", + "#autoit Special", + "#autoit Expand", + "#autoit UDF", + 0 +}; +LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists); diff --git a/scintilla/scintilla_changes.patch b/scintilla/scintilla_changes.patch index 7e0df8e75f..ff41a8a17e 100644 --- a/scintilla/scintilla_changes.patch +++ b/scintilla/scintilla_changes.patch @@ -82,7 +82,7 @@ diff --git scintilla/src/Catalogue.cxx scintilla/src/Catalogue.cxx index ed47aa8..e58f1ab 100644 --- scintilla/src/Catalogue.cxx +++ scintilla/src/Catalogue.cxx -@@ -77,120 +77,50 @@ int Scintilla_LinkLexers() { +@@ -77,120 +77,51 @@ int Scintilla_LinkLexers() { //++Autogenerated -- run scripts/LexGen.py to regenerate //**\(\tLINK_LEXER(\*);\n\) @@ -94,7 +94,7 @@ index ed47aa8..e58f1ab 100644 LINK_LEXER(lmAsm); - LINK_LEXER(lmAsn1); - LINK_LEXER(lmASY); -- LINK_LEXER(lmAU3); + LINK_LEXER(lmAU3); - LINK_LEXER(lmAVE); - LINK_LEXER(lmAVS); - LINK_LEXER(lmBaan); diff --git a/scintilla/src/Catalogue.cxx b/scintilla/src/Catalogue.cxx index e58f1ab207..a1a53a677d 100644 --- a/scintilla/src/Catalogue.cxx +++ b/scintilla/src/Catalogue.cxx @@ -80,6 +80,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmAbaqus); LINK_LEXER(lmAda); LINK_LEXER(lmAsm); + LINK_LEXER(lmAU3); LINK_LEXER(lmBash); LINK_LEXER(lmBatch); LINK_LEXER(lmCaml); diff --git a/src/filetypes.c b/src/filetypes.c index 609da02bf7..285156c24f 100644 --- a/src/filetypes.c +++ b/src/filetypes.c @@ -200,6 +200,7 @@ static void init_builtin_filetypes(void) FT_INIT( COFFEESCRIPT, NONE, "CoffeeScript", NULL, SOURCE_FILE, SCRIPT ); FT_INIT( GO, GO, "Go", NULL, SOURCE_FILE, COMPILED ); FT_INIT( ZEPHIR, ZEPHIR, "Zephir", NULL, SOURCE_FILE, COMPILED ); + FT_INIT( AU3, NONE, "AutoIt", NULL, SCRIPT, SCRIPT ); } diff --git a/src/filetypes.h b/src/filetypes.h index 5bdf3be6fa..f39c654ae5 100644 --- a/src/filetypes.h +++ b/src/filetypes.h @@ -106,6 +106,7 @@ typedef enum GEANY_FILETYPES_COFFEESCRIPT, GEANY_FILETYPES_GO, GEANY_FILETYPES_ZEPHIR, + GEANY_FILETYPES_AU3, /* ^ append items here */ GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */ } diff --git a/src/highlighting.c b/src/highlighting.c index 0a700b629a..189f447116 100644 --- a/src/highlighting.c +++ b/src/highlighting.c @@ -1048,6 +1048,7 @@ void highlighting_init_styles(guint filetype_idx, GKeyFile *config, GKeyFile *co init_styleset_case(XML); init_styleset_case(YAML); init_styleset_case(ZEPHIR); + init_styleset_case(AU3); default: if (ft->lexer_filetype) geany_debug("Filetype %s has a recursive lexer_filetype %s set!", @@ -1136,6 +1137,7 @@ void highlighting_set_styles(ScintillaObject *sci, GeanyFiletype *ft) styleset_case(XML); styleset_case(YAML); styleset_case(ZEPHIR); + styleset_case(AU3); case GEANY_FILETYPES_NONE: default: styleset_default(sci, ft->id); @@ -1563,6 +1565,9 @@ gboolean highlighting_is_string_style(gint lexer, gint style) case SCLEX_VERILOG: return (style == SCE_V_STRING); + + case SCLEX_AU3: + return (style == SCE_AU3_STRING); } return FALSE; } @@ -1736,6 +1741,10 @@ gboolean highlighting_is_comment_style(gint lexer, gint style) style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG || style == SCE_V_COMMENT_WORD); + + case SCLEX_AU3: + return (style == SCE_AU3_COMMENT || + style == SCE_AU3_COMMENTBLOCK); } return FALSE; } diff --git a/src/highlightingmappings.h b/src/highlightingmappings.h index d931696875..f9499cfc3c 100644 --- a/src/highlightingmappings.h +++ b/src/highlightingmappings.h @@ -1619,6 +1619,41 @@ static const HLKeyword highlighting_keywords_YAML[] = #define highlighting_keywords_ZEPHIR highlighting_keywords_PHP #define highlighting_properties_ZEPHIR highlighting_properties_PHP + +/* AutoIt */ +#define highlighting_lexer_AU3 SCLEX_AU3 +static const HLStyle highlighting_styles_AU3[] = +{ + { SCE_AU3_DEFAULT, "default", FALSE}, + { SCE_AU3_COMMENT, "comment", FALSE}, + { SCE_AU3_COMMENTBLOCK, "commentblock", FALSE}, + { SCE_AU3_NUMBER, "number", FALSE}, + { SCE_AU3_FUNCTION, "function", FALSE}, + { SCE_AU3_KEYWORD, "keyword", FALSE}, + { SCE_AU3_MACRO, "macro", FALSE}, + { SCE_AU3_STRING, "string", FALSE}, + { SCE_AU3_OPERATOR, "operator", FALSE}, + { SCE_AU3_VARIABLE, "variable", FALSE}, + { SCE_AU3_SENT, "sent", FALSE}, + { SCE_AU3_PREPROCESSOR, "preprocessor", FALSE}, + { SCE_AU3_SPECIAL, "special", FALSE}, + { SCE_AU3_EXPAND, "expand", FALSE}, + { SCE_AU3_COMOBJ, "comobj", FALSE}, + { SCE_AU3_UDF, "udf", FALSE} +}; +static const HLKeyword highlighting_keywords_AU3[] = +{ + { 0, "keywords", FALSE }, + { 1, "functions", FALSE }, + { 2, "macros", FALSE }, + { 3, "sent", FALSE }, + { 4, "preprocessor", FALSE }, + { 5, "special", FALSE }, + { 6, "expand", FALSE }, + { 7, "udf", FALSE } +}; +#define highlighting_properties_AU3 EMPTY_PROPERTIES + G_END_DECLS #endif /* GEANY_HIGHLIGHTING_MAPPINGS_H */ From 362cd8a9ee44f627bf9d2509b24d3d7ac2e6c31c Mon Sep 17 00:00:00 2001 From: Skif-off Date: Mon, 4 Apr 2016 01:07:10 +0300 Subject: [PATCH 2/3] Add: AutoIt syntax highlighting2 Fix: remove "udf" value (because it is test value) --- data/filedefs/filetypes.autoit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/filedefs/filetypes.autoit b/data/filedefs/filetypes.autoit index a7107ac6b9..214229db7b 100644 --- a/data/filedefs/filetypes.autoit +++ b/data/filedefs/filetypes.autoit @@ -45,7 +45,7 @@ sent={!} {#} {^} {{} {}} {+} {alt} {altdown} {altup} {appskey} {asc} {backspace} preprocessor=#ce #comments-end #comments-start #cs #include #include-once #notrayicon #onautoitstartregister #requireadmin special=#endregion #forcedef #forceref #ignorefunc #pragma #region expand= -udf=_arrayadd _arraybinarysearch _arraydelete _arraydisplay +udf= [lexer_properties] #settings for folding comment blocks and preprocessor lines From 915cdd1a4cc51e948f3527dd3755b17da591a831 Mon Sep 17 00:00:00 2001 From: Skif-off Date: Fri, 29 Apr 2016 20:35:46 +0400 Subject: [PATCH 3/3] Synchronization with geany-master --- doc/plugins.dox | 22 +-- doc/pluginsignals.c | 8 +- doc/pluginsymbols.c | 2 +- scintilla/gtk/PlatGTK.cxx | 272 +++--------------------------- scintilla/gtk/ScintillaGTK.cxx | 49 ++---- scintilla/include/SciLexer.h | 15 ++ scintilla/include/Scintilla.iface | 17 ++ scintilla/lexers/LexCPP.cxx | 3 + scintilla/lexers/LexPython.cxx | 16 +- scintilla/lexers/LexRust.cxx | 2 +- scintilla/lexlib/Accessor.cxx | 4 +- scintilla/lexlib/WordList.cxx | 4 +- scintilla/scintilla_changes.patch | 3 +- scintilla/src/Document.cxx | 4 +- scintilla/src/EditView.cxx | 2 +- scintilla/src/Editor.cxx | 5 +- scintilla/src/Editor.h | 2 +- scintilla/src/KeyMap.h | 1 + scintilla/src/Position.h | 15 +- scintilla/src/RESearch.h | 2 +- scintilla/version.txt | 2 +- src/ui_utils.c | 14 +- 22 files changed, 138 insertions(+), 326 deletions(-) diff --git a/doc/plugins.dox b/doc/plugins.dox index 7bc1fa06c7..4a0a87cbd0 100644 --- a/doc/plugins.dox +++ b/doc/plugins.dox @@ -95,10 +95,10 @@ All information about this project you can find at http://plugins.geany.org/ To add a new plugin to this project, get in touch with the people on the geany-devel-mailing list and create a fork of the geany-plugins project at https://github.com/geany/geany-plugins. -Beside of adding a new plugin, geany-devel-mailing list is also the place where +Beside of adding a new plugin, geany-devel-mailing list is also the place to discuss development related questions. However, once you have done your fork of geany-plugins you can develop -your plugin until you think its the right time to publish it. At this point, +your plugin until you think it is the right time to publish it. At this point, create a pull request for adding your patch set into the master branch of the main geany-plugins repository. @@ -170,7 +170,7 @@ distributions, the package names and commands to use may differ. Basically, you are done at this point and could continue with writing the plugin code. [1] For Windows, it is basically the same but you might have some more work on setting up -the general build environment(compiler, GTK development files, ...). This is described on +the general build environment (compiler, GTK development files, ...). This is described on Geany's website at http://www.geany.org/Support/BuildingOnWin32. @section helloworld "Hello World" @@ -207,7 +207,7 @@ that helps supporting GTK+2 and GTK+3 in the same source. Now you can go on and write your first lines for your new plugin. As mentioned before, you will need to implement a couple of functions. The first mandatory one is @a geany_load_module(). Geany -uses the presence fo this function to identify a library as a plugin. When Geany scans the +uses the presence of this function to identify a library as a plugin. When Geany scans the pre-defined and user-configured plugin directories, it will take a look at each shared library (or DLL on Windows) to see if it exports a @a geany_load_module() symbol. Files lacking these will be ignored. The second mandatory one is an initialization function that is only called when the plugin @@ -577,7 +577,7 @@ static gboolean hello_init(GeanyPlugin *plugin, gpointer pdata) This page briefly describes the deprecated, legacy plugin entry points. These have been in place prior to Geany 1.26 and are still loadable and working for the time being. However, do not create new plugins against these. For this reason, the actual description here is rather minimalistic and -concentrates on porting legacy plugins to the new interface. Basically it's main purpose +concentrates on porting legacy plugins to the new interface. Basically its main purpose is to give newcomers an idea of what they are looking at if they come across a legacy plugin. @section overview Overview @@ -595,10 +595,10 @@ plugin_configure_single(GtkWidget *) are optional, however Geany prints a warnin plugin_cleanup() is missing and only one of plugin_configure(GtkDialog *) and plugin_configure_single(GtkWidget *) is used for any single plugin. -By convention, plugin_version_check() is implicitely defined through the use of PLUGIN_VERSION_CHECK(), +By convention, plugin_version_check() is implicitly defined through the use of PLUGIN_VERSION_CHECK(), and similarly plugin_info is defined through PLUGIN_SET_INFO() or PLUGIN_SET_TRANSLATABLE_INFO(). -The functions should generally perform the same tasks as their eqivalents in GeanyPlugin::funcs. +The functions should generally perform the same tasks as their equivalents in GeanyPlugin::funcs. Geany also recognized numerous variable fields if the plugin exported them globally, and actually set a few of them inside the plugins data section. @@ -759,7 +759,7 @@ sub-plugin plugins in an abstract manner: - Unloading simply reverses the effect of loading. For providing these methods, GeanyPlugin has a field GeanyProxyFuncs which contains three function -pointers which must be initialized proir to calling geany_plugin_register_proxy(). This should be +pointers which must be initialized prior to calling geany_plugin_register_proxy(). This should be done in the GeanyPluginFuncs::init function of the proxy plugin. - In the call to geany_plugin_register_proxy() the proxy plugin passes a list of file extensions. @@ -769,7 +769,7 @@ done in the GeanyPluginFuncs::init function of the proxy plugin. provided file extensions) is actually a plugin. This may depend on the plugin file itself in case of ambiguity or availability of runtime dependencies or even configuration. @ref PROXY_IGNORED or @ref PROXY_MATCHED should be returned, possibly in combination - with the @ref PROXY_NOLOAD flag. Not implementing GeanyProxyFuncs::probe at all is eqivalent to + with the @ref PROXY_NOLOAD flag. Not implementing GeanyProxyFuncs::probe at all is equivalent to always returning @ref PROXY_MATCHED. - GeanyProxyFuncs::load must be implemented to actually load the plugin. It is called by Geany when the user enables the sub-plugin. What "loading" means is entirely up to the proxy plugin and @@ -843,7 +843,7 @@ syntactic problems or other errors. There are two basic classes: 1) Runtime errors that can be determined at load time. For example, the shebang of a script -indicates a specific interpeter version but that version is not installed on the system. Your proxy +indicates a specific interpreter version but that version is not installed on the system. Your proxy should respond the same way as for version-incompatible plugins: don't register the plugin at all, but leave a message the user suggesting what has to be installed in order to work. Handle syntax errors in the scripts of sub-plugins the same way if possible. @@ -973,7 +973,7 @@ static gint demoproxy_probe(GeanyPlugin *proxy, const gchar *filename, gpointer GeanyProxyFuncs::load is a bit more complex. It reads the file, fills the sub-plugin's PluginInfo fields and calls GEANY_PLUGIN_REGISTER_FULL(). Additionally, it creates a per-plugin context that -holds GKeyFile instance (a poor man's interpeter context). You can also see that it does not call +holds GKeyFile instance (a poor man's interpreter context). You can also see that it does not call GEANY_PLUGIN_REGISTER_FULL() if g_key_file_load_from_file() found an error (probably a syntax problem) which means the sub-plugin cannot be enabled. diff --git a/doc/pluginsignals.c b/doc/pluginsignals.c index ec51914f40..499506ec5b 100644 --- a/doc/pluginsignals.c +++ b/doc/pluginsignals.c @@ -135,18 +135,18 @@ signal void (*document_close)(GObject *obj, GeanyDocument *doc, gpointer user_da /** Sent after a project is opened but before session files are loaded. * * @param obj a GeanyObject instance, should be ignored. - * @param config an exising GKeyFile object which can be used to read and write data. + * @param config an existing GKeyFile object which can be used to read and write data. * It must not be closed or freed. * @param user_data user data. */ signal void (*project_open)(GObject *obj, GKeyFile *config, gpointer user_data); -/** Sent when a project is saved(happens when the project is created, the properties +/** Sent when a project is saved (happens when the project is created, the properties * dialog is closed or Geany is exited). This signal is emitted shortly before Geany * will write the contents of the GKeyFile to the disc. * * @param obj a GeanyObject instance, should be ignored. - * @param config an exising GKeyFile object which can be used to read and write data. + * @param config an existing GKeyFile object which can be used to read and write data. * It must not be closed or freed. * @param user_data user data. */ @@ -242,7 +242,7 @@ signal void (*update_editor_menu)(GObject *obj, const gchar *word, gint pos, Gea * The signal can be sent after Geany's default handler has been run when you set * PluginCallback::after field to TRUE. * - * An example callback implemention of this signal can be found in the Demo plugin. + * An example callback implementation of this signal can be found in the Demo plugin. * * @warning This signal has much power and should be used carefully. You should especially * care about the return value; make sure to return TRUE only if it is necessary diff --git a/doc/pluginsymbols.c b/doc/pluginsymbols.c index bbc8471135..b7c8bbc911 100644 --- a/doc/pluginsymbols.c +++ b/doc/pluginsymbols.c @@ -111,7 +111,7 @@ void plugin_init(GeanyData *data); void plugin_cleanup(); /** Called whenever the plugin should show its documentation (if any). This may open a dialog, - * a browser with a website or a local installed HTML help file(see utils_open_browser()) + * a browser with a website or a local installed HTML help file (see utils_open_browser()) * or something else. * Can be omitted when not needed. */ void plugin_help(); diff --git a/scintilla/gtk/PlatGTK.cxx b/scintilla/gtk/PlatGTK.cxx index 063c42b3aa..059cebfa68 100644 --- a/scintilla/gtk/PlatGTK.cxx +++ b/scintilla/gtk/PlatGTK.cxx @@ -3,10 +3,10 @@ // Copyright 1998-2004 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. +#include #include #include #include -#include #include #include @@ -33,13 +33,6 @@ #pragma GCC diagnostic ignored "-Wsentinel" #endif -/* GLIB must be compiled with thread support, otherwise we - will bail on trying to use locks, and that could lead to - problems for someone. `glib-config --libs gthread` needs - to be used to get the glib libraries for linking, otherwise - g_thread_init will fail */ -#define USE_LOCK defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE) - #include "Converter.h" static const double kPi = 3.14159265358979323846; @@ -88,118 +81,39 @@ using namespace Scintilla; enum encodingType { singleByte, UTF8, dbcs}; -struct LOGFONT { - int size; - int weight; - bool italic; - int characterSet; - char faceName[300]; -}; - -#if USE_LOCK -static GMutex *fontMutex = NULL; - -static void InitializeGLIBThreads() { -#if !GLIB_CHECK_VERSION(2,31,0) - if (!g_thread_supported()) { - g_thread_init(NULL); - } -#endif -} -#endif - -static void FontMutexAllocate() { -#if USE_LOCK - if (!fontMutex) { - InitializeGLIBThreads(); -#if GLIB_CHECK_VERSION(2,31,0) - fontMutex = g_new(GMutex, 1); - g_mutex_init(fontMutex); -#else - fontMutex = g_mutex_new(); -#endif - } -#endif -} - -static void FontMutexFree() { -#if USE_LOCK - if (fontMutex) { -#if GLIB_CHECK_VERSION(2,31,0) - g_mutex_clear(fontMutex); - g_free(fontMutex); -#else - g_mutex_free(fontMutex); -#endif - fontMutex = NULL; - } -#endif -} - -static void FontMutexLock() { -#if USE_LOCK - g_mutex_lock(fontMutex); -#endif -} - -static void FontMutexUnlock() { -#if USE_LOCK - if (fontMutex) { - g_mutex_unlock(fontMutex); - } -#endif -} - // Holds a PangoFontDescription*. class FontHandle { - XYPOSITION width[128]; - encodingType et; public: - int ascent; PangoFontDescription *pfd; int characterSet; - FontHandle() : et(singleByte), ascent(0), pfd(0), characterSet(-1) { - ResetWidths(et); + FontHandle() : pfd(0), characterSet(-1) { } FontHandle(PangoFontDescription *pfd_, int characterSet_) { - et = singleByte; - ascent = 0; pfd = pfd_; characterSet = characterSet_; - ResetWidths(et); } ~FontHandle() { if (pfd) pango_font_description_free(pfd); pfd = 0; } - void ResetWidths(encodingType et_) { - et = et_; - for (int i=0; i<=127; i++) { - width[i] = 0; - } - } - XYPOSITION CharWidth(unsigned char ch, encodingType et_) const { - XYPOSITION w = 0; - FontMutexLock(); - if ((ch <= 127) && (et == et_)) { - w = width[ch]; - } - FontMutexUnlock(); - return w; - } - void SetCharWidth(unsigned char ch, XYPOSITION w, encodingType et_) { - if (ch <= 127) { - FontMutexLock(); - if (et != et_) { - ResetWidths(et_); - } - width[ch] = w; - FontMutexUnlock(); - } - } + static FontHandle *CreateNewFont(const FontParameters &fp); }; +FontHandle *FontHandle::CreateNewFont(const FontParameters &fp) { + PangoFontDescription *pfd = pango_font_description_new(); + if (pfd) { + pango_font_description_set_family(pfd, + (fp.faceName[0] == '!') ? fp.faceName+1 : fp.faceName); + pango_font_description_set_size(pfd, pangoUnitsFromDouble(fp.size)); + pango_font_description_set_weight(pfd, static_cast(fp.weight)); + pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); + return new FontHandle(pfd,fp.characterSet); + } + + return NULL; +} + // X has a 16 bit coordinate space, so stop drawing here to avoid wrapping static const int maxCoordinate = 32000; @@ -217,143 +131,18 @@ Point Point::FromLong(long lpoint) { Platform::HighShortFromLong(lpoint)); } -static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, float size, int weight, bool italic) { - lf = LOGFONT(); - lf.size = size; - lf.weight = weight; - lf.italic = italic; - lf.characterSet = characterSet; - StringCopy(lf.faceName, faceName); -} - -/** - * Create a hash from the parameters for a font to allow easy checking for identity. - * If one font is the same as another, its hash will be the same, but if the hash is the - * same then they may still be different. - */ -static int HashFont(const FontParameters &fp) { - return - static_cast(fp.size+0.5) ^ - (fp.characterSet << 10) ^ - ((fp.weight / 100) << 12) ^ - (fp.italic ? 0x20000000 : 0) ^ - fp.faceName[0]; -} - -class FontCached : Font { - FontCached *next; - int usage; - LOGFONT lf; - int hash; - explicit FontCached(const FontParameters &fp); - ~FontCached() {} - bool SameAs(const FontParameters &fp); - virtual void Release(); - static FontID CreateNewFont(const FontParameters &fp); - static FontCached *first; -public: - static FontID FindOrCreate(const FontParameters &fp); - static void ReleaseId(FontID fid_); - static void ReleaseAll(); -}; - -FontCached *FontCached::first = 0; - -FontCached::FontCached(const FontParameters &fp) : -next(0), usage(0), hash(0) { - ::SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic); - hash = HashFont(fp); - fid = CreateNewFont(fp); - usage = 1; -} - -bool FontCached::SameAs(const FontParameters &fp) { - return - lf.size == fp.size && - lf.weight == fp.weight && - lf.italic == fp.italic && - lf.characterSet == fp.characterSet && - 0 == strcmp(lf.faceName, fp.faceName); -} - -void FontCached::Release() { - if (fid) - delete PFont(*this); - fid = 0; -} - -FontID FontCached::FindOrCreate(const FontParameters &fp) { - FontID ret = 0; - FontMutexLock(); - int hashFind = HashFont(fp); - for (FontCached *cur = first; cur; cur = cur->next) { - if ((cur->hash == hashFind) && - cur->SameAs(fp)) { - cur->usage++; - ret = cur->fid; - } - } - if (ret == 0) { - FontCached *fc = new FontCached(fp); - fc->next = first; - first = fc; - ret = fc->fid; - } - FontMutexUnlock(); - return ret; -} - -void FontCached::ReleaseId(FontID fid_) { - FontMutexLock(); - FontCached **pcur = &first; - for (FontCached *cur = first; cur; cur = cur->next) { - if (cur->fid == fid_) { - cur->usage--; - if (cur->usage == 0) { - *pcur = cur->next; - cur->Release(); - cur->next = 0; - delete cur; - } - break; - } - pcur = &cur->next; - } - FontMutexUnlock(); -} - -void FontCached::ReleaseAll() { - while (first) { - ReleaseId(first->GetID()); - } -} - -FontID FontCached::CreateNewFont(const FontParameters &fp) { - PangoFontDescription *pfd = pango_font_description_new(); - if (pfd) { - pango_font_description_set_family(pfd, - (fp.faceName[0] == '!') ? fp.faceName+1 : fp.faceName); - pango_font_description_set_size(pfd, pangoUnitsFromDouble(fp.size)); - pango_font_description_set_weight(pfd, static_cast(fp.weight)); - pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); - return new FontHandle(pfd, fp.characterSet); - } - - return new FontHandle(); -} - Font::Font() : fid(0) {} Font::~Font() {} void Font::Create(const FontParameters &fp) { Release(); - fid = FontCached::FindOrCreate(fp); + fid = FontHandle::CreateNewFont(fp); } void Font::Release() { if (fid) - FontCached::ReleaseId(fid); + delete static_cast(fid); fid = 0; } @@ -989,13 +778,6 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION if (font_.GetID()) { const int lenPositions = len; if (PFont(font_)->pfd) { - if (len == 1) { - int width = PFont(font_)->CharWidth(*s, et); - if (width) { - positions[0] = width; - return; - } - } pango_layout_set_font_description(layout, PFont(font_)->pfd); if (et == UTF8) { // Simple and direct as UTF-8 is native Pango encoding @@ -1089,10 +871,6 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION PLATFORM_ASSERT(i == lenPositions); } } - if (len == 1) { - PFont(font_)->SetCharWidth(*s, positions[0], et); - } - return; } } else { // No font so return an ascending range of values @@ -1148,20 +926,17 @@ XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) { XYPOSITION SurfaceImpl::Ascent(Font &font_) { if (!(font_.GetID())) return 1; - FontMutexLock(); - int ascent = PFont(font_)->ascent; - if ((ascent == 0) && (PFont(font_)->pfd)) { + int ascent = 0; + if (PFont(font_)->pfd) { PangoFontMetrics *metrics = pango_context_get_metrics(pcontext, PFont(font_)->pfd, pango_context_get_language(pcontext)); - PFont(font_)->ascent = + ascent = doubleFromPangoUnits(pango_font_metrics_get_ascent(metrics)); pango_font_metrics_unref(metrics); - ascent = PFont(font_)->ascent; } if (ascent == 0) { ascent = 1; } - FontMutexUnlock(); return ascent; } @@ -2298,10 +2073,7 @@ int Platform::Clamp(int val, int minVal, int maxVal) { } void Platform_Initialise() { - FontMutexAllocate(); } void Platform_Finalise() { - FontCached::ReleaseAll(); - FontMutexFree(); } diff --git a/scintilla/gtk/ScintillaGTK.cxx b/scintilla/gtk/ScintillaGTK.cxx index 11f09567bd..7f19294208 100644 --- a/scintilla/gtk/ScintillaGTK.cxx +++ b/scintilla/gtk/ScintillaGTK.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -423,7 +424,7 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) : } ScintillaGTK::~ScintillaGTK() { - g_idle_remove_by_data(this); + g_source_remove_by_user_data(this); if (evbtn) { gdk_event_free(reinterpret_cast(evbtn)); evbtn = 0; @@ -1077,7 +1078,7 @@ bool ScintillaGTK::FineTickerRunning(TickReason reason) { void ScintillaGTK::FineTickerStart(TickReason reason, int millis, int /* tolerance */) { FineTickerCancel(reason); - timers[reason].timer = g_timeout_add(millis, TimeOut, &timers[reason]); + timers[reason].timer = gdk_threads_add_timeout(millis, TimeOut, &timers[reason]); } void ScintillaGTK::FineTickerCancel(TickReason reason) { @@ -1093,7 +1094,7 @@ bool ScintillaGTK::SetIdle(bool on) { if (!idler.state) { idler.state = true; idler.idlerID = reinterpret_cast( - g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, IdleCallback, this, NULL)); + gdk_threads_add_idle_full(G_PRIORITY_DEFAULT_IDLE, IdleCallback, this, NULL)); } } else { // Stop idler, if it's running @@ -2192,6 +2193,7 @@ gboolean ScintillaGTK::KeyThis(GdkEventKey *event) { bool shift = (event->state & GDK_SHIFT_MASK) != 0; bool ctrl = (event->state & GDK_CONTROL_MASK) != 0; bool alt = (event->state & GDK_MOD1_MASK) != 0; + bool super = (event->state & GDK_MOD4_MASK) != 0; guint key = event->keyval; if ((ctrl || alt) && (key < 128)) key = toupper(key); @@ -2208,15 +2210,12 @@ gboolean ScintillaGTK::KeyThis(GdkEventKey *event) { bool consumed = false; #if !(PLAT_GTK_MACOSX) - bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0; + bool meta = false; #else bool meta = ctrl; ctrl = (event->state & GDK_META_MASK) != 0; - bool added = KeyDownWithModifiers(key, (shift ? SCI_SHIFT : 0) | - (ctrl ? SCI_CTRL : 0) | - (alt ? SCI_ALT : 0) | - (meta ? SCI_META : 0), &consumed) != 0; #endif + bool added = KeyDownWithModifiers(key, ModifierFlags(shift, ctrl, alt, meta, super), &consumed) != 0; if (!consumed) consumed = added; //fprintf(stderr, "SK-key: %d %x %x\n",event->keyval, event->state, consumed); @@ -2454,13 +2453,8 @@ void ScintillaGTK::PreeditChangedInlineThis() { pdoc->TentativeStart(); // TentativeActive() from now on - // Get preedit string attribues std::vector indicator = MapImeIndicators(preeditStr.attrs, preeditStr.str); - // Display preedit characters, one by one - glong imeCharPos[maxLenInputIME+1] = { 0 }; - glong charWidth = 0; - bool tmpRecordingMacro = recordingMacro; recordingMacro = false; for (glong i = 0; i < preeditStr.uniStrLen; i++) { @@ -2472,21 +2466,22 @@ void ScintillaGTK::PreeditChangedInlineThis() { AddCharUTF(docChar.c_str(), docChar.size()); - // Draw an indicator on the character, DrawImeIndicator(indicator[i], docChar.size()); - - // Record character positions in UTF-8 or DBCS bytes - charWidth += docChar.size(); - imeCharPos[i+1] = charWidth; } recordingMacro = tmpRecordingMacro; // Move caret to ime cursor position. - MoveImeCarets( - (imeCharPos[preeditStr.uniStrLen]) + imeCharPos[preeditStr.cursor_pos]); + int imeEndToImeCaretU32 = preeditStr.cursor_pos - preeditStr.uniStrLen; + int imeCaretPosDoc = pdoc->GetRelativePosition(CurrentPosition(), imeEndToImeCaretU32); + + MoveImeCarets(- CurrentPosition() + imeCaretPosDoc); if (KoreanIME()) { #if !PLAT_GTK_WIN32 - MoveImeCarets( - imeCharPos[1]); // always 2 bytes for DBCS or 3 bytes for UTF8. + if (preeditStr.cursor_pos > 0) { + int oneCharBefore = pdoc->GetRelativePosition(CurrentPosition(), -1); + MoveImeCarets(- CurrentPosition() + oneCharBefore); + } #endif view.imeCaretBlockOverride = true; } @@ -2939,9 +2934,6 @@ gboolean ScintillaGTK::IdleCallback(gpointer pSci) { ScintillaGTK *sciThis = static_cast(pSci); // Idler will be automatically stopped, if there is nothing // to do while idle. -#ifndef GDK_VERSION_3_6 - gdk_threads_enter(); -#endif bool ret = sciThis->Idle(); if (ret == false) { // FIXME: This will remove the idler from GTK, we don't want to @@ -2949,21 +2941,12 @@ gboolean ScintillaGTK::IdleCallback(gpointer pSci) { // returns false (although, it should be harmless). sciThis->SetIdle(false); } -#ifndef GDK_VERSION_3_6 - gdk_threads_leave(); -#endif return ret; } gboolean ScintillaGTK::StyleIdle(gpointer pSci) { -#ifndef GDK_VERSION_3_6 - gdk_threads_enter(); -#endif ScintillaGTK *sciThis = static_cast(pSci); sciThis->IdleWork(); -#ifndef GDK_VERSION_3_6 - gdk_threads_leave(); -#endif // Idler will be automatically stopped return FALSE; } @@ -2973,7 +2956,7 @@ void ScintillaGTK::QueueIdleWork(WorkNeeded::workItems items, int upTo) { if (!workNeeded.active) { // Only allow one style needed to be queued workNeeded.active = true; - g_idle_add_full(G_PRIORITY_HIGH_IDLE, StyleIdle, this, NULL); + gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, StyleIdle, this, NULL); } } diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h index 2103b47b9c..6b98b09fc7 100644 --- a/scintilla/include/SciLexer.h +++ b/scintilla/include/SciLexer.h @@ -132,6 +132,7 @@ #define SCLEX_SREC 117 #define SCLEX_IHEX 118 #define SCLEX_TEHEX 119 +#define SCLEX_JSON 120 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -1787,6 +1788,20 @@ #define SCE_HEX_CHECKSUM 16 #define SCE_HEX_CHECKSUM_WRONG 17 #define SCE_HEX_GARBAGE 18 +#define SCE_JSON_DEFAULT 0 +#define SCE_JSON_NUMBER 1 +#define SCE_JSON_STRING 2 +#define SCE_JSON_STRINGEOL 3 +#define SCE_JSON_PROPERTYNAME 4 +#define SCE_JSON_ESCAPESEQUENCE 5 +#define SCE_JSON_LINECOMMENT 6 +#define SCE_JSON_BLOCKCOMMENT 7 +#define SCE_JSON_OPERATOR 8 +#define SCE_JSON_URI 9 +#define SCE_JSON_COMPACTIRI 10 +#define SCE_JSON_KEYWORD 11 +#define SCE_JSON_LDKEYWORD 12 +#define SCE_JSON_ERROR 13 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ #endif diff --git a/scintilla/include/Scintilla.iface b/scintilla/include/Scintilla.iface index 91b3066b52..71defe09d8 100644 --- a/scintilla/include/Scintilla.iface +++ b/scintilla/include/Scintilla.iface @@ -2799,6 +2799,7 @@ val SCLEX_BIBTEX=116 val SCLEX_SREC=117 val SCLEX_IHEX=118 val SCLEX_TEHEX=119 +val SCLEX_JSON=120 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -4677,6 +4678,22 @@ val SCE_HEX_GARBAGE=18 lex IHex=SCLEX_IHEX SCE_HEX_ # Lexical state for SCLEX_TEHEX (shared with Srec) lex TEHex=SCLEX_TEHEX SCE_HEX_ +# Lexical states for SCLEX_JSON +lex JSON=SCLEX_JSON SCE_JSON_ +val SCE_JSON_DEFAULT=0 +val SCE_JSON_NUMBER=1 +val SCE_JSON_STRING=2 +val SCE_JSON_STRINGEOL=3 +val SCE_JSON_PROPERTYNAME=4 +val SCE_JSON_ESCAPESEQUENCE=5 +val SCE_JSON_LINECOMMENT=6 +val SCE_JSON_BLOCKCOMMENT=7 +val SCE_JSON_OPERATOR=8 +val SCE_JSON_URI=9 +val SCE_JSON_COMPACTIRI=10 +val SCE_JSON_KEYWORD=11 +val SCE_JSON_LDKEYWORD=12 +val SCE_JSON_ERROR=13 # Events diff --git a/scintilla/lexers/LexCPP.cxx b/scintilla/lexers/LexCPP.cxx index 76190002a9..4261084d47 100644 --- a/scintilla/lexers/LexCPP.cxx +++ b/scintilla/lexers/LexCPP.cxx @@ -761,6 +761,9 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i lineCurrent++; lineEndNext = styler.LineEnd(lineCurrent); vlls.Add(lineCurrent, preproc); + if (rawStringTerminator != "") { + rawSTNew.Set(lineCurrent-1, rawStringTerminator); + } sc.Forward(); if (sc.ch == '\r' && sc.chNext == '\n') { // Even in UTF-8, \r and \n are separate diff --git a/scintilla/lexers/LexPython.cxx b/scintilla/lexers/LexPython.cxx index 7cd3bc8de4..19dd0ca3b8 100644 --- a/scintilla/lexers/LexPython.cxx +++ b/scintilla/lexers/LexPython.cxx @@ -117,6 +117,17 @@ inline bool IsAWordStart(int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '_'); } +static bool IsFirstNonWhitespace(Sci_Position pos, Accessor &styler) { + Sci_Position line = styler.GetLine(pos); + Sci_Position start_pos = styler.LineStart(line); + for (Sci_Position i = start_pos; i < pos; i++) { + char ch = styler[i]; + if (!(ch == ' ' || ch == '\t')) + return false; + } + return true; +} + // Options used for LexerPython struct OptionsPython { int whingeLevel; @@ -560,7 +571,10 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in } else if (sc.ch == '#') { sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE); } else if (sc.ch == '@') { - sc.SetState(SCE_P_DECORATOR); + if (IsFirstNonWhitespace(sc.currentPos, styler)) + sc.SetState(SCE_P_DECORATOR); + else + sc.SetState(SCE_P_OPERATOR); } else if (IsPyStringStart(sc.ch, sc.chNext, sc.GetRelative(2), allowedLiterals)) { Sci_PositionU nextIndex = 0; sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex, allowedLiterals)); diff --git a/scintilla/lexers/LexRust.cxx b/scintilla/lexers/LexRust.cxx index 0d40de2cfe..a834e32f4e 100644 --- a/scintilla/lexers/LexRust.cxx +++ b/scintilla/lexers/LexRust.cxx @@ -339,7 +339,7 @@ static bool IsOneCharOperator(int c) { || c == '*' || c == '/' || c == '^' || c == '%' || c == '.' || c == ':' || c == '!' || c == '<' || c == '>' || c == '=' || c == '-' || c == '&' - || c == '|' || c == '$'; + || c == '|' || c == '$' || c == '?'; } static bool IsTwoCharOperator(int c, int n) { diff --git a/scintilla/lexlib/Accessor.cxx b/scintilla/lexlib/Accessor.cxx index 283de5bd44..f8b46ef883 100644 --- a/scintilla/lexlib/Accessor.cxx +++ b/scintilla/lexlib/Accessor.cxx @@ -1,6 +1,6 @@ // Scintilla source code edit control -/** @file KeyWords.cxx - ** Colourise for particular languages. +/** @file Accessor.cxx + ** Interfaces between Scintilla and lexers. **/ // Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. diff --git a/scintilla/lexlib/WordList.cxx b/scintilla/lexlib/WordList.cxx index be7fda5056..63d22338f6 100644 --- a/scintilla/lexlib/WordList.cxx +++ b/scintilla/lexlib/WordList.cxx @@ -1,6 +1,6 @@ // Scintilla source code edit control -/** @file KeyWords.cxx - ** Colourise for particular languages. +/** @file WordList.cxx + ** Hold a list of words. **/ // Copyright 1998-2002 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. diff --git a/scintilla/scintilla_changes.patch b/scintilla/scintilla_changes.patch index ff41a8a17e..b417eb0b55 100644 --- a/scintilla/scintilla_changes.patch +++ b/scintilla/scintilla_changes.patch @@ -82,7 +82,7 @@ diff --git scintilla/src/Catalogue.cxx scintilla/src/Catalogue.cxx index ed47aa8..e58f1ab 100644 --- scintilla/src/Catalogue.cxx +++ scintilla/src/Catalogue.cxx -@@ -77,120 +77,51 @@ int Scintilla_LinkLexers() { +@@ -77,121 +77,50 @@ int Scintilla_LinkLexers() { //++Autogenerated -- run scripts/LexGen.py to regenerate //**\(\tLINK_LEXER(\*);\n\) @@ -135,6 +135,7 @@ index ed47aa8..e58f1ab 100644 LINK_LEXER(lmHTML); - LINK_LEXER(lmIHex); - LINK_LEXER(lmInno); +- LINK_LEXER(lmJSON); - LINK_LEXER(lmKix); - LINK_LEXER(lmKVIrc); LINK_LEXER(lmLatex); diff --git a/scintilla/src/Document.cxx b/scintilla/src/Document.cxx index 0c68664093..5e58f26ee1 100644 --- a/scintilla/src/Document.cxx +++ b/scintilla/src/Document.cxx @@ -2617,9 +2617,9 @@ bool MatchOnLines(const Document *doc, const Regex ®exp, const RESearchRange for (size_t co = 0; co < match.size(); co++) { search.bopat[co] = match[co].first.Pos(); search.eopat[co] = match[co].second.PosRoundUp(); - size_t lenMatch = search.eopat[co] - search.bopat[co]; + Sci::Position lenMatch = search.eopat[co] - search.bopat[co]; search.pat[co].resize(lenMatch); - for (size_t iPos = 0; iPos < lenMatch; iPos++) { + for (Sci::Position iPos = 0; iPos < lenMatch; iPos++) { search.pat[co][iPos] = doc->CharAt(iPos + search.bopat[co]); } } diff --git a/scintilla/src/EditView.cxx b/scintilla/src/EditView.cxx index 805971a88c..9ca6e95ade 100644 --- a/scintilla/src/EditView.cxx +++ b/scintilla/src/EditView.cxx @@ -1,5 +1,5 @@ // Scintilla source code edit control -/** @file Editor.cxx +/** @file EditView.cxx ** Defines the appearance of the main text area of the editor window. **/ // Copyright 1998-2014 by Neil Hodgson diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index b480287c31..eddc0e623d 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -2265,12 +2265,13 @@ void Editor::DelCharBack(bool allowLineStartDeletion) { ShowCaretAtCurrentPosition(); } -int Editor::ModifierFlags(bool shift, bool ctrl, bool alt, bool meta) { +int Editor::ModifierFlags(bool shift, bool ctrl, bool alt, bool meta, bool super) { return (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | (alt ? SCI_ALT : 0) | - (meta ? SCI_META : 0); + (meta ? SCI_META : 0) | + (super ? SCI_SUPER : 0); } void Editor::NotifyFocus(bool focus) { diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h index 67aad42d72..9cc648e844 100644 --- a/scintilla/src/Editor.h +++ b/scintilla/src/Editor.h @@ -414,7 +414,7 @@ class Editor : public EditModel, public DocWatcher { void DelCharBack(bool allowLineStartDeletion); virtual void ClaimSelection() = 0; - static int ModifierFlags(bool shift, bool ctrl, bool alt, bool meta=false); + static int ModifierFlags(bool shift, bool ctrl, bool alt, bool meta=false, bool super=false); virtual void NotifyChange() = 0; virtual void NotifyFocus(bool focus); virtual void SetCtrlID(int identifier); diff --git a/scintilla/src/KeyMap.h b/scintilla/src/KeyMap.h index b102b356f3..7c4f807204 100644 --- a/scintilla/src/KeyMap.h +++ b/scintilla/src/KeyMap.h @@ -17,6 +17,7 @@ namespace Scintilla { #define SCI_CTRL SCMOD_CTRL #define SCI_ALT SCMOD_ALT #define SCI_META SCMOD_META +#define SCI_SUPER SCMOD_SUPER #define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT) #define SCI_ASHIFT (SCI_ALT | SCI_SHIFT) diff --git a/scintilla/src/Position.h b/scintilla/src/Position.h index 4ef6552633..120b92f62d 100644 --- a/scintilla/src/Position.h +++ b/scintilla/src/Position.h @@ -1,6 +1,6 @@ // Scintilla source code edit control /** @file Position.h - ** Will define global type name Position in the Sci internal namespace. + ** Defines global type name Position in the Sci internal namespace. **/ // Copyright 2015 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. @@ -8,14 +8,21 @@ #ifndef POSITION_H #define POSITION_H +/** + * A Position is a position within a document between two characters or at the beginning or end. + * Sometimes used as a character index where it identifies the character after the position. + */ + namespace Sci { -// After 3.6.0: -// typedef int Position; +typedef int Position; // A later version (4.x) of this file may: //#if defined(SCI_LARGE_FILE_SUPPORT) -//typedef ptrdiff_t Position; +//typedef std::ptrdiff_t Position; +// or may allow runtime choice between different position sizes. + +const Position invalidPosition = -1; } diff --git a/scintilla/src/RESearch.h b/scintilla/src/RESearch.h index 3a7f0e4d61..23795babed 100644 --- a/scintilla/src/RESearch.h +++ b/scintilla/src/RESearch.h @@ -39,7 +39,7 @@ class RESearch { int Execute(CharacterIndexer &ci, int lp, int endp); enum { MAXTAG=10 }; - enum { MAXNFA=2048 }; + enum { MAXNFA=4096 }; enum { NOTFOUND=-1 }; int bopat[MAXTAG]; diff --git a/scintilla/version.txt b/scintilla/version.txt index 9c6f0c3e0b..475310214c 100644 --- a/scintilla/version.txt +++ b/scintilla/version.txt @@ -1 +1 @@ -364 +365 diff --git a/src/ui_utils.c b/src/ui_utils.c index 22ab68a1ec..f0f800b87e 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -1910,21 +1910,19 @@ void ui_widget_modify_font_from_string(GtkWidget *widget, const gchar *str) GEANY_API_SYMBOL GtkWidget *ui_path_box_new(const gchar *title, GtkFileChooserAction action, GtkEntry *entry) { - GtkWidget *vbox, *dirbtn, *openimg, *hbox, *path_entry; + GtkWidget *vbox, *dirbtn, *openimg, *hbox, *path_entry, *parent, *next_parent; hbox = gtk_hbox_new(FALSE, 6); path_entry = GTK_WIDGET(entry); /* prevent path_entry being vertically stretched to the height of dirbtn */ vbox = gtk_vbox_new(FALSE, 0); - if (gtk_widget_get_parent(path_entry)) /* entry->parent may be a GtkComboBoxEntry */ - { - GtkWidget *parent = gtk_widget_get_parent(path_entry); - gtk_box_pack_start(GTK_BOX(vbox), parent, TRUE, FALSE, 0); - } - else - gtk_box_pack_start(GTK_BOX(vbox), path_entry, TRUE, FALSE, 0); + parent = path_entry; + while ((next_parent = gtk_widget_get_parent(parent)) != NULL) + parent = next_parent; + + gtk_box_pack_start(GTK_BOX(vbox), parent, TRUE, FALSE, 0); dirbtn = gtk_button_new(); openimg = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);