Canvasbasierter alternative zur Scintilla

Für allgemeine Fragen zur Programmierung mit PureBasic.
5mware
Beiträge: 47
Registriert: 14.12.2015 15:16

Canvasbasierter alternative zur Scintilla

Beitrag von 5mware »

Hallo Leute,

das ist jetzt ein Projekt das etwas länger andauert. Ich werde diesen Thread ebenfalls auf dem englischen Form aufmachen.

Es geht um eine essentielle Sache, das von dem ich glaube, viele von euch sehr interessieren wird: Eine echte alternative zur Scintilla.

Die Gründe für diese Alternative sind:

-> Besserer Umgang mit Unicode-Zeichen zb. beim Suchen und Ersetzen, beim Erkennen von Schlüsselwörtern etc.

-> Eine integrierte Intellisence-Box

-> Eine interne ToolTip-Funktion die zum Beispiel bei Funktionsnamenseingaben gleich die Parameter aufzeigt

-> Leichter Umgang

-> Cross-Plattform, auch mit möglichst Abwertskompatibilität

-----

In diesem Model sind derzeit keine Threads eingebaut und nicht nötig. Allerdings steht die Frage im Raum, ob der Einsatz von Threads nicht besser wäre.

Alle die interessiert sind mit zu machen, die bitte ich, schreibt mir separat unter aziz@5m-ware.de damit wir das koordinieren können. ich bin davon überzeugt, das wir gemeinsam dieses Tool hinbekommen.

-----

Was derzeit geht:

-> eine relative akzeptable Geschwindigkeit beim Tippen und hoch- sowie runterscrollen. Aber es könnte noch weiter optimiert werden.

-> Erkennung von Schlüsselwörtern (habe ein paar PB-Keys beispielsweise reingepackt) und deren Färbung

-> Kommentarerkennung

-> Stringerkennung zwischen ""

-> Zahlenerkennung

-> halbwegs funktionsfähiges Markieren und kopieren mit STRG+C und ausschneidne mit SRTG-X. Steckt noch in den Kinderschuhen und braucht viel optimierung.

-----

Was alles eingeplant ist:

-> Korrekturen für Markieren, Geschwindigkeit, mehrzeilige Kommentare, intellisence-Box
-> internes Suchen und Ersetzen
-> Folding
-> Undo-Redo
-> ToolTip
-> Zeilen-Spalten-Erkennung, Sprung etc.
-> Syntax-Checking mit Callback, bei Fehlerauffindung

Bin für weitere Infos offen.

-----

Ich arbeite unter Mac (montain lion), und habe es erst einmal nur auf dem Mac getestet, die Ergebnisse unter Windows und Linux sind mir derzeit nicht bekannt. Muss ich selber noch testen.

PB 5.60 im Einsatz.

-----

Der Forum Editor hat mir soeben folgendes mitgeteilt:
"Your message contains 93397 characters. The maximum number of allowed characters is 60000."

Deshalb gib ich den Code jetzt hier in Häpchen ab:
5mware
Beiträge: 47
Registriert: 14.12.2015 15:16

Re: Canvasbasierter alternative zur Scintilla

Beitrag von 5mware »

Code: Alles auswählen

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Keyboard
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Windows
    Enumeration
      #pure_keycode_down    = 40
      #pure_keycode_up      = 38
      #pure_keycode_left    = 37
      #pure_keycode_right   = 39
      #pure_keycode_enter   = 13
      #pure_keycode_delete  =  8
      #pure_keycode_space   = 32
      #pure_keycode_escape  = 27
      #pure_keycode_p_down  = 34
      #pure_keycode_p_up    = 33
      #pure_keycode_pos     = 36
      #pure_keycode_end     = 35
      #pure_keycode_shifted = 16
      #pure_keycode_tabbed  =  9
      #pure_keycode_remove = 127
    EndEnumeration
  CompilerCase #PB_OS_MacOS
    Enumeration
      #pure_keycode_down    = 31
      #pure_keycode_up      = 30
      #pure_keycode_left    = 28
      #pure_keycode_right   = 29
      #pure_keycode_enter   = 13
      #pure_keycode_delete  =  8
      #pure_keycode_space   = 32
      #pure_keycode_escape  = 27
      #pure_keycode_p_down  = 22
      #pure_keycode_p_up    = 11
      #pure_keycode_pos     =  1
      #pure_keycode_end     =  4
      #pure_keycode_shifted = 16 ; ???? 16
      #pure_keycode_tabbed  =  9
      #pure_keycode_remove = 127
    EndEnumeration
  CompilerCase #PB_OS_Linux
    Enumeration
      #pure_keycode_down    = 65364
      #pure_keycode_up      = 65362
      #pure_keycode_left    = 65361
      #pure_keycode_right   = 65363
      #pure_keycode_enter   = 65293
      #pure_keycode_delete  = 65535
      #pure_keycode_space   = 32
      #pure_keycode_escape  = 65307
      #pure_keycode_p_down  = 65365
      #pure_keycode_p_up    = 65366
      #pure_keycode_pos     = 65360
      #pure_keycode_end     = 65367
      #pure_keycode_shifted = 65505
      #pure_keycode_tabbed  = 9
      #pure_keycode_remove  = 65288
    EndEnumeration
CompilerEndSelect

Enumeration
  #fenster = 10
  #feld
  #hintergrund ; Hintergrundabbild
  #eingabe ; Aktuelle Eingabe
EndEnumeration

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Wie groß ist ein Integer?
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
  #intsize = 8
CompilerElse
  #intsize = 4
CompilerEndIf

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Türkisch LCase
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure.s TLCase( value.s )
  Protected t.s = value
;  ; ***
;  t = ReplaceString( t, "I", "ı" )
;  t = ReplaceString( t, "İ", "i" )
;  t = ReplaceString( t, "Ş", "ş" )
;  t = ReplaceString( t, "Ç", "ç" )
;  t = ReplaceString( t, "Ğ", "ğ" )
  ; ***
  ProcedureReturn LCase(t)
EndProcedure

Procedure.s TUCase( value.s )
  Protected t.s = value
  ; ***
