unit umyMemo;

{$mode objfpc}

interface

uses
  Classes, SysUtils, LResources, Controls, Graphics, Dialogs, ExtCtrls,Tools,lcltype,contnrs,lclintf,forms;

type
  TCharItem = class
    Brush:TBrush;
    Pen:TPen;
    Font:TFont;
    sel:Boolean;
    Position,size:TPoint;
//    DisplayText:Char;
    ChrBmp:TBitMap;
    cx,cy,cx2,cy2:Integer;
  end;
  
  TPoint2 = class
    x,y,y2,x2:Integer;
  end;
  
  TWordItem = class
    Charitem:TCharItem;
    displayText:String;
    r:TPoint2;
    TextView,av:TStringlist;
    ptList:array of TRect;
  end;

  TMyMemo = class(TCustomControl)
  public
    buffer:TBitMap;
    buffer2:TBitMap;
    CT:TPoint;
    start:Boolean;
    CharList:TObjectList;
    TextRect:TRect;
    m:TPoint;
    charitem:TCharItem;
    stdbrush:TBrush;
    stdfont:TFont;
    procedure AddCharItem(Stringlist:TSTringList;DT:String = '');
    function SetSelItem(mx,my,ex,ey:Integer):TPoint;
    procedure StringToCharItem(str:String);
    procedure SettzeBild(index:Integer = -1);
    procedure NewDrawBmp(index:Integer);

    constructor Create(AOwner:TComponent;w,h:Integer);
    destructor Destroy ; override ;
    procedure KeyDown(var Key: Word; Shift: TShiftState);override;
    procedure KeyPress(var Key: char);override;
    procedure MouseDown(Button: TMouseButton;
      Shift: TShiftState; X,Y: Integer);override;
    procedure MouseMove(Shift: TShiftState; X,
      Y: Integer);override;
    procedure MouseUp(Button: TMouseButton;
      Shift: TShiftState; X,Y: Integer);override;

    procedure Paint;override;
    procedure Add2(TV:TStringList);

  private
    function GetIndex(px,py:Integer):Integer;
  
  end;

implementation

constructor TMyMemo.Create(AOwner:TComponent;w,h:Integer);
var
  p:TPoint2;
  TextView:TStringlist;
begin
  inherited Create(AOwner);

  TextRect.left:=0; TextRect.top:=0;
  TextRect.Right:=W; TextRect.Bottom:=H;
  Width:=w; Height:=h;

  stdbrush:=TBrush.Create; stdFont:=TFont.Create;
  
  stdbrush.color:=clWhite;
  stdbrush.Style:=bsClear;
  stdfont.color:=clBlack; stdfont.style:=[];
  stdfont.Name:='-adobe-courier-medium-r-normal-*-*-120-*-*-*-*-iso10646-1';

  CharList:=TObjectList.Create;
  charitem:=TCharItem.Create;
  charitem.Brush:=TBrush.Create;
  charitem.Pen:=TPen.Create;
  charitem.Font:=TFont.Create;

  charitem.ChrBmp:=TBitmap.Create;

  buffer:=TBitmap.Create;
  buffer.Canvas.Font:=TFont.Create;
  buffer.Canvas.Font.Style:=[fsBold];

  buffer.Width:=Width; buffer.Height:=Height;

  buffer.Canvas.FillRect(0,0,Width,Height);


  buffer2:=TBitmap.Create;
  buffer2.Width:=Width; buffer2.Height:=Height;
  buffer2.Canvas.FillRect(buffer2.canvas.ClipRect);


  p:=TPoint2.Create; p.x:=0; p.y:=0;
  
  TextView:=TStringlist.Create;
  TextView.AddObject('00: Dies ist ein Test von Heute, Wie geht es dir so ?',p);
  TextView.AddObject('01: 608246 Das ist eine Telepfonnummer',p);

  charitem.Font.color:=ClRed;
  AddCharItem(TextView,'');
  TextView.clear;
  
  TextView.AddObject('02: Der himmel ist blau',p);
  charitem.Brush.Color:=clBlue;
  charitem.Font.color:=clAqua;
  charitem.Font.style:=[fsBold];
