unit NewColorMemo;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,math,clipbrd,stdctrls;

const BCA_DELFOCUS=1;
      BCA_AKTFOCUS=2;
      BCA_UPDATECHARCODES=3;
  //    BCA_INSERTCHAR=4;
      BCA_CURSOR=5;
//      BCA_CHECKCARET=6;
      BCA_MOUSEDOWN=7;
      BCA_UPDATESCROLLBARS=8;
      BCA_SELWORD=9;

      NoAlphaChars=['*','(',')',' ','.',',','=','!','"','§','/',']','[','{','}',':',';','?','&','''','<','>','#','+','-','%','~','\','²','´'];
type
 TBPModus=(bmFull,bmCaret,bmRect{,bm});
 TBPWord=record
           x,y,l:integer;
           wort:string;
 end;
{ TTextPosToVirtXY= function (pos:integer):TPoint of object;
 TVirtXYToTextPos= function (x,y:integer):cardinal of object;
 TPaintFunc=  procedure (modus:TbpModus;viewingrect:TRect) of object;}
 TUnReDo=record
     text:string;
     caretx,carety:integer;
 end;
 TNonAlphaSet=set of Char;
 TBCStateFlag=(bcsfInPaintFunc,bcsfInSelWriteFunc,bcsfInKeyBoardWrite,bcsfCaretLeft,bcsfBlockMove{,bcsfKeyPressed anderer Wert für InKeyBoardWrite});
 TBCStateFlags=set of TBCStateFlag;
 TNewColorMemo=class;
 TBenMark=integer;
 TBenMarks=array[0..9] of TBenMark;
 //KibitzWindow
 TBenKibitz=class(TForm)
   list:TListBox;
   items:TStringList;
   editor:Tnewcolormemo;
   procedure CloseKibitz;
   procedure UpdateWords;
   procedure OnKeyDown(sender:TObject;var Key: Word;Shift: TShiftState);
   procedure OnKeyPress(sender:TObject;var Key: char);
   procedure OnKeyUp(sender:TObject;var Key: Word;Shift: TShiftState);
   constructor CreateEdit(aowner:TComponent;aeditor:TNewColorMemo);
   procedure Loaded;override;
   destructor destroy;override;
 end;


 TKibitzFunc=procedure (sender:TObject;kibitz:TBenKibitz) of object;
 //Linker Rand
 TBenMargin=class (TPersistent)
 public
   width:integer;
   editor:TNewColorMemo;
   color:TColor;
   fmarks:TBenMarks;
   constructor create(aowner:TNewColorMemo);
   procedure paintTo(dc:HDC);
   function GetMark(index:integer):TbenMark;
   procedure SetMark(index:integer;value:TBenMark);
   property marks[index:integer]:TBenMark read GetMark write SetMark;
 end;
 //ColorSytem
 TBenHighlighter=class (TComponent)
   public
     fcommentfont,fstandardfont,fkeywordfont,fstringfont,fintfont,fsymbfont:TFont;
     fkeywords:TStringList;
     fhighlight:boolean;
     fCommentZeile,fGCom2Begin,fGCom2End,fGCom1Begin,fGCom1End:string;
     fstringBeginEnd:char;
     fSymbolKey:boolean;
     procedure SetCommentFont(value:TFont);
     procedure SetStandardFont(value:TFont);
     procedure SetKeyWordFont(value:TFont);
     procedure SetStringFont(value:TFont);
     procedure SetIntFont(value:TFont);
     procedure SetSybFont(value:TFont);
     procedure SetKeyWords(value:TStringList);
     procedure SetHighlight(value:boolean);

     constructor create(aowner:TComponent);override;
     destructor destroy;override;

   published
     property commentfont:TFont read fcommentfont write setcommentfont;
     property standardfont:TFont read fstandardfont write setStandardfont;
     property keywordfont:TFont read fkeywordfont write setkeywordfont;
     property stringfont:TFont read fstringfont write setstringfont;
     property integerfont:TFont read fintfont write setintfont;
     property symbolfont:TFont read fsymbfont write setsybfont;
     property KeyWords:TStringList read fkeywords write SetKeyWords;
     property HighLight:boolean read fhighlight write SetHighLight;
     property CommentZeile:string read fCommentZeile write fCommentZeile;
     property GCom2Begin:string read fGCom2Begin write fGCom2Begin;
     property GCom2End:string read fGCom2End write fGCom2End;
     property GCom1Begin:string read fGCom1Begin write fGCom1Begin;
     property GCom1End:string read fGCom1End write fGCom1End;
     property stringBeginEnd:char read fstringBeginEnd write fstringBeginEnd;
     property KeyWordsEnthaltenSymbole:boolean read fSymbolKey write fSymbolKey default false;
 end;
 //Zentrale Darstellungskomponente
 TNewColorMemo=class (TCustomControl)
 public
  margin:TBenMargin;
  oldfont:HFONT;
//  bit:TBitmap;
  SelStart,SelLength,tempsel:integer;
  lines:TStringList;
  nonalphas,exalphas,befehlsAlphas:TNonAlphaSet;
  caretx,carety:integer;
  charheight,charwidth:integer;
  fstateflags:TBCStateFlags;
//fcommentfont,fstandardfont,fkeywordfont,fstringfont,fintfont,fsymbfont:TFont;
  fvscroll,fhscroll:integer;
  fsolidlines:boolean;
  fhighlighter:TBenHighlighter;
  Modifiziert:boolean;
  kibitz:TBenKibitz;
  fkibitzfunc:TKibitzFunc;
  undos:array of TUnReDo;
  redos:array of TUnReDo;
{  TextPosToVirtXY:TTextPosToVirtXY;
  VirtXYToTextPos:TVirtXYToTextPos;
  PaintNew:TPaintFunc;}
  constructor create(aowner:TComponent);override;
  procedure CreateParams(var params:TCreateParams);override;
  procedure UpdateExAlphas;
//  procedure WMPaint(var mes:TWMPaint);message WM_PAINT;
  procedure Paint;override;
  procedure PaintNew(modus:TbpModus;viewingrect:TRect);
//  procedure _2PaintNew(modus:TbpModus;viewingrect:TRect);
  procedure WndProc(var mes:TMessage);override;
  procedure ProcessMessage(      typ:cardinal;pi,ps:integer);

  procedure SetHScroll(pos:integer);
  procedure SetVScroll(pos:integer);
//  procedure SetSolidLines(value:boolean);
  procedure SetScrollMax(scrollbar:cardinal;max:integer);
  function GetScrollMax(scrollbar:cardinal):integer;
  function TextPosToVirtXY(pos:integer):TPoint;
  function VirtXYToTextPos(x,y:integer):integer;
  procedure SetHighlighter(value:TBenHighlighter);
{  function _2TextPosToVirtXY(pos:integer):TPoint;
  function _2VirtXYToTextPos(x,y:integer):cardinal;}
  procedure SetSelText(value:string);
  function GetSelText:string;

  function GetActivWord:TBPWord;

  function GetCaretXPix:integer;
  function GetCaretYPix:integer;
  procedure ShowKibitz;
  procedure Notification(AComponent: TComponent;Operation: TOperation);override;

  procedure WMVScroll(var mes:TWMVScroll);message WM_VScroll;
  procedure WMHScroll(var mes:TWMHScroll);message WM_HScroll;
  destructor destroy; override;

  procedure Undo;
  procedure Redo;
  property canvas;
 published

  property VScroll:integer read fvscroll write SetVScroll;
  property HScroll:integer read fhscroll write SetHScroll;
  property SelText:string read GetSelText write SetSelText;
  property Highlighter:TBenHighlighter read fhighlighter write sethighlighter;
  property CaretXPix:integer read GetCaretXPix;
  property CaretYPix:integer read GetCaretYPix;

  property ShowHint;
  property BevelKind;
  property align;
  property Color;
  property popupmenu;

  property OnKibitzOpen:TKibitzFunc read fkibitzfunc write fkibitzfunc;


  property OnMouseDown;
  property OnMouseMove;
  property OnMouseUp;
  property OnKeyDown;
  property OnKeyPress;
  property OnKeyUp;
//  property FesteZeilenLength:boolean read fsolidlines write SetSolidLines default false;
end;

procedure Register;

implementation
procedure SetColorFont(dc:HDC;font:Tfont;newfont:integer; var aktfont:integer);
begin
 if newfont<>aktfont then begin
  SelectObject(dc,font.handle);
  SetTextColor(dc,font.color);
  aktfont:=newfont;
 end;
end;

function BenTextExtent(dc:HDC;const Text: string): TSize;
begin
  Result.cX := 0;
  Result.cY := 0;
  Windows.GetTextExtentPoint(dc, PChar(Text), Length(Text), Result);
end;

function BenTextWidth(dc:HDC;const Text: string): Integer;
begin
  Result := BenTextExtent(dc,Text).cX;
end;
function BenGetScrollPos(handle:THandle;modus:integer):integer;
var si:TScrollInfo;
begin
si.cbSize:=sizeof(si);
si.fMask:=SIF_POS;
GetScrollInfo(handle,modus,si);
Result:=si.nPos;
end;
procedure TBenKibitz.CloseKibitz;

begin

  if (editor.lines[editor.carety]='') or (editor.lines[editor.carety][editor.caretx] in editor.nonalphas) then
    editor.SelStart:=editor.VirtXYToTextPos(editor.caretx,editor.carety)
   else
    editor.ProcessMessage(BCA_SELWORD,editor.carety,editor.caretx);
  editor.SelText:=list.Items[list.itemindex];
  self.Visible:=false;
end;
procedure TBenKibitz.UpdateWords;
var aktwort:string;
    i,i2:integer;
label lab;
begin
      aktwort:=uppercase(editor.GetActivWord.wort);
      if aktwort<>'' then
        if aktwort[1]='.' then aktwort:=copy(aktwort,2,length(aktwort)-1);
      list.items.BeginUpdate;
      list.items.Assign(items);
      for i:=list.items.Count-1 downto 0 do begin
        for i2:=1 to length(aktwort) do //begin
//          c:=list.items[i][i2];
          if (uppercase(list.items[i][i2])<>aktwort[i2])and (list.items.Count>i2) then begin
            {list.items[i]:='---'; //;}list.items.Delete(i);
            goto lab;//continue;
          end;
//        end;
        lab:
      end;
//    end;
    list.items.EndUpdate;
end;
procedure TBenKibitz.OnKeyDown(sender:TObject;var Key: Word;Shift: TShiftState);
begin
  if assigned(editor) then begin
    if key=13 then
      CloseKibitz;
    if key=vk_escape then
      self.Visible:=false;

    editor.ProcessMessage(BCA_AKTFOCUS,0,0);
    if (key<>vk_next)and(key<>vk_prior)and (key<>vk_home)and(key<>vk_end)and(key<>13)and (key<>vk_escape)and(key<>vk_up) and (key<>vk_down) then
      editor.Perform(WM_KEYDOWN,key,0);
    if (key=vk_left)or(key=vk_right ) then
      key:=0;
  end;
end;
procedure TBenKibitz.OnKeyPress(sender:TObject;var Key: char);
label lab;
begin
  if assigned(editor) then begin
    case key of
      #13,'.','(',')',':',';',' ': CloseKibitz;
    end;
    if (key<>chr(vk_escape))and(key<>#13) then begin
      editor.Perform(WM_CHAR,ord(key),0);
      UpdateWords;
    end;
  end;
//  if (key=vk_left) or (key=vk_right) then key:=#0;
end;
procedure TBenKibitz.OnKeyUp(sender:TObject;var Key: Word;Shift: TShiftState);
begin
  if assigned(editor) then
    if (key<>vk_escape)and(key<>13) then
      editor.Perform(WM_keyup,key,0);
end;
constructor TBenKibitz.CreateEdit;
begin
  CreateNew(aowner);
  Self.BorderStyle:=bsNone;
  self.FormStyle:=fsStayOnTop;
  list:=TListBox.Create(self);
  list.Parent:=self;
  list.Visible:=true;
  list.Align:=alClient;
  list.Items.Text:='a'#13#10'hallo';
  Width:=200;
  Height:=100;
  editor:=aeditor;
  list.OnKeyDown:=OnKeyDown;
  list.OnKeyPress:=OnKeyPress;
  list.OnKeyUp:=OnKeyUp;
  items:=TStringList.create;
end;
procedure TBenKibitz.Loaded;
begin
inherited;
end;
destructor TBenKibitz.destroy;
begin
  list.free;
  items.free;
  inherited;
end;

procedure TBenHighlighter.SetCommentFont(value:TFont);
begin
  fcommentfont.Assign(value);
end;
procedure TBenHighlighter.SetStandardFont(value:TFont);
begin
//  ShowMessage('test');
  fstandardfont.Assign(value);
end;
procedure TBenHighlighter.SetKeyWordFont(value:TFont);
begin
  fkeywordfont.Assign(value);
end;
procedure TBenHighlighter.SetStringFont(value:TFont);
begin
  fstringfont.Assign(value);
end;
procedure TBenHighlighter.SetIntFont(value:TFont);
begin
  fintfont.Assign(value);
end;
procedure TBenHighlighter.SetSybFont(value:TFont);
begin
  fsymbfont.Assign(value);
end;
procedure TBenHighlighter.SetKeyWords(value:TStringList);
begin
  fkeywords.Assign(value);
  fkeywords.Sorted:=true;
  fkeywords.Duplicates:=dupIgnore;
end;
procedure TBenHighlighter.SetHighlight(value:boolean);
begin
  fhighlight:=value;
end;
constructor TBenHighlighter.create;
begin
  inherited;
  fkeywords:=TStringList.create;
  fkeywords.Sorted:=true;
  fkeywords.Duplicates:=dupIgnore;
  fkeywords.Text:='alpha'#13#10'beta'#13#10'gamma';

  fcommentfont:=tfont.create;
  fcommentfont.Name:='Courier New';
  fcommentfont.Height:=-12;
  fcommentfont.Color:=clGray;
  fcommentfont.Style:=[fsItalic];

  fstandardfont:=tfont.create;
  fstandardfont.Name:='Courier New';
  fstandardfont.Height:=-12;
  fstandardfont.Color:=clBlack;

  fkeywordfont:=tfont.create;
  fkeywordfont.Name:='Courier New';
  fkeywordfont.Height:=-12;
  fkeywordfont.Color:=clRed;
  fkeywordfont.Style:=[fsBold];

  fstringfont:=tfont.create;
  fstringfont.Name:='Courier New';
  fstringfont.Height:=-12;
  fstringfont.Color:=clBlack;

  fintfont:=tfont.create;
  fintfont.Name:='Courier New';
  fintfont.Height:=-12;
  fintfont.Color:=clBlue;

  fsymbfont:=tfont.create;
  fsymbfont.Name:='Courier New';
  fsymbfont.Height:=-12;
  fsymbfont.Color:=clBlack;

  fHighlight:=true;
  CommentZeile:='//';
  GCom1Begin:='(*';
  GCom1End:='*)';
  GCom2Begin:='{';
  GCom2End:='}';
  stringBeginEnd:='''';
end;
destructor TBenHighlighter.destroy;
begin
  fcommentfont.Free;
  fstandardfont.Free;
  fkeywordfont.Free;
  fstringfont.Free;
  fintfont.Free;
  fsymbfont.Free;
  fkeywords.free;
  inherited;
end;
constructor TBenMargin.create(aowner:TNewColorMemo);
var i:integer;
begin
  inherited create;
  editor:=aowner;
  width:=50;
  color:=clBtnFace;
  for i:=0 to 9 do
    fmarks[i]:=-1;
end;
function TBenMargin.GetMark(index:integer):TbenMark;
begin
  if (index<0) or (index>9) then
    result:=-1
   else begin
    if fmarks[index]>=editor.lines.count then
      fmarks[index]:=-1;
    result:=fmarks[index]
   end;
end;
procedure TBenMargin.SetMark(index:integer;value:TBenMark);
begin

  if (index>=0) and (index<=9) then
    if value<editor.lines.count then
      fmarks[index]:=value
     else
      fmarks[index]:=-1;
end;
procedure TBenMargin.paintTo;
var paintcolor:COLORREF;
    obrush,brush:HBRUSH;
    open,pen:HPen;
    i,ypos,sypos:integer;
    nummer:string;
begin
//  editor.Canvas.Rectangle(0,0,width,editor.height);
   if color=clbtnface then
     paintcolor:=GetSysColor(COLOR_BTNFACE)
    else
     paintcolor:=color;
   brush:=CreateSolidBrush(paintcolor);
   obrush:=selectobject(dc,brush);
   Rectangle(dc,-10,-10,width,editor.height);
   selectobject(dc,obrush);
   deleteobject(brush);
   pen:=CreatePen(PS_SOLID,1,clGray);
   open:=selectobject(dc,pen);
   MoveToEx(dc,width,0,nil);
   LineTo(dc,width,editor.height);
   selectobject(dc,open);
   deleteobject(pen);
   pen:=CreatePen(PS_SOLID,0,clWhite);
   open:=selectobject(dc,pen);
   MoveToEx(dc,width-1,0,nil);
   LineTo(dc,width-1,editor.height);
   selectobject(dc,open);
   deleteobject(pen);

   SelectObject(dc,editor.fhighlighter.fstandardfont.Handle);
//   SetColorFont(dc,editor.fstandardfont,0,i);
  SetTextColor(dc,editor.fhighlighter.fstandardfont.color);

//   ShowMessage(IntToStr(GetLastError));
   SetBkMode(dc,TRANSPARENT);
   sypos:=-editor.vscroll*editor.charheight+1;
   ypos:=sypos;
   for i:=0 to editor.lines.Count-1 do begin
     if (ypos<editor.height)and(ypos>-editor.charheight) then begin
       nummer:=inttostr(i+1);
       TextOut(dc,width-BenTextWidth(dc,nummer)-2,ypos,pchar(nummer),length(nummer));
     end;
     inc(ypos,editor.charheight);
   end;

   SetBkMode(dc,OPAQUE);
   SetBkColor(dc,clLime);
   for i:=0 to 9 do
     if fmarks[i]<>-1 then begin
       ypos:=sypos+fmarks[i]*editor.charheight;
       if (ypos<editor.height)and(ypos>-editor.charheight) then begin
         nummer:=inttostr(i);
         TextOut(dc,3,ypos,pchar(nummer),1);
       end;
     end;

end;

{procedure TBenColor.SetSolidLines(value:boolean);
begin
  fsolidlines:=value;
  if fsolidlines then begin
    TextPosToVirtXY:=_1TextPosToVirtXY;
    VirtXYToTextPos:=_1VirtXYToTextPos;
    PaintNew:=_1PaintNew;
  end else begin
    TextPosToVirtXY:=_2TextPosToVirtXY;
    VirtXYToTextPos:=_2VirtXYToTextPos;
    PaintNew:=_2PaintNew;
  end;
  ProcessMessage(BCA_UPDATESCROLLBARS,0,0);
  Refresh;
end;}
//Seiteneffekt: Verschiebt Caret!!!!!!
procedure TNewColorMemo.SetHighlighter(value:TBenHighlighter);
begin
 fhighlighter:=value;
 UpdateExAlphas;
 Refresh;
end;
procedure TNewColorMemo.SetSelText(value:string);
var ti:integer;
    p:Tpoint;
begin

  Modifiziert:=true;
  if value <> '' then
    if ord(value[1]) = vk_back then exit;
{if value[1] = chr(vk_escape) then begin
  SelLength:=0;
  exit;
end;}
  if SelLength>0 then begin
     ti:=SelStart;
     lines.text:=copy(lines.text,1,ti)+value+copy(lines.text,ti+SelLength+1,length(lines.text));
     if (length(value)>1)or not (bcsfCaretLeft in fstateflags) then begin
//       if (bcsfCaretLeft in fstateflags) then begin
         p:=TextPosToVirtXY(SelStart+length(value));
{         caretx:=p.x;
         carety:=p.y;
       end else
         p:=TextPosToVirtXY(SelStart-setlength+length(value));}
         caretx:=p.x;
         carety:=p.y;
     end else inc(caretx);
     Exclude(fstateflags,bcsfCaretLeft);
     SelLength:=0;
  end else begin
     ti:=VirtXYToTextPos(caretx,carety);
     lines.text:=copy(lines.text,1,ti)+value+copy(lines.text,ti+1,length(lines.text));
     if length(value)>1 then begin
       p:=TextPosToVirtXY(SelStart+length(value));
       caretx:=p.x;
       carety:=p.y;
     end else
       inc(caretx);
//     caretx:=caretx+length(value);
  end;
      if caretx>length(lines[carety]) then begin
       inc(carety);
       if carety>lines.count-1 then begin carety:=lines.count-1;caretx:=length(lines[carety]);  PaintNew(bmFull,rect(0,0,0,0));exit;end;
       caretx:=0;
     end;
  PaintNew(bmFull,rect(0,0,0,0));;
end;
function TNewColorMemo.GetSelText:string;
begin
  if SelLength>0 then begin
     Result:=copy(lines.text,SelStart+1,SelLength);
  end else
     result:='';
end;
procedure TNewColorMemo.SetScrollMax(scrollbar:cardinal;max:integer);
var scrollinf:TScrollInfo;
begin
  zeromemory(@scrollinf,sizeof(scrollinf));
  scrollinf.cbSize:=sizeof(scrollinf);
  scrollinf.fMask:=SIF_RANGE or SIF_DISABLENOSCROLL or SIF_POS;
  scrollinf.nMax:=max;
  scrollinf.nMin:=0;
  if (scrollbar=sb_vert)then
    scrollinf.nPos:=vscroll
   else
    scrollinf.nPos:=hscroll;
  if (scrollbar=sb_vert) and (max <0) then
    scrollinf.nMax:=0;
  if (scrollbar=sb_horz) and (max <0) then
    scrollinf.nMax:=0;
  SetScrollInfo(handle,scrollbar,scrollinf,true);
end;
function TNewColorMemo.GetScrollMax(scrollbar:cardinal):integer;
var scrollinf:TScrollInfo;
begin
  zeromemory(@scrollinf,sizeof(scrollinf));
  scrollinf.cbSize:=sizeof(scrollinf);
  scrollinf.fMask:=SIF_RANGE;
  GetScrollInfo(handle,scrollbar,scrollinf);
  Result:=scrollinf.nMax;
end;
procedure TNewColorMemo.SetHScroll(pos:integer);
var scrollinf:TScrollInfo;
begin
  zeromemory(@scrollinf,sizeof(scrollinf));
  scrollinf.cbSize:=sizeof(scrollinf);
  scrollinf.fMask:=SIF_POS;
  scrollinf.nPos:=pos;
  fhscroll:=pos;
  SetScrollInfo(handle,SB_HORZ,scrollinf,true);
end;
procedure TNewColorMemo.SetVScroll(pos:integer);
var scrollinf:TScrollInfo;
begin
  zeromemory(@scrollinf,sizeof(scrollinf));
  scrollinf.cbSize:=sizeof(scrollinf);
  scrollinf.fMask:=SIF_POS;
  scrollinf.nPos:=pos;
  fvscroll:=pos;
  SetScrollInfo(handle,SB_VERT,scrollinf,true);
end;
function TNewColorMemo.TextPosToVirtXY;
var y:cardinal;
begin
result:=point(0,0);
for y:=0 to lines.Count-1 do begin
  dec(pos,length(lines[y])+2);
  if pos<= 0 then begin
    Result.x:=length(lines[y])+pos+2;
    Result.y:=y;
    if pos= 0 then
      Result.y:=Result.y+1;
    exit;
  end;
end;
end;
function TNewColorMemo.VirtXYToTextPos;
var i:integer;
begin
 result:=0;
try
for i:=0 to min(y-1,lines.count-1) do
  Result:=Result+length(lines[i])+2;

Result:=Result+x;
except
 result:=0;
end;
end;
function TNewColorMemo.GetActivWord:TBPWord;
var ps,ti,ox,oy:integer;
    xy:TPoint;
    bool:boolean;
begin

      if SelLength=0 then begin
                  ps:=caretx;
                  ox:=caretx;
                  bool:=false;
                  for ti:=ps to length(lines[carety]) do begin
                    if bool and ((lines[carety][ti]in nonalphas)or (lines[carety][ti]=' ')) then
                      break
                     else if lines[carety] <>'' then
                      if not (lines[carety][ti]in nonalphas) then
                         bool:=true;
                    inc(ox);
                  end;
                  oy:=ox; bool:=false;
                    for ti:=ox downto 1 do begin
                    if bool and (lines[carety][ti]in nonalphas) then
                      break
                     else if lines[carety]<>'' then 
                      if not (lines[carety][ti]in nonalphas) then
                         bool:=true;
                    dec(oy);
                  end;
//                  ti:=VirtXYToTextPos(0,carety);
//                  selstart:=ti+oy;
//                  SelLength:=ox-oy-1;
                    Result.x:=oy;
                    Result.l:=ox-oy;
                    result.y:=carety;
     end else begin
                    xy:=TextPosToVirtXY(selstart);
                    Result.x:=xy.x+1;
                    Result.l:=sellength;
                    result.y:=carety;
     end;
                    Result.wort:=copy(lines[carety],Result.x,result.l);
{                  caretx:=TextPosToVirtXY(ox+ti).x-1;
                  PaintNew(bmFull,rect(0,0,0,0));;}
end;
procedure TNewColorMemo.Undo;
begin
  SetLength(redos,high(redos)+2);
  redos[high(redos)].text:=lines.text;
  redos[high(redos)].caretx:=caretx;
  redos[high(redos)].carety:=carety;
  lines.Text:=undos[high(undos)].text;
  caretx:=undos[high(undos)].caretx;
  carety:=undos[high(undos)].carety;
  if high(undos)<>0 then
    SetLength(undos,high(undos));
  undos[high(undos)].carety:=carety;
{  undos[high(undos)].text:=lines.Text;
  undos[high(undos)].caretx:=caretx;
}
end;
procedure TNewColorMemo.Redo;
begin
  if high(redos)<=-1 then exit;
  setlength(undos,high(undos)+2);
  undos[high(undos)].caretx:=caretx;
  undos[high(undos)].carety:=carety;
  undos[high(undos)].text:=lines.text;

  lines.Text:=redos[high(redos)].text;
  caretx:=redos[high(redos)].caretx;
  carety:=redos[high(redos)].carety;
  SetLength(redos,high(redos));
end;
constructor TNewColorMemo.create;
begin
  inherited;
{  TextPosToVirtXY:=_1TextPosToVirtXY;
  VirtXYToTextPos:=_1VirtXYToTextPos;
  PaintNew:=_1PaintNew;}

  SelLength:=0;
  SelStart:=0;
//  fkeywords.Text:='';
  lines:=TStringList.create;
  lines.add('');
//  WordWrap:=False;
//  commentfont:=0;
  nonalphas:=NoAlphaChars;
  UpdateExAlphas;

  canvas.Font.Name:='Courier New';
  canvas.Font.Height:=-12;
  canvas.Font.Color:=clBlack;    

  color:=clWindow;

  width:=300;
  height:=300;
  Visible:=true;
  BevelKind:=bkTile;
  BevelInner:=bvLowered;
  BevelOuter:=bvLowered;
  TabStop:=true;
  carety:=0;
  caretx:=0;
  fstateflags:=[];
  Cursor:=crIBeam;
  fvscroll:=0;fhscroll:=0;
  margin:=TBenMargin.create(self);
  fhighlighter:=nil;
  Modifiziert:=false;
  kibitz:=TBenKibitz.createEdit(application,self);;
  kibitz.Visible:=false;
  SetLength(undos,1);
  undos[0].text:=lines.text;
  undos[0].caretx:=0;
  undos[0].carety:=0;
  SetLength(redos,0);
  charheight:=15;
  charwidth:=5;
end;
procedure TNewColorMemo.CreateParams;
begin
 inherited;
 params.Style:=params.Style or WS_VSCROLL or WS_HSCROLL;
end;
function TNewColorMemo.GetCaretXPix:integer;
begin
//sxpos:=;
  result:=-BenGetScrollPos(handle,SB_HORZ)+1+margin.Width+caretx*canvas.TextWidth('W');
end;
function TNewColorMemo.GetCaretYPix:integer;
begin
  result:=(carety-vscroll)*charheight; //feghler
end;
procedure TNewColorMemo.WMHScroll;
begin
  case Mes.ScrollCode of
    SB_TOP: fhscroll:=0;
    SB_BOTTOM: fhscroll:=lines.count*charheight;
    SB_LINEDOWN: fhscroll:=fhscroll+charheight;
    SB_LINEUP: fhscroll:=fhscroll-charheight;
    SB_PAGEDOWN: fhscroll:=fhscroll+ClientHeight-10;
    SB_PAGEUP: fhscroll:=fhscroll-ClientHeight+10;
    SB_THUMBPOSITION,
    SB_THUMBTRACK: fhscroll := Mes.pos;
 end;
 if fhscroll<0 then fhscroll:=0;
 if fhscroll>GetScrollMax(SB_HORZ) then
   fhscroll:=GetScrollMax(SB_HORZ);
 hscroll:=fhscroll;
 PaintNew(bmFull,rect(0,0,0,0));;
end;
procedure TNewColorMemo.WMVScroll;
begin
  case Mes.ScrollCode of
    SB_TOP: fVScroll:=0;
    SB_BOTTOM: fVScroll:=lines.count;
    SB_LINEDOWN: fVScroll:=fVScroll+1;
    SB_LINEUP: fVScroll:=fVScroll-1;
    SB_PAGEDOWN: fVScroll:=fVScroll+ClientHeight div charheight-10;
    SB_PAGEUP: fVScroll:=fVScroll-ClientHeight div charheight+10;
    SB_THUMBPOSITION,
    SB_THUMBTRACK: begin
                     fVScroll := Mes.pos;
                     if fvscroll<0 then
                       fvscroll:=fvscroll+65534;
                   end;
 end;
 if fvscroll<0 then fvscroll:=0;
 if fvscroll>GetScrollMax(SB_VERT) then
   fvscroll:=GetScrollMax(SB_VERT);
 vscroll:=fvscroll;
 PaintNew(bmFull,rect(0,0,0,0));;
end;
procedure TNewColorMemo.WndProc(var mes:TMessage);
var ss:TShiftState;
    ox,oy,pi,temp:integer;
    s:string;
begin
 case mes.Msg of
   WM_KILLFOCUS: ProcessMessage(BCA_DELFOCUS,0,0);
   WM_SETFOCUS: begin exclude(fstateflags,bcsfInKeyBoardWrite);ProcessMessage(BCA_AKTFOCUS,0,0);ProcessMessage(BCA_UPDATECHARCODES,0,0);end;
   wm_char: begin
              ss:=KeyDataToShiftState(TWMChar(mes).KeyData);
              if not (ssCtrl in ss) then
                SelText:=chr(tWMCHAR(mes).CharCode) //ProcessMessage(BCA_INSERTCHAR,0,tWMCHAR(mes).CharCode);
            end;
   WM_GETDLGCODE: begin
                    TWMGETDLGCODE(mes).Result:=DLGC_WANTALLKEYS or DLGC_HASSETSEL	or DLGC_WANTARROWS	;
                    exit;
                  end;
   WM_KEYDOWN: begin
                include(fstateflags,bcsfInKeyBoardWrite);
                ProcessMessage(BCA_CURSOR, TWMKEYDOWN(mes).CharCode,TWMKEYDOWN(mes).KeyData);
               end;
   WM_KEYUP: begin
//                showmessage('aa');
                exclude(fstateflags,bcsfInKeyBoardWrite);
                ss:=KeyDataToShiftState(TWMkey(mes).KeyData);
                if (carety<>undos[high(undos)].carety)and(lines.text<>undos[high(undos)].text)and(not((TWMkey(mes).CharCode=ord('Z'))and(ssShift in ss))) then begin
                    setlength(undos,high(undos)+2);
                    undos[high(undos)].caretx:=caretx;
                    undos[high(undos)].carety:=carety;
                    undos[high(undos)].text:=lines.text;
                    SetLength(redos,0);
                end;
             end;
   WM_ERASEBKGND:begin
                   mes.Result:=1;
                   exit;
                 end;
   WM_LBUTTONDOWN: ProcessMessage(BCA_MOUSEDOWN,mes.lparam,0);
   WM_MOUSEMOVE: begin
                   if charheight=0 then ProcessMessage(BCA_UPDATECHARCODES,0,0);
                    ox:=(TWMMouseMove(mes).XPos-margin.width+canvas.TextWidth('W')div 2+fhscroll) div canvas.TextWidth('W');
                   oy:=(TWMMouseMove(mes).yPos) div charheight+fvscroll;
                   if ox<0 then
                     ox:=0;
                   pi:=VirtXYToTextPos(ox,oy);
                   if (pi>SelStart) and (pi<selstart+sellength)  then Cursor:=crArrow else cursor:=crIBeam;
                   if TWMMouseMove(mes).Keys and MK_lbutton = MK_lbutton then begin
                     caretx:=ox;
                     carety:=oy;
                     mes.Result:=pi;//VirtXYToTextPos(caretx,carety);
                     if not (bcsfBlockMove in fstateflags)  then begin
                   //    if
                       SelLength:=mes.Result-tempsel;
                       SelStart:=tempsel;
                       if SelLength<0 then begin
                         SelStart:=tempsel+SelLength;
                         SelLength:=-SelLength;
                         Include(fstateflags,bcsfCaretLeft);
                       end else
                         Exclude(fstateflags,bcsfCaretLeft);

                       ox:=GetScrollMax(SB_VERT);
                       if ox>0 then begin
                         pi:=carety*charheight;
                         if pi<VScroll then VScroll:=pi;
                         if pi>(VScroll+2)*charheight+ClientHeight then VScroll:=pi-(VScroll+2)*charheight+ClientHeight;
                       end else if (ox<ClientHeight)and(VScroll<>0) then VScroll:=0;
                       ox:=GetScrollMax(SB_HORZ);
                       if ox>0 then begin
                         oy:=Canvas.TextWidth('M');
                         pi:=caretx*oy;
                         if pi<HScroll then HScroll:=pi;
                         if pi>HScroll+ClientWidth-oy*2-margin.width then hScroll:=pi-ClientWidth+oy+margin.width;
                       end else if (ox<ClientWidth)and(hScroll<>0) then hScroll:=0;
                     end {else begin
                       s:=SelText;
                       SelText:='';
                       SelText:=s;
                     end};
                     if VScroll<0 then VScroll:=0;
                     if HScroll<0 then HScroll:=0;
                     PaintNew(bmFull,rect(0,0,0,0));;
                    end;
//                   ProcessMessage(BCA_akt,mes.lparam,0);
                   end;

   WM_MOUSEWHEEL:begin
                   fVScroll:=(fvscroll-(TWMMouseWheel(mes).WheelDelta div 120));
                   if fvscroll<0 then
                     VScroll:=0
                    else
                     VScroll:=fvscroll;
                   if fvscroll>GetScrollMax(sb_vert) then
                     VScroll:=GetScrollMax(sb_vert)
                    else
                     VScroll:=fvscroll;
                   PaintNew(bmFull,rect(0,0,0,0));;
                 end;
   WM_LBUTTONDBLCLK: begin
                        oy:=(twmlbuttondblclk(mes).YPos) div charheight+vscroll;
                        if oy>=lines.count then oy:=lines.count-1;
                        ProcessMessage(BCA_SELWORD,oy,(twmlbuttondblclk(mes).XPos-margin.width+hscroll) div canvas.TextWidth('H'));
                     end;
   WM_LBUTTONUP: if bcsfBlockMove in fstateflags then begin


                       temp:=TextPosToVirtXY(selstart).y;
                       ox:=(TWMMouseMove(mes).XPos-margin.width+canvas.TextWidth('W') div 2+fhscroll) div canvas.TextWidth('W');
                       oy:=(TWMMouseMove(mes).yPos) div charheight+fvscroll;
                       if oy>=lines.count then oy:=lines.count-1;
//                       pi:=VirtXYToTextPos(ox,oy);
                       pi:=VirtXYToTextPos(ox,oy);
                       if (SelStart<pi)and(selstart+SelLength>pi) then begin
                         SelLength:=0;

                         caretx:=ox;//TextPosToVirtXY(selstart).x;
                         carety:=oy;
                         inherited;
                         EXIT;
                       end;
                       s:=SelText;
                       SelText:='';
                       pi:=VirtXYToTextPos(ox,oy);
//                       if  then
                       if (temp=oy)and(SelStart<pi) then begin
                         if pi-selstart<length(s) then
                           ox:=ox-(pi-selstart)
                          else
                           ox:=ox-length(s);
                       end;
 {                        else
                         SelStart:=pi;}
                       SelLength:=0;

                       caretx:=ox;//TextPosToVirtXY(selstart).x;
                       carety:=oy;
//                       Application
                       SelText:=s;
                       {pi:=SelStart;
                       SelText:=s;
                       SelStart:=ox;
                       SelLength:=oy;
                       SelText:='';
                       SelStart:=pi;}
//                       insert(lines.text,
                     end;
 end;
 inherited;
end;
procedure TNewColorMemo.ProcessMessage;
var
    ti,ox,oy:integer;
    bool:boolean;
    ss:TShiftState;
begin
  case typ of
    BCA_DELFOCUS: DestroyCaret;
    BCA_AKTFOCUS: begin
                     //ProcessMessage(BCA_DELFOCUS,'',0);
                     if not (bcsfInKeyBoardWrite in fstateflags) then
                       CreateCaret(handle,0,2,charheight);
                     SetCaretPos(margin.width+caretx*(Canvas.TextWidth('W'))+1-fHScroll,(carety-fvscroll)*charheight);
                     ShowCaret(handle);
                  end;
    BCA_UPDATECHARCODES: begin
                           if fhighlighter<>nil then
                             canvas.font.Assign(fhighlighter.fstandardfont);
                           charheight:=Canvas.TextHeight('H,');
                           charwidth:=Canvas.TextWidth('W');
                         end;
{    BCA_INSERTCHAR: begin
                     if (bcsfInSelWriteFunc in fstateflags) then exit;
                     Include(fstateflags,bcsfInSelWriteFunc);
                     try
                      if (ps=vk_back) then begin
                        if caretx>0 then begin
                          dec(caretx);
                          lines[carety]:=copy(lines[carety],1,caretx)+copy(lines[carety],caretx+2,length(lines[carety])-caretx);
                        end else begin
                          if carety<=0 then exit;
                          dec(carety);
                          caretx:=length(lines[carety]);
                          lines[carety]:=lines[carety]+lines[carety+1];
                          lines.delete(carety+1);
                        end;
//                        insert(chr(mes.CharCode),text,curpos+1);
                      end else if (ps=vk_return) then begin
                        ts:=lines[carety];
                        lines[carety]:=copy(lines[carety],1,caretx);//+ps+copy(lines[carety],caretx,length(lines[carety])-caretx+1);
                        lines.Insert(carety+1,copy(ts,caretx+1,length(ts)-caretx+1));
                        caretx:=0;
                        inc(carety);
                      end else begin
                        inc(caretx);
                        ts:=lines.strings[carety];
                        insert(chr(ps),ts,caretx);
                        lines.strings[carety]:=ts;
//                        lines[carety]:=copy(lines[carety],1,caretx-1)+ps+copy(lines[carety],caretx,length(lines[carety])-caretx+1);
                      end;
 //                     if carety>lines.count-1 then carety:=lines.count-1;
                      if carety<0 then carety:=0;
{                      if caretx>length(lines[carety]) then begin
//                         if (pi<>vk_up)and(pi<>vk_down) then
                           inc(carety);
                           caretx:=0;
                           if carety>lines.count-1 then begin carety:=lines.count-1;caretx:=length(lines[carety]);{if caretx<0 then caretx:=0exit;end;
   {                      end else
                           caretx:=length(lines[carety]);
                      end;                                }
 {                     if caretx<0 then begin
                        dec(carety);
                        if carety<0 then begin caretx:=0;carety:=0;exit;end;
                        caretx:=length(lines[carety]);
                      end;
//                      ProcessMessage(BCA_AKTFOCUS,'',0);
                      ProcessMessage(BCA_UPDATESCROLLBARS,0,0);
                      PaintNew(bmFull,rect(0,0,0,0));;
                     finally
                      Exclude(fstateflags,bcsfInSelWriteFunc);
                     end;
                    end;}
    BCA_CURSOR: begin
                  if pi=vk_escape then
                    SelLength:=0;
                  ss:=KeyDataToShiftState(ps);
                      if ssShift in ss then
                      case pi of
                        VK_INSERT: if Clipboard.HasFormat(CF_TEXT) then SelText:=Clipboard.AsText;
                        VK_DELETE: begin Clipboard.SetTextBuf(pchar(seltext));SelText:=''; end;
                      end;
                  ox:=caretx;oy:=carety;
                  case pi of
                    VK_LEFT: dec(caretx);
                    vk_RIGHT: inc(caretx);
                    VK_UP: dec(carety);
                    VK_DOWN: inc(carety);
                    VK_DELETE:
                                if SelLength>0 then SelText:=''
                                else begin
                                 if caretx<length(lines[carety]) then
                                   lines[carety]:=copy(lines[carety],1,caretx)+copy(lines[carety],caretx+2,length(lines[carety])-caretx+1)
                                  else begin
                                   if carety+1>=lines.count then  exit;
                                   lines[carety]:=lines[carety]+lines[carety+1];
                                   lines.Delete(carety+1);
                                  end;
                               end;
                    VK_BACK:
                        if SelLength>0 then SelText:=''
                        else
                        if caretx>0 then begin
                          dec(caretx);
                          lines[carety]:=copy(lines[carety],1,caretx)+copy(lines[carety],caretx+2,length(lines[carety])-caretx);
                        end else begin
                          if carety<=0 then exit;
                          dec(carety);
                          caretx:=length(lines[carety]);
                          lines[carety]:=lines[carety]+lines[carety+1];
                          lines.delete(carety+1);
                        end;

                    VK_HOME: begin if ssCtrl in ss then carety:=0; caretx:=0;end;
                    VK_END:  begin if ssCtrl in ss then carety:=lines.count-1; caretx:=length(lines[carety]);end;
                    VK_PRIOR:begin carety:=carety-ClientHeight div charheight; if carety<0 then carety:=0;end;
                    VK_NEXT:begin carety:=carety+ClientHeight div charheight; if carety>lines.count-1 then carety:=lines.count-1;end;
                  end;
                    if ssCtrl in ss then begin
                      if ssAlt in ss then begin
                        case pi of
                          ord('8'): SelText:='['; 
                          ord('9'): SelText:=']';
                          ord('7'): SelText:='{';
                          ord('0'): SelText:='}';
                          219: SelText:='\';
                          187: SelText:='~';
                          226: SelText:='|';
                          ord('2'): SelText:='²';
                          ord('3'): SelText:='³';
                          189: SelText:='±';
                          ord('L'): SelText:='£';

                          ord('O'): SelText:='Ø';
                          ord('A'): SelText:='Æ';
                          ord('M'): SelText:='µ';
                          ord('E'): SelText:='€';
                          ord('C'): SelText:='©';
                          ord('R'): SelText:='®';
                          ord('Y'): SelText:='¥';

                          ord('T'): SelText:='™';
                          ord('F'): SelText:='ƒ';
                          ord('Q'): SelText:='@';
                          ord('X'): SelText:='×';
                        end;
                      end;
                      case pi of
                        ord('V'): if Clipboard.HasFormat(CF_TEXT) then SelText:=Clipboard.AsText;
                        ord('C'): Clipboard.SetTextBuf(pchar(seltext));
                        ord('X'): begin Clipboard.SetTextBuf(pchar(seltext));SelText:=''; end;
                        ord('0')..ord('9'):if ssShift in ss then
                                             margin.marks[StrToInt(chr(pi))]:=carety
                                            else
                                             if margin.marks[StrToInt(chr(pi))]<>-1 then
                                              carety:=margin.marks[StrToInt(chr(pi))];
                        vk_space: ShowKibitz;
                        VK_LEFT:
                                   for ti :=caretx downto 0 do
                                     if (lines[carety][ti] in nonalphas) or (ti=0) then begin          
                                       caretx:=ti;
                                       break;
                                     end;
                        VK_right:
                                   for ti :=caretx to length(lines[carety]) do
                                     if (lines[carety][ti] in nonalphas)or(ti>=length(lines[carety])) then begin
                                       caretx:=ti;
                                       break;
                                     end;
                        ord('Z'):
                                    if not (ssshift in ss) then
                                      undo
                                     else
                                      redo;


                      end;

                    end;
                      if carety>lines.count-1 then carety:=lines.count-1;
                      if carety<0 then carety:=0;
                      if caretx>length(lines[carety]) then
                         if (pi<>vk_up)and(pi<>vk_down) then begin
                           inc(carety);
                           caretx:=0;
                           if carety>lines.count-1 then begin
                             carety:=lines.count-1;
                             caretx:=length(lines[carety]);
                             exit;
                           end;
                         end else
                           caretx:=length(lines[carety]);
                   //   end;
                      if caretx<0 then begin
                        dec(carety);
                        if carety<0 then begin caretx:=0;carety:=0;exit;end;
                        caretx:=length(lines[carety]);
                      end;

                  if (pi=vk_left) or (pi=vk_right)or(pi=vk_up)or(pi=vk_down)or(pi=vk_end)or(pi=vk_home) then
                    if ssShift in ss then begin //Markierungsfunktion
                      if pi<>VK_SHIFT{16} then begin
                        if SelLength=0 then begin //Wenn nichts markiert ist, neu markieren
                          case pi of
                            VK_LEFT: begin
                                       if ssCtrl in ss then begin
                                         SelStart:=VirtXYToTextPos(caretx,carety);
                                         SelLength:=VirtXYToTextPos(ox,oy) -SelStart;
                                         Include(fstateflags,bcsfCaretLeft);
                                        end else begin
                                         SelStart:=VirtXYToTextPos(caretx,carety);
                                         SelLength:=1;
                                         Include(fstateflags,bcsfCaretLeft);
                                       end;
                                     end;
                            vk_up: begin
                                     SelStart:=VirtXYToTextPos(caretx,carety);
                                     SelLength:=VirtXYToTextPos(ox,oy)-selstart;
                                     Include(fstateflags,bcsfCaretLeft);
                                   end;
                            vk_down: begin
                                       SelStart:=VirtXYToTextPos(ox,oy);
                                       SelLength:=VirtXYToTextPos(caretx,carety)-selstart;
                                       Exclude(fstateflags,bcsfCaretLeft);
                                     end;
                           vk_RIGHT: begin
                                       if ssCtrl in ss then begin
                                         SelStart:=VirtXYToTextPos(ox,oy);
                                         SelLength:= VirtXYToTextPos(caretx,carety)-SelStart;
                                         Exclude(fstateflags,bcsfCaretLeft);
                                       end else begin
                                         SelStart:=VirtXYToTextPos(caretx,carety)-1;
                                         SelLength:=1;
                                         Exclude(fstateflags,bcsfCaretLeft);
                                       end;
                                     end;
                           VK_HOME: begin
                                      SelStart:=VirtXYToTextPos(caretx,carety);
                                      SelLength:=VirtXYToTextPos(ox,oy)-SelStart;
                                      Include(fstateflags,bcsfCaretLeft);
                                    end;
                           VK_END: begin
                                      SelStart:=VirtXYToTextPos(ox,oy);
                                      SelLength:=VirtXYToTextPos(caretx,carety)-SelStart;
                                    end;
                          end;
                        end else //Wenn etwas markiert ist
                          case pi of
                            vk_left,vk_right,vk_down,vk_up:
                                    if bcsfCaretLeft in fstateflags then begin
                                      ox:=SelStart;
                                      SelStart:=VirtXYToTextPos(caretx,carety);
                                      SelLength:=SelLength+(ox-selstart);
//                                      Showmessage(IntToStr(sellength));
                                      if sellength<0 then begin
                                          sellength:=-sellength;
                                          selstart:=selstart-sellength;
                                          exclude(fstateflags,bcsfCaretLeft);
                                      end;
//_                                      dec(SelLength);
                                    end else begin
                                      SelLength:=VirtXYToTextPos(caretx,carety)-SelStart;
                                      if sellength<0 then begin
                                          sellength:=-sellength;
                                          selstart:=selstart-sellength;
                                          include(fstateflags,bcsfCaretLeft);
                                        end;
                                    end;
                            vk_home:
                                    if bcsfCaretLeft in fstateflags then begin
                                      ox:=SelStart;
                                      SelStart:=VirtXYToTextPos(caretx,carety);
                                      SelLength:=SelLength+(ox-selstart);
//_                                      dec(SelLength);
                                    end else begin
                                     { ox:=SelStart;
                                      selstart:=VirtXYToTextPos(caretx,carety);
                                      SelLength:={selstart+(ox-SelStart);}
                                      ox:={(SelStart+SelLength)-}VirtXYToTextPos(caretx,carety)-SelStart;
                                      if ox<0 then begin
                                        SelStart:=SelStart+ox;
                                        SelLength:=-ox;
                                        Include(fstateflags, bcsfCaretLeft);
                                      end else SelLength:=ox;
                                    end;
                            vk_end:
                                    if bcsfCaretLeft in fstateflags then begin
                                      if pos(#13,seltext)>0 then begin
                                         ox:=SelStart;
                                         SelStart:=VirtXYToTextPos(caretx,carety);
                                         SelLength:=SelLength+(ox-selstart)
                                       end else begin
                                         SelStart:=SelStart+SelLength;
                                         SelLength:=VirtXYToTextPos(caretx,carety)-SelStart;
                                         Exclude(fstateflags,bcsfCaretLeft);
                                       end;
//_                                      dec(SelLength);
                                    end else begin
                                     { ox:=SelStart;
                                      selstart:=VirtXYToTextPos(caretx,carety);
                                      SelLength:={selstart+(ox-SelStart);}
                                      ox:={(SelStart+SelLength)-}VirtXYToTextPos(caretx,carety)-SelStart;
                                      if ox<0 then begin
                                        SelStart:=SelStart+ox;
                                        SelLength:=-ox;
                                        Include(fstateflags, bcsfCaretLeft);
                                      end else SelLength:=ox;
                                    end;
                         end;
          //            ShowMessage(INtToStr(textPosToVirtXY(SelLength).x)+':'+INtToStr(textPosToVirtXY(SelLength).y));
                     end;

                  end else  begin //Wenn Shift nicht gedrückt ist
                              Exclude(fstateflags,bcsfCaretLeft);
                              //SelStart:=VirtXYToTextPos(caretx,carety);
                              case pi of
                                vk_left: dec(selstart);
                                vk_right: inc(selstart);
                                vk_end,vk_home,vk_up,vk_down: SelStart:=VirtXYToTextPos(caretx,carety);
                              end;
                              SelLength:=0;
                            end;

                  if (pi=vk_return)or(ssLeft in ss)or (ssCtrl in ss) then
                    ProcessMessage(BCA_UPDATESCROLLBARS,0,0)
                   else
                    ProcessMessage(BCA_UPDATESCROLLBARS,0,-1);
                  ox:=GetScrollMax(SB_VERT);
                  if ox>0 then begin
                 {   pi:=carety*charheight;
                    if pi<VScroll then VScroll:=pi;
                    if pi>(VScroll)*charheight+ClientHeight-2 then
                      VScroll:=carety-ClientHeight div charheight+2;
                    if VScroll<0 then VScroll:=0;}
                    pi:=carety;
                    if pi<VScroll then VScroll:=pi;
                    if pi>VScroll+ClientHeight div charheight-1 then
                      VScroll:=carety-ClientHeight div charheight+1 ;
                    if VScroll<0 then VScroll:=0;
                  end else if (ox<ClientHeight)and(VScroll<>0) then VScroll:=0;
                  ox:=GetScrollMax(SB_HORZ);
                  if ox>0 then begin
                    oy:=Canvas.TextWidth('M');
                    pi:=caretx*oy;
                    if pi<HScroll then HScroll:=pi;
                    if pi>HScroll+ClientWidth-oy*2-margin.width then hScroll:=pi-ClientWidth+oy{+oy*2}+margin.width;
                  end else if (ox<ClientWidth)and(hScroll<>0) then hScroll:=0;
                  if lines.count=-1 then lines.add('');
                  PaintNew(bmFull,rect(0,0,0,0));;
                end;
{    BCA_CHECKCARET: begin
                      if carety>lines.count-1 then carety:=lines.count-1;
                      if carety<0 then carety:=0;
                      if caretx>length(lines[carety]) then begin
                         inc(carety);
                         caretx:=0;
                         if carety>lines.count-1 then begin carety:=lines.count-1;caretx:=length(lines[carety]);if caretx<0 then caretx:=0;exit;end;
                      end;
                      if caretx<0 then begin
                        dec(carety);
                        if carety<0 then begin caretx:=0;carety:=0;exit;end;
                        caretx:=length(lines[carety]);
                      end;
                      if carety<0 then carety:=0;
                      if carety>lines.count-1 then carety:=lines.count-1;
                    end;}
     BCA_MOUSEDOWN: begin
                      if not Focused then begin parent.SetFocus;SetFocus;end;
                      if charheight=0 then
                        ProcessMessage(BCA_UPDATECHARCODES,0,0);
                      carety:=(HIWORD(pi)) div charheight+fvscroll;
                      caretx:=(LOWORD(pi)-margin.width+canvas.TextWidth('W')div 2+fhscroll) div canvas.TextWidth('W');
                      if carety>=lines.count then carety:=lines.count-1;
                      if caretx>length(lines[carety]) then caretx:=length(lines[carety]);
                      if caretx<0 then caretx:=0;
                      ti:=VirtXYToTextPos(caretx,carety);
                      if not((ti>selstart) and (ti<selstart+sellength)) then begin
                        SelStart:=ti;
                        tempsel:=SelStart;
                        SelLength:=0;
                        exclude(fstateflags,bcsfBlockMove);
                      end else Include(fstateflags,bcsfBlockMove);
                      ox:=GetScrollMax(SB_VERT);
                      if ox>0 then begin
                        pi:=carety*charheight;
                        if pi<VScroll then VScroll:=pi;
                        if pi>(VScroll)*charheight+ClientHeight-2 then
                         VScroll:=carety-ClientHeight div charheight+2;
                      if VScroll<0 then VScroll:=0;
                      end else if (ox<ClientHeight)and(VScroll<>0) then VScroll:=0;
                      ox:=GetScrollMax(SB_HORZ);
                      if ox>0 then begin
                        oy:=Canvas.TextWidth('M');
                        pi:=caretx*oy;
                        if pi<HScroll then HScroll:=pi;
                        if pi>HScroll+ClientWidth-oy*2-margin.width then
                          hScroll:=pi-ClientWidth+oy+margin.width;
                     end else if (ox<ClientWidth)and(hScroll<>0) then hScroll:=0;
                     //ProcessMessage(BCA_AKTFOCUS,0,0);
                     PaintNew(bmFull,rect(0,0,0,0));;
                    end;
     BCA_UPDATESCROLLBARS: begin
//                            pi:=GetScrollMax(SB_VERT);
                            SetScrollMax(SB_VERT,lines.count -clientheight div charheight+1);
                            ps:=Canvas.TextWidth('W');
                            pi:=0;
                             //if ps<>-1 then begin
                                 for ti:=0 to lines.count-1 do
                                    if pi<=length(lines[ti])*ps then
                                      pi:=length(lines[ti])*ps;
//                                    pi:=max(pi,);
                                 SetScrollMax(SB_HORZ,pi-clientwidth+margin.width+Canvas.TextWidth('H'));
                             //end;
                          end;
    BCA_SELWORD:begin
                  carety:=pi;
                  ox:=ps;
                  bool:=false;
                  for ti:=ps to length(lines[carety]) do begin
                    if bool and ((lines[carety][ti]in nonalphas)or (lines[carety][ti]=' ')) then
                      break
                     else

                      if lines[carety]<>'' then
                      if not ((lines[carety][ti]in nonalphas)or (lines[carety][ti]=' ')) then
                         bool:=true;
                    inc(ox);
                  end;
                  oy:=ox; bool:=false;
                    for ti:=ox downto 1 do begin
                    if bool and (lines[carety][ti]in nonalphas) then
                      break
                     else if lines[carety] <>'' then
                      if not (lines[carety][ti]in nonalphas) then
                         bool:=true;
                    dec(oy);
                  end;
                  ti:=VirtXYToTextPos(0,carety);
                  selstart:=ti+oy;
                  SelLength:=ox-oy-1;

                  caretx:=TextPosToVirtXY(ox+ti).x-1;
                  PaintNew(bmFull,rect(0,0,0,0));;
                end;
  end;
end;
procedure TNewColorMemo.UpdateExAlphas;
var i,j:integer;
begin
exalphas:=nonalphas;
if fhighlighter<>nil then begin
exclude(exalphas, fhighlighter.stringBeginEnd);
for i:=1 to length(fhighlighter.GCom1Begin) do
   exclude(exalphas,fhighlighter.GCom1Begin[i]);
for i:=1 to length(fhighlighter.GCom1End) do
   exclude(exalphas,fhighlighter.GCom1end[i]);
for i:=1 to length(fhighlighter.CommentZeile) do
   exclude(exalphas,fhighlighter.CommentZeile[i]);
for i:=1 to length(fhighlighter.GCom2Begin) do
   exclude(exalphas,fhighlighter.GCom2Begin[i]);
for i:=1 to length(fhighlighter.GCom2End) do
   exclude(exalphas,fhighlighter.GCom2end[i]);
if fhighlighter.fSymbolKey then begin
  befehlsAlphas:=nonalphas;
  for i:=0 to fhighlighter.KeyWords.Count -1 do
    for j:=1 to length(fhighlighter.KeyWords[i]) do
      exclude(befehlsAlphas,fhighlighter.KeyWords[i][j]);
end;
end;
end;
procedure TNewColorMemo.PaintNew;
var rec:TRect;
    x,xpos,sxpos,a,ypos,lz,temp:integer;
    s{,con}:string;
    tenp:boolean;
    textan,comment,groscom,zgroscom:boolean;
    wdc,dc:HDC;
    hintergrundbrush,oldbrush:HBRUSH;
    refcol:COLORREF;
    aktfont:integer;
    aktchar:char; //Zeichenposition
    zeile:string;
    bmp,oldbmp:HBITMAP;
    cx, cy:integer;
    aktpos:integer;// Pos in text
    oalpha,alpha:byte;
    ss,se:integer;//Selstart, Selend
    p:TPoint;//Nimmt CaretPosition
    o_insel,zinsel,inSel:boolean;//Aktueller Buchstabe selektiert
    von, bis:cardinal;//Zu kopierender Bereich
    _a,_b,_c,_d,_e,_aa,_bb,_cc,_dd,_ee:integer;//temporäre Variablen
  label endlab;
begin
 if bcsfInPaintFunc in  fstateflags then exit;
 if fhighlighter=nil then begin
   Canvas.Brush.Color:=color;
   Canvas.Rectangle(0,0,width,height);
   canvas.Font.Color:=clRed;
   canvas.TextOut(margin.width+10,0,'KEIN HIGHLIGHTER DEFINIERT!!!!!!!!!!!!');
//   margin.paintTo(canvas.handle);
   canvas.Font.Color:=clBlack;
   exit;
 end;
{ if painting then
   FileWrite('true','C:\textdebug.dat');            }
//    Perform(WM_NCPAINT,0,0);
 include(fstateflags,bcsfInPaintFunc);
      wdc:=GetDC (handle);
 try
    //  margin.paint;
   //   if Focused then ProcessMessage(BCA_AKTFOCUS,0,0);
      dc:=CreateCompatibleDC(wdc);
      bmp:=CreateCompatibleBitmap(wdc,clientwidth,clientheight);
      oldbmp:=SelectObject(dc,bmp);
      //
      ypos:=-vscroll*charheight-charheight+1 ;//-BenGetScrollPos(handle,SB_VERT)*charheight;
//  dc:=bmp.Canvas.Handle;//:=GetDC (handle);//bmp.Canvas.Handle;
//    if paint.fErase then begin
    if (modus=bmFull) then begin
      rec.left:=margin.width;
      rec.top:=0;
      rec.Right:=width;
      rec.bottom:=height;
    end else if (modus=bmcaret) then begin
//      p:=GetCaretPos;
      p.y:=p.y*charheight;
      rec.left:=margin.width;
      rec.top:=p.y-charheight*2;
      rec.Right:=width;
      rec.bottom:=p.y+charheight*2;
    end else
      rec:=viewingrect;
 if (color<> clWindow)and(color<> clBtnFAce) then
   refcol:=color
  else
   refcol:=GetSysColor(color_window);
//  SetBkColor(dc,GetSysColor(COLOR_HIGHLIGHT));
   HideCaret(handle);
{
   if Focused or kibitz.list.Focused then
     ProcessMessage(BCA_AKTFOCUS,0,0);
}
  SetBkColor(dc,clAqua);
  SetBkMode(dc,TRANSPARENT);
  hintergrundbrush:=CreateSolidBrush(refcol);
  oldbrush:=SelectObject(dc,hintergrundbrush);
  fillrect(dc,rec,hintergrundbrush);
  if (bcsfInKeyBoardWrite in fstateflags) then begin
    //cx/cy benutzt als Caretpos
    cx:=margin.width+caretx*(Canvas.TextWidth('W'))+1-fHScroll;
    cy:=(carety-fvscroll)*charheight;
    MoveToEx(dc,cx,cy,nil);
    LineTo(dc,cx,cy+charHeight);
    LineTo(dc,cx+1,cy+charHeight);
    LineTo(dc,cx+1,cy);
    //--------cx/cy nicht mehr benutzt als Caretpos------------
  end;
//  Perform(WM_NCPAINT,0,0);
  aktfont:=-1;
//    brush.style:=bsClear;
sxpos:=-BenGetScrollPos(handle,SB_HORZ)+1+margin.Width;
groscom:=false;zgroscom:=false;ss:=SelStart-1;se:=ss+1+SelLength;aktpos:=0;
inSel:=false;
rec.top:=rec.top-charheight;
 if fhighlighter.fhighlight then begin
    for a:=0 to lines.count-1 do begin

      ypos:=ypos+charheight;
      if (ypos>rec.bottom) then break;
      zeile:=lines[a]+#0;
      lz:=length(zeile);
      if (ypos<rec.top) then begin
         aktpos:=aktpos+lz+1;
//         _a:=length(fhighlighter.fCommentZeile);
         _b:=length(fhighlighter.fGCom2Begin);
         _c:=length(fhighlighter.fGCom2End);
         _d:=length(fhighlighter.fGCom1Begin);
         _e:=length(fhighlighter.fGCom1End);
         {_aa:=_a;}_bb:=_b;_cc:=_c;_dd:=_d;_ee:=_e;
         for _a:=lz downto 1 do begin
            aktchar:=zeile[_a];
            if fhighlighter.fGCom2Begin[_bb]=aktchar then begin
              dec(_bb);
              if _bb=0 then begin
                zgroscom:=true;
                groscom:=true;
                break;
              end;
            end else if _bb<>_b then _bb:=_b;
            if fhighlighter.fGCom2End[_cc]=aktchar then begin
              dec(_cc);
              if _cc=0 then begin
                zgroscom:=false;
                groscom:=false;
                break;
              end;
            end else if _cc<>_c then _cc:=_c;
            if fhighlighter.fGCom1Begin[_dd]=aktchar then begin
              dec(_dd);
              if _dd=0 then begin
                zgroscom:=true;
                groscom:=true;
                break;
              end;
            end else if _dd<>_d then _dd:=_d;
            if fhighlighter.fGCom1End[_ee]=aktchar then begin
              dec(_e);
              if _ee=0 then begin
                zgroscom:=false;
                groscom:=false;
                break;
              end;
            end else if _ee<>_e then _ee:=_e;
        end;
        continue;
      end;
      s:='';von:=1;bis:=0;xpos:=sxpos;;      tenp:=false;comment:=false;textan:=false;

      if lz>0 then
      if (zeile[1] in nonalphas)  then begin
        alpha:=1;
        if not(zeile[1] in exalphas) then alpha:=2;
        if fhighlighter.fSymbolKey and not (zeile[1] in befehlsAlphas) then alpha:=0;
       end else
        alpha:=0;
      for x:=1 to lz do begin
        aktchar:=zeile[x];
        oalpha:=alpha;
      if (aktchar in nonalphas)  then begin
        alpha:=1;
        if not(aktchar in exalphas) then alpha:=2;
        if fhighlighter.fSymbolKey and not (aktchar in befehlsAlphas) then alpha:=0;
       end else
        alpha:=0;

          if oalpha<> alpha then begin

            s:=copy(zeile,von,bis);
            tenp:=true;
          if oalpha=2 then begin
            if comment or groscom=false then
             if (pos(fhighlighter.stringBeginEnd,s)>0)  then
                 textan:=not textan;

            if textan=false then begin
                if (pos(fhighlighter.CommentZeile,s)>0) then
                   comment:=true;

              if comment=false then begin
                if (pos(fhighlighter.GCom1Begin,s)>0) or (pos(fhighlighter.GCom2Begin,s)>0) then begin groscom:=true;zgroscom:=true; end;
                if (pos(fhighlighter.GCom1End,s)>0) or (pos(fhighlighter.GCom2End,s)>0) then zgroscom:=false;
              end;
            end;
            end;
          end;

          o_insel:=inSel;
          zinSel:= (aktpos< se)and(aktpos>Ss) ;

        if ((tenp)or(o_insel <> zinsel)or(x=lz)) then begin
         if (xpos<clientwidth){and(xpos>0)} then begin
         if s='' then
         s:=copy(zeile,von,bis);
         if comment or groscom then
          SetColorFont(dc,fhighlighter.fcommentfont,1,aktfont)
         else if (oalpha>0) then
           SetColorFont(dc,fhighlighter.fsymbfont,5,aktfont)
          else if (textan) then
            SetColorFont(dc,fhighlighter.fstringfont,0,aktfont)
           else
             if fhighlighter.fkeywords.IndexOf(s)>-1 then
                SetColorFont(dc,fhighlighter.fkeywordfont,2,aktfont)
               else if StrToInt64Def(s,low(integer))<>low(integer) then
                  SetColorFont(dc,fhighlighter.fintfont,3,aktfont)
               else

                  SetColorFont(dc,fhighlighter.fstandardfont,4,aktfont);
//Weihnachtsbaum:             SetTextColor(dc,rgb(random(255),random(255),random(255)));
             TextOut(dc,xpos,ypos,pchar(s),length(s));
//             inc(xpos,BenTextWidth(dc,s));
             inc(xpos,length(s)*charwidth);
             s:='';

           end;
        //  end;
          tenp:=false;
          inc(von,bis);bis:=0;
        end;
        groscom:=zgroscom;
        //s:=s+aktchar;
        inc(bis);
        inc(aktpos);
          inSel:=zinsel;
         if (o_inSel <> inSel) then
           if inSel then
              SetBkMode(dc,OPAQUE)
             else
              SetBkMode(dc,TRANSPARENT);
      end;
      inc(aktpos);
    end;

//  SelectObject(dc,bmp);
  end else begin
    s:=lines.Text;
    SetColorFont(dc,fhighlighter.fstandardfont,4,aktfont);
    rec:=Rect(sxpos,ypos+charheight,clientwidth,ClientHeight);
    DrawText(dc,pchar(s),length(s),rec,DT_LEFT );
  end;
  margin.paintTo(dc);
  BitBlt(wdc,0,0,clientwidth,clientheight,dc,0,0,SRCCOPY);
  SelectObject(dc,oldfont);
  SelectObject(dc,oldbrush);
  SelectObject(dc,oldbmp);
  DeleteObject(bmp);
  DeleteObject(hintergrundbrush);
  DeleteDC(dc);
 // BitBlt(wdc,0,0,clientwidth,clientheight,dc,0,0,SRCCOPY);

//  ShowMessage(IntToStr(getlasterror));
//  ShowScrollBar(handle,SB_BOTH,false);
//  ShowScrollBar(handle,SB_BOTH,true);
  //margin.paint;
//  bmp.free;
  finally
   ReleaseDC(handle,wdc);
   exclude(fstateflags,bcsfInPaintFunc);

   if Focused or kibitz.list.Focused then
     ProcessMessage(BCA_AKTFOCUS,0,0);

  end;
end;
{procedure TNewColorMemo._2PaintNew;
var rec:TRect;
    x,xpos,sxpos,a,ypos,lz,temp:integer;
    s{,con:string;
    tenp:boolean;
    textan,comment,groscom,zgroscom:boolean;
    wdc,dc:HDC;
    hintergrundbrush,oldbrush:HBRUSH;
    refcol:COLORREF;
    aktfont:integer;
    aktchar:char; //Zeichenposition
    zeile:string;
    bmp,oldbmp:HBITMAP;
    cx, cy:integer;
    aktpos:integer;// Pos in text
    oalpha,alpha:byte;
    ss,se:integer;//Selstart, Selend
    p:TPoint;//Nimmt CaretPosition
    o_insel,zinsel,inSel:boolean;//Aktueller Buchstabe selektiert
    von, bis:cardinal;//Zu kopierender Bereich
  label endlab;
begin
 if bcsfInPaintFunc in  fstateflags then exit;
{ if painting then
   FileWrite('true','C:\textdebug.dat');
//    Perform(WM_NCPAINT,0,0);
 include(fstateflags,bcsfInPaintFunc);

      wdc:=GetDC (handle);
 try
    //  margin.paint;
   //   if Focused then ProcessMessage(BCA_AKTFOCUS,0,0);
      dc:=CreateCompatibleDC(wdc);
      bmp:=CreateCompatibleBitmap(wdc,clientwidth,clientheight);
      oldbmp:=SelectObject(dc,bmp);
      //
      ypos:=-vscroll-charheight+1 ;//-BenGetScrollPos(handle,SB_VERT)*charheight;
//  dc:=bmp.Canvas.Handle;//:=GetDC (handle);//bmp.Canvas.Handle;
//    if paint.fErase then begin
    if (modus=bmFull) then begin
      rec.left:=margin.width;
      rec.top:=0;
      rec.Right:=width;
      rec.bottom:=height;
    end else if (modus=bmcaret) then begin
//      p:=GetCaretPos;
      p.y:=p.y*charheight;
      rec.left:=margin.width;
      rec.top:=p.y-charheight*2;
      rec.Right:=width;
      rec.bottom:=p.y+charheight*2;
    end else
      rec:=viewingrect;
 if color<> clWindow then
   refcol:=color
  else
   refcol:=GetSysColor(color_window);
//  SetBkColor(dc,GetSysColor(COLOR_HIGHLIGHT));
  HideCaret(handle);
  SetBkColor(dc,clAqua);
(*  SetBkMode(dc,TRANSPARENT);
  hintergrundbrush:=CreateSolidBrush(refcol);
  oldbrush:=SelectObject(dc,hintergrundbrush);
  fillrect(dc,rec,hintergrundbrush);
//  Perform(WM_NCPAINT,0,0);
  aktfont:=-1;
//    brush.style:=bsClear;
sxpos:=-BenGetScrollPos(handle,SB_HORZ)+1+margin.Width;
groscom:=false;zgroscom:=false;ss:=SelStart-1;se:=ss+1+SelLength;aktpos:=0;
inSel:=false;
rec.top:=rec.top-charheight;
    for a:=0 to lines.count-1 do begin

      ypos:=ypos+charheight;
      if (ypos>rec.bottom) then break;
      zeile:=lines[a]+#0;
      lz:=length(zeile);
      if (ypos<rec.top) then begin
         aktpos:=aktpos+lz+1;
         if groscom=false then
           temp:=max(pos(GCom2Begin,zeile),pos(GCom1Begin,zeile)) //Temp: Kommentar Begi
          else
           temp:=0;
         if groscom then
           xpos:=max(pos(GCom2End,zeile),pos(GCom1End,zeile))   //(xpos)Temp: Kommentar Ende
          else
           xpos:=0;
         if temp=xpos then continue;
         if temp<xpos then zgroscom:=false;
         if temp>xpos then zgroscom:=true;
         groscom:=zgroscom;
         continue;
      end;
      s:='';von:=1;bis:=0;xpos:=sxpos;;tenp:=false;comment:=false;textan:=false;
      if lz>0 then
      if (zeile[1] in nonalphas)  then begin
        alpha:=1;
        if not(zeile[1] in exalphas) then alpha:=2;
       end else
        alpha:=0;
      for x:=1 to lz do begin
        aktchar:=zeile[x];

        oalpha:=alpha;
      if (aktchar in nonalphas)  then begin
        alpha:=1;
        if not(aktchar in exalphas) then alpha:=2;
       end else
        alpha:=0;

          if oalpha<> alpha then begin

            s:=copy(zeile,von,bis);
            tenp:=true;
          if oalpha=2 then begin
            if comment or groscom=false then
             if (pos(stringBeginEnd,s)>0)  then
                 textan:=not textan;

            if textan=false then begin
                if (pos(CommentZeile,s)>0) then
                   comment:=true;

              if comment=false then begin
                if (pos(GCom1Begin,s)>0) or (pos(GCom2Begin,s)>0) then begin groscom:=true;zgroscom:=true; end;
                if (pos(GCom1End,s)>0) or (pos(GCom2End,s)>0) then zgroscom:=false;
              end;
            end;
            end;
          end;

          o_insel:=inSel;
          zinSel:= (aktpos< se)and(aktpos>Ss) ;

        if ((tenp)or(o_insel <> zinsel)or(x=lz)) then begin
         if (xpos<clientwidth)and(xpos>0) then begin
         s:=copy(zeile,von,bis);
         if comment or groscom then
          SetColorFont(dc,fcommentfont,1,aktfont)
         else if (oalpha>0) then
           SetColorFont(dc,fsymbfont,5,aktfont)
          else if (textan) then
            SetColorFont(dc,fstringfont,0,aktfont)
           else
             if fkeywords.IndexOf(s)>-1 then
                SetColorFont(dc,fkeywordfont,2,aktfont)
               else if StrToInt64Def(s,low(integer))<>low(integer) then
                  SetColorFont(dc,fintfont,3,aktfont)
               else

                  SetColorFont(dc,fstandardfont,4,aktfont);
//Weihnachtsbaum:             SetTextColor(dc,rgb(random(255),random(255),random(255)));
             TextOut(dc,xpos,ypos,pchar(s),length(s));
           end;
        //  end;
          inc(xpos,Bentextwidth(dc,s));
          s:='';tenp:=false;
          inc(von,bis);bis:=0;
        end;
        groscom:=zgroscom;
        //s:=s+aktchar;
        inc(bis);
        inc(aktpos);
          inSel:=zinsel;
         if (o_insel <> insel) then
           if inSel then
              SetBkMode(dc,OPAQUE)
             else
              SetBkMode(dc,TRANSPARENT);
      end;
      inc(aktpos,max(400-lz,0));
    end;

//  SelectObject(dc,bmp);
  margin.paintTo(dc);
  BitBlt(wdc,0,0,clientwidth,clientheight,dc,0,0,SRCCOPY);
  SelectObject(dc,oldfont);
  SelectObject(dc,oldbrush);
  SelectObject(dc,oldbmp);
  DeleteObject(bmp);
  DeleteObject(hintergrundbrush);
  DeleteDC(dc);
 // BitBlt(wdc,0,0,clientwidth,clientheight,dc,0,0,SRCCOPY);

//  ShowMessage(IntToStr(getlasterror));
//  ShowScrollBar(handle,SB_BOTH,false);
//  ShowScrollBar(handle,SB_BOTH,true);
  //margin.paint;
//  bmp.free;
  finally
   ReleaseDC(handle,wdc);
   exclude(fstateflags,bcsfInPaintFunc);
   if Focused then ProcessMessage(BCA_AKTFOCUS,0,0);

  end;
end;  }
procedure TNewColorMemo.Paint;
begin
  PaintNew(bmFull,rect(0,0,0,0));
  Perform(WM_NCPAINT,1,0);
end;
procedure TNewColorMemo.Notification;
begin
  inherited;
  if (Operation=opremove)and (aComponent=fhighlighter) then begin
    fhighlighter:=nil;
    Refresh;
  end;
end;

procedure TNewColorMemo.ShowKibitz;
var p:TPoint;
begin
p:=point(CaretXPix,CaretYPix+charheight);
p:=ClientToScreen(p);
kibitz.left:=p.x;kibitz.Top:=p.y+2;
kibitz.Visible:=true;
if Assigned(fkibitzfunc) then fkibitzfunc(self,kibitz);
kibitz.UpdateWords;
SetFocus;
end;

destructor TNewColorMemo.destroy;
begin
  margin.free;
{  fcommentfont.free;
  fstandardfont.free;
  fkeywordfont.free;
  fstringfont.Free;
  fintfont.Free;
  fsymbfont.free;}
  lines.free;
  inherited;
end;
procedure Register;
begin
  RegisterComponents('Benito', [TNewColorMemo]);
  RegisterComponents('Benito', [TBenHighlighter]);
end;

end.
