; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license."          |
;|_______________________________________________________________________________________|
;
;  Description: Syntax highlighter procedure for FASM syntax.
;
;  Target OS:
;
;  Dependencies:
;
;  Notes:
;_________________________________________________________________________________________
module "FASM syntax highlighter"

ttText = 0
ttRem  = 1
ttStr  = 2
ttNum  = 3
ttChar = 4



iglobal

  var SynTheme = fasm_colors_windows

; Windows theme.

  if used fasm_colors_windows
    label fasm_colors_windows dword
      .comment      dd $ff808080
      .string       dd $ffff0080
      .number       dd $ff0080ff
      .symbol       dd $ff000000
      .register     dd $ff008080
      .instruction  dd $ff0080ff
      .directive    dd $ff000080
      .preprocessor dd $ff008000
      .macro        dd $ffff00ff
  end if

; Classic theme.

  if used fasm_colors_classic
    label fasm_colors_classic dword
      .comment      dd $ffa0a0a0
      .string       dd $ff00ffff
      .number       dd $ff00ffff
      .symbol       dd $ffd0d0d0
      .register     dd $ff00ff00
      .instruction  dd $ffffff00
      .directive    dd $ffff00ff
      .preprocessor dd $ffff00ff
      .macro        dd $ffff00ff
  end if
endg


;_________________________________________________________________________________________
;
; Arguments:
;   .hString - handle to the line string.
;   .pAttr   - pointer to the array of TCharAttributes for the characters of the string.
;   .SynContext - input context of the highligher.
;
; Returns:
;       eax - output context of the highligher.
;
proc SyntaxFASM, .hString, .pAttr, .SynContext
.Quo rb 4
.start dd ?
begin

        mov     edi, [.pAttr]
        mov     ebx, [SynTheme]

        stdcall StrPtr, [.hString]
        mov     esi, eax
        mov     [.start], eax

.loop:
        mov     al, [esi]
        test    al,al
        jz      .end_of_line

        cmp     [.SynContext], ttRem
        je      .endif

        cmp     [.SynContext], ttStr
        jne     .ifnotstr

        cmp     al,[.Quo]
        jne     .endif

        mov     [.SynContext], ttText
        mov     eax, ttStr
        jmp     .setcolor

.ifnotstr:
        cmp     al, ';'
        jne     .notrem

        mov     [.SynContext], ttRem
        jmp     .endif

.notrem:
        cmp     al, '"'
        je      .str
        cmp     al, "'"
        jne     .notstr

.str:
        mov     [.SynContext], ttStr
        mov     [.Quo], al
        jmp     .endif

.notstr:
        call    .CharInSymbols
        jnc     .notsym

        mov     [.SynContext], ttChar
        jmp     .endif

.notsym:
        cmp     [.SynContext], ttNum
        je      .endif

        cmp     esi, [.start]
        je      .maybenum

        cmp     [.SynContext], ttChar
        jne     .endif

; The number begins only after ttChar or at the begining of the line.
.maybenum:
        call    .CharInNum
        jnc     .notnum

        mov      [.SynContext], ttNum
        jmp      .endif

.notnum:
        mov     [.SynContext], ttText

.endif:
        mov     eax, [.SynContext]
        cmp     eax, ttText
        je      .next

.setcolor:
        cmp     [edi+TCharAttr.flags], 0
        jne     .next                           ; the char have protected attributes.

        mov     ecx, [ebx+4*eax-4]
        mov     [edi+TCharAttr.color], ecx

.next:
        add     edi, sizeof.TCharAttr
        inc     esi
        stdcall ScanForwardUtf8
        jmp     .loop

.end_of_line:
        mov     eax, ttText
        return
endp


.CharInSymbols:
        push    edi ecx

        mov     edi, symbol_characters+1
        movzx   ecx, byte [edi-1]

        repne scasb
        jne   @f
        stc
        pop     ecx edi
        ret
@@:
        clc
        pop     ecx edi
        retn


.CharInNum:
        cmp     al, '$'
        jne     @f
        stc
        retn

@@:
        cmp     al, '0'
        jb      @f
        cmp     al, '9'
        ja      @f
        stc
        retn
@@:
        clc
        retn


symbol_characters db 27
                  db 9,0Ah,0Dh,1Ah,20h,'+-/*=<>()[]{}:,|&~#`;\'

endmodule