;  t = ReplaceString( t, "ı", "I" )
;  t = ReplaceString( t, "i", "İ" )
;  t = ReplaceString( t, "ş", "Ş" )
;  t = ReplaceString( t, "ç", "Ç" )
;  t = ReplaceString( t, "ğ", "Ğ" )
  ; ***
  ProcedureReturn LCase(t)
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Der Stringlisten-Objekt wird verwendet, um String-Arrays zu realisieren
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Interface stringlist
  add( value.s )
  set( index.i, value.s )
  get.s( index.i )
  length.i()
  find.a( value.s, casesens.a = #False, index.i = -1 )
  count.i( value.s, casesens.a = #False, index.i = -1 )
  lines.i()
  remove( index.i )
  clear()
EndInterface

Structure stringlist_body
  met.i
  cnt.i
  *ram
EndStructure

Procedure   stringlist__add( *this.stringlist_body, value.s )
  Protected p.i, *mem
  ; ***
  If *this\ram = 0
    *this\ram = AllocateMemory( #intsize )
  Else
    *this\ram = ReAllocateMemory( *this\ram, MemorySize(*this\ram) + #intsize )
  EndIf
  ; ***
  p = MemorySize(*this\ram) - #intsize
  ; ***
  *mem = AllocateMemory( (Len(value)*2) + 2 )
  ; ***
  PokeS( *mem, value, (Len(value)*2) + 2, #PB_Unicode )
  ; ***
  PokeI( *this\ram + p, *mem )
  ; ***
  *this\cnt + 1
EndProcedure

Procedure   stringlist__set( *this.stringlist_body, index.i, value.s )
  Protected p.i, *mem
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    p = #intsize * index
    ; ***
    *mem = PeekI( *this\ram + p )
    ; ***
    *mem = ReAllocateMemory( *mem, (Len(value)*2) + 2 )
    ; ***
    PokeS( *mem, value, (Len(value)*2) + 2, #PB_Unicode )
    ; ***
    PokeI( *this\ram + p, *mem )
  EndIf
EndProcedure

Procedure.s stringlist__get( *this.stringlist_body, index.i )
  Protected p.i, *mem
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    p = #intsize * index
    ; ***
    *mem = PeekI( *this\ram + p )
    ; ***
    ProcedureReturn PeekS( *mem, -1, #PB_Unicode )
  EndIf
EndProcedure

Procedure.i stringlist__length( *this.stringlist_body )
  ; - wegen dem chr(13)
  If *this\cnt
    If *this\ram
      ProcedureReturn MemorySize( *this\ram ) - *this\cnt
    EndIf
  EndIf
EndProcedure

Procedure.a stringlist__find( *this.stringlist_body, value.s, casesens.a = #False, index.i = -1 )
  Protected p.i, i.i = 0, l.i, sz.i, s.s = "", c.i = 0, f.i = 0
  ; ***
  Protected *tmp = AllocateMemory( 2048 )
  ; ***
  If *this\ram And *this\cnt
    For p = 0 To MemorySize(*this\ram) - 1
      If PeekA( *this\ram + p ) = 13
        s = PeekS( *tmp, -1, #PB_Unicode )
        ; ***
        If casesens = #False
          s = TLCase(s)
        EndIf
        ; ***
        If index = -1
          If FindString( s, value )
            f = 1
            Break
          EndIf
        Else
          If i = index
            If FindString( s, value )
              f = 1
            EndIf
            ; ***
            Break
          EndIf
        EndIf
        ; ***
        sz + ( Len(s) * 2 ) + 1
        l = p + 1
        i + 1
        ; ***
        s = ""
        ; ***
        c = 0
        ; ***
        FreeMemory( *tmp )
        *tmp = AllocateMemory( 2048 )
      Else
        PokeA( *tmp + c, PeekA( *this\ram + p ) )
        c + 1
      EndIf
    Next
  EndIf
  ; ***
  FreeMemory( *tmp )
  ; ***
  ProcedureReturn f
EndProcedure

Procedure.i stringlist__count( *this.stringlist_body, value.s, casesens.a = #False, index.i = -1 )
  Protected p.i, i.i = 0, l.i, sz.i, s.s = "", c.i = 0, f.i = 0
  ; ***
  Protected *tmp = AllocateMemory( 2048 )
  ; ***
  If *this\ram And *this\cnt
    For p = 0 To MemorySize(*this\ram) - 1
      If PeekA( *this\ram + p ) = 13
        s = PeekS( *tmp, -1, #PB_Unicode )
        ; ***
        If casesens = #False
          s = TLCase(s)
        EndIf
        ; ***
        If index = -1
          f + CountString( s, value )
        Else
          If i = index
            f + CountString( s, value )
            ; ***
            Break
          EndIf
        EndIf
        ; ***
        sz + ( Len(s) * 2 ) + 1
        l = p + 1
        i + 1
        ; ***
        s = ""
        ; ***
        c = 0
        ; ***
        FreeMemory( *tmp )
        *tmp = AllocateMemory( 2048 )
      Else
        PokeA( *tmp + c, PeekA( *this\ram + p ) )
        c + 1
      EndIf
    Next
  EndIf
  ; ***
  FreeMemory( *tmp )
  ; ***
  ProcedureReturn f
EndProcedure

Procedure.i stringlist__lines( *this.stringlist_body )
  ProcedureReturn *this\cnt
EndProcedure

Procedure   stringlist__remove( *this.stringlist_body, index.i )
  Protected p.i, n.i = -1, *mem
  Protected Dim *lst(*this\cnt)
  ; ***
  If *this\ram
    For p = 0 To *this\cnt - 1
      If p <> index
        n + 1
        ; ***
        *lst(n) = PeekI( *this\ram + (p * #intsize) )
      EndIf
    Next
    ; ***
    FreeMemory( *this\ram )
    ; ***
    *this\cnt - 1
    ; ***
    If *this\cnt
      *this\ram = AllocateMemory( *this\cnt * #intsize )
      ; ***
      For p = 0 To *this\cnt - 1
        If *lst(p)
          PokeI( *this\ram + (p * #intsize), *lst(p) )
        EndIf
      Next
    EndIf
  EndIf
EndProcedure

Procedure   stringlist__clear( *this.stringlist_body )
  Protected p.i, *mem
  ; ***
  If *this\ram
    For p = 0 To *this\cnt - 1
      *mem = PeekI( *this\ram + (p * #intsize) )
      FreeMemory( *mem )
    Next
    ; ***
    FreeMemory( *this\ram )
    ; ***
    *this\ram = 0
    *this\cnt = 0
  EndIf
EndProcedure

Procedure   stringlist()

  Protected *this.stringlist_body

  *this = AllocateMemory(SizeOf(stringlist_body))

  If *this
    InitializeStructure(*this, stringlist_body)
    ; ***
    *this\ram = *ram
    ; ***
    *this\Met.i = ?_stringlist_
  EndIf

  ProcedureReturn *this

EndProcedure

DataSection
  _stringlist_:
  Data.i @stringlist__add()
  Data.i @stringlist__set()
  Data.i @stringlist__get()
  Data.i @stringlist__length()
  Data.i @stringlist__find()
  Data.i @stringlist__count()
  Data.i @stringlist__lines()
  Data.i @stringlist__remove()
  Data.i @stringlist__clear()
EndDataSection
5mware
Beiträge: 47
Registriert: 14.12.2015 15:16

Re: Canvasbasierter alternative zur Scintilla

Beitrag von 5mware »

Code: Alles auswählen

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Der editor_dataset-Objekt wird verwendet, um String-Arrays zu realisieren
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Interface editor_dataset
  add( value.s, intvalue.i = 0, mode.a = 0, altindex.i = 0, flag.a = 0 )
  set( index.i, value.s )
  get.s( index.i )
  length.i()
  find.a( value.s, casesens.a = #False, index.i = -1 )
  count.i( value.s, casesens.a = #False, index.i = -1 )
  lines.i()
  remove( index.i )
  clear()
  cursor.w( index.i, value.w = -1 )
  fold.a( index.i, value.a = 200 )
  locked.a( index.i, value.a = 200 )
  attr.l( index.i, value.i = -2147483648 )
  insert( index.i, value.s, intvalue.i = 0 )
EndInterface

Structure editor_dataset_body
  met.i
  cnt.u
  *ram
  *atr
  *org
EndStructure

Procedure   editor_dataset__add( *this.editor_dataset_body, value.s, intvalue.i = 0, mode.a = 0, altindex.i = 0, flag.a = 0 )
  ; value    = Die Stringzeile selbst
  ; intvalue = Attributswert
  ; mode     = Passt die relativen Zeilenpositionen an
  ; altindex = Relevant ab mode>=1 und definiert den relativen Zeilenindex für die Verschiebung
  ; flag     = Regelt die Darstellbarkeit und Erreichbarkeit der Zeilen in Kombination mit dem Verhalten des Code-Editors
  ; ***
  Protected p.i, *mem, u.u, aix.i, rix.u, flg.a
  ; ***
  If *this\ram = 0
    *this\ram = AllocateMemory( #intsize )
    *this\atr = AllocateMemory( 4 )
    *this\org = AllocateMemory( 3 )
  Else
    *this\ram = ReAllocateMemory( *this\ram, MemorySize(*this\ram) + #intsize )
    *this\atr = ReAllocateMemory( *this\atr, MemorySize(*this\atr) + 4 )
    *this\org = ReAllocateMemory( *this\org, MemorySize(*this\org) + 3 )
  EndIf
  ; ***
  p = MemorySize(*this\ram) - #intsize
  ; ***
  *mem = AllocateMemory( (Len(value)*2) + 2 )
  ; ***
  PokeS( *mem, value, (Len(value)*2) + 2, #PB_Unicode )
  ; ***
  PokeI( *this\ram + p, *mem )
  ; ***
  p = MemorySize(*this\atr) - 4
  ; ***
  PokeL( *this\atr + p, intvalue )
  ; ***
  p = MemorySize(*this\org) - 3
  ; ***
  Select mode
    Case 0
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; Die neue Zeile wurde ganz unten normal angehangen.
      ; Deshalb ist die absolute sowie die relative
      ; Zeilennummer dieselbe.
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; ***
      u = *this\cnt
    Case 1
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; Der Anwender hat im Editor auf den Enter gedrückt
      ; und damit alle anderen Zeilen, welche unterhalb
      ; des Cursors lagen, nach untenhin verschoben
      ; ***
      ; Der altindex ist nun die absolute Zeilennummer
      ; der Zeile, auf dem sich der Anwender gerade 
      ; befindet, die nun als "LEER" markiert ist.
      ; ***
      ; Diese Zeile wird zur relativen Index dieser neu
      ; angelegten Zeile.
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; ***
      u = altindex
      ; ***
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; Nun haben wir das Problem, dass auch alle anderen
      ; relativen Zeilennummern, die nach dem Cursor
      ; folgen, um einen Punkt nach untenhin verschoben
      ; werden. Da die Cursorposition altindex ist, wird
      ; also dessen absolute Gegenstück im DataSet als 
      ; Grundlage genommen und von dort aus wird nun
      ; die Anpassung durchgeführt.
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; ***
      If MemorySize(*this\org) > 3
        For aix = (altindex + 1) * 3 To (MemorySize(*this\org) - 1) - 3 Step 3
          rix = PeekU( *this\org + aix + 0 )
          flg = PeekA( *this\org + aix + 2 )
          ; ***
          rix + 1
          ; ***
          PokeU( *this\org + aix + 0,  rix )
          PokeA( *this\org + aix + 2,  flg )
        Next
      EndIf
    Case 2
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; Der Anwender hat im Editor die aktuelle Zeile
      ; getilgt, in dem er mit dem Cursor zum übergeordneten
      ; Zeile gesprungen ist, in dem er an der Cursor-
      ; Position 0 auf die Delete-Taste gedrückt hat.
      ; ***
      ; Die altindex ist nun die Zeilennummer der 
      ; übergeordneten Zeile. Die relative Index der 
      ; gelöschten Zeile wird nun auf den maximalen Wert
      ; 65535 gesetzt.
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; ***
      aix = altindex + 1
      ; ***
      PokeU( *this\org + aix + 0, 65535 ) ; Die Position wird ganz nach hinten verlegt
      PokeA( *this\org + aix + 2,    10 ) ; Die Zeile wird als Gelöscht markiert
      ; ***
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; alle anderen Zeilen nach dem Cursor werden num um
      ; eine Position nach oben verschoben.
      ; - - - - - - - - - - - - - - - - - - - - - - - - - - ;
      ; ***
      If MemorySize(*this\org) > 6
        For aix = (altindex + 2) * 3 To (MemorySize(*this\org) - 1) - 3 Step 3
          rix = PeekU( *this\org + aix + 0 )
          flg = PeekA( *this\org + aix + 2 )
          ; ***
          rix - 1
          ; ***
          PokeU( *this\org + aix + 0,  rix )
          PokeA( *this\org + aix + 2,  flg )
        Next
      EndIf
  EndSelect
  ; ***
  ; Relative Index einer Zeile nach außen (rli)
  PokeU( *this\org + p + 0,    u )
  ; Flag um das Verhalten der Zeile im Code-Editor zu regeln
  PokeA( *this\org + p + 2, flag )
  ; ***
  *this\cnt + 1
EndProcedure

Procedure   editor_dataset__set( *this.editor_dataset_body, index.i, value.s )
  Protected p.i, *mem, idx.i
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    idx = PeekU( *this\org + (index * 3) )
    ; ***
    p = #intsize * index;idx
    ; ***
    *mem = PeekI( *this\ram + p )
    ; ***
    *mem = ReAllocateMemory( *mem, (Len(value)*2) + 2 )
    ; ***
    PokeS( *mem, value, (Len(value)*2) + 2, #PB_Unicode )
    ; ***
    PokeI( *this\ram + p, *mem )
  EndIf
EndProcedure

Procedure.s editor_dataset__get( *this.editor_dataset_body, index.i )
  Protected p.i, *mem, idx.i
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    idx = PeekU( *this\org + (index * 3) )
    ; ***
    p = #intsize * index;idx
    ; ***
    *mem = PeekI( *this\ram + p )
    ; ***
    ProcedureReturn PeekS( *mem, -1, #PB_Unicode )
  EndIf
EndProcedure

Procedure.i editor_dataset__length( *this.editor_dataset_body )
  ; - wegen dem chr(13)
  If *this\cnt
    If *this\ram
      ProcedureReturn MemorySize( *this\ram ) - *this\cnt
    EndIf
  EndIf
EndProcedure

Procedure.a editor_dataset__find( *this.editor_dataset_body, value.s, casesens.a = #False, index.i = -1 )
  Protected p.i, i.i = 0, l.i, sz.i, s.s = "", c.i = 0, f.i = 0
  ; ***
  Protected *tmp = AllocateMemory( 2048 )
  ; ***
  If *this\ram And *this\cnt
    For p = 0 To MemorySize(*this\ram) - 1
      If PeekA( *this\ram + p ) = 13
        s = PeekS( *tmp, -1, #PB_Unicode )
        ; ***
        If casesens = #False
          s = TLCase(s)
        EndIf
        ; ***
        If index = -1
          If FindString( s, value )
            f = 1
            Break
          EndIf
        Else
          If i = index
            If FindString( s, value )
              f = 1
            EndIf
            ; ***
            Break
          EndIf
        EndIf
        ; ***
        sz + ( Len(s) * 2 ) + 1
        l = p + 1
        i + 1
        ; ***
        s = ""
        ; ***
        c = 0
        ; ***
        FreeMemory( *tmp )
        *tmp = AllocateMemory( 2048 )
      Else
        PokeA( *tmp + c, PeekA( *this\ram + p ) )
        c + 1
      EndIf
    Next
  EndIf
  ; ***
  FreeMemory( *tmp )
  ; ***
  ProcedureReturn f
EndProcedure

Procedure.i editor_dataset__count( *this.editor_dataset_body, value.s, casesens.a = #False, index.i = -1 )
  Protected p.i, i.i = 0, l.i, sz.i, s.s = "", c.i = 0, f.i = 0
  ; ***
  Protected *tmp = AllocateMemory( 2048 )
  ; ***
  If *this\ram And *this\cnt
    For p = 0 To MemorySize(*this\ram) - 1
      If PeekA( *this\ram + p ) = 13
        s = PeekS( *tmp, -1, #PB_Unicode )
        ; ***
        If casesens = #False
          s = TLCase(s)
        EndIf
        ; ***
        If index = -1
          f + CountString( s, value )
        Else
          If i = index
            f + CountString( s, value )
            ; ***
            Break
          EndIf
        EndIf
        ; ***
        sz + ( Len(s) * 2 ) + 1
        l = p + 1
        i + 1
        ; ***
        s = ""
        ; ***
        c = 0
        ; ***
        FreeMemory( *tmp )
        *tmp = AllocateMemory( 2048 )
      Else
        PokeA( *tmp + c, PeekA( *this\ram + p ) )
        c + 1
      EndIf
    Next
  EndIf
  ; ***
  FreeMemory( *tmp )
  ; ***
  ProcedureReturn f
EndProcedure

Procedure.i editor_dataset__lines( *this.editor_dataset_body )
  ProcedureReturn *this\cnt
EndProcedure

Procedure   editor_dataset__remove( *this.editor_dataset_body, index.i )
  Protected p.i, n.i = -1, *mem
  Protected Dim *lst(*this\cnt)
  Protected Dim atr.l(*this\cnt)
  ; ***
  If *this\ram
    For p = 0 To *this\cnt - 1
      If p <> index
        n + 1
        ; ***
        *lst(n) = PeekI( *this\ram + (p * #intsize) )
        ; ***
        atr(n) = PeekL( *this\atr + (p * 4) )
      EndIf
    Next
    ; ***
    FreeMemory( *this\ram )
    FreeMemory( *this\atr )
    ; ***
    *this\cnt - 1
    ; ***
    If *this\cnt
      *this\ram = AllocateMemory( *this\cnt * #intsize )
      *this\atr = AllocateMemory( *this\cnt * 4 )
      ; ***
      For p = 0 To *this\cnt - 1
        If *lst(p)
          PokeI( *this\ram + (p * #intsize), *lst(p) )
          ; ***
          PokeL( *this\atr + (p * 4), atr(p) )
        EndIf
      Next
    EndIf
  EndIf
EndProcedure

Procedure   editor_dataset__clear( *this.editor_dataset_body )
  Protected p.i, *mem
  ; ***
  If *this\ram
    For p = 0 To *this\cnt - 1
      *mem = PeekI( *this\ram + (p * #intsize) )
      FreeMemory( *mem )
    Next
    ; ***
    FreeMemory( *this\ram )
    FreeMemory( *this\atr )
    FreeMemory( *this\org )
    ; ***
    *this\org = 0
    *this\atr = 0
    *this\ram = 0
    *this\cnt = 0
  EndIf
EndProcedure

Procedure.w editor_dataset__cursor( *this.editor_dataset_body, index.i, value.w = -1 )
  Protected p.i
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    p = 4 * index
    ; ***
    If value <= -1
      ProcedureReturn PeekW( *this\atr + p )
    Else
      PokeW( *this\atr + p, value )
    EndIf
  EndIf
EndProcedure

Procedure.a editor_dataset__fold( *this.editor_dataset_body, index.i, value.a = 200 )
  Protected p.i
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    p = 4 * index
    ; ***
    If value = 200
      ProcedureReturn PeekA( *this\atr + p + 1 )
    Else
      If value = #True Or value = #False
        PokeA( *this\atr + p + 1, value )
      EndIf
    EndIf
  EndIf
EndProcedure

Procedure.a editor_dataset__locked( *this.editor_dataset_body, index.i, value.a = 200 )
  Protected p.i
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    p = 4 * index
    ; ***
    If value = 200
      ProcedureReturn PeekA( *this\atr + p + 2 )
    Else
      If value = #True Or value = #False
        PokeA( *this\atr + p + 2, value )
      EndIf
    EndIf
  EndIf
EndProcedure

Procedure.l editor_dataset__attr( *this.editor_dataset_body, index.i, value.i = -2147483648 )
  Protected p.i
  ; ***
  If *this\ram And index >= 0 And index < *this\cnt And *this\cnt
    p = 4 * index
    ; ***
    If value = -2147483648
      ProcedureReturn PeekL( *this\atr + p )
    Else
      PokeL( *this\atr + p, value )
    EndIf
  EndIf
EndProcedure

Procedure   editor_dataset__insert( *this.editor_dataset_body, index.i, value.s, intvalue.i = 0 )
  Protected n.i, g.i = 0, p.i, p1.i, p2.i, *adr, *ram, *atr
  ; ***
  If *this\ram
    editor_dataset__add(*this,"")
    ; ***
    If *this\cnt And index < *this\cnt - 1
      p = *this\cnt -1
      ; ***
      p1 = MemorySize(*this\ram)
      p2 = MemorySize(*this\atr)
      ; ***
      *adr = PeekI( *this\ram + p1 - #intsize )
      ; ***
      *ram = AllocateMemory(p1)
      *atr = AllocateMemory(p2)
      ; ***
      For n = 0 To p
        If g = index
          g + 1
        EndIf
        ; ***
        PokeI( *ram + (g * #intsize), PeekI( *this\ram + (n * #intsize) ) )
        PokeL( *atr + (g * 4), PeekL( *this\atr + (n * 4) ) )
        ; ***
        g + 1
      Next
      ; ***
      PokeI( *ram + (index * #intsize), *adr )
      PokeL( *atr + (index * 4), intvalue )
      ; ***
      FreeMemory(*this\ram) : *this\ram = *ram
      FreeMemory(*this\atr) : *this\atr = *atr
    EndIf
  EndIf
EndProcedure

Procedure   editor_dataset()

  Protected *this.editor_dataset_body

  *this = AllocateMemory(SizeOf(editor_dataset_body))

  If *this
    InitializeStructure(*this, editor_dataset_body)
    ; ***
    *this\ram = *ram
    ; ***
    *this\Met.i = ?_editor_dataset_
  EndIf

  ProcedureReturn *this

EndProcedure

DataSection
  _editor_dataset_:
  Data.i @editor_dataset__add()
  Data.i @editor_dataset__set()
  Data.i @editor_dataset__get()
  Data.i @editor_dataset__length()
  Data.i @editor_dataset__find()
  Data.i @editor_dataset__count()
  Data.i @editor_dataset__lines()
  Data.i @editor_dataset__remove()
  Data.i @editor_dataset__clear()
  Data.i @editor_dataset__cursor()
  Data.i @editor_dataset__fold()
  Data.i @editor_dataset__locked()
  Data.i @editor_dataset__attr()
  Data.i @editor_dataset__insert()
EndDataSection
Zuletzt geändert von 5mware am 12.11.2018 13:05, insgesamt 1-mal geändert.
5mware
Beiträge: 47
Registriert: 14.12.2015 15:16

Re: Canvasbasierter alternative zur Scintilla

Beitrag von 5mware »

Code: Alles auswählen

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Daten des Editors
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Structure struct_intellisence
  ; Das sind die CommandKeys, die zum Aufklappen der 
  ; Intellisence-Box erkannt werden
  groupkeys.stringlist
  ; Der Inhalt
  content.stringlist
  ; Einfügen mit oder ohne Leerabstand
  space.a
  ; Maximalbreite der Liste
  width.u
EndStructure

Structure struct_intellisence_list
  cnt.u
  lst.struct_intellisence[1000]
EndStructure

Structure struct_current_line_char
  char.s
  color.l
  pos.w
EndStructure

Structure struct_pure_multiline_code_editor
  ; Aktueller Zeichnen-Status
  justdraw.a
  ; CanvasGadet
  id.i
  ; Intellisense-Anbindung
  *intellisence.struct_intellisence_list
  ; Inhalt
  content.editor_dataset
  ; Syntax-Highlighting für die Schlüsselwörter
  *keywords.editor_dataset
  ; Groß- und Kleinschreibung beachten für Keywords?
  casesens.a
  ; Kommantierung aktiv?
  comment.a
  ; Stringeingabe aktiv?
  stringi.a
  ; Kommentarzeichen
  comment_char.s
  ; Stringketten-Zeichen
  string_char.s
  ; Double-Trenner für Zahlen
  double_separator.s
  ; Farben
  color_comment.l
  color_string.l
  color_number.l
  color_operator.l
  color_bkg.l
  color_selbkg.l
  color_errorbkg.l
  color_marked_bkg.l
  color_marked_border.l
  color_number_block_txt.l
  color_number_block_bkg.l
  color_number_block_active.l
  color_intelli_background.l
  color_intelli_border.l
  color_intelli_lborder.l
  color_intelli_dborder.l
  color_intelli_text.l
  color_intelli_sel_bkg.l
  color_intelli_sel_txt.l
  ; Zeilennummer anzeigen
  linenumbers.a
  ; Temporärer Abbild
  tempor.i
  ; Visible Background:
  ; Das ist der aktuelle Hintergrund, der alle sichtbaren 
  ; Code-Zeilen wiedergibt
  visbkg.i
  ; Temporary Background:
  ; Dieses Bild wird bei up/down gentzt, um eine Kopie 
  ; des visbkg zu nehmen und es um eine Zeile nach oben
  ; oder nach unten zu reduzieren und die neu dazu kommende
  ; Zeile anzuhängen
  tmpbkg.i
  ; Last active Line- Image
  lalimg.i
  ; Current Line Inkey
  inkey.s
  ; Current Line:
  ; Das Abbild der aktuellen Zeile wird beim up/down oder
  ; Mausklick aus dem Background-Bereich herauskopiert oder
  ; beim JIT-Eingabe automatisch realisiert, jedoch nur ab dem
  ; Part, der gerade bearbeitet wird
  curlin.i
  ; Aktuelles Start-Zeichen der aktuellen Zeile, ab dem
  ; neugezeichnet wird
  curpos.w
  ; Aktuelle Tokenlänge
  curlen.w
  ; Zeichencursor
  cursor.w
  ; Aktuelle Länge der Eingabe
  length.w
  ; Zeichenstrom der aktuellen Zeile
  strom.struct_current_line_char[20000]
  ; Temporärer Token
  tmptok.s
  ; Letzte Tokenstart
  lastpo.w
  ; Aktuelle Zeilenindex : Tatsächliche Zeilennummer
  index.i
  ; Top-Limit
  toplimit.i
  ; Vis-Limit
  vislimit.u
  ; Cursor-Row-Position : Relative Zeilennummer im sichtbaren Feld
  ; Ermittlung: position = index - toplimit
  position.i
  ; Hintergrund-Update
  update_bkg.a
  ; Nummernblock-Abstand
  nwid.u
  ; Text-Height
  theight.u
  ; Cursor-Display
  cursorDisplay.a
  ; Richtung der Content-Aktualisierung
  condir.a
  ; Cursor-Blinker
  curstate.w
  ; Den Cursor ganz nach hinter der Zeile verschieben
  movetolast.a
  ; Letzte Zeichenfolge
  lastkey.s
  ; Letzte im Intellisence-Box ausgewählter Eintrag
  intellitok.s
  ; Intellisence-Anzeige-Modus
  intellivis.a
  ; Intellisence-Index
  intellicur.w
  ; Intellisence-Total vom aktuellen Inhalt
  intellitot.u
  ; Intellisence-Abstand
  intellimar.a
  ; Letzte Intellisence-Breite
  intelliLastWidth.l
  ; Markierungsflag
  mark.a
  ; Markierungsmodus:
  ; 0 = Nur die aktuelle Zeile
  ; 1 = Mehrere Zeilen
  markmode.a
  ; Markierungspunkt
  markrow.l : markrel.l
  ; Startposition der Markierung auf der Startzeile für die Markierung
  markCursorFrom.w
  ; Endposition der Markierung auf der Endzeile für die Markierung
  markCursorInto.w
  ; Startzeile
  markstart.u
  ; Endzeile
  markclose.u
  ; Begin der Markierung an Zeichen X
  markpos.w
  ; Ende der Markierung an Zeichen N
  marklen.w
  ; Markierungsstartzeichen-Differenz variiert um einen Wert zwischen
  ; der Tastaturmarkierung und der Mauszeigermarkierung
  markdif.a
EndStructure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Funktionen
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure.s pick( index.l, char.s, value.s )
  Protected n.l, s.s, idx.l = 0
  ; ***
  For n = 1 To Len( value )
    Select Mid( value, n, 1 )
      Case char
        If idx = index
          Break
        Else
          idx + 1
          ; ***
          s = ""
        EndIf
      Default
        s + Mid( value, n, 1 )
    EndSelect
  Next
  ; ***
  If idx > index
    s = ""
  EndIf
  ; ***
  If index < 0
    s = ""
  EndIf
  ; ***
  If index > CountString( value, char )
    s = ""
  EndIf
  ; ***
  ProcedureReturn s
EndProcedure

Procedure.i opaque( value.i, transparency.u = 255 )
  ProcedureReturn RGBA( Red(value), Green(value), Blue(value), transparency )
EndProcedure

;https://physikunterricht-online.de/hilfsmittel/physikalische-groessen-und-einheiten/
; ***
;https://www.gut-erklaert.de/mathematik/gewichtseinheiten-tabelle.html
;https://www.gut-erklaert.de/mathematik/volumeneinheiten-tabelle-mit-liter.html
;https://www.gut-erklaert.de/mathematik/laengeneinheiten-tabelle.html
;https://www.frustfrei-lernen.de/mathematik/laengeneinheiten.html
;https://www.gut-erklaert.de/mathematik/zeiteinheiten-tabelle-und-abkuerzungen.html
;http://www.tabelle.info/elektrische_einheiten.htm

Procedure.a is_arithmetical( value.s )
  Protected p.i, ret.a = 1, v.s = value, tk.s, ti.s, fn.s, nu.a = 0
  ; ***
  ; ha = Hektar
  ; g = gramm
  ; mg = milligramm
  ; kg = kilogramm
  ; dt = Dezitonne
  ; cg = Centigramm
  ; t = Tonne
  ; kt = Kilotonne
  ; mt = Megatonne
  ; gt = Gigatonne
  ; ml = milliliter
  ; cl = centiliter
  ; dl = deziliter
  ; hl = hektoliter
  ; mi,mil = mil
  ; yd = yard
  ; ft = foot
  ; sm = seemeile
  ; in,inc=inc
  ; a=ampere,strom
  ; c=coulomb,ladung
  ; v=volt,spannung
  ; w=watt,leistung
  ; o=ohm,Widerstand
  ; f=farad,Kapazität
  ; si=siemens,leitwert
  tk = "yıl,gün,hafta,ay,saat,dakika,saniye,milisaniye,bayt,ppi,dpi,kb,mb,tb,bit,mbit,kbit,tbit,km,dm,cm,mm,ml,ms,pt,px,inç,mil,ha,mg,kg,dt,cg,kt,mt,gt,cl,dl,hl,in,mi,yd,ft,sm,si,a,c,v,w,o,f,m,t,l,s,h,b,o,g"
  ; ***
  v = TLCase(v)
  v = Trim(v)
  ; ***
  For p = 0 To CountString(tk,",")+1
    ti = pick(p,",",tk) 
    ; ***
    If ti
      If FindString( v, ti )
        fn = ti
        ; ***
        v = Trim(ReplaceString( v, ti, "" ))
        ; ***
        Break
      EndIf
    EndIf
  Next
  ; ***
  For p = 1 To Len(v)
    Select Mid( v, p, 1 )
      Case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
        nu = 1
      Default
        nu = 0
        ret = 0
        Break
    EndSelect
  Next
  ; ***
  If nu = 0
    ret = 0
  EndIf
  ; ***
  ProcedureReturn ret
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Zeichnen
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

LoadFont(100,"Anonymous Pro",20)

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Markierungsfeldinhalt ermitteln
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure.s getMarkedText(*daten.struct_pure_multiline_code_editor)
  Protected p.w, y.w, h.w, x.w, w.w, t.s
  ; ***
  y = *daten\markstart + *daten\toplimit
  h = *daten\markclose + *daten\toplimit
  ; ***
  If h > y
    h - 1
  EndIf
  ; ***
  x = *daten\markpos
  w = *daten\marklen
  ; ***
  If w < x
    p = x
    x = w
    w = p
  EndIf
  ; ***
  x + *daten\markdif
  ; ***
  For p = y To h
    If p > y
      t + #CRLF$
    EndIf
    ; ***
    t + Mid( *daten\content\get(p), x, (w - x) + 1 )
  Next
  ; ***
  ProcedureReturn t
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Markierungsfeldinhalt leeren
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure clearMarkedText(*daten.struct_pure_multiline_code_editor)
  Protected p.w, n.i, y.w, h.w, x.w, w.w, t.s, s.s
  ; ***
  y = *daten\markstart + *daten\toplimit
  h = *daten\markclose + *daten\toplimit
  ; ***
  x = *daten\markpos
  w = *daten\marklen
  ; ***
  If w < x
    p = x
    x = w
    w = p
  EndIf
  ; ***
  For p = y To h
    t = Mid( *daten\content\get(p), x, (w - x) + 1 )
    ; ***
    For n = 1 To Len(t)
      If n >= x And n <= (w - x) + 1
        s + " "
      Else
        s + Mid( t, n, 1 )
      EndIf
    Next
    ; ***
    *daten\content\set(p,s)
  Next
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Ermittelt die Zeichen des aktuell angesteuerten Zeile
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure update_current_token(*daten.struct_pure_multiline_code_editor,pos.w,lth.w)
  If IsGadget(#feld)
    Protected w.i, h.i, p.i, n.i, c.i, g.i = 0, t.s, s.s, b.s, com.a = 0, stg.a = 0, ps.i, ls.i, spa.a = 0
    ; ***
    w = GadgetWidth(#feld)
    h = GadgetHeight(#feld)
    ; ***
    ls = lth
    ; ***
    ps = pos
    ; ***
    For p = ps To ls
      *daten\strom[p]\color = 0
      ; ***
      If com = 1 And stg = 0
        *daten\strom[p]\color = *daten\color_comment
      ElseIf stg = 1 And com = 0
        *daten\strom[p]\color = *daten\color_string
      EndIf
      ; ***
      Select *daten\strom[p]\char
        Case *daten\comment_char
          If stg = 0
            com = 1
            ; ***
            *daten\strom[p]\color = *daten\color_comment
          EndIf
        Case *daten\string_char
          If com = 0
            Select stg
              Case 0 : stg = 1
              Case 1 : spa = 1
            EndSelect
            ; ***
            *daten\strom[p]\color = *daten\color_string
          EndIf
        Case " ", ".", "(", ")", "{", "}", "[", "]", "/", "\", "%", "+", "-", "&", "'",
             "*", ":", ";", ",", "<", ">", "|", "#", "=", "!", "|", "^", "°", "$", "§",
             "~", "≈", Chr(10), Chr(13)
          If com = 0 And stg = 1
            *daten\strom[p]\color = *daten\color_string
          ElseIf com = 1 And stg = 0
            *daten\strom[p]\color = *daten\color_comment
          ElseIf com = 0 And stg = 0
            *daten\strom[p]\color = *daten\color_operator
            ; ***
            g = p - Len(t)
            ; ***
            For c = 0 To Len(b) - 1
              *daten\strom[g + c]\color = 0
            Next
            ; ***
            If *daten\keywords
              For n = 0 To *daten\keywords\lines() -1
                If TLCase(*daten\keywords\get(n)) = TLCase(t)
                  t = *daten\keywords\get(n)
                  ; ***
                  g = p - Len(*daten\keywords\get(n))
                  ; ***
                  For c = 0 To Len(*daten\keywords\get(n)) - 1
                    *daten\strom[c + g]\color = *daten\keywords\attr(n)
                    *daten\strom[c + g]\char = Mid( t, c + 1, 1 )
                  Next
                  ; ***
                  Break
                EndIf
              Next
            EndIf
          EndIf
          ; ***
          t = ""
          ; ***
          If spa = 1
            spa = 0
            stg = 0
          EndIf
        Default
          t + *daten\strom[p]\char
      EndSelect
    Next
    ; ***
    If spa = 1
      spa = 0
      stg = 0
    EndIf
    ; ***
    If t
      p = *daten\cursor + lth
      ; ***
      If com = 0 And stg = 0
        *daten\strom[p]\color = *daten\color_operator
        ; ***
        g = p - Len(t)
        ; ***
        For c = 0 To Len(b) - 1
          *daten\strom[g + c]\color = 0
        Next
        ; ***
        If *daten\keywords
          For n = 0 To *daten\keywords\lines() -1
            If TLCase(*daten\keywords\get(n)) = TLCase(t)
              t = *daten\keywords\get(n)
              ; ***
              g = p - Len(*daten\keywords\get(n))
              ; ***
              For c = 0 To Len(*daten\keywords\get(n)) - 1
                *daten\strom[c + g]\color = *daten\keywords\attr(n)
                *daten\strom[c + g]\char = Mid( t, c + 1, 1 )
              Next
              ; ***
              Break
            EndIf
          Next
        EndIf
      EndIf
    EndIf
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Setzt den Syntax-Färbung der aktuellen Zeile
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure update_current_syntax(*daten.struct_pure_multiline_code_editor)
  If IsGadget(#feld)
    Protected w.i, h.i, p.i, n.i, c.i, g.i = 0, t.s, s.s, b.s, com.a = 0, stg.a = 0, ps.i, ls.i, spa.a = 0
    ; ***
    w = GadgetWidth(#feld)
    h = GadgetHeight(#feld)
    ; ***
    ls = *daten\length
    ; ***
    ps = 0
    ; ***
    If ps < 0 : ProcedureReturn : EndIf
    If ls > 19999 : ProcedureReturn : EndIf
    ; ***
    For p = ps To ls
      *daten\strom[p]\color = 0
      ; ***
      If com = 1 And stg = 0
        *daten\strom[p]\color = *daten\color_comment
      ElseIf stg = 1 And com = 0
        *daten\strom[p]\color = *daten\color_string
      EndIf
      ; ***
      Select *daten\strom[p]\char
        Case *daten\comment_char
          If stg = 0
            com = 1
            ; ***
            *daten\strom[p]\color = *daten\color_comment
          EndIf
        Case *daten\string_char
          If com = 0
            Select stg
              Case 0 : stg = 1
              Case 1 : spa = 1
            EndSelect
            ; ***
            *daten\strom[p]\color = *daten\color_string
          EndIf
        Case " ", ".", "(", ")", "{", "}", "[", "]", "/", "\", "%", "+", "-", "&", "'",
             "*", ":", ";", ",", "<", ">", "|", "#", "=", "!", "|", "^", "°", "$", "§",
             "~", "≈", Chr(10), Chr(13)
          If com = 0 And stg = 1
            *daten\strom[p]\color = *daten\color_string
          ElseIf com = 1 And stg = 0
            *daten\strom[p]\color = *daten\color_comment
          ElseIf com = 0 And stg = 0
            *daten\strom[p]\color = *daten\color_operator
            ; ***
            If t
              If is_arithmetical( t ) = #True
                g = p - Len(t)
                ; ***
                For c = 0 To Len(t) - 1
                  *daten\strom[g + c]\color = *daten\color_number
                Next
                ; ***
                Select *daten\strom[p]\char
                  Case ".", "%"
                    *daten\strom[p]\color = *daten\color_number
                EndSelect
                ; ***
                If g - 1 > 0
                  If *daten\strom[g - 1]\char = "%"
                    *daten\strom[g - 1]\color = *daten\color_number
                  EndIf
                EndIf
              Else
                g = p - Len(t)
                ; ***
                For c = 0 To Len(b) - 1
                  *daten\strom[g + c]\color = 0
                Next
                ; ***
                If *daten\keywords
                  For n = 0 To *daten\keywords\lines() -1
                    If TLCase(*daten\keywords\get(n)) = TLCase(t)
                      t = *daten\keywords\get(n)
                      ; ***
                      g = p - Len(*daten\keywords\get(n))
                      ; ***
                      For c = 0 To Len(*daten\keywords\get(n)) - 1
                        *daten\strom[c + g]\color = *daten\keywords\attr(n)
                        *daten\strom[c + g]\char = Mid( t, c + 1, 1 )
                      Next
                      ; ***
                      Break
                    EndIf
                  Next
                EndIf
              EndIf
            EndIf
          EndIf
          ; ***
          t = ""
          ; ***
          If spa = 1
            spa = 0
            stg = 0
          EndIf
        Default
          t + *daten\strom[p]\char
      EndSelect
      ; ***
      *daten\comment = com
      *daten\stringi = stg
    Next
    ; ***
    If spa = 1
      spa = 0
      stg = 0
    EndIf
    ; ***
    If t
      p = ls
      ; ***
      If com = 0 And stg = 0
        *daten\strom[p]\color = *daten\color_operator
        ; ***
        If is_arithmetical( t ) = #True
          g = p - Len(t)
          ; ***
          For c = 0 To Len(t) - 1
            *daten\strom[g + c]\color = *daten\color_number
          Next
          ; ***
          Select *daten\strom[p]\char
            Case ".", "%"
              *daten\strom[p]\color = *daten\color_number
          EndSelect
          ; ***
          If g - 1 > 0
            If *daten\strom[g - 1]\char = "%"
              *daten\strom[g - 1]\color = *daten\color_number
            EndIf
          EndIf
        Else
          g = p - Len(t)
          ; ***
          For c = 0 To Len(b) - 1
            *daten\strom[g + c]\color = 0
          Next
          ; ***
          If *daten\keywords
            For n = 0 To *daten\keywords\lines() -1
              If TLCase(*daten\keywords\get(n)) = TLCase(t)
                t = *daten\keywords\get(n)
                ; ***
                g = p - Len(*daten\keywords\get(n))
                ; ***
                For c = 0 To Len(*daten\keywords\get(n)) - 1
                  *daten\strom[c + g]\color = *daten\keywords\attr(n)
                  *daten\strom[c + g]\char = Mid( t, c + 1, 1 )
                Next
                ; ***
                Break
              EndIf
            Next
          EndIf
        EndIf
      EndIf
    EndIf
  EndIf
  ; ***
  *daten\comment = com
  *daten\stringi = stg
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Beim Eintritt auf die neue Zeile wird dieser leer geräumt, wenn sie keine
; Tokens enthalten darf, weil sie eigentlich leer ist
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure clear_new_line(*daten.struct_pure_multiline_code_editor)
  Protected p.i
  ; ***
  *daten\length = 19999
  ; ***
  For p = 0 To *daten\length
    *daten\strom[p]\char = ""
    ; ***
    *daten\strom[p]\color = 0
    *daten\strom[p]\pos = 0
    ; ***
    If *daten\strom[p]\char = ""
      Break
    EndIf
  Next
  ; ***
  *daten\strom[0]\char = ""
EndProcedure
5mware
Beiträge: 47
Registriert: 14.12.2015 15:16

Re: Canvasbasierter alternative zur Scintilla

Beitrag von 5mware »

Code: Alles auswählen

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Threadspezifisch, leert den Rest einer Zeile
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure clear_current_line(*daten.struct_pure_multiline_code_editor)
  Protected p.i
  ; ***
  For p = *daten\length To 19999
    *daten\strom[p]\color = 0
    *daten\strom[p]\char = ""
    *daten\strom[p]\pos = 0
  Next
  ; ***
  If IsThread(*daten)
    KillThread(*daten)
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Ermittelt die aktuell angesteuerte Zeile
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure allocate_current_line(*daten.struct_pure_multiline_code_editor)
  Protected p.i, s.s
  ; ***
  *threaded_current_line = *daten
  ; ***
  *daten\strom[0]\color = 0
  *daten\strom[0]\char = ""
  *daten\strom[0]\pos = 0
  ; ***
  *daten\strom[1]\color = 0
  *daten\strom[1]\char = ""
  *daten\strom[1]\pos = 0
  ; ***
  *daten\strom[2]\color = 0
  *daten\strom[2]\char = ""
  *daten\strom[2]\pos = 0
  ; ***
  If *daten\content\lines()
    *daten\index = *daten\position + *daten\toplimit
    ; ***
    *daten\length = Len(s)
    ; ***
    If IsThread(*daten)
      KillThread(*daten)
    EndIf
    ; ***
    CreateThread( @clear_current_line(), *daten )
    ; ***
    If *daten\index >= 0 And *daten\index < *daten\content\lines()
      s = *daten\content\get(*daten\index)
      ; ***
      If Trim(s)
        *daten\length = 19999
        ; ***
        For p = 1 To *daten\length
          If p <= Len(s)
            *daten\strom[p]\char = Mid( s, p, 1 )
          Else
            *daten\strom[p]\char = ""
          EndIf
          ; ***
          *daten\strom[p]\color = 0
          *daten\strom[p]\pos = 0
          ; ***
          If p > Len(s)
            If *daten\strom[p]\char = ""
              Break
            EndIf
          EndIf
        Next
        ; ***
        *daten\strom[0]\char = ""
        ; ***
        *daten\length = Len(s) + 1
        ; ***
        update_current_syntax( *daten )
      Else
        *daten\cursor = 1
        *daten\length = 0
        ; ***
        *daten\strom[0]\color = 0
        *daten\strom[0]\char = ""
        *daten\strom[0]\pos = 0
      EndIf
    EndIf
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Geht zu einer Zeile
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure goto_current_line(*daten.struct_pure_multiline_code_editor,w.i,h.i,currentUpdate.a=#False)
  Protected ww.d, hh.i
  ; ***
  If *daten\index >= 0
    If *daten\index < *daten\content\lines()
      *daten\position = *daten\index - *daten\toplimit
      ; ***
;Debug Str(*daten\position) + ":" + Str(*daten\index) + " > " + *daten\content\get(*daten\index)
      allocate_current_line( *daten )
      ; ***
      If IsImage( *daten\visbkg ) > 0
        CopyImage( *daten\visbkg, *daten\tmpbkg )
      EndIf
      ; ***
      If *daten\justdraw = 0
        *daten\justdraw = 1
        ; ***
        If CreateImage( *daten\visbkg, w, h, 32, #PB_Image_Transparent ) And 
           StartDrawing( ImageOutput( *daten\visbkg ) )
          ; ***
          DrawingMode( #PB_2DDrawing_AlphaBlend )
          ; ***
          If IsFont(100):DrawingFont(FontID(100)):EndIf
          ; ***
          If IsImage( *daten\tmpbkg )
            DrawAlphaImage( ImageID( *daten\tmpbkg ), 0, 0 )
          EndIf
          ; ***
          DrawingMode( #PB_2DDrawing_AlphaChannel )
          ; ***
          Box( 0, TextHeight("A") * *daten\position, w, TextHeight("A"), RGBA(0,0,0,0) )
          ; ***
          StopDrawing()
          ; ***
          CopyImage( *daten\visbkg, *daten\tmpbkg )
          ; ***
          If currentUpdate
            ww = 0
            ; ***
            If CreateImage( *daten\curlin, w, 100, 32, #PB_Image_Transparent ) And 
               StartDrawing( ImageOutput( *daten\curlin ) )
              If IsFont(100):DrawingFont(FontID(100)):EndIf
              ; ***
              hh = TextHeight("A")
              ; ***
              StopDrawing()
            EndIf
            ; ***
            If CreateImage( *daten\curlin, w, hh, 32, #PB_Image_Transparent ) And 
               StartDrawing( ImageOutput( *daten\curlin ) )
              DrawingMode( #PB_2DDrawing_Transparent|#PB_2DDrawing_AlphaBlend )
              ; ***
              If IsFont(100):DrawingFont(FontID(100)):EndIf
              ; ***
              For p = 0 To *daten\length ;- 1
                DrawText( ww, 0, *daten\strom[p]\char, opaque(*daten\strom[p]\color) )
                ; ***
                *daten\strom[p]\pos = ww : ww + TextWidth(*daten\strom[p]\char)
              Next
              ; ***
              StopDrawing()
            EndIf
          EndIf
          ; ***
          *daten\justdraw = 0
        EndIf
      EndIf
    EndIf
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Hintergrundbild zeichnen
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure update_content(*daten.struct_pure_multiline_code_editor,id,w.i,h.i)
  Protected p.i, a.a = 0, tw.i
  ; ***
  If IsGadget(id)
    If *daten\condir <> 0
      allocate_current_line( *daten )
      ; ***
      If *daten\theight < 8
        *daten\theight = 8
      EndIf
      ; ***
      If CreateImage(*daten\curlin,w,*daten\theight) And StartDrawing(ImageOutput(*daten\curlin))
        Box( 0, 0, w, h, $FFFFFF ) ; VORÜBRGEHEND
        ; ***
        If IsFont(100)
          DrawingFont( FontID(100) )
        EndIf
        ; ***
        DrawingMode( #PB_2DDrawing_Transparent )
        ; ***
        If evt = #PB_EventType_Input
          *daten\theight = TextHeight("A")
          ; ***
          *daten\vislimit = (h / *daten\theight) - 1
          ; ***
          If *daten\vislimit <= 0
            *daten\vislimit = 1
          EndIf
        EndIf
        ; ***
        For p = 0 To *daten\length -1
          If p = 0
            DrawText( 0, 0, *daten\strom[p]\char, *daten\strom[p]\color )
          Else
            DrawText( tw, 0, *daten\strom[p]\char, *daten\strom[p]\color )
          EndIf
          ; ***
          tw + TextWidth(*daten\strom[p]\char)
        Next
        ; ***
        StopDrawing()
      EndIf
    EndIf
    ; ***
    If IsImage(*daten\visbkg)
      a = 1
      CopyImage( *daten\visbkg, *daten\tmpbkg )
    EndIf
    ; ***
    If CreateImage(*daten\visbkg,w,h) And StartDrawing(ImageOutput(*daten\visbkg))
      If a = 0
        ; Es wird das erste Mal gezeichnet, deshalb kommt auch der
        ; vollständige Hintergrund gleich mit
        Box( 0, 0, w, h, *daten\color_bkg )
      EndIf
      ; ***
      Select *daten\condir
        Case 0 ; Normal
          If a = 1
            If IsImage(*daten\tmpbkg)
              DrawImage( ImageID(*daten\tmpbkg), 0, 0 )
            EndIf
          EndIf
          ; ***
          If IsImage(*daten\curlin)
            DrawImage( ImageID(*daten\curlin), 0, *daten\position * *daten\theight )
          EndIf
        Case 1 ; Rauf
          If a = 1
            If IsImage(*daten\tmpbkg)
              DrawImage( ImageID(*daten\tmpbkg), 0, *daten\theight )
            EndIf
          EndIf
          ; ***
          If IsImage(*daten\curlin)
            DrawImage( ImageID(*daten\curlin), 0, 0 )
          EndIf
        Case 2 ; Runter
          If a = 1
            If IsImage(*daten\tmpbkg)
              DrawImage( ImageID(*daten\tmpbkg), 0, - *daten\theight )
            EndIf
          EndIf
          ; ***
          If IsImage(*daten\curlin)
            DrawImage( ImageID(*daten\curlin), 0, h - *daten\theight )
          EndIf
      EndSelect
      ; ***
      *daten\condir = 0
      ; ***
      StopDrawing()
    EndIf
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Aktuelle Zeile in ein echtes String umwandeln
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure.s getInputStringLine(*daten.struct_pure_multiline_code_editor)
  Protected p.i, s.s
  ; ***
  For p = 0 To *daten\length
    s + *daten\strom[p]\char
  Next
  ; ***
  ProcedureReturn s
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Markierungsfeldumfeld leeren
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure clearImageArea(*daten.struct_pure_multiline_code_editor,id,w,h)
  Protected mmx.i
  ; ***
  y = *daten\markstart + *daten\toplimit
  h = *daten\markclose + *daten\toplimit
  ; ***
  x = *daten\markCursorFrom
  w = *daten\markCursorInto
  ; ***
Debug "Y: " + Str(y) + " | H: " + Str(h) + " | X: " + Str(x) + " | W: " + Str(w)
  If IsGadget(id)
    If StartDrawing(ImageOutput(*daten\visbkg))
      If IsFont(100)
        DrawingFont( FontID(100) )
      EndIf
      ; ***
      mmx = ImageWidth(*daten\visbkg) - (*daten\markCursorInto - *daten\markCursorFrom)
      ; ***
      Box( ImageWidth(*daten\tempor) + 6 + *daten\markCursorFrom, *daten\markstart * *daten\theight, w - mmx, (*daten\markclose - *daten\markstart) * *daten\theight, *daten\color_bkg )
      ; ***
      StopDrawing()
    EndIf
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Markierungsstart und Richtungskorrektur setzen, sobald die Markierung
; mittels Tastatur durchgeführt wird
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

Procedure setKeyMarkStart(key.i, *daten.struct_pure_multiline_code_editor)
  Protected p.i, tww.i, cc.i = *daten\cursor
  ; ***
  Select key
    Case #pure_keycode_left
      cc + 1
    Case #pure_keycode_right
      cc - 1
  EndSelect
  ; ***
  If StartDrawing(ImageOutput(*daten\curlin))
    If IsFont(100)
      DrawingFont( FontID(100) )
    EndIf
    ; ***
    DrawingMode( #PB_2DDrawing_Transparent )
    ; ***
    For p = 0 To 19999
      If cc = p
        Break
      EndIf
      ; ***
      *daten\markpos = p
      *daten\markCursorFrom = tww
      ; ***
      If *daten\strom[p]\char
        tww + TextWidth(*daten\strom[p]\char)
      Else
        tww + TextWidth(" ")
      EndIf
    Next
    ; ***
    StopDrawing()
    ; ***
    *daten\marklen = *daten\markpos
    *daten\markCursorInto = *daten\markCursorFrom
    ; ***
;Debug Str(*daten\markpos) + " -> " + Str(*daten\markCursorFrom)
    *daten\mark = #True
    *daten\markmode = #False
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Realisiert den Syntax-Editor, samt Eingabe und Maus-Events
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  #ControlUpMore = #PB_Canvas_Command
CompilerElse
  #ControlUpMore = #PB_Canvas_Control
CompilerEndIf

Procedure update(*daten.struct_pure_multiline_code_editor,id.i,evt.i,key.i,inp.i,mx.i,my.i)
  If IsGadget(id)
    Protected w.i, h.i, p.i, n.i, tw.d, cc.s, du.a = #False, sb.a = #False, top.i, pos.i
    Protected tt.i, tx.s, ti.i, m.i, tww.d, mmx.i, emi.a = 0, gi.i, gu.i, tps.s = "", dd.d
    Protected tix.i, tiy.i, tiw.i, tih.i
    ; ***
    w = GadgetWidth(id)
    h = GadgetHeight(id)
    ; ***
    Select evt
      Case #PB_EventType_LeftButtonDown, #PB_EventType_RightButtonDown, #PB_EventType_MiddleButtonDown
        ;{
        mmx = -90000
        ; ***
        *daten\markdif = 0
        ; ***
        If *daten\mark = #True
          tix = ImageWidth(*daten\tempor) + 6 + *daten\markCursorFrom
          tiy = *daten\markstart * *daten\theight
          tiw = w - ImageWidth(*daten\visbkg) - (*daten\markCursorInto - *daten\markCursorFrom)
          tih = (*daten\markclose - *daten\markstart) * *daten\theight
          ; ***
          ;Box( ImageWidth(*daten\tempor) + 6 + *daten\markCursorFrom, *daten\markstart * *daten\theight, w - mmx, (*daten\markclose - *daten\markstart) * *daten\theight, *daten\color_marked_bkg )
          If mx >= tix And mx <= tix + tiw And my >= tiy And my <= tiy + tih
            ; nix
          Else
            *daten\mark = #False
            *daten\markmode = #False
          EndIf
        EndIf
        ; ***
        For m = 0 To *daten\vislimit
          If my >= ( m * *daten\theight ) And my <= ( m * *daten\theight ) + *daten\theight
            *daten\index = *daten\position + *daten\toplimit
            ; ***
            update_current_syntax(*daten)
            ; ***
            update_content( *daten, id, w, h )
            ; ***
            *daten\content\set( *daten\index, getInputStringLine(*daten) )
            ; ***
            *daten\position = m
            ; ***
            *daten\index = *daten\position + *daten\toplimit
            ; ***
            allocate_current_line( *daten )
            ; ***
            mmx = mx - ImageWidth(*daten\tempor)
            ; ***
            If mmx < 0
              *daten\cursor = 1
            Else
              If StartDrawing(ImageOutput(*daten\curlin))
                If IsFont(100)
                  DrawingFont( FontID(100) )
                EndIf
                ; ***
                DrawingMode( #PB_2DDrawing_Transparent )
                ; ***
                For p = 0 To *daten\length -1
                  If mmx >= tww And mmx <= tww + TextWidth(*daten\strom[p]\char)
                    *daten\cursor = p
                    ; ***
                    emi = 1
                    ; ***
                    *daten\markCursorFrom = tww
                    ; ***
                    *daten\markpos = p
                    ; ***
                    Break
                  EndIf
                  ; ***
                  tww + TextWidth(*daten\strom[p]\char)
                Next
                ; ***
                StopDrawing()
                ; ***
                If emi = 0
                  *daten\cursor = *daten\length
                EndIf
              EndIf
            EndIf
            ; ***
            du = #True
            ; ***
            Break
          EndIf
        Next
        ; ***
        If mx <= ImageWidth(*daten\tempor)
          *daten\markpos = 0
          *daten\marklen = 19999
          *daten\markCursorFrom = 0
          *daten\markCursorInto = ImageWidth(*daten\visbkg) - ImageWidth(*daten\tempor) - 6
        EndIf
        ; ***
        If mmx <> -90000
          If evt = #PB_EventType_LeftButtonDown
            *daten\mark = #True
            ; ***
            *daten\markrel = *daten\position
            *daten\markrow = *daten\index
            ; ***
            *daten\markstart = *daten\markrel
            *daten\markclose = *daten\markrel
          EndIf
        EndIf
        ;}
      Case #PB_EventType_LeftButtonUp
        ;{
        *daten\markmode = #True
        ProcedureReturn
        ;}
      Case #PB_EventType_MouseMove
        ;{
        If *daten\mark = #True And *daten\markmode = #False
          mmx = mx - ImageWidth(*daten\tempor) : tww = 0
          ; ***
          If StartDrawing(ImageOutput(*daten\curlin))
            If IsFont(100)
              DrawingFont( FontID(100) )
            EndIf
            ; ***
            DrawingMode( #PB_2DDrawing_Transparent )
            ; ***
            For p = 0 To 19999
              If tww >= w - ImageWidth(*daten\tempor)
                Break
              EndIf
              ; ***
              If mmx >= tww And mmx <= tww + TextWidth(*daten\strom[p]\char)
                *daten\markCursorInto = tww
                ; ***
                *daten\marklen = p
                ; ***
                Break
              EndIf
              ; ***
              If *daten\strom[p]\char
                tww + TextWidth(*daten\strom[p]\char)
              Else
                tww + TextWidth(" ")
              EndIf
            Next
            ; ***
            StopDrawing()
          EndIf
          ; ***
          mmx = -90000
          ; ***
          tww = 0
          ; ***
          For m = 0 To *daten\vislimit
            If my >= ( m * *daten\theight ) And my <= ( m * *daten\theight ) + *daten\theight
              mmx = m
              ; ***
              Break
            EndIf
          Next
          ; ***
          If mmx <> -90000
            If mmx >= *daten\markrel
              *daten\markstart = *daten\markrel
              *daten\markclose = mmx + 1
            Else
              *daten\markstart = mmx
              *daten\markclose = *daten\markrel + 1
            EndIf
          EndIf
        Else
          ProcedureReturn
        EndIf
        ;}
      Case #PB_EventType_MouseWheel
        ;{
        
        ;}
      Case #PB_EventType_Input
        ;{
        If Not GetGadgetAttribute(id, #PB_Canvas_Modifiers) & #ControlUpMore
        If inp = 32 Or inp = 9 Or inp = 10 Or inp = 13
          If *daten\curlen
            If *daten\curpos >= 0 And *daten\curpos < *daten\length
              cc = ""
              ; ***
              update_current_token( *daten, *daten\curpos, *daten\curlen )
            EndIf
          EndIf
          ; ***
          *daten\curpos = *daten\cursor + 1
          *daten\curlen = 0
        ElseIf inp <> 32 And inp <> 9
          *daten\curlen + 1
        EndIf
        ; ***
        If *daten\cursor = 0
          If *daten\length
            p = *daten\length
            ; ***
            If p >= 0 And p < 20000
              Repeat
                *daten\strom[p+1]\char = *daten\strom[p]\char
                *daten\strom[p+1]\color = *daten\strom[p]\color
                *daten\strom[p]\color = 0
                ; ***
                p - 1
              Until p = 0
            EndIf
          EndIf
          ; ***
          *daten\strom[0]\char = Chr(inp)
        ElseIf *daten\cursor = *daten\length
          *daten\strom[*daten\cursor]\char = Chr(inp)
        Else
          p = *daten\length
          ; ***
          Repeat
            If p >= 0 And p <= 19998
              *daten\strom[p+1]\char = *daten\strom[p]\char
              *daten\strom[p+1]\color = *daten\strom[p]\color
            Else
              Break
            EndIf
            ; ***
            p - 1
          Until p = *daten\cursor -1
          ; ***
          *daten\strom[*daten\cursor]\char = Chr(inp)
          *daten\strom[*daten\cursor]\color = 0
        EndIf
        ; ***
        *daten\cursor + 1
        *daten\length + 1
        ; ***
        *daten\cursorDisplay = #True
        ; ***
        update_current_syntax(*daten)
        ; ***
        *daten\mark = #False
        *daten\markmode = #False
        ; ***
        *daten\markrel = *daten\position
        *daten\markrow = *daten\index
        ; ***
        *daten\markstart = *daten\markrel
        *daten\markclose = *daten\markrel
        ; ***
        du = #True
        EndIf
        ;}
      Case #PB_EventType_KeyUp
        ;{
        If *daten\intellivis = #False
          If *daten\mark = #True
            *daten\markmode = #True
            ; ***
            *daten\markdif = 1
            ; ***
            ;*daten\markrel = *daten\position
            ;*daten\markrow = *daten\index
            ; ***
            *daten\markstart = *daten\markrel
            *daten\markclose = *daten\markrel + 1
            ; ***
            *daten\index = *daten\position + *daten\toplimit
            ; ***
            update_current_syntax(*daten)
            ; ***
            update_content( *daten, id, w, h )
            ; ***
            *daten\content\set( *daten\index, getInputStringLine(*daten) )
          EndIf
        EndIf
        ;}
      Case #PB_EventType_KeyDown
        Select key
          Case #pure_keycode_tabbed
            ;{
            If *daten\cursor < 19998 - 1
              *daten\length + 1
              *daten\cursor + 1
              *daten\strom[*daten\cursor]\char = " "
              *daten\strom[*daten\cursor]\color = 0
              *daten\strom[*daten\cursor]\pos = 0
              ; ***
              If *daten\cursor < 19998 - 1
                *daten\length + 1
                *daten\cursor + 1
                *daten\strom[*daten\cursor]\char = " "
                *daten\strom[*daten\cursor]\color = 0
                *daten\strom[*daten\cursor]\pos = 0
                ; ***
                If *daten\cursor < 19998 - 1
                  *daten\length + 1
                  *daten\cursor + 1
                  *daten\strom[*daten\cursor]\char = " "
                  *daten\strom[*daten\cursor]\color = 0
                  *daten\strom[*daten\cursor]\pos = 0
                  ; ***
                  SetActiveGadget( id )
                  ; ***
                  du = #True
                EndIf
              EndIf
            EndIf
            ;}
          Case #pure_keycode_pos
            *daten\cursor = 1
          Case #pure_keycode_end
            *daten\cursor = *daten\length
          Case #pure_keycode_up
            ;{
            If *daten\intellivis = #False
              If *daten\position = 0 And *daten\toplimit = 0
                ProcedureReturn
              EndIf
              ; ***
              *daten\index = *daten\position + *daten\toplimit
              ; ***
              update_current_syntax(*daten)
              ; ***
              update_content( *daten, id, w, h )
              ; ***
              *daten\content\set( *daten\index, getInputStringLine(*daten) )
              ; ***
              *daten\position - 1
              ; ***
              If *daten\position < 0
                *daten\toplimit - 1
                *daten\position = 0
                ; ***
                If *daten\toplimit < 0
                  *daten\toplimit = 0
                EndIf
                ; ***
                *daten\condir = 1
                update_content( *daten, id, w, h )
                ; ***
                sb = #True
              EndIf
              ; ***
              *daten\index = *daten\position + *daten\toplimit
              ; ***
              allocate_current_line( *daten )
              ; ***
              If *daten\movetolast = #True
                *daten\movetolast = #False
                ; ***
                *daten\cursor = *daten\length
              EndIf
              ; ***
              du = #True
            Else
              *daten\intellicur - 1
              ; ***
              If *daten\intellicur < 0
                *daten\intellicur = 0
              EndIf
            EndIf
            ;}
          Case #pure_keycode_enter, #pure_keycode_down
            ;{
            If *daten\intellivis = #False
              *daten\index = *daten\position + *daten\toplimit
              ; ***
              update_current_syntax(*daten)
              ; ***
              update_content( *daten, id, w, h )
              ; ***
              *daten\content\set( *daten\index, getInputStringLine(*daten) )
              ; ***
              If *daten\index > *daten\content\lines() -2
                If key = #pure_keycode_down
                  ProcedureReturn
                EndIf
              EndIf
              ; ***
              *daten\position + 1
              ; ***
              If *daten\position > *daten\vislimit
                *daten\toplimit + 1
                ; ***
                If *daten\toplimit > *daten\content\length() - 1 - *daten\vislimit
                  *daten\toplimit = *daten\content\length() - 1 - *daten\vislimit
                  *daten\position = *daten\vislimit
                Else
                  *daten\position - 1
                EndIf
                ; ***
                *daten\condir = 2
                update_content( *daten, id, w, h )
                ; ***
                sb = #True
              EndIf
              ; ***
              *daten\index = *daten\position + *daten\toplimit
              ; ***
              du = #True
              ; ***
              If key = #pure_keycode_enter
                *daten\content\add(" ")
                ; ***
                *daten\cursor = 1
              ElseIf key = #pure_keycode_down
                If *daten\index > *daten\content\length() - 1
                  *daten\index = *daten\content\length() - 1
                  *daten\toplimit = *daten\content\length() - *daten\vislimit
                  *daten\position = *daten\index - *daten\toplimit
                EndIf
              EndIf
              ; ***
              allocate_current_line( *daten )
            Else
              If key = #pure_keycode_enter
                If *daten\intellimar
                  tps + " "
                EndIf
                ; ***
                tps + *daten\intellitok
                ; ***
                *daten\intellivis = 12
                ; ***
                *daten\intellitok = ""
                ; ***
                *daten\index = *daten\position + *daten\toplimit
                ; ***
                *daten\content\set( *daten\index, getInputStringLine(*daten) + tps )
                ; ***
                *daten\cursor + Len(tps)
                *daten\length + Len(tps)
                ; ***
                allocate_current_line( *daten )
                ; ***
                update_current_syntax(*daten)
                ; ***
                update_content( *daten, id, w, h )
                ; ***
                du = #True
              ElseIf key = #pure_keycode_down
                *daten\intellicur + 1
                ; ***
                If *daten\intellicur > *daten\intellitot -1
                  *daten\intellicur = *daten\intellitot -1
                EndIf
              EndIf
            EndIf
            ;}
          Case #pure_keycode_delete
            ;{
            If *daten\cursor = 0
              ; Rauf auf die obere Zeile oder ignorieren
            ElseIf *daten\cursor = *daten\length
              *daten\strom[*daten\cursor]\char = ""
              *daten\strom[*daten\cursor]\color = 0
              *daten\strom[*daten\cursor]\pos = 0
              *daten\cursor -1
              *daten\length -1
            Else
              For p = *daten\cursor To *daten\length
                *daten\strom[p-1]\char = *daten\strom[p]\char
                *daten\strom[p-1]\color = *daten\strom[p]\color
                *daten\strom[p-1]\pos = *daten\strom[p]\pos
              Next
              ; ***
              *daten\strom[*daten\length]\char = ""
              *daten\strom[*daten\length]\color = 0
              *daten\strom[*daten\length]\pos = 0
              ; ***
              *daten\cursor -1
              *daten\length -1
            EndIf
            ; ***
            If *daten\cursor = 1
              If *daten\length <= 1
                *daten\strom[0]\char = ""
                *daten\strom[0]\color = 0
                *daten\strom[0]\pos = 0
              EndIf
            EndIf
            ; ***
            du = #True
            ;}
          Case #pure_keycode_left
            ;{
            If *daten\intellivis = #False
              If *daten\cursor <= 1
                *daten\movetolast = #True
                update(*daten,id,#PB_EventType_KeyDown,#pure_keycode_up,0,0,0)
                ProcedureReturn
              Else
                *daten\cursor - 1
                ; ***
                If *daten\cursor < 0
                  *daten\cursor = 0
                EndIf
                ; ***
                *daten\curpos = *daten\cursor
                ; ***
                du = #True
              EndIf
              ; ***
              ;setKeyMarkStart(*daten)
            Else
              *daten\intellivis = 12
            EndIf
            ;}
          Case #pure_keycode_right
            ;{
            If *daten\intellivis = #False
              If *daten\cursor = *daten\length
                update(*daten,id,#PB_EventType_KeyDown,#pure_keycode_down,0,0,0)
                ProcedureReturn
              Else
                *daten\cursor + 1
                ; ***
                If *daten\cursor > *daten\length
                  *daten\cursor = *daten\length
                EndIf
                ; ***
                *daten\curpos = *daten\cursor
                ; ***
                du = #True
              EndIf
              ; ***
              ;setKeyMarkStart(*daten)
            Else
              *daten\intellivis = 12
            EndIf
            ;}
          Case #pure_keycode_escape, #pure_keycode_space
            ;{
            If *daten\intellivis = #True
              *daten\intellivis = 12
            EndIf
            ;}
        EndSelect
        ; ***
        If GetGadgetAttribute(id, #PB_Canvas_Modifiers) & #ControlUpMore
          Select key
            Case Asc("c"), Asc("C") ; Kopieren
              ClearClipboard()
              SetClipboardText(getMarkedText(*daten))
            Case Asc("x"), Asc("X") ; Schneiden
              ClearClipboard()
              SetClipboardText(getMarkedText(*daten))
              clearMarkedText(*daten)
              clearImageArea(*daten,id,w,h)
            Case Asc("v"), Asc("V") ; Einfügen
              Debug "Paste"
            Case Asc("a"), Asc("A") ; Alles markieren
              Debug "Select all"
          EndSelect
        ElseIf GetGadgetAttribute(id, #PB_Canvas_Modifiers) & #PB_Canvas_Shift
          tww = 0
          ; ***
          Select key
            Case #pure_keycode_up
              If *daten\mark = #True
                *daten\markstart - 1
                ; ***
                If *daten\markstart < 0
                  *daten\markstart = 0
                Else
                  *daten\markclose = *daten\markrel + 1
                  ; ***
                  If *daten\markclose > *daten\vislimit
                    *daten\markclose = *daten\vislimit
                  EndIf
                EndIf
              EndIf
            Case #pure_keycode_down
              If *daten\mark = #True
                *daten\markclose + 1
                ; ***
                If *daten\markclose > *daten\vislimit
                  *daten\markclose = *daten\vislimit
                Else
                  *daten\markstart = *daten\markrel
                  ; ***
                  If *daten\markstart < 0
                    *daten\markstart = 0
                  EndIf
                EndIf
              EndIf
            Case #pure_keycode_left, #pure_keycode_right
              If *daten\mark = #False
                setKeyMarkStart(key,*daten)
                ; ***
                *daten\markrel = *daten\position
                *daten\markrow = *daten\index
              Else;If *daten\mark = #True And *daten\markmode = #False
                If StartDrawing(ImageOutput(*daten\curlin))
                  If IsFont(100)
                    DrawingFont( FontID(100) )
                  EndIf
                  ; ***
                  DrawingMode( #PB_2DDrawing_Transparent )
                  ; ***
                  For p = 0 To 19999
                    If tww >= w - ImageWidth(*daten\tempor)
                      Break
                    EndIf
                    ; ***
                    If *daten\cursor = p
                      Break
                    EndIf
                    ; ***
                    *daten\marklen = p
                    *daten\markCursorInto = tww
                    ; ***
                    If *daten\strom[p]\char
                      tww + TextWidth(*daten\strom[p]\char)
                    Else
                      tww + TextWidth(" ")
                    EndIf
                  Next
                  ; ***
                  StopDrawing()
                EndIf
              EndIf
          EndSelect
          ; ***
          tww = 0
        Else
          *daten\mark = #False
          *daten\markmode = #False
        EndIf
    EndSelect
    ; ***
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; Cursor korrigieren
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; ***
    ;{
    If *daten\cursor <= 0
      *daten\cursor = 1
    EndIf
    ; ***
    If *daten\length < *daten\cursor
      *daten\length = *daten\cursor
    EndIf
    ;}
    ; ***
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; Zeilennummernblock
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; ***
    ;{
    If *daten\theight = 0
      sb = #True
    EndIf
    ; ***
    If sb
      du = #True
      ; ***
      If CreateImage(*daten\tempor,w,h) And StartDrawing(ImageOutput(*daten\tempor))
        If IsFont(100)
          DrawingFont( FontID(100) )
        EndIf
        ; ***
        DrawingMode( #PB_2DDrawing_Transparent )
        ; ***
        *daten\theight = TextHeight("A")
        ; ***
        *daten\vislimit = (h / *daten\theight) - 1
        ; ***
        If *daten\vislimit <= 0
          *daten\vislimit = 1
        EndIf
        ; ***
        ti = TextWidth(Str(*daten\content\lines())) + 60
        ; ***
        StopDrawing()
      EndIf
      ; ***
      If CreateImage(*daten\tempor,ti,h) And StartDrawing(ImageOutput(*daten\tempor))
        If IsFont(100)
          DrawingFont( FontID(100) )
        EndIf
        ; ***
        DrawingMode( #PB_2DDrawing_Transparent )
        ; ***
        Box( 0, 0, ti, h, *daten\color_number_block_bkg )
        ; ***
        For n = 0 To *daten\vislimit + 2
          tx = Str(n + *daten\toplimit + 1)
          ; ***
          DrawText( ti - 50 - TextWidth(tx), n * *daten\theight, tx, *daten\color_number_block_txt )
        Next
        ; ***
        StopDrawing()
      EndIf
    EndIf
    ;}
    ; ***
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; Aktuelle Zeile zeichnen
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; ***
    ;{
    If du
      *daten\lastkey = ""
      ; ***
      If CreateImage(*daten\curlin,w,*daten\theight) And StartDrawing(ImageOutput(*daten\curlin))
        Box( 0, 0, w, h, $FFFFFF ) ; VORÜBRGEHEND
        ; ***
        If IsFont(100)
          DrawingFont( FontID(100) )
        EndIf
        ; ***
        DrawingMode( #PB_2DDrawing_Transparent )
        ; ***
        If evt = #PB_EventType_Input
          *daten\theight = TextHeight("A")
          ; ***
          *daten\vislimit = (h / *daten\theight) - 1
          ; ***
          If *daten\vislimit <= 0
            *daten\vislimit = 1
          EndIf
        EndIf
        ; ***
        For p = 0 To *daten\length -1
          If p = 0
            DrawText( 0, 0, *daten\strom[p]\char, *daten\strom[p]\color )
          Else
            DrawText( tw, 0, *daten\strom[p]\char, *daten\strom[p]\color )
          EndIf
          ; ***
          If *daten\strom[p]\char = " "
            *daten\lastkey = ""
          Else
            *daten\lastkey + *daten\strom[p]\char
          EndIf
          ; ***
          *daten\strom[p]\pos = tw
          ; ***
          tw + TextWidth(*daten\strom[p]\char)
          ; ***
          If p = *daten\cursor -1
            pos = tw
          EndIf
        Next
        ; ***
        StopDrawing()
      EndIf
    EndIf
    ;}
    ; ***
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; CanvasGadget aktualisieren
    ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
    ; ***
    ;{
    top = *daten\position * *daten\theight
    ; ***
    If du
      *daten\curstate = pos + ImageWidth(*daten\tempor) + 6
    EndIf
    ; ***
    If StartDrawing(CanvasOutput(id))
      ;{ Abbilder für die Darstellung
      Box( 0, 0, w, h, *daten\color_bkg )
      ; ***
      If IsFont(100)
        DrawingFont( FontID(100) )
      EndIf
      ; ***
      If IsImage(*daten\tempor)
        DrawImage( ImageID(*daten\tempor), 0, 0 )
      EndIf
      ; ***
      If IsImage(*daten\visbkg)
        DrawImage( ImageID(*daten\visbkg), ImageWidth(*daten\tempor) + 6, 0 )
      EndIf
      ; ***
      If IsImage(*daten\curlin)
        DrawImage( ImageID(*daten\curlin), ImageWidth(*daten\tempor) + 6, top )
      EndIf
      ; ***
      If *daten\cursorDisplay; And *daten\intellivis = #False
        Box( *daten\curstate, top, 2, *daten\theight, 0 )
      EndIf
      ; ***
      Box( ImageWidth(*daten\tempor) - 50 + 4, top, 46, *daten\theight, *daten\color_number_block_active )
      ;}
      ; ***
      ;{ Markierung zeichnen
      DrawingMode( #PB_2DDrawing_Transparent )
      ; ***
      If *daten\mark = #True
        If *daten\markstart * *daten\theight - (*daten\markclose - *daten\markstart) * *daten\theight <> 6
          Box( ImageWidth(*daten\tempor) - 50 + 4, *daten\markstart * *daten\theight, 46, (*daten\markclose - *daten\markstart) * *daten\theight, *daten\color_number_block_active )
          ; ***
          DrawingMode( #PB_2DDrawing_AlphaBlend )
          ; ***
          mmx = ImageWidth(*daten\visbkg) - (*daten\markCursorInto - *daten\markCursorFrom)
          ; ***
          Box( ImageWidth(*daten\tempor) + 6 + *daten\markCursorFrom, *daten\markstart * *daten\theight, w - mmx, (*daten\markclose - *daten\markstart) * *daten\theight, *daten\color_marked_bkg )
          ; ***
          DrawingMode( #PB_2DDrawing_Outlined )
          ; ***
          Box( ImageWidth(*daten\tempor) + 6 + *daten\markCursorFrom, *daten\markstart * *daten\theight, w - mmx, (*daten\markclose - *daten\markstart) * *daten\theight, *daten\color_marked_border )
        EndIf
      EndIf
      ;}
      ; ***
      ;{ Cursor
      Box( ImageWidth(*daten\tempor), 0, 6, h, *daten\color_bkg )
      ;}
      ; ***
      ; DIESEN PART IN EIN THREAD AUSLAGERN!!!
      ;{ Intellisence*
      If *daten\intellivis = 12
        *daten\intellivis = #False
      ElseIf evt = #PB_EventType_KeyDown Or *daten\intellivis = #True
        If key = 46 Or *daten\intellivis = #True Or TLCase(*daten\lastkey) = "belirle" Or TLCase(*daten\lastkey) = "dizilim" Or TLCase(*daten\lastkey) = "değişken"
          If *daten\intellivis = #False
            *daten\intellivis = #True
            *daten\intellicur = 0
          EndIf
          ; ***
          If *daten\lastkey And *daten\intellisence And *daten\comment = 0 And *daten\stringi = 0
            For p = 0 To *daten\intellisence\cnt -1
              For x = 0 To *daten\intellisence\lst[p]\groupkeys\lines() -1
                If Trim(TLCase(*daten\intellisence\lst[p]\groupkeys\get(x))) = Trim(TLCase(*daten\lastkey))
                  *daten\intelliLastWidth = *daten\intellisence\lst[p]\width + 16
                  ; ***
                  If *daten\curstate + *daten\intelliLastWidth > w
                    *daten\curstate = w - *daten\intelliLastWidth
                  EndIf
                  ; ***
                  If top > h - (4 * *daten\theight) - 16
                    top = h - (4 * *daten\theight) - 16
                  EndIf
                  ; ***
                  Box( *daten\curstate + 10, top, *daten\intellisence\lst[p]\width + 6, (4 * *daten\theight) + 6, *daten\color_intelli_background )
                  ; ***
                  DrawingMode( #PB_2DDrawing_Outlined )
                  ; ***
                  Box( *daten\curstate + 10, top, *daten\intellisence\lst[p]\width + 5, (4 * *daten\theight) + 5, *daten\color_intelli_dborder )
                  Box( *daten\curstate + 10 + 1, top + 1, *daten\intellisence\lst[p]\width + 5, (4 * *daten\theight) + 5, *daten\color_intelli_lborder )
                  Box( *daten\curstate + 10, top, *daten\intellisence\lst[p]\width + 6, (4 * *daten\theight) + 6, *daten\color_intelli_border )
                  ; ***
                  DrawingMode( #PB_2DDrawing_Transparent )
                  ; ***
                  m = 0
                  ; ***
                  *daten\intellimar = *daten\intellisence\lst[p]\space
                  ; ***
                  *daten\intellitot = *daten\intellisence\lst[p]\content\lines()
                  ; ***
                  ti = *daten\intellicur
                  ; ***
                  If ti > *daten\intellitot - 4
                    ti = *daten\intellitot - 4
                  EndIf
                  ; ***
                  For n = ti To ti + 3
                    If n = *daten\intellicur
                      Box( *daten\curstate + 13, top + 3 + (m * *daten\theight), *daten\intellisence\lst[p]\width, *daten\theight, *daten\color_intelli_sel_bkg )
                      DrawText( *daten\curstate + 10 + 6, top + 3 + (m * *daten\theight), *daten\intellisence\lst[p]\content\get(n), *daten\color_intelli_sel_txt )
                      *daten\intellitok = *daten\intellisence\lst[p]\content\get(n)
                    Else
                      DrawText( *daten\curstate + 10 + 6, top + 3 + (m * *daten\theight), *daten\intellisence\lst[p]\content\get(n), *daten\color_intelli_text )
                    EndIf
                    m + 1
                  Next
                  ; ***
                  Break
                EndIf
              Next
            Next
          EndIf
        EndIf
      EndIf
      ;}
      ; ***
      StopDrawing()
    EndIf
    ;}
  EndIf
EndProcedure

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Test
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;

ExamineDesktops()
OpenWindow(#fenster,0,0,800,700,"Eingabe",
           #PB_Window_SystemMenu|#PB_Window_Invisible)
CanvasGadget(#feld,0,0,800,700,#PB_Canvas_Keyboard)
SetActiveGadget(#feld)
ResizeWindow(#fenster,DesktopWidth(0)-800,
             DesktopHeight(0)-800,800,700)
StickyWindow(#fenster,1)
HideWindow(#fenster,0)
AddWindowTimer(#fenster,#fenster,400)

Global ib.struct_intellisence_list
; ***
ib\cnt = 0

keyw.editor_dataset = editor_dataset()
mich.struct_pure_multiline_code_editor

mich\intellisence = ib

mich\content = editor_dataset()
For vi = 0 To 99
  mich\content\add( "" )
Next

mich\color_comment = RGB( 147, 133, 148 )
mich\color_string = RGB( 106, 144, 166 )
mich\color_number = RGB( 204, 51, 153 )
mich\color_operator = RGB( 170, 148, 84 );RGB( 153, 51, 255 );RGB( 118, 92, 163 )
mich\color_bkg = RGB( 255, 255, 255 )
mich\color_selbkg = RGB( 238, 238, 238 )
mich\color_errorbkg = RGB( 239, 207, 203 )
mich\color_number_block_active = RGB( 228, 228, 228 )
mich\color_number_block_bkg = RGB( 238, 238, 238 );RGB( 154, 149, 166 );RGB( 137, 121, 158 );RGB( 98, 62, 133 )
mich\color_number_block_txt = RGB( 154, 149, 166 );RGB(255,255,255)

mich\color_intelli_background = RGB( 238, 238, 238 )
mich\color_intelli_border = RGB(140,150,160)
mich\color_intelli_lborder = RGB(245,248,251)
mich\color_intelli_dborder = RGB(160,170,180)
mich\color_intelli_text = 0
mich\color_intelli_sel_bkg = RGB( 0, 153, 204 )
mich\color_intelli_sel_txt = RGB( 243, 255, 255 )

mich\color_marked_border = RGB( 0, 153, 204 )
mich\color_marked_bkg = RGBA( 0, 153, 204, 20 )

mich\intellivis = #False

c = RGB( 51, 153, 204 );RGB( 36, 134, 255 )
keyw\add( "Define", c )
keyw\add( "Global", c )
keyw\add( "Protected", c )
keyw\add( "Static", c )
keyw\add( "Threaded", c )
keyw\add( "ElseIf", c )
keyw\add( "Else", c )
keyw\add( "EndIf", c )
keyw\add( "If", c )
keyw\add( "ForEach", c )
keyw\add( "For", c )
keyw\add( "Next", c )
keyw\add( "Break", c )
keyw\add( "Repeat", c )
keyw\add( "Forever", c )
keyw\add( "Until", c )
keyw\add( "EndProcedure", c )
keyw\add( "Procedure", c )
keyw\add( "EndInterface", c )
keyw\add( "Interface", c )
keyw\add( "EndStructure", c )
keyw\add( "Structure", c )
keyw\add( "ReDim", c )
keyw\add( "Dim", c )
keyw\add( "XIncludeFile", c )
keyw\add( "IncludeFile", c )
keyw\add( "Debug", c )
keyw\add( "CompilerElseIf", c )
keyw\add( "CompilerElse", c )
keyw\add( "CompilerIf", c )
keyw\add( "CompilerEndIf", c )
keyw\add( "And", c )
keyw\add( "Not", c )
keyw\add( "Or", c )
keyw\add( "CompilerEndSelect", c )
keyw\add( "CompilerCase", c )
keyw\add( "CompilerDefault", c )
keyw\add( "CompilerSelect", c )
keyw\add( "EndSelect", c )
keyw\add( "Case", c )
keyw\add( "Default", c )
keyw\add( "Select", c )
; ***
c = RGB( 102, 102, 153 )
keyw\add( "Len", c )
keyw\add( "Mid", c )
keyw\add( "Left", c )
keyw\add( "Right", c )
keyw\add( "Trim", c )
keyw\add( "LTrim", c )
keyw\add( "RTrim", c )
keyw\add( "ReplaceString", c )
keyw\add( "FindString", c )
keyw\add( "CountString", c )
keyw\add( "ReverseString", c )
keyw\add( "LCase", c )
keyw\add( "UCase", c )
keyw\add( "StrD", c )
keyw\add( "StrF", c )
keyw\add( "Str", c )
keyw\add( "ValD", c )
keyw\add( "ValF", c )
keyw\add( "Val", c )
keyw\add( "RunProgram", c )
keyw\add( "Delay", c )
keyw\add( "OpenWindow", c )
keyw\add( "ButtonGadget", c )
keyw\add( "ButtonImageGadget", c )
keyw\add( "CheckBoxGadget", c )
keyw\add( "OptionGadget", c )
keyw\add( "CanvasGadget", c )
keyw\add( "ImageGadget", c )
keyw\add( "PanelGadget", c )
keyw\add( "TreeGadget", c )
keyw\add( "ListViewGadget", c )
keyw\add( "ListIconGadget", c )
keyw\add( "SpinGadget", c )
keyw\add( "SplitterGadget", c )
keyw\add( "WebGadget", c )
keyw\add( "StringGadget", c )
keyw\add( "TextGadget", c )
keyw\add( "ComboBoxGadget", c )
keyw\add( "DateGadget", c )
keyw\add( "CalenderGadget", c )
; ***
c = RGB( 154, 71, 193 )
keyw\add( "PB_Compiler_OS", c )
keyw\add( "PB_OS_MacOS", c )
keyw\add( "PB_OS_Linux", c )
keyw\add( "PB_OS_Windows", c )
keyw\add( "PB_Event_Gadget", c )
keyw\add( "PB_Event_CloseWindow", c )
keyw\add( "PB_Event_SizeWindow", c )
keyw\add( "PB_Event_MoveWindow", c )
keyw\add( "PB_Event_MaximizeWindow", c )
keyw\add( "PB_Event_MinimizeWindow", c )
keyw\add( "True", c )
keyw\add( "False", c )
keyw\add( "PB_Any", c )
keyw\add( "PB_Ignore", c )

mich\comment_char = ";"
mich\string_char = Chr(34)
mich\double_separator = "."
mich\keywords = keyw
mich\visbkg = 10
mich\tmpbkg = 11
mich\curlin = 12
mich\tempor = 13

update(mich,#feld,0,0,0,0,0)

Repeat
  ev.i = WaitWindowEvent()
  ; ***
  If ev = #PB_Event_CloseWindow
    ;For r = 0 To mich\content\lines() -1
      ;Debug Str(r) + ":" + Str(r+1) + " >> " + mich\content\get(r)
    ;Next
  EndIf
  ; ***
  If ev = #PB_Event_Timer And EventTimer() = #fenster
    Select mich\cursorDisplay
      Case 0 : mich\cursorDisplay = 1
      Case 1 : mich\cursorDisplay = 0
    EndSelect
    ; ***
    update(mich,#feld,0,0,0,0,0)
  EndIf
  ; ***
  If ev = #PB_Event_Gadget And EventGadget() = #feld
    Select EventType()
      Case #PB_EventType_Input, #PB_EventType_KeyDown, #PB_EventType_KeyUp,
           #PB_EventType_LeftButtonDown, #PB_EventType_LeftButtonUp,
           #PB_EventType_RightButtonUp, #PB_EventType_MouseMove,
           #PB_EventType_MouseWheel
        update(mich,#feld,EventType(),
               GetGadgetAttribute(#feld,#PB_Canvas_Key),
               GetGadgetAttribute(#feld,#PB_Canvas_Input),
               GetGadgetAttribute(#feld,#PB_Canvas_MouseX),
               GetGadgetAttribute(#feld,#PB_Canvas_MouseY))
    EndSelect
  EndIf
Until ev = #PB_Event_CloseWindow

End
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Canvasbasierter alternative zur Scintilla

Beitrag von Kiffi »

@5mware: Hut ab! Da hast Du Dir ja ein ambitioniertes Projekt vorgenommen.

Kleiner Tipp: Wie wäre es, wenn Du hierfür ein GibHub-Projekt anlegen würdest? Dann gestaltet sich die Veröffentlichung Deines Codes einfacher und übersichtlicher (dieses Forum ist einfach nicht für so große Codes geeignet).

Grüße ... Peter
Hygge
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Canvasbasierter alternative zur Scintilla

Beitrag von Sicro »

Ich programmiere zur Zeit ein PB-Lexer für weitere geplante Projekte.
Den kannst du für dein Projekt gerne verwenden.
Sobald er fertig ist, gebe ich dir Bescheid.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Canvasbasierter alternative zur Scintilla

Beitrag von RSBasic »

Warum benutzt du nicht den von Remy? Da gibt es schon gute fertige PB-Lexer.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Canvasbasierter alternative zur Scintilla

Beitrag von Sicro »

RSBasic hat geschrieben:Warum benutzt du nicht den von Remy? Da gibt es schon gute fertige PB-Lexer.
Ich habe großes Interesse daran, so einen Lexer komplett selber zu programmieren, um im Detail zu verstehen, was ein Lexer (und später Parser) macht und welche Probleme zu bewältigen sind.
Außerdem stehen die existierenden Codes unter keiner OpenSource-Lizenz und können daher nicht ohne Zustimmung der Autoren neu veröffentlicht werden. Remi war schon lange nicht mehr im Forum angemeldet und hat auch keine Kontaktdaten in seinem PureBoard-Profil bereitgestellt.

@5mware:

Eine Lizenz fehlt übrigens auch bei deinem Code.
Schau mal hier: GitHub: Licensing a repository

Vermutlich wäre für deine Zwecke aktuell ein Gist auf GitHub schon ausreichend, anstatt einem vollwertigem Repository: GitHub: About gists

Für mehr Übersichtlichkeit könntest du die Codes hier im Thread entfernen und diesen Thread nur noch für Diskussionen zum Code verwenden.

Da du deinen Code auch im englischem Forum veröffentlicht hast und von diesen Forum-Mitgliedern offensichtlich ebenfalls um Mithilfe hoffst, wäre es von Vorteil, wenn die Code-Kommentare in englisch geschrieben sind.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Antworten