//  charitem.Font.Size:=16;
  AddCharItem(TextView);

  TextView.clear;
  TextView.AddObject('03: Das Auto ist rot',p);
  TextView.AddObject('04: Wie geht es so ?',p);
  TextView.AddObject('05: Heute ist es aber schoen !',p);
  TextView.AddObject('06: Hallo guten Tag',p);

  charitem.Font.style:=[fsBold];
  charitem.brush.color:=clBlack;
  charitem.Font.color:=clWhite;
  AddCharItem(TextView);

  charitem.Font.style:=[fsItalic];
  charitem.brush.color:=clBlue;
  charitem.Font.color:=clRed;
  AddCharItem(nil,'dies ist ein Test von heute !');

//  charitem.Font.style:=[];
//  charitem.brush.color:=clWhite;
//  charitem.Font.color:=clBlack;

  TextView.clear;
  TextView.AddObject('07: Test Test Test Test Test Test',p);
  TextView.AddObject('08: Guten Tag wie geht es dir ?',p);

  charitem.Font.style:=[fsItalic];
  charitem.brush.color:=clBlack;
  charitem.Font.color:=clYellow;
  AddCharItem(TextView);

{  TextView.AddObject('09: Heute ist Winter',p);
  TextView.AddObject('10: Draussen liegt schnee',p);
  TextView.AddObject('11: Der Wald ist gruen !',p);
  TextView.AddObject('12: Das Meer sollte Blau sein oder nicht ?',p);
  AddCharItem(TextView);
  TextView.clear;}
end;

procedure TMyMemo.NewDrawBmp(index:Integer);
begin
end;

procedure TMyMemo.SettzeBild(index:Integer = -1);
begin
end;

procedure TMyMemo.StringToCharItem(str:String);
begin
end;

function Tmymemo.GetIndex(px,py:Integer):Integer;
var
  i,i2:integer;
begin
  for i:=0 to CharList.count-1 do begin
    with TWordItem(CharList.items[i]) do begin
      if TWordItem(CharList.items[i]).TextView =nil then begin
        if PtInRect(rect(r.x,r.y,r.x2,r.y2),Point(px,py)) = true then
          writeLn('i:',i,'r.x:',r.x, ' r.x2:',r.x2,' r.y:',r.y,' r.y2:',r.y2);
      end
      else begin
        for i2:=0 to TWordItem(CharList.items[i]).av.count-1 do begin
          with TWordItem(CharList.items[i]).ptList[i2] do begin
            if (PtInRect(ptList[i2],Point(px,py)) = true) then begin
              writeLn('i:',i,'i2:',i2,'L:',left,'T:',Top,'R:',Right,'B:',Bottom);
            end; // if ptinrect
          end; // with
        end; // for i2:=0
      end; // else begin
    end; // with WordItem
  end; // for i:=0

end;

function TMyMemo.SetSelItem(mx,my,ex,ey:Integer):TPoint;
var
  fx,fy,fz,fzy,i1,sx1,sx2:Integer;
  str:String;
  s:Boolean;
  p:TPoint2;
  r:Trect;
begin
{  fz:=0; i1:=0; sx1:=0; sx2:=0; fzy:=0; fy:=0; s:=False;
  r.left:=0; r.Right:=Width; r.top:=0; r.Bottom:=0;
  for fy:=0 to TextView.count-1 do begin
    p:=TPoint2(Textview.Objects[fy]);
    str:=TextView.strings[fy];
    r.top:=p.y-4;
    r.Bottom:=p.y2;

    if PtInRect(r,point(0,my)) then begin
      i1:=fy;
      break;
    end;
  end;

  str:='';
  str:=TextView.strings[i1];
  fz:=0;
  for fx:=1 to Length(str) do begin
    fz:=fz + Buffer.Canvas.TextWidth(str[fx]);
    if (fz >=mx) and (s = false) then begin
      s:=True;
      sx1:=fx;
    end;

    if (s = true) and (fz >=ex) then begin
      sx2:=fx;
      s:=False;
      Screen.Forms[0].caption:=copy(str,sx1,( sx2-sx1)+1);
      break;
    end;
  end;}
