diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi
index ec0441ed..cc62d073 100644
--- a/lazproj/coedit.lpi
+++ b/lazproj/coedit.lpi
@@ -128,7 +128,7 @@
         <PackageName Value="LCL"/>
       </Item5>
     </RequiredPackages>
-    <Units Count="15">
+    <Units Count="17">
       <Unit0>
         <Filename Value="coedit.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -228,6 +228,16 @@
         <ResourceBaseClass Value="Form"/>
         <UnitName Value="ce_search"/>
       </Unit14>
+      <Unit15>
+        <Filename Value="..\src\ce_dlang.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ce_dlang"/>
+      </Unit15>
+      <Unit16>
+        <Filename Value="..\src\ce_dlangutils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ce_dlangutils"/>
+      </Unit16>
     </Units>
   </ProjectOptions>
   <CompilerOptions>
diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr
index 4098f904..85d751c0 100644
--- a/lazproj/coedit.lpr
+++ b/lazproj/coedit.lpr
@@ -9,7 +9,7 @@ uses
   Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, ce_widget,
   ce_dmdwrap, ce_common, ce_synmemo, ce_main, ce_messages, ce_editor,
   ce_projinspect, ce_projconf, jsonparser, ce_project, 
-  ce_widgettypes, ce_staticexplorer, ce_search;
+  ce_widgettypes, ce_staticexplorer, ce_search, ce_dlang, ce_dlangutils;
 
 {$R *.res}
 
diff --git a/src/ce_d2syn.pas b/src/ce_d2syn.pas
index f1cf0885..ad75fe51 100644
--- a/src/ce_d2syn.pas
+++ b/src/ce_d2syn.pas
@@ -6,7 +6,8 @@ interface
 
 uses
   Classes, SysUtils, Graphics,
-  SynEditHighlighter, SynEditHighlighterFoldBase, SynEditTypes;
+  SynEditHighlighter, SynEditHighlighterFoldBase, SynEditTypes,
+  ce_dlangutils;
 
 const
 
@@ -152,95 +153,6 @@ type
 
 implementation
 