end;

procedure TMyMemo.Add2(TV:TStringList);
begin
end;

procedure TMyMemo.AddCharItem(Stringlist:TSTringList;DT:String = '');
var
  WortItem:TWordItem;
begin
  WortItem:=TWordItem.Create;
  WortItem.Charitem:=TCharitem.Create;
  WortItem.Charitem.Brush:=TBrush.Create;
  WortItem.Charitem.Pen:=TPen.Create;
  WortItem.Charitem.Font:=TFont.Create;

  WortItem.Charitem.Brush.Assign(Charitem.brush);
  WortItem.Charitem.Brush.Style:=bsSolid;
  WortItem.Charitem.Pen.Assign(Charitem.Pen);
  WortItem.Charitem.Font.Assign(Charitem.Font);

  WortItem.Charitem.Font.name:='-adobe-courier-medium-r-normal-*-*-120-*-*-*-*-iso10646-1';
  WortItem.Charitem.Font.Size:=Charitem.Font.size;
  WortItem.r:=TPoint2.Create;
  WortItem.Charitem.Position:=Point(0,0);
  WortItem.Charitem.Size:=Point(0,0);
  WortItem.av:=TSTringlist.Create;

  if dt = '' then begin
    WortItem.TextView:=TStringList.Create;
    WortItem.TextView.Text:=Stringlist.text;
  end
  else begin
    Wortitem.r:=TPoint2.Create;
    Wortitem.r.x:=0;
    Wortitem.r.y:=0;
    Wortitem.r.x2:=0;
    Wortitem.r.y2:=0;
    WortItem.displayText:=dt;
  end;
  
  CharList.Add(WortItem);

  charitem.Font.Assign(stdfont);
  charitem.Brush.Assign(stdbrush);
end;

procedure TMyMemo.Paint;
var
  i,i1,y,x,px,i2,l3:Integer;
  p,pl:TPoint2;
  str1:String;
  fss:TFontStyles;
  t:Boolean;
  str2:String;
begin
  inherited Paint;
  y:=0; px:=0;  i2:=0;
  // Paint
    str2:='';
  for i1:=0 to CharList.count-1 do begin
    with TWordItem(Charlist.items[i1]) do begin

      SetLength(ptList,0);
      av.clear;p:=TPoint2.Create; p.x:=3243; av.AddObject('',p);
      SetLength(ptList,high(ptList)+2);
      l3:=av.count-1;
      Buffer.Canvas.Font:=TWordItem(Charlist.items[i1]).Charitem.Font;
      Buffer.Canvas.Brush:=TWordItem(Charlist.items[i1]).Charitem.Brush;
      Buffer.Canvas.pen.style:=psClear;
      // wenn eine TStringlist verwendet wird
      if (TextView <> NIL) and (DisplayText = '') then begin
        for i:=0 to TextView.Count-1 do begin
          p:=TPoint2.Create;
          str1:=TextView.Strings[i];
          p.y:=y;
          r.y:=y;
          t:=False;
          str2:='';
          ptlist[high(ptlist)].Bottom:=y+Buffer.canvas.TextHeight(str1[1])+3;;

          for x:=1 to Length(str1) do begin
            if px+(Buffer.canvas.TextWidth(str1[x])*2) > Width then begin

             t:=true;
             p.y:=y;
             ptList[high(ptList)].Right:=px;

             px:=0;
             y:=y + Buffer.canvas.TextHeight(str1[1])+3;
             ptlist[high(ptlist)].Bottom:=y;
             p.y2:=y;
             p.x:=-1;
             SetLength(ptList,high(ptList)+2);
             ptlist[high(ptlist)].Bottom:=y+Buffer.canvas.TextHeight(str1[1])+3;;;;
             ptList[high(ptList)].top:=p.y;
             av.Add('');
            end;
            Buffer.Canvas.Rectangle(px,
                                    y,
                                    px+Buffer.canvas.TextWidth(str1[1]),
                                    y+Buffer.canvas.TextHeight(str1[1])+3
                                   );
            av.strings[av.count-1]:=av.strings[av.count-1]+str1[x];
            str2:=av.strings[av.count-1];
            if Length(str2) = 1 then begin
              ptlist[high(ptlist)].left:=px;
              ptlist[high(ptlist)].Top:=y;
            end;
            buffer.canvas.TextOut(px,y,str1[x]);
            px:=px + Buffer.canvas.TextWidth(str1[1]);
            if x=Length(str2)  then begin
              ptlist[high(ptlist)].Right:=px;
              ptlist[high(ptlist)].Bottom:=y+Buffer.canvas.TextHeight(str1[1])+3;
            end;
          end; // for x:=1 to ...
          ptlist[high(ptlist)].Right:=px;
        end; // for i:=0
      end //if TextVieew <> NIL
      else begin
        r.x:=px;
        r.y:=y;
        for x:=1 to Length(displayText) do begin
          if px+Buffer.canvas.TextHeight(displayText[1]) >= Width then begin
            px:=0;
            y:=y + Buffer.canvas.TextHeight(displayText[1])+3;
          end;
          buffer.canvas.TextOut(px,y,displayText[x]);
          px:=px + Buffer.canvas.TextWidth(displayText[x]);
          r.x2:=px;
        end;
        r.y2:=y+Buffer.canvas.TextHeight(displayText[1])+3;
      end;
    end;
  end;