-function isWhite(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := c in [#0..#32];
-end;
-
-function isSpace(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := c in [#9,' '];
-end;
-
-function isAlpha(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := (c in ['a'..'z']) or (c in ['A'..'Z']);
-end;
-
-function isNumber(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := (c in ['0'..'9']);
-end;
-
-function isDigit(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := (c in ['0'..'1']);
-end;
-
-function isAlNum(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := isAlpha(c) or isNumber(c);
-end;
-
-function isHex(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := isNumber(c) or (c in ['A'..'F']) or (c in ['a'..'f']);
-end;
-
-function isSymbol(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := c in [';', '{', '}', '(', ')', '[', ']', ',', '.', ':' , '"', #39, '?'];
-end;
-
-function isOperator(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := c in ['/', '*', '-', '+', '%', '>', '<', '=', '!',
-                  '&', '|', '^', '~', '$'];
-end;
-
-function isDoubleOperator(const s: string): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
-begin
-  result := false;
-  case s[1] of
-    '.': result := (s[2] = '.');
-
-    '>': result := s[2] in ['>', '='];
-    '<': result := s[2] in ['<', '=', '>'];
-    '=': result := s[2] in ['=', '>'];
-    '!': result := s[2] in ['=', '>', '<'];
-
-    '+': result := s[2] in ['+', '='];
-    '-': result := s[2] in ['-', '='];
-    '/': result := s[2] in ['='];
-    '*': result := s[2] in ['='];
-    '%': result := s[2] in ['='];
-    '~': result := s[2] in ['='];
-
-    '&': result := s[2] in ['&', '='];
-    '|': result := s[2] in ['|', '='];
-    '^': result := s[2] in ['^', '='];
-  end;
-end;
-
-function isTripleOperator(const s: string): boolean; {$IFNDEF DEBUG} inline; {$ENDIF}
-begin
-  result := false;
-  case s[1] of
-    '.': result := (s[2] = '.')   and (s[3] = '.');
-    '^': result := (s[2] = '^')   and (s[3] = '=');
-    '>': result := (s[2] = '>')   and (s[3] in ['>', '=']);
-    '<': result := ((s[2] = '<')  and (s[3] in ['<', '=']))
-                  or (s[2] = '>') and (s[3] = '=');
-    '!': result := ((s[2] = '<')  and (s[3] in ['>', '=']))
-                  or ((s[2] = '>')and (s[3] = '='));
-  end;
-end;
-
-function isQuadOperator(const s: string): boolean; {$IFNDEF DEBUG} inline; {$ENDIF}
-begin
-  result := (s = '>>>=') or (s = '!<>=');
-end;
-
 {$IFDEF USE_DICT_LINKEDCHARMAP}
 constructor TD2Dictionary.create;
 var
@@ -526,6 +438,7 @@ TODO:
 - string literals: escape bug: std.path/std.regex: "\\"
 - comments: correct nested comments handling.
 }
+{$BOOLEVAL ON}
 procedure TSynD2Syn.next;
 label
   _postString1;
@@ -670,7 +583,7 @@ begin
       fRange := rkNone;
       readNext;
       // check postfix
-      if readCurr in ['c','w','d'] then
+      if isStringPostfix(readCurr) then
         readNext;
       exit;
     end;
@@ -679,7 +592,7 @@ begin
   begin
     if fRange = rkNone then
     begin
-      // check hex/WYSIWYG prefix
+      // check WYSIWYG/hex prefix
       if readCurr in ['r','x'] then
       begin
         if not (readNext = '"') then
@@ -695,7 +608,7 @@ begin
       begin
         readNext;
         // check postfix
-        if readCurr in ['c','w','d'] then
+        if isStringPostfix(readCurr) then
           readNext;
       end;
       fTokKind := tkStrng;
@@ -720,7 +633,7 @@ begin
       fRange := rkNone;
       readNext;
       // check postfix
-      if readCurr in ['c','w','d'] then
+      if isStringPostfix(readCurr) then
         readNext;
       exit;
     end;
@@ -736,7 +649,7 @@ begin
       begin
         readNext;
         // check postfix
-        if readCurr in ['c','w','d'] then
+        if isStringPostfix(readCurr) then
           readNext;
       end;
       fTokKind := tkStrng;
@@ -778,30 +691,30 @@ begin
   end;
 
   // symbols 2: operators
-  if isOperator(readCurr) then
+  if isOperator1(readCurr) then
   begin
     fTokKind := tkSymbl;
-    while isOperator(readNext) do (*!*);
+    while isOperator1(readNext) do (*!*);
     case fTokStop - fTokStart of
       1:begin
-          if not isOperator(readCurr) then exit
+          if not isOperator1(readCurr) then exit
             else Dec(fTokStop);
         end;
       2:begin
-          if (not isOperator(readCurr)) and
-            isDoubleOperator(fLineBuf[fTokStart..fTokStop-1])
+          if (not isOperator1(readCurr)) and
+            isOperator2(fLineBuf[fTokStart..fTokStop-1])
           then exit
             else Dec(fTokStop, 2);
         end;
       3:begin
-          if (not isOperator(readCurr)) and
-            isTripleOperator(fLineBuf[fTokStart..fTokStop-1])
+          if (not isOperator1(readCurr)) and
+            isOperator3(fLineBuf[fTokStart..fTokStop-1])
           then exit
             else Dec(fTokStop, 3);
         end;
       4:begin
-          if (not isOperator(readCurr)) and
-            isQuadOperator(fLineBuf[fTokStart..fTokStop-1])
+          if (not isOperator1(readCurr)) and
+            isOperator4(fLineBuf[fTokStart..fTokStop-1])
           then exit
             else Dec(fTokStop, 4);
         end;
@@ -817,7 +730,7 @@ begin
     begin
       if isWhite(readNext) then break;
       if isSymbol(readCurr) then break;
-      if isOperator(readCurr) then break;
+      if isOperator1(readCurr) then break;
     end;
     if fKeyWords.find(fLineBuf[FTokStart..fTokStop-1]) then
       fTokKind := tkKeywd
@@ -832,6 +745,7 @@ begin
   // Should not happend
   assert(false);
 end;
+{$BOOLEVAL OFF}
 
 function TSynD2Syn.GetEol: Boolean;
 begin
diff --git a/src/ce_dlang.pas b/src/ce_dlang.pas
new file mode 100644
index 00000000..3d403e08
--- /dev/null
+++ b/src/ce_dlang.pas
@@ -0,0 +1,831 @@
+unit ce_dlang;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, ce_dlangutils;
+
+const
+
+  D2Kw: array[0..109] of string =
+  ( 'abstract', 'alias', 'align', 'asm', 'assert', 'auto',
+    'body', 'bool', 'break', 'byte',
+    'case', 'cast', 'catch', 'cdouble', 'cent', 'cfloat', 'char', 'class',
+    'const', 'continue', 'creal',
+    'dchar', 'debug', 'default', 'delegate', 'delete', 'deprecated', 'do', 'double',
+    'else', 'enum', 'export', 'extern',
+    'false', 'final', 'finally', 'float', 'for', 'foreach',
+    'foreach_reverse', 'function',
+    'goto',
+    'idouble', 'if', 'ifloat', 'immutable', 'import', 'in', 'inout', 'int',
+    'interface', 'invariant', 'ireal', 'is',
+    'lazy', 'long',
+    'macro', 'mixin', 'module',
+    'new', 'nothrow', 'null',
+    'out', 'override',
+    'package', 'pragma', 'private', 'protected', 'ptrdiff_t', 'public', 'pure',
+    'real', 'ref', 'return',
+    'size_t', 'scope', 'shared', 'short', 'static', 'string', 'struct',
+    'super', 'switch', 'synchronized',
+    'template', 'this', 'throw', 'true', 'try', 'typedef', 'typeid', 'typeof',
+    'ubyte', 'ucent', 'uint', 'ulong', 'union', 'unittest', 'ushort',
+    'version', 'void', 'volatile',
+    'wchar', 'while', 'with',
+    '__FILE__', '__MODULE__', '__LINE__', '__FUNCTION__', '__PRETTY_FUNCTION__'
+  );
+
+type
+
+  (**
+   * sector for an array of Keyword with a common hash.
+   *)
+  TD2DictionaryEntry = record
+    filled: Boolean;
+    values: array of string;
+  end;
+
+  (**
+   * Dictionary for the D2 keywords.
+   *)
+  TD2Dictionary = object
+  private
+    fLongest, fShortest: NativeInt;
+    fEntries: array[Byte] of TD2DictionaryEntry;
+    function toHash(const aValue: string): Byte; {$IFNDEF DEBUG}inline;{$ENDIF}
+    procedure addEntry(const aValue: string);
+  public
+    constructor create;
+    destructor destroy; // do not remove even if empty (compat with char-map version)
+    function find(const aValue: string): boolean;
+  end;
+
+  (**
+   * Represents the pointer in a source file.
+   * Automatically updates the line and the column.
+   *)
+  TReaderHead = object
+  private
+    fLineIndex: Integer;
+    fColumnIndex: Integer;
+    fAbsoluteIndex: Integer;
+    fReaderHead: PChar;
+    function getColAndLine: TPoint;
+  public
+    constructor create(const aText: PChar; const aColAndLine: TPoint);
+    procedure setReader(const aText: PChar; const aColAndLine: TPoint);
+    //
+    function next: PChar;
+    function previous: PChar;
+    //
+    property AbsoluteIndex: Integer read fAbsoluteIndex;
+    property LineIndex: Integer read fLineIndex;
+    property ColumnIndex: Integer read fColumnIndex;
+    property LineAnColumn: TPoint read getColAndLine;
+    //
+    property head: PChar read fReaderHead;
+  end;
+
+  TLexTokenKind = (ltkIllegal, ltkChar, ltkComment, ltkIdentifier, ltkKeyword,
+    ltkNumber, ltkOperator, ltkString, ltkSymbol);
+
+const
+  LexTokenKindString : array[TLexTokenKind] of string =
+    ( 'Illegal', 'Character', 'Comment', 'Identifier', 'Keyword',
+      'Number', 'Operator', 'String', 'Symbol');
+
+type
+
+  (*****************************************************************************
+   * Lexer token
+   *)
+  PLexToken = ^TLexToken;
+  TLexToken = record
+    position: TPoint;
+    kind: TLexTokenKind;
+    data: string;
+  end;
+
+  (*****************************************************************************
+   * List of lexer tokens
+   *)
+  TLexTokenList = class(TList)
+  private
+    function getToken(index: integer): TLexToken;
+  public
+    procedure clear; override;
+    procedure addToken(aValue: PLexToken);
+    property token[index: integer]: TLexToken read getToken;
+  end;
+
+  TLexTokenEnumerator = class
+    fList: TLexTokenList;
+    fIndex: Integer;
+    function GetCurrent: TLexToken;
+    function MoveNext: Boolean;
+    property Current: TLexToken read GetCurrent;
+  end;
+
+  (*****************************************************************************
+   * Error record
+   *)
+  PLexError = ^TLexError;
+  TLexError = record
+    position: TPoint;
+    msg: string;
+  end;
+
+  (*****************************************************************************
+   * Error list
+   *)
+  TLexErrorList = class(TList)
+  private
+    function getError(index: integer): TLexError;
+  public
+    procedure clear; override;
+    procedure addError(aValue: PLexError);
+    property error[index: integer]: TLexError read getError;
+  end;
+
+  TLexErrorEnumerator = class
+    fList: TLexErrorList;
+    fIndex: Integer;
+    function GetCurrent: TLexError;
+    function MoveNext: Boolean;
+    property Current: TLexError read GetCurrent;
+  end;
+
+  operator enumerator(aTokenList: TLexTokenList): TLexTokenEnumerator;
+  operator enumerator(anErrorList: TLexErrorList): TLexErrorEnumerator;
+
+  (*****************************************************************************
+   * Lexes aText and fills aList with the TLexToken found.
+   *)
+  procedure lex(const aText: string; const aList: TLexTokenList);
+  (*****************************************************************************
+   * Detects various syntaxic error in a TLexTokenList
+   *)
+  procedure checkSyntaxicErrors(const aTokenList: TLexTokenList; const anErrorList: TLexErrorList);
+
+
+
+  (*****************************************************************************
+   * Compares two TPoints.
+   *)
+  operator = (lhs: TPoint; rhs: TPoint): boolean;
+
+implementation
+
+var
+  D2Dictionary: TD2Dictionary;
+
+{$REGION TReaderHead------------------------------------------------------------}
+operator = (lhs: TPoint; rhs: TPoint): boolean;
+begin
+  exit( (lhs.y = rhs.y) and (lhs.x = rhs.x) );
+end;
+
+constructor TReaderHead.create(const aText: PChar; const aColAndLine: TPoint);
+begin
+  setReader(aText,aColAndLine);
+end;
+
+procedure TReaderHead.setReader(const aText: PChar; const aColAndLine: TPoint);
+begin
+  fLineIndex := aColAndLine.y;
+  fColumnIndex := aColAndLine.x;
+  fReaderHead := aText;
+  while (LineAnColumn <> aColAndLine) do next;
+  //
+  // editor not 0 based ln index
+  if fLineIndex = 0 then fLineIndex := 1;
+end;
+
+function TReaderHead.getColAndLine: TPoint;
+begin
+  exit( Point(fColumnIndex, fLineIndex) );
+end;
+
+function TReaderHead.next: PChar;
+begin
+  Inc(fReaderHead);
+  Inc(fAbsoluteIndex);
+  Inc(fColumnIndex);
+  if (fReaderHead^ = #10) then
+  begin
+    Inc(fLineIndex);
+    fColumnIndex := 0;
+  end;
+  exit(fReaderHead);
+end;
+
+function TReaderHead.previous: PChar;
+begin
+  // note: it breaks the column but not the line count
+  Dec(fReaderHead);
+  Dec(fColumnIndex);
+  Dec(fAbsoluteIndex);
+  exit(fReaderHead);
+end;
+{$ENDREGION}
+
+{$REGION TD2Dictionary----------------------------------------------------------}
+constructor TD2Dictionary.create;
+var
+  value: string;
+begin
+  for value in D2Kw do
+    addEntry(value);
+end;
+
+destructor TD2Dictionary.destroy;
+begin
+end;
+
+{$IFDEF DEBUG}{$R-}{$ENDIF}
+function TD2Dictionary.toHash(const aValue: string): Byte;
+var
+  i: Integer;
+begin
+  result := 0;
+	for i := 1 to length(aValue) do result +=
+    (Byte(aValue[i]) shl (4 and (1-i))) xor 25;
+end;
+{$IFDEF DEBUG}{$R+}{$ENDIF}
+
+procedure TD2Dictionary.addEntry(const aValue: string);
+var
+  hash: Byte;
+begin
+  if find(aValue) then exit;
+  hash := toHash(aValue);
+  fEntries[hash].filled := true;
+  setLength(fEntries[hash].values, length(fEntries[hash].values) + 1);
+  fEntries[hash].values[high(fEntries[hash].values)] := aValue;
+  if fLongest <= length(aValue) then
+    fLongest := length(aValue);
+  if fShortest >= length(aValue) then
+    fShortest := length(aValue);
+end;
+
+function TD2Dictionary.find(const aValue: string): boolean;
+var
+  hash: Byte;
+  i: NativeInt;
+begin
+  result := false;
+  if length(aValue) > fLongest then exit;
+  if length(aValue) < fShortest then exit;
+  hash := toHash(aValue);
+  if (not fEntries[hash].filled) then exit(false);
+  for i:= 0 to high(fEntries[hash].values) do
+    if fEntries[hash].values[i] = aValue then exit(true);
+end;
+{$ENDREGION}
+
+{$REGION Lexing-----------------------------------------------------------------}
+function TLexTokenList.getToken(index: integer): TLexToken;
+begin
+  result := PLexToken(Items[index])^;
+end;
+
+procedure TLexTokenList.clear;
+begin
+  while Count > 0 do
+  begin
+    Dispose( PLexToken(Items[Count-1]) );
+    Delete(Count-1);
+  end;
+end;
+
+procedure TLexTokenList.addToken(aValue: PLexToken);
+begin
+  add(Pointer(aValue));
+end;
+
+function TLexTokenEnumerator.GetCurrent: TLexToken;
+begin
+  exit(fList.token[fIndex]);
+end;
+
+function TLexTokenEnumerator.MoveNext: Boolean;
+begin
+  Inc(fIndex);
+  exit(fIndex < fList.Count);
+end;
+
+operator enumerator(aTokenList: TLexTokenList): TLexTokenEnumerator;
+begin
+  result := TLexTokenEnumerator.Create;
+  result.fList := aTokenList;
+  result.fIndex := -1;
+end;
+
+{$BOOLEVAL ON}
+procedure lex(const aText: string; const aList: TLexTokenList);
+var
+  reader: TReaderHead;
+  identifier: string;
+
+  function isOutOfBound: boolean;
+  begin
+    exit(reader.AbsoluteIndex > length(aText))
+  end;
+
+  procedure addToken(aTk: TLexTokenKind);
+  var
+    ptk: PLexToken;
+  begin
+    ptk := new(PLexToken);
+    ptk^.kind := aTk;
+    ptk^.position := reader.LineAnColumn;
+    ptk^.data := identifier;
+    aList.Add(ptk);
+  end;
+
+begin
+
+  reader.create(@aText[1], Point(0,0));
+  while (true) do
+  begin
+
+    if isOutOfBound then
+      exit;
+
+    identifier := '';
+
+    // skip blanks
+    while isWhite(reader.head^) do
+    begin
+      reader.next;
+      if isOutOfBound then exit;
+    end;
+
+    // line comment
+    if (reader.head^ = '/') then
+    begin
+      if (reader.next^ = '/') then
+      begin
+        if isOutOfBound then exit;
+        while (reader.head^ <> #10) do
+        begin
+          reader.next;
+          identifier += reader.head^;
+          if isOutOfBound then exit;
+        end;
+        reader.next;
+        addToken(ltkComment);
+        continue;
+      end
+      else
+        reader.previous;
+    end;
+
+    // block comments 1
+    if (reader.head^ = '/') then
+    begin
+      if (reader.next^ = '*') then
+      begin
+        if isOutOfBound then exit;
+        while (reader.head^ <> '*') or (reader.next^ <> '/') do
+          if isOutOfBound then exit;
+        reader.next;
+        addToken(ltkComment);
+        continue;
+      end
+      else
+        reader.previous;
+    end;
+
+    // block comments 2
+    if (reader.head^ = '/') then
+    begin
+      if (reader.next^ = '+') then
+      begin
+        if isOutOfBound then exit;
+        while (reader.head^ <> '+') or (reader.next^ <> '/') do
+          if isOutOfBound then exit;
+        reader.next;
+        addToken(ltkComment);
+        continue;
+      end
+      else
+        reader.previous;
+    end;
+
+    // string 1, note: same escape error as in SynD2Syn
+    if (reader.head^ in ['r', 'x']) then
+    begin
+      if not (reader.next^ = '"') then
+        reader.previous;
+    end;
+    if (reader.head^ = '"') then
+    begin
+      reader.next;
+      if isOutOfBound then exit;
+      if (reader.head^ = '"') then
+      begin
+        reader.next;
+        addToken(ltkString);
+        continue;
+      end;
+      while (true) do
+      begin
+        if reader.head^ = '\' then
+        begin
+          reader.next;
+          if (reader.head^ = '"') then
+          begin
+            reader.next;
+            continue;
+          end;
+        end;
+        if (reader.head^ = '"') then
+          break;
+        identifier += reader.head^;
+        reader.next;
+        if isOutOfBound then exit;
+      end;
+      if isStringPostfix(reader.next^) then
+        reader.next;
+      addToken(ltkString);
+      continue;
+    end;
+
+    // string 2
+    if (reader.head^ = '`') then
+    begin
+      reader.next;
+      if isOutOfBound then exit;
+      while (reader.head^ <> '`') do
+      begin
+        identifier += reader.head^;
+        reader.next;
+        if isOutOfBound then exit;
+      end;
+      if isStringPostfix(reader.next^) then
+        reader.next;
+      if isOutOfBound then exit;
+      addToken(ltkString);
+      continue;
+    end;
+
+    //chars, note: same escape error as in SynD2Syn
+    if (reader.head^ = #39) then
+    begin
+      reader.next;
+      if isOutOfBound then exit;
+      if (reader.head^ = #39) then
+      begin
+        reader.next;
+        addToken(ltkString);
+        continue;
+      end;
+      while (true) do
+      begin
+        if reader.head^ = '\' then
+        begin
+          reader.next;
+          if (reader.head^ = #39) then
+          begin
+            reader.next;
+            continue;
+          end;
+        end;
+        if (reader.head^ = #39) then
+          break;
+        identifier += reader.head^;
+        reader.next;
+        if isOutOfBound then exit;
+      end;
+      reader.next;
+      addToken(ltkChar);
+      continue;
+    end;
+
+    // check negative float '-0.'
+    if (reader.head^ = '-') then
+    begin
+      identifier += reader.head^;
+      if reader.next^ = '0' then
+      begin
+        if reader.next^ = '.' then
+          reader.previous // back to 0, get into "binary/hex numbr/float"
+        else
+          begin
+            reader.previous;
+            reader.previous; // back to -
+            identifier := '';
+          end;
+      end
+      else
+      begin
+        reader.previous; // back to -
+        identifier := '';
+      end;
+    end;
+
+    // + suffixes
+    // + exponent
+    // float .xxxx
+
+    // binary/hex numbr/float
+    if (reader.head^ = '0') then
+    begin
+      identifier += reader.head^;
+      if (reader.next^ in ['b','B']) then
+      begin
+        identifier += reader.head^;
+        while isBit(reader.next^) or (reader.head^ = '_') do
+        begin
+          if isOutOfBound then exit;
+          identifier += reader.head^;
+        end;
+        addToken(ltkNumber);
+        continue;
+      end
+      else reader.previous;
+      if (reader.next^ in ['x','X']) then
+      begin
+        identifier += reader.head^;
+        while isHex(reader.next^) or (reader.head^ = '_') do
+        begin
+          if isOutOfBound then exit;
+          identifier += reader.head^;
+        end;
+        addToken(ltkNumber);
+        continue;
+      end
+      else reader.previous;
+      if (reader.next^ = '.') then
+      begin
+        identifier += reader.head^;
+        while isNumber(reader.next^) do
+        begin
+          if isOutOfBound then exit;
+          identifier += reader.head^;
+        end;
+        addToken(ltkNumber);
+        continue;
+      end
+      else reader.previous;
+      identifier := '';
+    end;
+
+    // check negative float/int '-xxx'
+    if (reader.head^ = '-') then
+    begin
+      identifier += reader.head^;
+      if not isNumber(reader.next^) then
+      begin
+        reader.previous; // back to '-'
+        identifier := '';
+      end;
+    end;
+
+    // numbers
+    if isNumber(reader.head^) then
+    begin
+      identifier += reader.head^;
+      while isNumber(reader.next^) or (reader.head^ = '_')  do
+      begin
+        if isOutOfBound then exit;
+        identifier += reader.head^;
+      end;
+      addToken(ltkNumber);
+      continue;
+    end;
+
+    // symbols
+    if isSymbol(reader.head^) then
+    begin
+      identifier += reader.head^;
+      reader.next;
+      addToken(ltkSymbol);
+      if isOutOfBound then exit;
+      continue;
+    end;
+
+    // operators
+    if isOperator1(reader.head^) then
+    begin
+      identifier += reader.head^;
+      while isOperator1(reader.next^) do
+      begin
+        if isOutOfBound then exit;
+        identifier += reader.head^;
+      end;
+      case length(identifier) of
+        4:begin
+            if (not isOperator1(reader.head^)) and
+              isOperator4(identifier) then
+            begin
+              addToken(ltkOperator);
+              continue;
+            end;
+          end;
+        3:begin
+            if (not isOperator1(reader.head^)) and
+              isOperator3(identifier) then
+            begin
+              addToken(ltkOperator);
+              continue;
+            end;
+          end;
+        2:begin
+            if (not isOperator1(reader.head^)) and
+              isOperator2(identifier) then
+            begin
+              addToken(ltkOperator);
+              continue;
+            end;
+          end;
+        1:begin
+            if not isOperator1(reader.head^)
+            then
+              begin
+                addToken(ltkOperator);
+                continue;
+              end;
+          end;
+      end;
+    end;
+
+    // identifier accum
+    if isFirstIdentifier(reader.head^) then
+    begin
+      while isIdentifier(reader.head^) do
+      begin
+        identifier += reader.head^;
+        reader.next;
+        if isOutOfBound then exit;
+      end;
+      if D2Dictionary.find(identifier) then
+        addToken(ltkKeyword)
+      else
+        addToken(ltkIdentifier);
+      continue;
+    end;
+
+    // error
+    identifier += ' (unrecognized lexer input)';
+    addToken(ltkIllegal);
+
+  end;
+end;
+{$BOOLEVAL OFF}
+{$ENDREGION}
+
+{$REGION Syntaxic errors}
+function TLexErrorList.getError(index: integer): TLexError;
+begin
+  result := PLexError(Items[index])^;
+end;
+
+procedure TLexErrorList.clear;
+begin
+  while Count > 0 do
+  begin
+    Dispose( PLexError(Items[Count-1]) );
+    Delete(Count-1);
+  end;
+end;
+
+procedure TLexErrorList.addError(aValue: PLexError);
+begin
+  add(Pointer(aValue));
+end;
+
+function TLexErrorEnumerator.GetCurrent: TLexError;
+begin
+  exit(fList.error[fIndex]);
+end;
+
+function TLexErrorEnumerator.MoveNext: Boolean;
+begin
+  Inc(fIndex);
+  exit(fIndex < fList.Count);
+end;
+
+operator enumerator(anErrorList: TLexErrorList): TLexErrorEnumerator;
+begin
+  result := TLexErrorEnumerator.Create;
+  result.fList := anErrorList;
+  result.fIndex := -1;
+end;
+
+procedure checkSyntaxicErrors(const aTokenList: TLexTokenList; const anErrorList: TLexErrorList);
+const
+  errPrefix = 'syntaxic error: ';
+var
+  tk, old1, old2: TLexToken;
+  err: PLexError;
+  tkIndex: NativeInt;
+  pareCnt, curlCnt, squaCnt: NativeInt;
+procedure addError(const aMsg: string);
+begin
+  err := new(PLexError);
+  err^.msg := errPrefix + aMsg;
+  err^.position := aTokenList.token[tkIndex].position;
+  anErrorList.addError(err);
+end;
+label
+  _preSeq;
+begin
+
+  tkIndex := -1;
+  pareCnt := 0;
+  curlCnt := 0;
+  squaCnt := 0;
+
+  for tk in aTokenList do
+  begin
+
+    // token index
+    Inc(tkIndex);
+
+    // brackets count
+    if tk.kind = ltkSymbol then
+    begin
+      case tk.data of
+      '(': Inc(pareCnt);
+      '{': Inc(curlCnt);
+      '[': Inc(squaCnt);
+      ')': Dec(pareCnt);
+      '}': Dec(curlCnt);
+      ']': Dec(squaCnt);
+      end;
+
+      // only for the first occurence
+      if pareCnt = -1 then
+        addError('a left parenthesis is missing');
+      if curlCnt = -1 then
+        addError('a left curly bracket is missing');
+      if squaCnt = -1 then
+        addError('a left square bracket is missing');
+
+      // at the end
+      if (tkIndex = aTokenList.Count-1) then
+      begin
+        if pareCnt > 0 then
+          addError('a right parenthesis is missing');
+        if curlCnt > 0 then
+          addError('a right curly bracket is missing');
+        if squaCnt > 0 then
+          addError('a right square bracket is missing');
+      end;
+
+      goto _preSeq;
+    end;
+
+    // lexer invalid token
+    if tk.kind = ltkIllegal then
+    begin
+      addError(tk.data);
+      goto _preSeq;
+    end;
+
+    // invalid numbers
+    if tk.kind = ltkNumber then
+    begin
+
+      goto _preSeq;
+    end;
+
+_preSeq:
+    // invalid sequences
+    if tkIndex > 0 then // can use old1
+    begin
+      if (old1.kind = ltkKeyword) and (tk.kind = ltkKeyword) then
+        if old1.data = tk.data then
+          addError('keyword is duplicated');
+
+      // needs negative numbr to be tokenized correctly: ... = -1; '-' is currently token as an operator.
+      if (old1.kind = ltkOperator) and (tk.kind = ltkOperator) then
+        addError('operator rhs cannot be an operator');
+
+      if (old1.kind = ltkNumber) and (tk.kind = ltkNumber) then
+        addError('symbol or operator expected after number');
+
+    end;
+    if tkIndex > 1 then // can use old2
+    begin
+
+    end;
+
+
+    old1 := tk;
+    old2 := old1;
+  end;
+
+
+end;
+{$ENDREGION}
+
+initialization
+  D2Dictionary.create;
+finalization
+  D2Dictionary.destroy;
+end.
+
diff --git a/src/ce_dlangutils.pas b/src/ce_dlangutils.pas
new file mode 100644
index 00000000..684aa91d
--- /dev/null
+++ b/src/ce_dlangutils.pas
@@ -0,0 +1,135 @@
+unit ce_dlangutils;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  SysUtils;
+
+function isWhite(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isSpace(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isAlpha(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isNumber(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isBit(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isAlNum(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isHex(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isSymbol(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isOperator1(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isOperator2(const s: string): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isOperator3(const s: string): boolean; {$IFNDEF DEBUG} inline; {$ENDIF}
+function isOperator4(const s: string): boolean; {$IFNDEF DEBUG} inline; {$ENDIF}
+function isStringPostfix(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isIdentifier(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+function isFirstIdentifier(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+
+implementation
+
+{$BOOLEVAL ON}
+function isWhite(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(c in [#0..#32]);
+end;
+
+function isSpace(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(c in [#9,' ']);
+end;
+
+function isAlpha(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit((c in ['a'..'z']) or (c in ['A'..'Z']));
+end;
+
+function isNumber(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(c in ['0'..'9']);
+end;
+
+function isBit(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit((c in ['0'..'1']));
+end;
+
+function isAlNum(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(isAlpha(c) or isNumber(c));
+end;
+
+function isHex(const c: Char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(isNumber(c) or (c in ['A'..'F']) or (c in ['a'..'f']));
+end;
+
+function isSymbol(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(c in [';', '{', '}', '(', ')', '[', ']', ',', '.', ':' , '"', #39, '?', '$']);
+end;
+
+function isOperator1(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(c in ['/', '*', '-', '+', '%', '>', '<', '=', '!',
+                  '&', '|', '^', '~']);
+end;
+
+function isOperator2(const s: string): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  result := false;
+  case s[1] of
+    '.': result := (s[2] = '.');
+
+    '>': result := s[2] in ['>', '='];
+    '<': result := s[2] in ['<', '=', '>'];
+    '=': result := s[2] in ['=', '>'];
+    '!': result := s[2] in ['=', '>', '<'];
+
+    '+': result := s[2] in ['+', '='];
+    '-': result := s[2] in ['-', '='];
+    '/': result := s[2] in ['='];
+    '*': result := s[2] in ['='];
+    '%': result := s[2] in ['='];
+    '~': result := s[2] in ['='];
+
+    '&': result := s[2] in ['&', '='];
+    '|': result := s[2] in ['|', '='];
+    '^': result := s[2] in ['^', '='];
+  end;
+end;
+
+function isOperator3(const s: string): boolean; {$IFNDEF DEBUG} inline; {$ENDIF}
+begin
+  result := false;
+  case s[1] of
+    '.': result := (s[2] = '.')   and (s[3] = '.');
+    '^': result := (s[2] = '^')   and (s[3] = '=');
+    '>': result := (s[2] = '>')   and (s[3] in ['>', '=']);
+    '<': result := ((s[2] = '<')  and (s[3] in ['<', '=']))
+                  or (s[2] = '>') and (s[3] = '=');
+    '!': result := ((s[2] = '<')  and (s[3] in ['>', '=']))
+                  or ((s[2] = '>')and (s[3] = '='));
+  end;
+end;
+
+function isOperator4(const s: string): boolean; {$IFNDEF DEBUG} inline; {$ENDIF}
+begin
+  result := (s = '>>>=') or (s = '!<>=');
+end;
+
+function isStringPostfix(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(c in ['c', 'w', 'd']);
+end;
+
+function isIdentifier(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit((not isSymbol(c)) and (not isOperator1(c)) and (not isWhite(c)));
+end;
+
+function isFirstIdentifier(const c: char): boolean; {$IFNDEF DEBUG}inline;{$ENDIF}
+begin
+  exit(isIdentifier(c) and (not isNumber(c)));
+end;
+{$BOOLEVAL OFF}
+
+end.
+
diff --git a/src/ce_editor.pas b/src/ce_editor.pas
index 11a605d3..03d91322 100644
--- a/src/ce_editor.pas
+++ b/src/ce_editor.pas
@@ -8,7 +8,8 @@ uses
   Classes, SysUtils, FileUtil, ExtendedNotebook, Forms, Controls, lcltype,
   Graphics, SynEditKeyCmds, ComCtrls, SynEditHighlighter, ExtCtrls, Menus,
   SynEditHighlighterFoldBase, SynMacroRecorder, SynPluginSyncroEdit, SynEdit,
-  SynHighlighterLFM, ce_widget, ce_d2syn, ce_synmemo, ce_common, AnchorDocking;
+  SynHighlighterLFM, ce_widget, ce_d2syn, ce_synmemo, ce_common, AnchorDocking,
+  ce_dlang;
 
 type
   { TCEEditorWidget }
@@ -26,7 +27,6 @@ type
     fKeyChanged: boolean;
     fSyncEdit: TSynPluginSyncroEdit;
     procedure memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
-    procedure memoKeyPress(Sender: TObject; var Key: Char);
     procedure memoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
     procedure memoChange(Sender: TObject);
     procedure memoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
@@ -138,7 +138,6 @@ begin
   memo.OnMouseDown := @memoMouseDown;
   memo.OnChange := @memoChange;
   memo.OnMouseMove := @memoMouseMove;
-  memo.OnKeyPress := @memoKeyPress;
   //
   pageControl.ActivePage := sheet;
   //http://bugs.freepascal.org/view.php?id=26320
@@ -158,15 +157,13 @@ end;
 
 procedure TCEEditorWidget.memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
 begin
-end;
-
-procedure TCEEditorWidget.memoKeyPress(Sender: TObject; var Key: Char);
-begin
-  if (sender is TCESynMemo) then
+if (sender is TCESynMemo) then
     identifierToD2Syn(TCESynMemo(Sender));
+  fKeyChanged := true;
   case Byte(Key) of
-    VK_UNKNOWN..VK_BACK: exit;
-    VK_PRIOR..VK_HELP: exit;
+    VK_UNKNOWN..VK_XBUTTON2: exit;
+    VK_SHIFT..VK_HELP: fKeyChanged := false;
+    VK_LWIN..VK_SLEEP: exit;
     VK_F1..$91: exit;
   end;
   fKeyChanged := true;
@@ -200,6 +197,9 @@ const
   modstr: array[boolean] of string = ('...', 'MODIFIED');
 var
   ed: TCESynMemo;
+  tokLst: TLexTokenList;
+  errLst: TLexErrorList;
+  err: TLexError;
 begin
   ed := getCurrentEditor;
   if ed <> nil then
@@ -210,8 +210,31 @@ begin
   end;
   //
   if fKeyChanged then if editorIndex <> -1 then
+  begin
     mainForm.docChangeNotify(Self, editorIndex);
+
+    mainForm.MessageWidget.List.Clear;
+    tokLst := TLexTokenList.Create;
+    errLst := TLexErrorList.Create;
+    try
+      lex( ed.Lines.Text, tokLst );
+      checkSyntaxicErrors( tokLst, errLst);
+
+      for err in errLst do
+        mainForm.MessageWidget.addMessage(format(
+        '%s  (@line:%4.d @char:%.4d)',[err.msg, err.position.y, err.position.x]));
+
+      mainForm.MessageWidget.scrollToBack;
+
+    finally
+      tokLst.Free;
+      errLst.Free;
+    end;
+
+
+  end;
   fKeyChanged := false;
+
 end;
 
 end.
diff --git a/src/ce_main.lfm b/src/ce_main.lfm
index 71471e14..4d461d75 100644
--- a/src/ce_main.lfm
+++ b/src/ce_main.lfm
@@ -2547,39 +2547,39 @@ object CEMainForm: TCEMainForm
       0000000000330000003300000033000000332D73BAAF1B3D60523F93D4FF3F93
       D4FF102438413578BAC300000024000000000000000000000000000000000000
       0000000000000000000000000000000000000000001F00000008000000330000
-      0033000000040000002400000000B3B3B1EFB0B0ADFFAEAEACFFAEAEABFFAEAE
-      ABFFAEAEABFFADAEABFFAEAEABFFAFAFADFFB0B0AEEAB3B3B100B5B5B300B5B5
-      B300B5B5B300B5B5B300B5B5B300AFAFADFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
-      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9E9E9FFAEAEACA6B3B3B100B5B5
-      B300B5B5B300B5B5B300B5B5B300AEAEACFFFFFFFFFFE0DFDEFFE1DFDEFFE1E0
-      DFFFE1DFDEFFE0DFDEFFFFFFFFFFA5A5A3FFFFFFFFFFE8E8E8FFAFAFACA7B3B3
-      B100B5B5B300B5B5B300B6B6B400AEAEABFFFFFFFFFFE3E3E2FFE4E4E3FFE4E5
-      E4FFE4E4E3FFE3E3E2FFFFFFFFFFA7A7A5FFECECEBFFFFFFFFFFEAEAEAFFB1B1
-      AFACB6B6B400B8B8B600B9B9B700ADAEABFFFFFFFFFFE7E5E4FFE8E7E6FFE8E7
-      E6FFE8E7E6FFE7E6E5FFFFFFFFFFCDCDCCFFAAAAA8FFADADABFFFFFFFFFFB3B3
-      B1FFB8B9B7008A8886008C898700ADADABFFFFFFFFFFE9E9E8FFEAEAE9FFEAEA
-      E9FFEAEAE9FFECECEBFFFAFAF9FFFFFFFFFFFFFFFFFF7B7976FF7E7B79FFB8B8
-      B6FF979593008D8B89008F8D8B00ADADABFFFFFFFFFFECEBEAFFEDECEBFFEDEC
-      EBFFEEEDECFFF3F2F1FF7B7977FF8C8987FFCBCAC8FFB2AFADFFB5B2B0FFA3A3
-      A1FF979593FF8D8B89FF908E8B00ADADABFFFFFFFFFFEFEFEEFFEFEFEEFFEFEF
-      EEFFF1F1F0FFF7F8F7FF8B8987FFD8D5D5FF9B9996FFD0CECDFFD1CFCEFF9D9B
-      99FFDCDAD9FF918F8DFF94929000ADADABFFFFFFFFFFF2F1F0FFF2F1F0FFF3F1
-      F0FFF6F5F4FFFFFEFDFFB6B3B3FF9B9996FFBCBAB9FF92908FFF92908FFFBCBA
-      B9FF9E9C9AFF6C6B699B908E8C00ADADABFFFFFFFFFFF4F4F3FFF4F4F3FFF5F6
-      F4FFFCFCFBFF73706EFFABA9A8FFCCCAC9FF918F8DFFE1E1E1FFECECEBFF918F
-      8CFFCDCBCBFFB1AFAEFF8F8D8BFFADADABFFFFFFFFFFF6F6F6FFF6F6F6FFF7F8
-      F8FFFEFFFFFF726F6DFFAAA8A7FFCAC8C7FF8E8C8BFFFFFFFFFFFFFFFFFF8E8C
-      8BFFCBC9C8FFB0AEADFF8E8C8AFFADADABFFFFFFFFFFFAF8F8FFF9F8F8FFFAF9
-      F9FFFEFDFDFFE1E1E0FFC2C1C0FF959392FFB5B3B2FF8D8B89FF8D8B88FFB5B3
-      B2FF999796FF646260894847465BAEAEABFFFFFFFFFFFDFDFDFFFCFCFDFFFCFD
-      FDFFFFFFFFFFFFFFFFFF84817FFFCCCAC9FF949291FFC5C3C2FFC6C4C3FF9694
-      93FFD0CECDFF8B8988FF0000000AB0B0ADFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
-      FFFFFFFFFFFFFFFFFFFF787573FF817E7CFFDDDCDDFFA5A3A2FFA7A5A4FFA4A3
-      A1FF878583FF868482FF88868400A4A4A2C0AFAFADFFAEAEABFFADADABFFADAD
-      ABFFAEAEACFFB1B1AEFFB6B6B4FFB7B8B6FFB9BAB7FF797776FF7A7877FFADAE
-      ACB9000000330000003388868400000000000000003300000033000000330000
-      0033000000330000003300000033000000330000003300000033000000330000
-      0022000000000000000000000000FFFFFF000000000000000000000000000000
+      0033000000040000002400000000BB871F00BB871F00BB871E00B9841A00B67E
+      0FEAC4973BFFC79D49FFC39538FFB37904FFB47A07FFB47A07FFB47A08FFB57C
+      0AFFB67F0FFFB88114FFBA851B23BB871F00BB871F00BA861D00B7801283E4CF
+      A7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFE9DABAFFEEE2C9FFB67F14BFBB871F00BB871F00B9851B00B27A09E5FFFF
+      FFFFFFFFFFFFFEFEFBFFFEFEFBFFFEFEFCFFFEFEFCFFFEFEFCFFFFFFFEFFFFFF
+      FFFFC69941FFECDFC2FFC19234FFBB871F00BB871E00B9831800C89E49FFFFFF
+      FFFFFCF9F3FFFBF8F1FFFBF8F1FFFBF8F1FFFBF8F1FFFCF9F3FFFDFBF6FFFFFF
+      FFFFB27701FFBA851BFFBC8921FFBB871F00BB861E00B882150CCCA556FFFFFF
+      FFFFF9F6EBFFF9F5EAFFFAF6ECFFFBF7EDFFFDF9EEFFFFFCF1FFFFFFFCFFFFFF
+      FFFFAB7405CE0000003300000033BB871F00BB861D00B07B1134DBBF88FFFFFF
+      FFFFF7F2E5FFFAF4E6FFFEF7E9FFFFF9EAFFFFFCEDFF767574FF777778FFF8E9
+      CAFFAA7200A8888D99008B8E9700BB871F00BA861D00AD790E73EADBBBFFFAF7
+      EEFFF6EFDEFFFCF4E2FF7B797AFF8B8A89FFD2CCBFFFB1AFAEFFB1B1B1FFC3B2
+      8EFF939499FF8C8B8EFF8E8E8E00BB871F00BA851C00AA760C9BF0E4CCFFF6EF
+      E0FFF4ECD7FFFAF2DCFF8B8A8AFFD7D6D6FF9A9997FFD0CECEFFD0CFCFFF9C9A
+      9AFFDBDADBFF918F8EFF94929000BB871F00BA851C00B0790BD2FFFFFFFFF1E9
+      D2FFF4EBD2FFFCF2D7FFB4AFA2FF9B9997FFBCBABAFF939191FF929191FFBCBA
+      BAFF9E9C9AFF6C6B699B908E8C00BB871E00B9841900B8831BEFFFFFFFFFF2E9
+      D3FFF7EDD4FF747577FFABA9AAFFCCCACAFF92908FFFDCD2B9FFE9E7E2FF918F
+      8EFFCECCCBFFB1AFAEFF8F8D8BFFB98419FFB67E0EFFB67F0FFFC0902EFFC08E
+      29FFC59128FF747578FFAAA8A9FFCAC8C7FF8F8D8EFFFFF2D2FFFFFFF5FF8F8D
+      8DFFCBC9C9FFB0AEADFF8E8C8AFFB78012FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFE3E3DFFFC2C1BBFF959493FFB5B3B4FF8D8C8CFF8D8C8BFFB6B4
+      B3FF999796FF646260894847465BAC7A14CADCC189FFF5F0E0FFF4EDDBFFF4ED
+      DBFFF6EFDBFFFDF4DCFF878789FFCECDCEFF969698FFC6C5C6FFC7C5C5FF9896
+      95FFD1CFCEFF8B8988FF0000000A60440E44B88114FFB67E0FFFB57D0DFFB57D
+      0CFFB67E0CFFBC7F06FF7F8188FF86878AFFA87F2DFFA8A8ABFFAAA8A8FF5250
+      4F698A8886FF868482FF88868400000000070000003300000033000000330000
+      003300000033000000330000003300000033000000337C7C81FF7E7D7DFF0000
+      000E000000330000003388868400000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000033000000330000
+      0000000000000000000000000000FFFFFF000000000000000000000000000000
       0000000000000000000000000000A6A4A133A5A39FE5AEACA9FFB9B6B5FFABA9
       A5FFA7A5A2D2A8A6A323FFFFFF00FFFFFF000000000000000000000000000000
       00000000000000000000A19F9C48AEACAAFFDADAD9FFF0EEEFFFECEBEAFFE2E0
diff --git a/src/ce_main.pas b/src/ce_main.pas
index 38a706a5..9c4e1a9e 100644
--- a/src/ce_main.pas
+++ b/src/ce_main.pas
@@ -16,7 +16,7 @@ type
   TCEMainForm = class;
 
   (**
-   * Encapsulates the options.
+   * Encapsulates the options in a writable component.
    * note: likely to change however needed to test correctly Coedit.
    *)
   TCEOptions = class(TComponent)
@@ -45,7 +45,7 @@ type
     procedure saveToFile(const aFilename: string);
     procedure loadFromFile(const aFilename: string);
     procedure beforeSave;
-    procedure afterSave;
+    procedure afterLoad;
     procedure DefineProperties(Filer: TFiler); override;
   end;
 
@@ -375,8 +375,8 @@ begin
       actEdIndent.Enabled := true;
       actEdUnIndent.Enabled := true;
       //
-      actFileCompAndRun.Enabled := true;
-      actFileCompAndRunWithArgs.Enabled := true;
+      actFileCompAndRun.Enabled := curr.isDSource;
+      actFileCompAndRunWithArgs.Enabled := curr.isDSource;
       actFileSave.Enabled := true;
       actFileSaveAs.Enabled := true;
       actFileClose.Enabled := true;
@@ -694,7 +694,7 @@ var
 begin
   if fEditWidg = nil then exit;
   if fEditWidg.editorIndex < 0 then exit;
-  if fEditWidg.editor[fEditWidg.editorIndex].Highlighter = LfmSyn
+  if fEditWidg.editor[fEditWidg.editorIndex].isProjectSource
     then exit;
   //
   str := fEditWidg.editor[fEditWidg.editorIndex].fileName;
@@ -1327,10 +1327,10 @@ begin
   except
     exit;
   end;
-  afterSave;
+  afterLoad;
 end;
 
-procedure TCEOptions.afterSave;
+procedure TCEOptions.afterLoad;
 var
   widg: TCEWidget;
 begin
diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas
index 75bbf3c6..26e617f9 100644
--- a/src/ce_synmemo.pas
+++ b/src/ce_synmemo.pas
@@ -15,12 +15,17 @@ type
     fFilename: string;
     fModified: boolean;
     fAssocProject: TCEProject;
+    function getIfDSource: Boolean;
+    function getIfConfig: Boolean;
   public
     constructor Create(aOwner: TComponent); override;
     //
     property fileName: string read fFilename write fFilename;
     property modified: boolean read fModified write fModified;
     property project: TCEProject read fAssocProject write fAssocProject;
+    //
+    property isDSource: boolean read getIfDSource;
+    property isProjectSource: boolean read getIfConfig;
   end;
 
 var
@@ -29,7 +34,7 @@ var
 implementation
 
 uses
-  graphics;
+  graphics, ce_main;
 
 constructor TCESynMemo.Create(aOwner: TComponent);
 begin
@@ -52,6 +57,16 @@ begin
   Highlighter := D2Syn;
 end;
 
+function TCESynMemo.getIfDSource: Boolean;
+begin
+  exit(Highlighter = D2Syn);
+end;
+
+function TCESynMemo.getIfConfig: Boolean;
+begin
+  exit(Highlighter = mainForm.LfmSyn);
+end;
+
 initialization
   D2Syn := TSynD2Syn.create(nil);
 finalization
diff --git a/src/ce_widget.pas b/src/ce_widget.pas
index 801704f2..e1c1158b 100644
--- a/src/ce_widget.pas
+++ b/src/ce_widget.pas
@@ -100,9 +100,6 @@ type
 implementation
 {$R *.lfm}
 
-uses
-  ce_main;
-
 (*******************************************************************************
  * TCEWidget
  *)
@@ -119,8 +116,8 @@ begin
   fUpdaterAuto.OnTimer := @updaterAutoProc;
   fUpdaterDelay := TTimer.Create(self);
 
-  updaterByLoopInterval := 50;
-  updaterByDelayDuration := 1000;
+  updaterByLoopInterval := 70;
+  updaterByDelayDuration := 1250;
 
   DockMaster.MakeDockable(Self, true, true, true);
   DockMaster.GetAnchorSite(Self).Header.HeaderPosition := adlhpTop;