{
  for i:=0 to TextView.Count-1 do begin
    p:=TPoint2.Create; p.x:=0; p.y:=y;
    str:=TextView.Strings[i];

    for x:=1 to Length(str) do begin
      if px+Buffer.canvas.TextWidth(str[x]) > Width then begin
        px:=0;
        break;
      end
      else begin
        Buffer.canvas.TextOut(px,y,str[x]);

        px:=px + Buffer.canvas.TextWidth(str[x]);
      end;
    end;
    px:=0;
    y:=y + Buffer.canvas.TextHeight(TextView.Strings[1]);
    p.y2:=y;

    TextView.Objects[i]:=p;
  end;
}
//  Buffer.Canvas.TextRect(Rect(0,0,Width,Height),0,0,TextView.Text);
//  Der cuser wird gezeichnet
//  buffer.canvas.pen.color:=clred;
//  buffer.canvas.moveto(ct.x,zi );
//  buffer.canvas.LineTo(ct.x,zi+15);
//  Paintbox1.Canvas.CopyRect(TextRect,buffer.canvas,TextRect)

  Canvas.Draw(0,0,buffer)
end;


procedure TMyMemo.KeyDown(var Key: Word; Shift: TShiftState
  );
begin
  if (key in [ord('A')..ord('Z')]) or (Key in [ord('a')..ord('z')]) or (shift <> []) or (key = VK_SPACE) then begin
    start:=True;
  end;
end;

procedure TMyMemo.KeyPress(var Key: char);
begin
  inherited keypress(key);
  if start = true then begin
//    AddCharItem(key);
//    Invalidate;
//    start:=False;
  end;
end;

procedure TMyMemo.MouseDown(Button: TMouseButton;
  Shift: TShiftState; X,Y: Integer);
begin
  GetIndex(x,y);
  inherited MouseDown(button,shift,x,y);
  m.x:=x; m.y:=y;

//    SetSelItem(m.x,m.y,x,y);

end;

procedure TMyMemo.MouseMove(Shift: TShiftState; X,
  Y: Integer);
begin
  inherited MouseMove(shift,x,y);
  Screen.Forms[0].Caption:=IntTostr(x) + '\' + intTostr(y);
//  if ssleft in Shift then begin
  //  SetSelItem(m.x,m.y,x,y);

//    Invalidate;
//  end;
  //PaintBox1.Invalidate;
end;

procedure TMyMemo.MouseUp(Button: TMouseButton;
  Shift: TShiftState; X,Y: Integer);
begin
  inherited MouseUP(button,shift,x,y);
end;

destructor TMyMemo.Destroy ;
begin
  buffer.free
end;

end.

