unit editpole;
{$I defines.inc}
{$I-,B-,R-}

interface
uses Dos,Objects,Ovaznik,TEdRadky,Wokna32,VenomGFX,Lacrt,Laklv,FNfont2;

const
    edna_OK       = 0;
    edna_NOFILE   = 1;
    edna_CANCELED = 2;
type
Tkurpoz = record
   x,y:longint;      {Y=cislo radky;X=bajt v radku (v unicode nemusi platit 1bajt=1znak)}
   vx:longint;      {verejne X. cislo znaku v radce v NEunicode VX=X}
   r:PVaznik;      {na nem bude PEdRadek tzn. ukazatel na radek s kurzorem}
end;


Procedure NulujBodKurzoru(var kur:Tkurpoz);
Function PorovnejPozKurzoru(kur1,kur2:TKurpoz):byte;


type
TBlokTextu = object
radky:PVaznik;
PocetRadku:longint;
Constructor Init;
Procedure VlozBlok(zac,kon:TKurPoz); {zdroj textu se bere ze ZAC.R a KON.R}
Procedure SmazObsah;
Destructor Done;virtual;
end;


PEditacniPole = ^EditacniPole;
EditacniPole = object(TWoknaZaklad)
       radky:PVaznik;      {jsou tam navazany typy PEdRadek}
       pozice:TKurpoz;
       posledni_vyskyt:TKurPoz;
       poz_ozn:array[1..2] of TKurpoz;   {pro oznaceny blok textu}
       PozText:record
          odz,doz,
          posunv,posunm:longint;
          end;
       PocetRadku:longint;
       konverze_tagu:boolean;
       jednotna_vyska_radku:boolean;
       jednorazove_zakazani_zobrazeni:boolean;
       unicode:boolean;
       povolene_zmeny:boolean;
       {true=kdyz nacita soubor, tak zdvojuje vsechny znaky "<", aby se neinterpretovaly
       jako tagy. Pri ukladani je zase naopak odmazava.
       false=u nacitaneho souboru predpoklada, ze tagy obsahuje, takze zadne konverze nedela
       Default je TRUE}
       kx,ky,kd:longint;      {X a Y poloha kurzoru a jeho vyska}
       kkx,kky:longint;
       kpoz:virtualwindow;
       odz,doz:longint;       {na radku s kurzorem jsou vypsany znaky od ODZ do DOZ}
       virt:PVirtualWindow;
       pozadi,popredi:word;   {default: 65535,0}
       poc_zobrX,poc_zobrY:longint;    {posun virtualni obrazovky (pro rizeni scrollingu)}

       po_kl_pozice:TKurpoz;       {sem si ulozim pozici kurzoru pred odjetim posuvnikem}
       po_kl_poc_zobrX,po_kl_poc_zobrY:longint; {uschova scrolovatek}
       po_kl_jsme_mimo:boolean;
       po_kl_rozpr:boolean;{posuvniko-klavesovy rozpor}

       prv_rad,posl_rad:PVaznik;       {Prvni a posledni vypsany radek}
       po_kl_prv_rad,po_kl_posl_rad:PVaznik; {a jejich uschova}
       tot_posl:PVaznik;               {Uplne posledni radka souboru}
       py:posuvnik;
       puvodni_citac:dword;
       je_videt:boolean;      {je zrovna videt kurzor?}
       rychlost_blikani:byte;
       zalamuj:boolean;       {ma zalamovat radky?}
       tab_na_mezery:byte;
       byla_zmena:boolean;
       ED_key_proc:Function(o:word):word;
       ukaz_postup_nahravani:Function(r:real):boolean;
       mimoradne_osetreni_klavesnice:Function(o:word):string;
       prac1,prac2:longint;
       sx,svx,sy:longint;     {zaloha polohy kurzoru}
       sr:PVaznik;            {nekdy se to muze hodit}
       Constructor Init(ix,iy,_sirka,_vyska:longint;iakt:boolean);
       {Blok zobrazovacich rutin}
       Procedure Zobraz;virtual;
       Procedure VypisRadekTextu(ix:longint;p:PVaznik;v:PEdRadek);virtual;
       Procedure DodatkyPoZobrazeni;virtual;
       {------------------------}
       procedure Kontrola;virtual;
       Function NactiSoubor(s:string):byte;
       {edna_OK = vse v poradku, edna_NOFILE = neexistujici soubor,
        edna_CANCELED = zrusene nacitani}
       Function UlozSoubor(s:string):boolean;
       Function NactiZeStreamu(var s:TStream):byte;
       Function UlozDoStreamu(var s:TStream):boolean;
       Function NactiZVazniku(p:PVaznik):boolean;
       {Na vaznik jsou pripojeny PStringy}
       Procedure EP_UberVetsi(v:PEdRadek);
       Procedure EP_PridejVetsi(v:PEdRadek);
       Procedure EP_ZavriSoubor;
       Procedure ZkusZrusitRozpr;
       Procedure Prilep_K_predeslemu(pr:PVaznik;smezerou:boolean);
       Procedure NalamejBuffer(pr:PVaznik);
       Procedure PosunRadek(p:PVaznik);
       Function MoznyPreskokNahoru:boolean;
       Procedure PridejTextNaPoziciKurzoru(kp:PChar;ksd:longint);
       Procedure NastavRozmeziRadku(v:PEdRadek;var yz:longint);
       Procedure UpravRozmeziRadku(v:PEdRadek;var yz:longint);
       Procedure PospojujRadky(merit:boolean);
       Procedure PridelRadky;
       Procedure PreskladejRadky(poz:TKurPoz);
       Procedure PreskladejRadky(poz:TKurPoz;m1,m2,m3:boolean);
       Procedure VycentrujNaKurzor;
       Procedure horz_VycentrovaniKurzoru;
       Procedure vert_VycentrovaniKurzoru;
       Procedure ZmenFont(s:string);
       Function VXpozice_z_Xpozice(v:PEdRadek;xpoz:longint;tagy:boolean):longint;
       Procedure PresunKurzor_na_grafickou_pozici(xx,yy:longint;var kur:TKurPoz);
       Function UkazatelNaRadku(n:longint):PVaznik;
       Procedure OverPoziciKurzorovehoBodu(var kur:TKurPoz);
       Function DejLinearniPozici:longint;
       Procedure NastavLinearniPozici(i:longint);
       Procedure PosouvaciRezim;
       Procedure ZalamovaciRezim;
       Procedure ZmenBarvuPozadi(w:word);
       Procedure BlikejKurzorem;
       Procedure ZhasniKurzor;
       Procedure RozsvitKurzor;
       Procedure RozdelRadku(poz:TKurPoz;var posun:longint);
       Procedure DalsiRadka(u:PChar;poz:longint;ukoncena:boolean);
       Function PismenoZpet:longint;
       Procedure SmazRadku(var poz:TKurPoz);
       Procedure SmazRadku(var poz:TKurPoz;moznosunout:boolean);
       Procedure SmazCastRadky(poz1,poz2:TKurpoz);
       Procedure SmazSlovo;
       Procedure SmazBlokTextu(zac,kon:TKurPoz);
       Procedure Presun_o_slovo_vpravo;
       Procedure Presun_o_slovo_vlevo;
       Procedure VlozTextNaPozici(blok:PVaznik;poz:TKurPoz);
       Procedure SkocNaZacatek;
       Procedure NovySoubor;
       procedure OsetriVstup;
       Function KrokVpred:longint;
       Function KrokZpet:longint;
       Procedure SipkaDolu;
       Procedure SipkaNahoru;
       Procedure BackSpace;
       Procedure KlavesaDel;
       Procedure KlavesaEnter;
       Procedure KlavesaPGDN;
       Procedure KlavesaPGUP;
       Procedure KlavesaCtrlPGUP;
       Procedure KlavesaCtrlPGDN;
       Procedure KlavesaEnd;
       Procedure KlavesaHome;
       Procedure ZpracujPraveMysitko(nx,ny:longint;kur:TKurPoz);virtual;
       Procedure ZpracujStredniMysitko(nx,ny:longint;kur:TKurPoz);virtual;
       Procedure ZpracujLeveMysitko(nx,ny:longint;kur:TKurPoz);virtual;
       Function ZkontrolujYY:boolean;

       Procedure NastavBodOznaceni(b:byte;poz:TKurPoz);
       Procedure SmazBodyOznaceni;
       Function Zda_oznacen_blok:boolean;
       Function Pocet_radek_bloku:longint;

       Destructor Done;virtual;
       end;

Procedure TextoveOkno(x,y,sirka,vyska:longint;popis:string;p:PVaznik);

implementation
{var font:fn;}

Procedure Dummy;begin end;

Function Default_ed_key_proc(o:word):word;
begin
Default_ed_key_proc:=o;
end;


Procedure NulujBodKurzoru(var kur:Tkurpoz);
begin
kur.x:=0;
kur.vx:=0;
kur.y:=0;
kur.r:=nil;  {ukazatel na udaje radku}
end;


Function PorovnejPozKurzoru(kur1,kur2:TKurpoz):byte;
{0 = jsou shodne; 1 = kur1>kur2; 2 = kur2>kur1}
begin
if kur1.y<kur2.y then Exit(2) else
if kur1.y>kur2.y then Exit(1) else
   if kur1.vx<kur2.vx then Exit(2) else
   if kur1.vx>kur2.vx then Exit(1) else PorovnejPozKurzoru:=0;
end;


Constructor EditacniPole.Init(ix,iy,_sirka,_vyska:longint;iakt:boolean);
var hv:boolean;
     r:PEdRadek;
     a:longint;
    _virt:Virtualwindow;
begin
inherited init;
automys:=false;
x:=ix; y:=iy;
radky:=New(PVaznik,Init(nil,nil));
r:=New(PEdRadek,Init);
radky^.InitNext(r);
r^.y1:=0;
r^.y2:=Vyska_FN_default-1;
r^.yy:=1;
if iakt then
   begin
   stav:=_aktivni;
   xm:=-mouse.last_lpx;
   ym:=-mouse.last_lpy;
   end
   else begin
   stav:=_neaktivni;
   xm:=1;
   ym:=1;
   end;
pozice.x:=1;             {kurzor bude na 1.bajtu radku}
pozice.vx:=1;            {tzn. na prvnim znaku}
pozice.y:=1;             {a na 1.radku}
pozice.r:=radky^.dalsi;  {ukazatel na udaje radku}
tot_posl:=pozice.r;      {uplne posledni radka je zaroven prvni radkou}
posledni_vyskyt.r:=nil;
NulujBodKurzoru(poz_ozn[1]);  {neni oznacen...}
NulujBodKurzoru(poz_ozn[2]);  {...zadny text}
PocetRadku:=1;
odz:=0;
doz:=0;          {na aktualnim radku se nam prave zobrazuje nulty az nulty znak :-)}
poc_zobrX:=4;    {od ktere X-ove souradnice okna ma zacit vykreslovat radky}
poc_zobrY:=0;    {...a od ktere Y-ove}

vyska:=_vyska;
sirka:=_sirka-_SirPos;   {od celkove sirky odectu velikost posuvniku}
hv:=hned_vykresluj;
hned_vykresluj:=false;
jednorazove_zakazani_zobrazeni:=false;
py.Init(ix+sirka,iy,vyska,vyska,0,10,poVERT);
hned_vykresluj:=hv;
po_kl_rozpr:=false;      {posuvniko-klavesovy rozpor}
konverze_tagu:=true;     {pri nacitani zdvojuj znaky "<"}
povolene_zmeny:=true;    {text smi byt menen}
jednotna_vyska_radku:=true; {neni treba zkoumat text radku, vime predem, jak bude vysoky}
unicode:=false;          {nepouzivame rezim unicode}
zalamuj:=false;          {defaultne zalamovat radky nebudu}
mimoradne_osetreni_klavesnice:=nil;
ED_key_proc:=@Default_ed_key_proc;
ukaz_postup_nahravani:=nil;
Init_VW(_virt,sirka,vyska,false);
virt:=@_virt;
hlavni_font:=FN_syst_font;
ofn:=FN_default;
kx:=4;           {pocatecni poloha a delka kurzoru}
kkx:=-1;
ky:=0;
kd:=Vyska_FN_default;
kpoz.hoehe:=kd;
Init_VW(kpoz,1,100,false);
popredi:=txtbarva;
pozadi:=txtpolevbarva;
Clr(virt^,pozadi);
puvodni_citac:=0;
je_videt:=false;      {je zrovna videt kurzor?}
rychlost_blikani:=10;
tab_na_mezery:=5;
byla_zmena:=false;
if hned_vykresluj then zobraz;
end;


procedure editacnipole.ZpracujPraveMysitko(nx,ny:longint;kur:TKurPoz);
begin
MouseRel;
end;

procedure editacnipole.ZpracujStredniMysitko(nx,ny:longint;kur:TKurPoz);
begin
MouseRel;
end;


Procedure Editacnipole.ZpracujLeveMysitko(nx,ny:longint;kur:TKurPoz);
begin
pozice:=kur;
po_kl_rozpr:=false;  {levym mysitkem se odstrani posuvniko-klavesovy rozpor}
MouseRel;
end;


Procedure EditacniPole.PresunKurzor_na_grafickou_pozici(xx,yy:longint;var kur:TKurPoz);
var v:PEdRadek;
    p:Pvaznik;
begin
p:=prv_rad;          {prvni realne na obrazovce vypsana radka}
while p<>nil do
   begin
   v:=p^.vazba;
   if (yy>=v^.y1) and (yy<=v^.y2) then
      begin
      kur.y:=v^.yy;
      kur.x:=Pozice_v_retezci(xx,{v^.y1}-1,poc_zobrX,poc_zobrY,v^.p,{font}nil);
      kur.vx:=FN_skut_znak;
      kur.r:=p;
      Exit;
      end;
   p:=p^.dalsi;
   end;
{Pokud jsme se dostali az sem, tak to znamena, ze jsme klikli az
 pod posledni radku do volneho prostoru}
p:=tot_posl;
v:=p^.vazba;
kur.y:=v^.yy;
kur.x:=Pozice_v_retezci(xx,{v^.y1}-1,poc_zobrX,poc_zobrY,v^.p,nil);
kur.vx:=FN_skut_znak;
kur.r:=p;
end;


procedure editacnipole.kontrola;
   Procedure KlepnutiMysi;
   var op,p:pvaznik;
       v:PEdRadek;
       mx,my:longint;
       b:integer;
       kur:TKurPoz;

   begin
   if povolene_zmeny=false then Exit;
   b:=mouse.b;
   if b=0 then Exit;
   if (not Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska)) then Exit;

   {dodatecna kontrola. kdyby nebyla, mohlo by pri manipulaci zvnejsku s
    promennymi STAV a XM a YM dochazet v teto procedure k neplecham}
   mx:=mouse.x-x;
   my:=mouse.y-y+poc_zobrY;

   PresunKurzor_na_grafickou_pozici(mx,my,kur);
   if b=1 then ZpracujLeveMysitko(mx,my,kur);
   if b=2 then ZpracujPraveMysitko(mx,my,kur);
   if b=4 then ZpracujStredniMysitko(mx,my,kur);
   end;


   Procedure ZkontrolujPosuvnik;
   begin
   if (mouse.b=1) or (mouse._wdif<>0) or (py.tahaci_stav) then
      if py.kontrola or (mouse._wdif<>0) then
         begin
         if po_kl_rozpr=false then
            begin
            po_kl_pozice:=pozice;  {zapamatuju si momentalni polohu kurzoru}
            po_kl_poc_zobrx:=Poc_ZobrX;
            po_kl_poc_zobry:=Poc_ZobrY;
            po_kl_prv_rad:=prv_rad;
            po_kl_posl_rad:=posl_rad;
            if je_videt then BlikejKurzorem;
            po_kl_rozpr:=true;
            (*PutClippedSprite(cil^,kpoz,kkx,kky);  {chvilkove vypnuti kurzoru}*)
            end;

         poc_zobrY:=py.hodnota;
         end else else py.probehni:=false;
   end;

var i:longint;
    d:dword;
    zmena_bliknuti:boolean;
Begin
{napred rizeni blikani kurzoru}
inherited kontrola;
zmena_bliknuti:=false;
d:=FromTimer;
if d>puvodni_citac+rychlost_blikani then
   begin
   je_videt:=not(je_videt);
   puvodni_citac:=d;
   zmena_bliknuti:=true;
   end;

ZkontrolujPosuvnik;

if not ((stav=_aktivni)or(stav=_escapem)) then
  if Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska) then
     begin {aktivace v pripade kliknuti mysi do pole}
     stav:=_aktivni;
     zobraz;
     mouserel;
     xm:=-mouse.last_lpx;
     ym:=-mouse.last_lpy;
     end else
  else
  begin       {tedy kdyz stav=_aktivni}
  if Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska) or
     ((mouse.last_lpx=-xm) and (mouse.last_lpy=-ym)) then
     begin
     {Jsme aktivni a plati jedno z nasledujiciho:
      a) posledni klepnuti L.mysitka bylo u nas
      b) nadrizeny proces chce simulovat, ze ke kliknuti doslo u nas
      Posuvnik je mimo - pozor}
     if zmena_bliknuti then BlikejKurzorem;
     if (mouse.b<>0) and (py.tahaci_stav=false) then
        begin                {je zmackle nejake tlacitko}
        stav:=_aktivni;
        ofn:=FN_default;
        nastavFont(hlavni_font);
        PutClippedSprite(cil^,kpoz,kkx,kky);  {chvilkove vypnuti kurzoru}
        KlepnutiMysi;
        je_videt:=true;puvodni_citac:=FromTimer;BlikejKurzorem;
        nastavFont(ofn);
        xm:=-mouse.last_lpx;
        ym:=-mouse.last_lpy;
        zobraz;
        {Vypustil jsem MouseRel a presunul do KlepnutiMysi}
        end;
     end {ne Uvnitr a ne simulace Uvnitr}
     else begin
     if stav in [_aktivni,_escapem] then
        begin
        stav:=_odkliknutim;
        zobraz;
        end;
     xm:=mouse.last_lpx;
     ym:=mouse.last_lpy;
     Exit;
     end;   {else begin :: uvnitr}
     {Jsme budto na posuvniku nebo nekde uplne jinde}
     if (mouse._wdif<>0) and (po_kl_rozpr) then
        begin
        i:={mouse.w-puv_kolecko}mouse._wdif;
        inc(poc_zobrY,i*30);
        if poc_zobrY<0 then poc_zobrY:=0;
        if poc_zobrY>py.virtvyska-py.vyska then poc_zobrY:=py.virtvyska-py.vyska;
        py.hodnota:=poc_zobrY;
        mouse._wdif:=0;        {ne zcela ciste, ale prijatelne}
        zobraz;
        Exit;
        end;
OsetriVstup;
end;   {else begin :: not ((stav=_akt...}
{OsetriVstup;}
end;


{Mozna by bylo lepsi presunout nasledujici dve funkce do FNFONT2.PAS...}
Function editacniPole.KrokZpet:longint;
var v:PEdRadek;
    i,j:longint;
begin
v:=pozice.r^.vazba;
if pozice.x<=1 then Exit(0);
i:=FNznakZpet(v^.p,v^.spp{-1},pozice.x-1,unicode,j);

if i=0 then Exit(0);  {nemelo by nikdy nastat}

dec(pozice.x,i);
dec(pozice.vx);
if PozText.odz<>0 then         {presahuje tento radek levy okraj obrazovky?}
   if pozice.x<=PozText.odz then
      {inc(poc_zobrX,PozText.posunm);}
      inc(poc_ZobrX,-PozText.posunm);
KrokZpet:=j;
end;

Function editacniPole.KrokVpred:longint;
var v:PEdRadek;
    i,j:longint;
begin
v:=pozice.r^.vazba;
if pozice.x>=v^.spp then Exit(0);
i:=FNznakVpred(v^.p,v^.spp-1,pozice.x-1,unicode,j);
if i=0 then begin beep;Exit(0);end; {nemelo by nikdy nastat}
inc(pozice.x,i);
inc(pozice.vx);
if PozText.doz<>0 then         {presahuje tento radek pravy okraj obrazovky?}
   if pozice.x-1>=PozText.doz then dec(poc_zobrX,PozText.posunv);
KrokVpred:=j;
end;

Procedure editacniPole.SipkaDolu;
var  v:PEdRadek;
     a1,a2:longint;
begin
if po_kl_rozpr and po_kl_jsme_mimo then
   begin
   v:=po_kl_prv_rad^.vazba;
   pozice.r:=po_kl_prv_rad;
   pozice.y:=v^.yy;
   poc_zobrY:=po_kl_poc_zobrY;
   poc_zobrX:=po_kl_poc_zobrX;
   end;
if povolene_zmeny then
   begin
   if pozice.y>=PocetRadku then Exit;
   inc(pozice.y);
   pozice.r:=pozice.r^.dalsi;
   v:=pozice.r^.vazba;
   pozice.x:=Pozice_v_retezci(kx,{v^.y1}-1,poc_zobrX,poc_zobrY,v^.p,v^.spp-1,nil);

   pozice.vx:=FN_skut_znak;
   {if pozice.x<v^.spp then inc(pozice.x);}
   {Bude potreba zascrolovat?}
   if FN_poz_v_ret_delka_radky<-poc_zobrX then  {horizontalni scrolling}
      begin
      poc_zobrX:=-FN_poz_v_ret_delka_radky+virt^.breite div 4;
      if poc_zobrX>4 then poc_zobrX:=4;
      end;
   if v^.y2>poc_ZobrY+virt^.hoehe-1 then     {vertikalni scrolling}
      poc_ZobrY:=v^.y2-virt^.hoehe-1+1;   {pozor HOEHEMINUS1 neni totez co HOEHE}
   end
   else begin
   v:=tot_posl^.vazba;
   inc(poc_ZobrY,py.tlacitkovy_skok);
   if poc_ZobrY>v^.y2-virt^.hoehe-1 then
      poc_ZobrY:=v^.y2-virt^.hoehe-1;
   end;
end;

Procedure editacniPole.SipkaNahoru;
var  v:PEdRadek;
begin
if po_kl_rozpr and po_kl_jsme_mimo then
   begin
   v:=po_kl_posl_rad^.vazba;
   pozice.r:=po_kl_posl_rad;
   pozice.y:=v^.yy;
   poc_zobrY:=po_kl_poc_zobrY;
   poc_zobrX:=po_kl_poc_zobrX;
   end;
if povolene_zmeny then
   begin
   if pozice.y<=1 then Exit;
   dec(pozice.y);
   pozice.r:=pozice.r^.predchozi;
   v:=pozice.r^.vazba;
   pozice.x:=Pozice_v_retezci(kx,{v^.y1}-1,poc_zobrX,poc_zobrY,v^.p,nil);
   pozice.vx:=FN_skut_znak;
   {if pozice.x<v^.spp then inc(pozice.x);}
   {Bude potreba zascrolovat?}
   if FN_poz_v_ret_delka_radky<-poc_zobrX then  {horizontalni scrolling}
      begin
      poc_zobrX:=-FN_poz_v_ret_delka_radky+virt^.breite div 4;
      if poc_zobrX>4 then poc_zobrX:=4;
      end;
   if v^.y1<poc_ZobrY then                      {vertikalni scrolling}
      poc_ZobrY:=v^.y1;
   end
   else begin
   dec(poc_ZobrY,py.tlacitkovy_skok);
   if poc_ZobrY<0 then
      poc_ZobrY:=0;
   end;

end;

Procedure editacniPole.Prilep_K_predeslemu(pr:PVaznik;smezerou:boolean);
var p:PVaznik;
    v,v2:PEdRadek;

begin
if pr=nil then Exit;
p:=pr^.predchozi;
if pr=tot_posl then {jestli rusim posledni radek, tak musim TOT_POSL preznacit}
   tot_posl:=p;
v2:=p^.vazba;
v:=pr^.vazba;
if smezerou then v2^.Vloz(' ',1,v2^.spp);

if pozice.r=pr then          {kurzor je na prilepovanem radku?}
   begin
   pozice.r:=p;                 {presunu ho na predchozi radek}
   dec(pozice.y);
   pozice.x:=v2^.spp-1+pozice.x; {a prepocitam X-ovou souradnici}
   end;

if posledni_vyskyt.r=pr then
   posledni_vyskyt.r:=nil;   {meni se tu rozlozeni radek. Tezko by se to}
                             {hlidalo poradne, tak aspon zrusim zaznam o posl.}
                             {vyskytu}

v2^.Vloz(v^.p,v^.spp-1,v2^.spp);
inc(v2^.gd,v^.gd);
v2^.crlf:=v^.crlf;
Dispose(v,Done);
Dispose(pr,Done);
dec(PocetRadku);    {pocet radku se snizil o jednu}
end;

Function DelkaPrvnihoSlova(p:Pvaznik;var poz:longint):longint;
var i,j:longint;
    q:pchar;
    v2:PEDradek;
begin
v2:=p^.vazba;
q:=v2^.p;
i:=PrvniVyskytZnaku(v2^.p,' ',1);
poz:=i;
if i=0 then Exit(0);
j:=sirka_FN_na_Xpoz(v2^.p,nil,i);
DelkaPrvnihoSlova:=j;
end;

Procedure editacniPole.BackSpace;
var l,a,b:longint;
    v,v2:PEdRadek;
    p:PVaznik;
    n:Pchar;
    s:string;
begin
if not povolene_zmeny then Exit;
byla_zmena:=true;
v:=pozice.r^.vazba;
if pozice.x=1 then if pozice.y=1 then Exit else
   begin
   p:=pozice.r^.predchozi;            {P bude radek nad kurzorem}
   v2:=p^.vazba;
   a:=Sirka_FN(v2^.p,nil,v2^.spp-1);  {delka radku nad kurzorem}
   pozice.vx:=FN_skut_znak;  {FN_skut_znak muze byt nastaven funkcemi Sirka_FN a Pozice_v_retezci}
   Prilep_K_predeslemu(p^.dalsi,  {P^.dalsi = radek s kurzorem}
                       false);    {soucasne upravi kurzor}

   if (zalamuj=false) then
      begin
      if a>virt^.breiteminus1 then
         poc_zobrX:=-(a-virt^.breiteminus1)-virt^.breite div 4;
      PosunRadek(p^.dalsi);
      {Bude potreba zascrolovat?}
      if v2^.y1<poc_ZobrY then {jo}
         poc_ZobrY:=v2^.y1;
      end
      else begin
      while v2^.crlf<>true do Prilep_k_predeslemu(p^.dalsi,true);
      v2^.gd:=virt^.breite;
      NalamejBuffer(p);
      end;
   Exit;
   end;

l:=pozice.x;
a:=KrokZpet;  {A=0: zadny tag v ceste, A=n: n znaku zabira tag}

b:=l-pozice.x-a;                {o kolik bajtu budeme zkracovat radku?}
s:=v^.VratString(pozice.x,b); {co odmazu?}


{okokno('...','stara poz.: '+mystr(l)+'  nova poz.:'+mystr(pozice.x)+'  smazat:'+s);}

b:=Sirka_FN(s,nil);          {a jakou to ma grafickou delku?}
v^.Vyjmi(pozice.x,l-pozice.x-a);

dec(v^.gd,b);
if zalamuj {and (v^.crlf=false) and (pozice.r<>tot_posl)} then
   begin
   {napred ke stavajicimu radku pripojim radky nasledujici}
   while v^.crlf=false do Prilep_k_predeslemu(pozice.r^.dalsi,true);

   {a navic jeste musim zkusit pripojit tento radek k predchazejicimu}
   p:=pozice.r^.predchozi;
   if p^.predchozi=nil then p:=p^.dalsi;
   v:=p^.vazba;
   while v^.crlf=false do Prilep_k_predeslemu(p^.dalsi,true);
   v^.gd:=virt^.breite;
   {a ted to vsechno nalamu}
   if Je_Capslock then
      begin
      end;
   NalamejBuffer(p);
   end;
end;

Procedure editacniPole.KlavesaDel;
var l,a,b:longint;
    v,v2:PEdRadek;
    p:Pvaznik;
    s:string;
begin
if not povolene_zmeny then Exit;
byla_zmena:=true;
v:=pozice.r^.vazba;
if (pozice.x<v^.spp) then
   begin
   l:=pozice.x;
   a:=poc_zobrX;
   KrokVpred;
   b:=pozice.x-l;
   s:=v^.VratString(l,b); {co odmazu?}
   b:=Sirka_FN(s,nil);          {a jakou to ma grafickou delku?}
   v^.Vyjmi(l,pozice.x-l);
   dec(v^.gd,b);
   poc_zobrX:=a;
   pozice.x:=l;
   if (zalamuj=true) and (v^.crlf=false) and (pozice.r<>tot_posl) then
      begin
      a:=DelkaPrvnihoSlova(pozice.r^.dalsi,b);
      b:=virt^.breiteminus1-4-v^.gd;
      if b>a then
         begin
         while v^.crlf=false do Prilep_k_predeslemu(pozice.r^.dalsi,true);
         v^.gd:=virt^.breite;
         NalamejBuffer(pozice.r);
         end;
      end;
   end else

if pozice.r=tot_posl then Exit else
   begin
   p:=pozice.r^.dalsi;
   if p=tot_posl then     {jestlize zrusim posledni radek, tak musim preznacit}
      tot_posl:=pozice.r; {TOT_POSL}
   v2:=p^.vazba;
   Prilep_K_predeslemu(p,false); {Pozor, muze hybat s promennou POZICE}
   if zalamuj then
      begin
      while v^.crlf=false do Prilep_K_predeslemu(pozice.r^.dalsi,true);
      v^.gd:=virt^.breite;
      NalamejBuffer(pozice.r);
      end else PosunRadek(pozice.r^.dalsi);
   Exit;
   end;

end;


Procedure EditacniPole.RozdelRadku(poz:TKurPoz;var posun:longint);
var v,v2:PEdRadek;
    p,q:PVaznik;
begin
v:=poz.r^.vazba;
v2:=New(PEdRadek,Init);        {novy prazdy PEdRadek}
p:=New(PVaznik,Init(nil,nil)); {novy clanek vazniku}
p^.vazba:=v2;
poz.r^.Insert(p);              {clanek vazniku zapojim do retezu}
if poz.r=tot_posl then {jesltli jsme na uplne poslednim radku souboru}
   tot_posl:=p;           {a vytvorim novy, tak musim aktualizovat TOT_POSL}

v^.Rozdel(v2^,poz.x,0);
v^.crlf:=true;
posun:=v^.y2-v^.y1+1;      {BETA - zatim predpokladam, ze nikde neni zmena vysky fontu}
v2^.y1:=v^.y1;
v2^.y2:=v^.y2;
v2^.yy:=v^.yy;
v2^.crlf:=v^.crlf;
inc(PocetRadku);       {prozatim predpokladejme, ze se pocet radku zvysil}
                       {to se po pruchodu zalamovaci procedurou muze zmenit}
end;


Procedure editacniPole.KlavesaEnter;
var v,v2:PEdRadek;
    p,q:PVaznik;
    n:PChar;
    a:longint;
begin
if not povolene_zmeny then Exit;
byla_zmena:=true;

RozdelRadku(pozice,a);

pozice.x:=1;           {po zmacknuti Enteru budeme urcite na prvnim sloupci}
pozice.vx:=1;
inc(pozice.y);
Poc_ZobrX:=4;

v:=pozice.r^.vazba;

p:=pozice.r^.dalsi; {nove vznikly radek}
v2:=p^.vazba;

if (zalamuj=false) {or (v^.crlf=true)} then PosunRadek(p)
   else begin
   {zalamovani}
   if pozice.y>2 then
      begin
      pozice.r:=p;
      q:=p^.predchozi^.predchozi;
      v:=q^.vazba;
      v^.gd:=virt^.breite;
      if v^.crlf=false then Prilep_k_predeslemu(p^.predchozi,true);
      end else q:=pozice.r;
   while v2^.crlf=false do Prilep_K_predeslemu(p^.dalsi,true);
   v2^.gd:=virt^.breite;
   NalamejBuffer(q);
   end;

pozice.r:=p;           {neboli pozice.r:=pozice.r^.dalsi}
{v^.crlf:=true;}

{Bude potreba zascrolovat?}
if v2^.y2>poc_ZobrY+virt^.hoehe-1 then {jo}
   poc_ZobrY:=v2^.y2-virt^.hoehe-1+1;
end;

Procedure editacniPole.KlavesaPGDN;
var v:PEdRadek;
    p,op:PVaznik;
    l:longint;
    b:boolean;
begin
if po_kl_rozpr and po_kl_jsme_mimo then begin SipkaNahoru;Exit;end;
b:=false;
if posl_rad^.dalsi=nil then b:=true else
   begin
   v:=posl_rad^.dalsi^.vazba;
   if v^.y2-poc_ZobrY<virt^.hoehe then b:=true;
   posl_rad:=posl_rad^.dalsi;
   end;
if B then
   begin
   v:=posl_rad^.vazba;
   inc(pozice.y,v^.yy-pozice.y{+1}{posl_od_poz+1});
   pozice.r:=posl_rad;
   pozice.x:=Pozice_v_retezci(kx+poc_ZobrX,{v^.y1}-1,poc_zobrX,poc_zobrY,v^.p,nil);
   pozice.vx:=FN_skut_znak;
   Exit;
   end;
posl_rad:=posl_rad^.predchozi;   {mirne pofiderni...}
v:=posl_rad^.vazba;
l:=ky-poc_zobrY+v^.y1;
poc_zobrY:=v^.y1;

{Mame posunuto. Ted je potreba zjistit, kde se vlastne nachazi kurzor}
p:=posl_rad;
while p<>nil do        {udelam scan od shora dolu...}
   begin
   v:=p^.vazba;
   if v^.y2>l then    {kurzor je na tehle radce}
      begin
      pozice.x:=Pozice_v_retezci(kx+poc_ZobrX,{v^.y1}-1,poc_zobrX,poc_zobrY,v^.p,nil);
      pozice.vx:=FN_skut_znak;
      {if pozice.x<v^.spp then inc(pozice.x);}
      pozice.y:=v^.yy;
      pozice.r:=p;
      Exit;
      end;
   op:=p;
   p:=p^.dalsi;
   end;
{sem bychom se nikdy nemeli dostat, nicmene sem neco napisu...}
pozice.x:=1;
pozice.vx:=1;
pozice.r:=op;
pozice.y:=v^.yy;
end;

Procedure editacniPole.KlavesaPGUP;
var l,m:longint;
    v:PEdRadek;
    p,op:Pvaznik;
begin
if po_kl_rozpr and po_kl_jsme_mimo then begin SipkaDolu;Exit;end;

if prv_rad^.predchozi^.predchozi=nil then
   begin
   pozice.y:=1;
   pozice.r:=radky^.dalsi;
   poc_ZobrY:=0;
   Exit;
   end;

v:=prv_rad^.vazba;
l:=ky-poc_zobrY;
dec(poc_zobrY,virt^.hoehe-(v^.y2-v^.y1+1));
p:=prv_rad;                    {jemne doladeni}
while p^.predchozi<>nil do
   begin
   v:=p^.vazba;
   if v^.y1-poc_zobrY=0 then Break;
   if v^.y1-poc_zobrY<0 then
      begin
      poc_zobrY:=v^.y2+1;      {neprilis ciste :-(}
      Break;
      end;
   p:=p^.predchozi;
   end;
if poc_zobrY<0 then poc_zobrY:=0;

{Mame posunuto. Ted je potreba zjistit, kde se vlastne nachazi kurzor}
l:=l+poc_ZobrY;

if povolene_zmeny then
   begin
   p:=prv_rad;
   while p<>nil do             {provedu scan zdola nahoru}
      begin
      v:=p^.vazba;
      if v^.y1<=l then
         begin
         pozice.x:=Pozice_v_retezci(kx+poc_ZobrX,{v^.y1}-1,poc_zobrX,poc_zobrY,v^.p,nil);
         pozice.vx:=FN_skut_znak;
         {if pozice.x<v^.spp then inc(pozice.x);}
         pozice.y:=v^.yy;
         pozice.r:=p;
         Exit;
         end;
      p:=p^.predchozi;
      end;
   end;

{Nasledujici kod by se mel vykonat jenom v pasivnim modu}
pozice.x:=1;
pozice.vx:=1;
pozice.y:=1;
pozice.r:=radky^.dalsi;
end;

Procedure editacniPole.KlavesaCtrlPGUP;
begin
SkocNaZacatek;
end;

Procedure editacniPole.KlavesaCtrlPGDN;
var v:PEdRadek;
begin
pozice.x:=1;
pozice.vx:=1;
pozice.r:=tot_posl;
v:=tot_posl^.vazba;
pozice.y:=v^.yy;
VycentrujNaKurzor;
end;

Procedure editacniPole.KlavesaEND;
var v:PEdRadek;
    a:longint;
begin
v:=pozice.r^.vazba;
a:=Sirka_FN(v^.p,nil,v^.spp-1);
pozice.x:=v^.spp;
pozice.vx:=FN_skut_znak;
if a>virt^.breiteminus1 then
   Poc_ZobrX:=-(a-virt^.breiteminus1+4);
end;

Procedure editacniPole.KlavesaHome;
var p:PEdRadek;
begin
pozice.x:=1;
pozice.vx:=1;
Poc_ZobrX:=4;
end;

Function EditacniPole.MoznyPreskokNahoru:boolean;
var v:PEdradek;
    p:Pvaznik;
    i,j:longint;
begin
MoznyPreskokNahoru:=false;
if pozice.y<=1 then Exit;
p:=pozice.r^.predchozi;
v:=p^.vazba;
if v^.crlf then Exit;

i:=DelkaPrvnihoSlova(pozice.r,j);
if j<>pozice.x-1 then Exit;
j:=virt^.breiteminus1-v^.gd-4;
if i<j then
   begin
   Prilep_k_predeslemu(p^.dalsi,true);
   v^.gd:=virt^.breite;
   MoznyPreskokNahoru:=true;
   end;
end;

Procedure editacniPole.PridejTextNaPoziciKurzoru(kp:PChar;ksd:longint);
var v:PEdRadek;
    i:longint;
    b:boolean;
begin
if povolene_zmeny=false then Exit;
if kp[0]=#0 then Exit;
byla_zmena:=true;
v:=pozice.r^.vazba;
v^.Vloz(kp,pozice.x);
inc(pozice.x,ksd);
inc(pozice.vx,1);
i:=Sirka_FN(kp,nil,ksd);
inc(v^.gd,i);
if pozice.x=v^.spp then          {piseme na konci radku?}
   begin
   inc(i,kx);
   if i>virt^.breiteminus1 then
      dec(poc_zobrX,{i-virt^.breiteminus1}160);
      end else
      if PozText.doz<>0 then         {presahuje tento radek pravy okraj obrazovky?}
         if pozice.x-1>=PozText.doz then dec(poc_zobrX,{PozText.posunv}160);

   if zalamuj then
      begin
      poc_zobrX:=4;
      if kp^=' ' then b:=MoznyPreskokNahoru else b:=false;
      v:=pozice.r^.vazba;
      if v^.gd>virt^.breiteminus1-4 then
         begin
         while v^.crlf=false do Prilep_k_predeslemu(pozice.r^.dalsi,true{false});
         NalamejBuffer(pozice.r);
         end;
      {if B then
         begin
         pozice.x:=1;
         pozice.vx:=1;
         inc(pozice.y);
         pozice.r:=pozice.r^.dalsi;
         end;}
      end;
end;

Procedure editacnipole.ZkusZrusitRozpr;
var p:Pvaznik;
begin
if po_kl_jsme_mimo then
   begin
   swap(poc_zobrX,po_kl_poc_zobrX);
   swap(poc_zobrY,po_kl_poc_zobrY);
   p:=prv_rad;prv_rad:=po_kl_prv_rad;po_kl_prv_rad:=p;
   p:=posl_rad;posl_rad:=po_kl_posl_rad;po_kl_posl_rad:=p;
   end
   else begin
   horz_VycentrovaniKurzoru;
   end;
end;

Procedure editacniPole.OsetriVstup;
var o:word;
    i,ksd:longint;
    kp:pchar;
    ks:string[20];
    r:char;
begin
ks:='';
  if xKeyPressed then
    begin
    o:=ed_key_proc(xreadkey);
    ofn:=FN_default;
    nastavFont(hlavni_font);
    if po_kl_rozpr and (o<>0) then ZkusZrusitRozpr;
    case o of
       xLsipka:KrokZpet;
       xPsipka:KrokVpred;
       xDSipka:SipkaDolu;
       xHsipka:SipkaNahoru;
       xDel:KlavesaDel;
       xEnter:KlavesaEnter;
       xEndk:KlavesaEnd;
       xHome:KlavesaHome;
       xPGDN:KlavesaPGDN;
       xPGUP:KlavesaPGUP;
       xCtrlPgUp:KlavesaCtrlPGUP;
       xCtrlPgDn:KlavesaCtrlPGDN;
       xESC:stav:=_escapem;
       8{BackSpace}:BackSpace;
       byte('<'):begin ks:='<<'#0;ksd:=2;end;
       byte('>'):begin ks:='>>'#0;ksd:=2;end;
       else{case o}
       if mimoradne_osetreni_klavesnice=nil then
          if (o<256) and (o>31) then  {ochrana proti CTRL-neco a ALT-neco}
             begin
             if unicode then
                begin
                ks:=Word2UTF8(PrelozZnak(o,utf8_tbl^))+#0;
                ksd:=Length(ks)-1;
                end
                else begin ks:=char(o)+#0;ksd:=1;end;
             end else
          else begin
          ks:=mimoradne_osetreni_klavesnice(o);
          ksd:=Length(ks)-1
          end;
       end;{case o}
    kp:=@ks;inc(kp);

    if (ks<>'') and povolene_zmeny then
       begin
       kp:=@ks;inc(kp);
       PridejTextNaPoziciKurzoru(kp,ksd);
       end;

    nastavFont(ofn);
    if o<>0 then
       begin
       if po_kl_rozpr then po_kl_rozpr:=false;
       zobraz;
       end;
    end{if xKeyPressed}
    else
    if py.probehni then Zobraz;
End;



Function EditacniPole.VXpozice_z_Xpozice(v:PEdRadek;xpoz:longint;tagy:boolean):longint;
var c:char;
    n:longint;
begin
if tagy=false then
   begin
   if unicode=false then Exit(xpoz);
   if xpoz>v^.spp{-1} then xpoz:=v^.spp{-1};
   if xpoz<2 then Exit(1);
   dec(xpoz);
   c:=v^.p[xpoz];
   v^.p[xpoz]:=#0;
   n:=Unilength(v^.p);
   v^.p[xpoz]:=c;
   VXpozice_z_Xpozice:=n+1;
   end
   else begin  {tagy=true}
   n:=Sirka_FN(v^.p,nil,xpoz-1);
   VXpozice_z_Xpozice:=FN_skut_znak;
   end;
end;


Function EditacniPole.UkazatelNaRadku(n:longint):PVaznik;
begin
UkazatelNaRadku:=radky^.SearchRecord(n);
end;


Procedure EditacniPole.OverPoziciKurzorovehoBodu(var kur:TKurPoz);
var v:PEdRadek;
begin
if kur.y>PocetRadku then
   begin
   kur.y:=PocetRadku;
   kur.r:=tot_posl;
   v:=tot_posl^.vazba;
   kur.x:=v^.spp;
   kur.vx:=VXpozice_z_Xpozice(v,kur.x,true);
   Exit;
   end;

v:=kur.r^.vazba;
if kur.x>v^.spp then kur.x:=v^.spp;
kur.vx:=VXpozice_z_Xpozice(v,kur.x, true);
end;


Procedure EditacniPole.SmazRadku(var poz:TKurPoz);
begin
SmazRadku(poz,true);
end;


Procedure EditacniPole.SmazRadku(var poz:TKurPoz;moznosunout:boolean);
{Kur je pozice na ktere se smaze radek (t.j. bud poloha kurzoru nebo jina
 pozice)}
var v:PEdRadek;
    a,b,y1,y2:longint;
    sunout:boolean;
    p:Pvaznik;
begin
v:=poz.r^.vazba;
y1:=v^.y1;
y2:=v^.y2;
v^.Done;
if PocetRadku=1 then
   begin
   v^.Init;     {jestli existuje jen 1 radka, tak ji proste smazu}
   {v^.y1:=y1;
   v^.y2:=y2;}

   v^.y1:=0;
   v^.y2:=Vyska_FN_default-1;
   v^.yy:=1;

   pozice.r^.vazba:=v;  {zalozim novou}
   pozice.x:=1; {a nastavim kurzor na zacatek radky}
   pozice.vx:=1;
   end
   else begin
   v:=poz.r^.vazba;
   Dispose(v,Done);
   if poz.y=pozice.y then b:=0 else
   if poz.y>pozice.y then b:=1 else b:=2;

   if poz.r=tot_posl then        {jsme na posledni radce?}
      begin
      poz.r:=poz.r^.predchozi;
      tot_posl:=poz.r;
      dec(poz.y);
      Dispose(poz.r^.dalsi,Done);
      sunout:=false;
      end
      else begin
      poz.r:=poz.r^.dalsi;
      Dispose(poz.r^.predchozi,Done);
      sunout:=true;
      end;

   dec(PocetRadku);

   if b=0 then
      begin
      v:=poz.r^.vazba;
      poz.x:=Pozice_v_retezci(kx,-1,poc_zobrX,poc_zobrY,v^.p,nil);
      poz.vx:=FN_skut_znak;
      pozice:=poz;
      end else   {kurzor je na mazanem radku}
   if b=2 then dec(pozice.y);     {kurzor je pod mazanym radkem}


   if sunout and moznosunout then
      begin
      if (zalamuj=false) or (poz.y=1)
         then PosunRadek(poz.r)
         else PreskladejRadky(poz);
      end;
   end;
end;


Procedure EditacniPole.SmazCastRadky(poz1,poz2:TKurpoz);
var v:PEdRadek;
    p:PVaznik;
begin
if poz1.x=poz2.x then Exit;
v:=poz1.r^.vazba;
v^.Vyjmi(poz1.x,poz2.x-poz1.x);
if pozice.y=poz1.y then
   if pozice.x>poz2.x then dec(pozice.x,poz2.x-poz1.x+1)
      else if (pozice.x>poz1.x) and (pozice.x<=poz2.x) then pozice.x:=poz1.x;

if zalamuj=true then PreskladejRadky(poz1);
end;


Procedure EditacniPole.SmazSlovo;
var v:PEdRadek;
    a,b,n:longint;
    p,p2:pchar;
    c:char;
begin
v:=pozice.r^.vazba;
if v^.spp=1 then Exit;
LokalizujSlovo_FN(v^.p,v^.spp-1,pozice.x,unicode,0,a,b);
if a=-1 then v^.Vyjmi(pozice.x,1)  {kdyz jsme mezi slovy, tak smaz mezeru}
        else begin  {kurzor neni mezi slovy, ale primo na slove}
        v^.Vyjmi(a+1,b-a+1);
        if a<>b then
           begin
           pozice.x:=a;
           pozice.vx:=VXpozice_z_Xpozice(v,pozice.x,true);
           if zalamuj=true then PreskladejRadky(pozice);
           end;
        end;
end;


Procedure EditacniPole.Presun_o_slovo_vpravo;
var v:PEdRadek;
    a,b,c,d,i,z,k:longint;
begin
v:=pozice.r^.vazba;
if v^.spp=1 then Exit;  {prazdny radek?}

{Nyni pomerne slozite rozhodovani, zda budeme skakat na konec soucasneho
 ci na zacatek nasledujiciho slova}
a:=ZjistiKolikateSlovo_FN(v^.p,v^.spp-1,pozice.x-1,unicode);
if a<=1 then
   begin
   b:=1;
   if a=1 then
      begin
      LokalizujSlovo_FN(v^.p,v^.spp-1,pozice.x-1,unicode,0,z,k);
      if z=-1 then b:=2;
      end;
   end
   else b:=a+1;


Lokalizuj_Nte_slovo_FN(v^.p,v^.spp-1,b,unicode,z,k);
{Z a K jsou podle standardu PChar, t.j. cislovane od 0}
if z=-1 then
   begin
   LokalizujSlovo_FN(v^.p,v^.spp-1,pozice.x-1,unicode,0,z,k);
   {Z a K jsou podle standardu PChar, t.j. cislovane od 0}
   c:=k+2;
   end
   else begin
   if b=1 then c:=k+2 else c:=z+1;
   end;

pozice.x:=c;
pozice.vx:=VXpozice_z_Xpozice(v,pozice.x,true);
d:=pozice.vx;
d:=d;
end;


Procedure EditacniPole.Presun_o_slovo_vlevo;
var v:PEdRadek;
    a,i,ps,z,k:longint;
begin
v:=pozice.r^.vazba;
if v^.spp=1 then Exit;
if pozice.x=1 then Exit;

ps:=Dej_Pocet_slov_FN(v^.p,v^.spp-1,unicode);
{zjisti pocet slov v akt. radku}
a:=ZjistiKolikateSlovo_FN(v^.p,v^.spp-1,pozice.x-1,unicode);
{a na kolikatem slove je kurzor?}
LokalizujSlovo_FN(v^.p,v^.spp-1,pozice.x-1,unicode,1,z,k);
{a odkud kam to slovo saha?}


(*if a<ps then      {kdyz nejsme na poslednim slove...}
   begin*)
   if a=0 then         {jsme jeste pred prvnim slovem?}
      begin
      KlavesaHome;
      Exit;
      end;

   if pozice.x-1>z then
      begin
      pozice.x:=z+1;
      end
      else
      begin
      Lokalizuj_Nte_slovo_FN(v^.p,v^.spp-1,a-1,unicode,z,k);
      pozice.x:=z+1;
      end;
(*   end;*)

pozice.vx:=VXpozice_z_Xpozice(v,pozice.x,true);
end;



Procedure EditacniPole.SmazBlokTextu(zac,kon:TKurPoz);
var v:PEdRadek;
    temp,temp2:TKurPoz;
    z:boolean;
    b:byte;
    i,j:longint;
    p:PVaznik;

begin
v:=zac.r^.vazba;
if zac.y=kon.y then
   begin
   if (zac.x=1) and (kon.x=v^.spp)
      then begin SmazRadku(zac);Exit;end
      else begin SmazCastRadky(zac,kon);Exit;end;
   end
   else begin
   z:=zalamuj;
   zalamuj:=false;


   {Napred smazu vsechny zarucene kompletni radky}
   i:=kon.y-zac.y;
   if i>=2 then
      for j:=1 to i-1 do
          begin {mazani kompletnich radek mezi startovni a cilovou pozici}
          temp:=zac;
          inc(temp.y);
          temp.r:=zac.r^.dalsi;
          v:=temp.r^.vazba;
          dec(kon.y);
          SmazRadku(temp,false);
          end;
   {zbyva pocatecni radek a koncovy radek}
   if zac.x=1 then
      begin
      temp:=zac;
      zac.r:=zac.r^.predchozi;
      v:=temp.r^.vazba;
      SmazRadku(temp,false);
      dec(kon.y);
      end
      else begin
      temp:=zac;
      v:=temp.r^.vazba;
      temp.x:=v^.spp;
      SmazCastRadky(zac,temp);
      end;

   {zbyva posledni radek}
   v:=kon.r^.vazba;
   if kon.x>=v^.spp then
      begin
      temp:=kon;
      kon.r:=kon.r^.dalsi;
      v:=temp.r^.vazba;
      SmazRadku(temp,false);
      end
      else begin
      temp:=kon;
      temp.x:=1;
      SmazCastRadky(temp,kon);
      end;

   zalamuj:=z;
   if kon.r=nil then
      begin
      VycentrujNaKurzor;
      Exit;  {byla smazana i cela posledni radka?}
      end;

   if zalamuj=true then PreskladejRadky(zac,true,false,true)
      else begin

         if zac.x>1 then
            begin
            v:=kon.r^.vazba;
            temp.r:=kon.r^.dalsi;
            Prilep_K_predeslemu(kon.r,false);
            kon.r:=temp.r;
            if kon.r=nil then
               begin
               VycentrujNaKurzor;
               Exit;
               end;
            end;

         PosunRadek(kon.r);

         {Pozor, muze hybat s promennou POZICE}
      end;
   end;
VycentrujNaKurzor;
byla_zmena:=true;
end;


Procedure EditacniPole.VlozTextNaPozici(blok:PVaznik;poz:TKurPoz);
var v1,v2,v3,v4:PEdRadek;
    p,r,t,u:PVaznik;
    gd,kk,kl,n:longint;
    temp:TKurPoz;

begin
p:=blok^.dalsi;

{napred vlozim radku textu na radku, kde je kurzor
(tzn. nezakladam nove radky)}
v1:=p^.vazba;
r:=poz.r;
v2:=r^.vazba;
v2^.Vloz(v1^.p,v1^.spp-1,poz.x);

gd:=Sirka_FN(v1^.p,nil,v1^.spp-1);
inc(v2^.gd,gd);
v3:=v2;
p:=p^.dalsi;
if p=nil then Exit;  {Kopiruje se jen jeden radek? V tom pripade jsme hotovi}

{ted preskocim na posledni radek}
n:=1;
kk:=0;
temp:=poz;
inc(temp.x,v1^.spp-1);
RozdelRadku(temp,kl);   {vznikla nova radka (je na ni cast predchozi radky)}
inc(kk,kl);
v2:=r^.dalsi^.vazba;
t:=blok^.SearchLast;    {pripravim si posledni radku bloku}
v1:=t^.vazba;

v2^.Vloz(v1^.p,v1^.spp-1,1);  {vlozeni}
v4:=v2;
gd:=Sirka_FN(v1^.p,nil,v1^.spp-1);
inc(v2^.gd,gd);

if p<>t then {Kopirovaly se jen dva radky?}
   while p<>t do
      begin         {ted uz budu muset zakladat nove radky}
      v1:=p^.vazba;
      v2:=New(PEdRadek,Init);
      v2^.Vloz(v1^.p,v1^.spp-1,1);
      gd:=Sirka_FN(v1^.p,nil,v1^.spp-1);
      inc(v2^.gd,gd);
      v2^.yy:=v3^.yy+1;
      v2^.y1:=v3^.y2+1;
      v2^.y2:=v2^.y1+(v3^.y2-v3^.y1);

      u:=New(PVaznik,Init(nil,nil));
      u^.vazba:=v2;
      r^.Insert(u);

      inc(n);
      inc(PocetRadku);
      v3:=v2;
      r:=u;
      p:=p^.dalsi;
      end;

v4^.yy:=v3^.yy+1;
v4^.y1:=v3^.y2+1;
v4^.y2:=v4^.y1+(v3^.y2-v3^.y1);

if r^.dalsi=tot_posl then Exit;

if zalamuj=false
   then PosunRadek(r^.dalsi^.dalsi)
   else PreskladejRadky(poz);
end;


Procedure EditacniPole.vert_VycentrovaniKurzoru;
var v:PEdRadek;
    a,b:longint;
begin
v:=pozice.r^.vazba;

a:=v^.y1;
b:=v^.y2;

if (v^.y1<poc_zobrY) or (v^.y2>poc_zobrY+virt^.hoehe) then
   poc_ZobrY:=v^.y1-virt^.hoehe div 2;
if poc_ZobrY<0 then poc_ZobrY:=0;
end;

Procedure EditacniPole.horz_VycentrovaniKurzoru;
var v:PEdRadek;
    c:char;
    xx:longint;
begin
v:=pozice.r^.vazba;
xx:=Sirka_FN_na_Xpoz(v^.p,nil,pozice.x);
pozice.vx:=FN_skut_znak;
if zalamuj=false then
   begin
   poc_ZobrX:=-(xx-virt^.breite div 2);
   if poc_ZobrX>-100 then poc_ZobrX:=4;
   end;
end;

Procedure EditacniPole.VycentrujNaKurzor;
{jestlize nejaky jiny proces nastavil promenou POZICE a je treba zajistit,
aby tato pozice byla v zobrazovanem useku.}
begin
vert_VycentrovaniKurzoru;
horz_VycentrovaniKurzoru;
end;

Procedure EditacniPole.BlikejKurzorem;
var b,n:boolean;
    kyy1,kyy2:longint;
begin
{if prinutit and (kkx<>-1) then PutSprite(cil^,kpoz,kkx,kky);}
if povolene_zmeny=false then Exit;
kpoz.hoehe:=kd;
kkx:=kx+x;
kky:=ky-poc_ZobrY+y;

kyy1:=kky;
kyy2:=kky+kd-1;

b:=ProvedClippingVertikalniCary(kyy1,kyy2,y,y+vyska-1);
if b=false then Exit;

if je_videt then
   begin
   {kpoz.hoehe:=20;}
   n:=PrunikMysi(kkx,kyy1,kkx,kyy2);
   if N then mousehide;
   GetClippedSprite(cil^,kpoz,kkx,kyy1);
   LineClipped(cil^,kkx,kyy1,kkx,kyy2,popredi);
   if N then mouseshow;
   end
   else begin
   n:=PrunikMysi(kkx,kyy1,kkx,kyy2);
   if N then mousehide;
   PutClippedSprite(cil^,kpoz,kkx,kyy1);
   if N then mouseshow;
   end;
end;

Procedure editacniPole.ZhasniKurzor;
begin
if je_videt then
   begin
   je_videt:=false;
   BlikejKurzorem;
   end;
end;

Procedure editacniPole.RozsvitKurzor;
begin
if je_videt=false then
   begin
   je_videt:=true;
   BlikejKurzorem;
   end;
end;

Function EditacniPole.PismenoZpet:longint;
var p,i,j:longint;
begin
p:=poc_ZobrX;
i:=pozice.x;
j:=pozice.vx;
KrokZpet;
PismenoZpet:=pozice.x;
pozice.vx:=j;
pozice.x:=i;
poc_ZobrX:=p;
end;


Procedure EditacniPole.VypisRadekTextu(ix:longint;p:PVaznik;v:PEdRadek);
begin
Print_FN(ix,AUTO_LINE,v^.p,v^.spp-1,nil);
end;


Procedure EditacniPole.Zobraz;
   Procedure EdPrint_Vaznik_ROZPR;
   {VOLA SE V PRIPADE POSUVNIKO-KLAVESOVEHO ROZPORU - NEOPTIMALIZOVANO}
   var v,kv:PEdradek;
       p:PVaznik;
   begin
   po_kl_jsme_mimo:=true;
   p:=radky^.dalsi;
   while p<>nil do   {napred preskocim radky, ktere jsou nad vyrezem}
      begin v:=p^.vazba;if v^.y2-poc_ZobrY>0 then Break;p:=p^.dalsi;end;
   prv_rad:=p;
   while p<>nil do
      begin
      v:=p^.vazba;
      if v^.y1-poc_zobrY>=virt^.hoehe then Break;   {jsme pod vyrezem? tak konec}
      if p=po_kl_pozice.r then
         po_kl_jsme_mimo:=false;  {radek s kurzorem byl vypsan i v tomto rezimu}

      SetBasicLine(v^.y1-poc_ZobrY);
      VypisRadekTextu(poc_zobrX,p,v);

      posl_rad:=p;
      p:=p^.dalsi;
      end;
   end;

   Procedure EDPrint_Vaznik_NORM;
   {VOLA SE POKUD NIKDO NEHRABAL NA POSUVNIK - JE RYCHLEJSI}
   var v:PEdRadek;
       i:longint;
       b:boolean;
       p:PVaznik;

   begin
   {Zvlastnosti teto procedury je, ze nepise radky po sobe}
   i:=pozice.y;
   v:=pozice.r^.vazba;
   {napred vypisu radek, na kterem je kurzor}
   FN_poloha.B:=URCIZNAK;     {budu chtit znam polohu aktualniho znaku na obrazovce}

   FN_poloha.N:=pozice.x-1;     {(stejne jako jeste dalsi podobne veci)}
   (*FN_poloha.N:=PismenoZpet;  {PROC TOHLE  NEFUNGUJE???}*)

   SetBasicLine(v^.y1-poc_ZobrY);
   VypisRadekTextu(poc_zobrX,p,v);
   {Print_FN(poc_zobrX,AUTO_LINE,v^.p,v^.spp-1,nil);}

   prv_rad:=pozice.r;   {napred predpokladam, ze to je prvni viditelna radka}
   posl_rad:=pozice.r;  {a ze je to taky posledni viditelna radka}

   ky:=v^.y1;
   if pozice.x=1 then
      kx:=poc_zobrX else kx:=FN_poloha.x; {polohu zname, takze tam umistime kurzor}
   kd:=v^.y2-v^.y1+1;
   PozText.doz:=FN_poloha._doz;
   PozText.odz:=FN_poloha._odz;
   PozText.posunv:=FN_poloha._posunv;
   PozText.posunm:=FN_poloha._posunm;
   {ted vypisu radky pod kurzorem - ovsem jenom ty, co se vejsou na obrazovku}
   p:=pozice.r^.dalsi;
   while p<>nil do
      begin
      v:=p^.vazba;
      if v^.y1-poc_ZobrY<virt^.hoehe then
         begin
         SetBasicLine(v^.y1-poc_ZobrY);
         {Print_FN(poc_zobrX,AUTO_LINE,v^.p,v^.spp-1,nil);}
         VypisRadekTextu(poc_zobrX,p,v);

         posl_rad:=p;
         end
         else begin
         posl_rad:=p^.predchozi;  {zapamatuje si posledni zcela viditelnou radku}
         Break;
         end;
      p:=p^.dalsi;
      end;

   {a nad kurzorem - zase jenom ty, co se vejsou na obrazovku}
   p:=pozice.r^.predchozi;
   while p^.predchozi<>nil do
      begin
      v:=p^.vazba;
      if v^.y2-poc_ZobrY>0 then
         begin
         SetBasicLine(v^.y1-poc_ZobrY);
         {Print_FN(poc_zobrX,AUTO_LINE,v^.p,v^.spp-1,nil);}
         VypisRadekTextu(poc_zobrX,p,v);
         prv_rad:=p;        {zapamatuje si prvni viditelnou radku}
         end
         else begin
         Break;
         end;
      p:=p^.predchozi;
      end;
   end;

{===================== HLAVNI TELO PROCEDURY ZOBRAZ =========================}
var skutecna_sirka:longint;
    i,ll,ofnc:longint;
    v:PEdRadek;
begin
if jednorazove_zakazani_zobrazeni=true then
   begin
   jednorazove_zakazani_zobrazeni:=false;
   Exit;
   end;

Ufon;
{ZkontrolujYY;}
ofnc:=FN_color;
FN_color:=popredi;
NastavVystup(virt^);
SetBasicLine(poc_zobrY);
ll:=GetLastLine;
SetLastLine(virt^.hoehe-1);

if po_kl_rozpr then EdPrint_Vaznik_ROZPR
               else EdPrint_Vaznik_NORM;
SetLastLine(ll);
MouseLock;
MouseSelfCopy(virt^,x,y);
PutSprite_and_clear(cil^,virt^,x,y,pozadi);
MouseUnLock;

if (stav<>_odkliknutim) then
   begin
   je_videt:=true;
   puvodni_citac:=FromTimer;
   BlikejKurzorem;
   end;

{mouseshow;}
py.hodnota:=poc_ZobrY;
v:=tot_posl^.vazba;
py.virtvyska:=v^.y2;
py.Zobraz;
NastavVystup(cil^);

FN_color:=ofnc;

DodatkyPoZobrazeni; {Prilezitost pro aplikaci zobrazit si doplnky}
Ofon;
end;


Procedure EditacniPole.DodatkyPoZobrazeni;
begin {Defaultne prazdne} end;


Procedure EditacniPole.ZmenBarvuPozadi(w:word);
begin
pozadi:=w;
Clr(virt^,pozadi);
end;


Procedure EditacniPole.EP_ZavriSoubor;
var v:PEdRadek;
    i:dword;
begin
i:=0;
while radky^.dalsi<>nil do
    begin
    inc(i);
    v:=radky^.dalsi^.vazba;
    if v<>nil then dispose(v,Done); {V by ale melo byt prirazeno vzdy...}
    dispose(radky^.dalsi,done);
    end;
end;

Procedure EditacniPole.NovySoubor;
var v:PEdRadek;
    i:longint;
begin
ufon;
EP_ZavriSoubor;
v:=New(PEdRadek,Init);
v^.y1:=0;
i:=Vyska_FN_default-1;
v^.y2:=i;
v^.yy:=1;
radky^.InitNext(v);
SkocNaZacatek;
tot_posl:=pozice.R;
PocetRadku:=1;
byla_zmena:=false;
ofon;
end;

Procedure EditacniPole.EP_PridejVetsi(v:PEdRadek);
var k,u,n:longint;
    r:real;
    tbm:string;

begin
k:=0;
n:=v^.spp-1;
while k<=n do
   begin
   if v^.p[k]='<' then
      begin
      v^.vloz('<',1,k+1);
      inc(k,2);
      inc(n);
      end else
   if v^.p[k]='>' then
      begin
      v^.vloz('>',1,k+1);
      inc(k,2);
      inc(n);
      end else
   if v^.p[k]=#9 then {rozklad tabulatoru na mezery}
      begin
      v^.vyjmi(k+1,1);
      u:=(k+1) mod tab_na_mezery;
      u:=tab_na_mezery-u+1;
      tbm:=XMezer(u);
      v^.vlozS(tbm,k+1);
      inc(n,u-1);
      end
      else begin
      if v^.p[k]>#127 then
      {Detekce, je-li soubor v unicode ci, jsou-li to 8-bitove narodni znaky}
         begin
         inc(prac1);
         if v^.p[k]<#224 then
            if k<n then if (v^.p[k+1]>#127) and (v^.p[k+1]<#192) then
               begin inc(k);inc(prac2);end
            else else else {>224 tzn. 3bajtove znaky}
            if k-1<n then if (v^.p[k+1]>#127) and (v^.p[k+1]<#192) and (v^.p[k+1]>#127) and (v^.p[k+1]<#192) then
               begin inc(k,2);inc(prac2);end;
         end;
      inc(k);

      end;
   end;
end;

Procedure EditacniPole.EP_UberVetsi(v:PEdRadek);
var k,l:longint;
begin
l:=v^.spp-1;
k:=0;
while k<=l do
   begin
   if (v^.p[k]='<') {and (hodnota[k+1]='<')} then
      begin
      v^.vyjmi(k+1,1);
      dec(l);
      end else
   if (v^.p[k]='>') {and (hodnota[k+1]='<')} then
      begin
      v^.vyjmi(k+1,1);
      dec(l);
      end;
   inc(k);
   end;
end;


Procedure EditacniPole.NastavRozmeziRadku(v:PEdRadek;var yz:longint);
begin
if jednotna_vyska_radku then
   begin
   v^.y1:=yz;
   v^.y2:=yz+vyska_fn(NastavenyFont)-1;
   yz:=v^.y2+1;
   end
   else begin
   v^.y1:=yz;
   v^.y2:=v^.y1+RychlaVyskaRadky(v^.p);
   yz:=v^.y2+1;
   end;
end;


Procedure EditacniPole.UpravRozmeziRadku(v:PEdRadek;var yz:longint);
begin
if jednotna_vyska_radku=false then
   begin
   v^.y2:=v^.y1+RychlaVyskaRadky(v^.p);
   yz:=v^.y2+1;
   end;
end;



Procedure EditacniPole.PridelRadky;
var p:PVaznik;
    v:PEdRadek;
    vfn,pryy,i:longint;
    f:fn;
begin
vfn:=Vyska_FN(FN_selector^[Nacti_FNSLR(hlavni_font)].font);
ofn:=fn_default;
nastavfont(hlavni_font);
i:=0;
pryy:=0;
p:=radky^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   inc(pryy);
   NastavRozmeziRadku(v,i);  {nastavi v^.y1 a v^.y2 a upravi I}
   v^.yy:=pryy;
   if zalamuj then v^.gd:=virt^.breite else
      v^.gd:=Sirka_FN(v^.p,nil,v^.spp-1);
   p:=p^.dalsi;
   end;
nastavfont(ofn);
if zalamuj then NalamejBuffer(radky^.dalsi);
end;


Procedure EditacniPole.PosunRadek(p:PVaznik);
{Nesnazi se zjistovat vysku radek, ale proste upravi jejich Y1 a Y2 a YY aby
 na sebe navazovaly}
var v,w:PEdRadek;
begin
if p=nil then Exit;
if p^.predchozi=nil then Error('Error in EditacniPole.PosunRadky!','');
{jsme na nultem radku? Tak to je chyba.}

if p^.predchozi^.predchozi=nil then  {jsme na prvnim radku? To muze byt.}
   begin
   v:=p^.vazba;
   v^.yy:=1;
   v^.y2:=v^.y2-v^.y1;
   v^.y1:=0;
   p:=p^.dalsi;
   end;

while p<>nil do     {Ted zpracuji dalsi radky}
   begin
   v:=p^.vazba;
   w:=p^.predchozi^.vazba;
   v^.yy:=w^.yy+1;
   v^.y2:=v^.y2-v^.y1+w^.y2+1;
   v^.y1:=w^.y2+1;
   p:=p^.dalsi;
   end;
end;


Procedure EditacniPole.PreskladejRadky(poz:TKurPoz);
begin
PreskladejRadky(poz,true,true,true);
end;


Procedure EditacniPole.PreskladejRadky(poz:TKurPoz;m1,m2,m3:boolean);
var p:PVaznik;
    v:PEdRadek;
begin
p:=poz.r^.predchozi;
v:=p^.vazba;

if not v^.crlf then
   begin
   Prilep_k_predeslemu(p^.dalsi,m1); {eventualni spojeni s hornim radkem}
   end
   else begin
   p:=poz.r;
   v:=p^.vazba;
   end;

if not v^.crlf then Prilep_k_predeslemu(p^.dalsi,m2);
while not v^.crlf do Prilep_k_predeslemu(p^.dalsi,m3);

v^.gd:=virt^.breite;
if p^.predchozi^.predchozi<>nil then p:=p^.predchozi;
NalamejBuffer(p);
end;



Procedure EditacniPole.NalamejBuffer(pr:PVaznik);
var v,v2,nv:PEdRadek;
    p,novy:PVaznik;
    a,i,l,oi,pryy,yz,vrad:longint;
    d1,d2,d3,d4:longint;
    dbg:string;
    f:fn;
begin
p:=pr;
v:=p^.vazba;
yz:=v^.y1;
pryy:=v^.yy;
{f:=String2FN(hlavni_font);}
ofn:=fn_default;
nastavfont(hlavni_font);

while p<>nil do
   begin
   v:=p^.vazba;
   NastavRozmeziRadku(v,yz); {YZ se automaticky inkrementuje}
   v^.yy:=pryy;
   if v^.gd>virt^.breiteminus1-4 then
      begin
      i:=Pozice_v_retezci(virt^.breiteminus1,v^.y1+1,4,0,v^.p,nil);
      if i<v^.spp then
         begin               {dlouha radka - bude treba zalamovat}
         oi:=i;
         v^.smezerou:=true;

         {pujdu zpatky a budu hledat mezeru}
         while v^.p[i-1]<>' ' do
            if i=1 then begin i:=oi;v^.smezerou:=false;Break;end else dec(i);
         {I je ted na posledni mezere od predchoziho slova}
         if v^.smezerou then l:=1 else l:=0;

         nv:=New(PedRadek,Init);
         v^.Rozdel(nv^,i,l);
         v^.gd:=Sirka_FN(v^.p,nil,v^.spp-1);
         a:=FN_skut_znak;


         UpravRozmeziRadku(v,yz);  {eventualne prenastavi v^.y2 a YZ}

         v^.crlf:=false;     {radek uz neni ukoncen natvrdo pomoci CRLF, ale je ukoncen pruzne}
         nv^.gd:=Sirka_FN(nv^.p,nil,nv^.spp-1);
         dec(i,l);
         novy:=New(PVaznik,Init(nil,nil));
         novy^.vazba:=nv;
         p^.insert(novy);
         inc(pocetradku);
         if pozice.y=v^.yy then
            begin
            if pozice.x>i then {nemuze tu byt >=}
               begin
               v2:=posl_rad^.vazba;
               if v^.y2+RychlaVyskaRadky(v^.p)-Poc_ZobrY>virt^.hoehe-1
                  then inc(poc_ZobrY,vyska_fn(f)+1);
               pozice.y:=pozice.y+1;
               pozice.x:=pozice.x-i-1;

               Sirka_FN_na_Xpoz(nv^.p,nil,pozice.x);

               pozice.vx:=FN_skut_znak;
               pozice.r:=novy;
               end;
            end;

         if posledni_vyskyt.y=v^.yy then posledni_vyskyt.r:=nil;

         end
         else begin          {radka se na obrazovku preci jen vejde - nebudu zalamovat}
         v^.gd:=FN_poz_v_ret_delka_radky;
         v^.crlf:=true;
         end;
      end;
   inc(pryy);
   tot_posl:=p;
   p:=p^.dalsi;
   end;
if pozice.x=0 then pozice.x:=1; {vojeb, spravne by nemelo nikdy nastat}
nastavfont(ofn);
end;


Procedure EditacniPole.PospojujRadky(merit:boolean);
var p:PVaznik;
    v:PEdRadek;
    i,j:longint;
begin
i:=0;
j:=Vyska_FN(FN_selector^[Nacti_FNSLR(hlavni_font)].font);
p:=radky^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   while v^.crlf=false do
      Prilep_k_predeslemu(p^.dalsi,true); {druhy radek prilepi k prvnimu}
   v^.y1:=i;
   v^.y2:=i+j-1;
   inc(i,j);
   if merit then v^.gd:=Sirka_FN(v^.p,nil,v^.spp-1) else v^.gd:=virt^.breite;
   tot_posl:=p;
   p:=p^.dalsi;
   end;
end;

Procedure EditacniPole.ZmenFont(s:string);
var a,b:longint;
    p:PVaznik;
    v:PEdRadek;
    f:fn;
begin
if zalamuj then
   begin
   PospojujRadky(false);
   hlavni_font:=s;
   NalamejBuffer(radky^.dalsi);
   end else
   begin
   p:=radky^.dalsi;
   hlavni_font:=s;
   a:=Nacti_FNSLR(s);
   f:=FN_selector^[a].font;
   b:=vyska_fn(f);
   a:=0;
   while p<>nil do
      begin
      v:=p^.vazba;
      v^.y1:=a;
      v^.y2:=a+b-1;
      inc(a,b);
      v^.gd:=Sirka_FN(v^.p,nil,v^.spp-1);
      p:=p^.dalsi;
      end;
   end;
end;

Procedure SrovnejYYradek(p:Pvaznik);
var v:PEdRadek;
    i:longint;
begin
i:=0;
p:=p^.dalsi;
while p<>nil do
   begin
   inc(i);
   v:=p^.vazba;
   v^.yy:=i;
   p:=p^.dalsi;
   end;
end;

Function EditacniPole.DejLinearniPozici:longint;
var p:PVaznik;
    v:PEdRadek;
    i:longint;
begin
i:=0;
p:=radky^.dalsi;
while p<>pozice.r do
   begin
   v:=p^.vazba;
   i:=i+v^.spp;
   p:=p^.dalsi;
   if p=nil then Break;  {vojeb, nemelo by nikdy nastat}
   end;
i:=i+pozice.x;
DejLinearniPozici:=i;
end;

Procedure EditacniPole.NastavLinearniPozici(i:longint);
var p:PVaznik;
    v:PEdRadek;
    j,k,l:longint;
begin
j:=0;
k:=1;
p:=radky^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   if j+v^.spp>i-1 then break else inc(j,v^.spp);
   inc(k);
   p:=p^.dalsi;
   end;
pozice.r:=p;
pozice.y:=k;
pozice.x:=i-j;

if pozice.x=0 then pozice.x:=1; {vojeb, nemelo by nikdy nastat}
v:=pozice.r^.vazba;
pozice.vx:=VXpozice_z_Xpozice(v,pozice.x,true);
end;

Procedure EditacniPole.PosouvaciRezim;
var i:longint;
begin
i:=DejLinearniPozici;
zalamuj:=false;
PospojujRadky(true);
SrovnejYYradek(radky);
NastavLinearniPozici(i);
{SkocNaZacatek;}
VycentrujNaKurzor;
end;

Procedure EditacniPole.ZalamovaciRezim;
var i:longint;
begin
i:=DejLinearniPozici;
zalamuj:=true;
NalamejBuffer(radky^.dalsi);
NastavLinearniPozici(i);
{SkocNaZacatek;}
VycentrujNaKurzor;
end;

Procedure EditacniPole.SkocNaZacatek;
begin
poc_ZobrX:=4;
poc_ZobrY:=0;
pozice.x:=1;
pozice.vx:=1;
pozice.y:=1;
pozice.r:=radky^.dalsi;
end;

Function EditacniPole.NactiZeStreamu(var s:TStream):byte;
const BUFFER = 65536;
var l,m,k:longint;
    p:pchar;
    r:PVaznik;
    v:PEdRadek;
    pokracovat,byl_zobrazen_postup_nahravani:boolean;
    z_timeru:dword;

begin
ufon;
MouseSetCursor(UKmysCekej);
l:=s.GetSize;
if l=0 then
   begin
   ofon;
   NovySoubor;
   MouseSetCursor(UKmys);
   NactiZeStreamu:=edna_OK;
   Exit;
   end;
MyGetMem(p,BUFFER+1);
EP_ZavriSoubor;         {Odstrani prave nactenou vec}
tot_posl:=nil;
pokracovat:=true;
PocetRadku:=0;

byl_zobrazen_postup_nahravani:=false;
z_timeru:=FromTimer;

{postup:=l>=BUFFER*10;}

repeat
l:=s.GetPos;               {zaznamenam pozici ve streamu pred ctenim}
s.Read(p^,BUFFER);        {pokusim se precist VELBUF bajtu}
if s.status<>stOK then  {nedoslo ke cteni za koncem souboru?}
   begin
   s.reset;                {resetuj chybovy stav}
   l:=s.GetSize-l;         {a zjisti, jak velky byl tento posledni usek}
   s.Read(p^,l);           {udelam tedy druhy pokus o nacteni}
   end
   else l:=s.GetPos-l;     {o kolik bajtu jsme se soupli?}
if l<>0 then
   begin
   if p[0]=#10 then m:=1 else m:=0;  {kdyz minuly blok skoncil #13 a na zacatku }                                  {tohodle by z CRLF zustalo #10}
   repeat
      k:=IndexByte(p[m],l,13);    {budu hledat #13 - tedy Enter}
      if k=-1 then
         begin
         DalsiRadka(p,m,false);
         m:=l;
         end;

      if k<>-1 then
         begin
         {Ted by nebylo od veci zkontrolovat, jesli se v tomhle useku nevyskytuje
         znak #0 a v tom pripade ho nahradit mezerou}
         p[m+k]:=#0;           {znak #13 nahradim znakem #0}
         DalsiRadka(p,m,true);
         if p[m+k+1]=#10 then inc(m,k+2) else inc(m,k+1);
         end;
   until m>=l;
   if ukaz_postup_nahravani<>nil then
      if TimerTicksFrom(z_timeru,15)=true then
         begin
         z_timeru:=FromTimer;
         byl_zobrazen_postup_nahravani:=true;
         pokracovat:=Ukaz_Postup_Nahravani(s.GetPos/s.GetSize*100);
         if pokracovat=false then
            begin
            ofon;
            NovySoubor;
            MouseSetCursor(UKmys);
            FreeMem(p,BUFFER+1);
            NactiZeStreamu:=edna_CANCELED;
            Exit;
         end;
      end;
   end;

until l<>BUFFER;
if byl_zobrazen_postup_nahravani=true then Ukaz_Postup_Nahravani(-1);

DalsiRadka(nil,0,true);     {ukoncime pripadnou rozdelanou radku}
FreeMem(p,BUFFER+1);
SkocNaZacatek;
MouseSetCursor(UKmys);
NactiZeStreamu:=edna_OK;
if zalamuj then NalamejBuffer(pozice.r);
ofon;
end;

Procedure EditacniPole.DalsiRadka(u:PChar;poz:longint;ukoncena:boolean);
var k,y1,yy:longint;
    v,e:PEdRadek;
    b:boolean;
begin
if tot_posl<>nil then
   begin
   e:=tot_posl^.vazba;
   y1:=e^.y2+1;
   yy:=e^.yy+1;
   b:=e^.smezerou;     {je predchozi radek ukoncen?}
   end
   else begin
   y1:=0;yy:=1;
   tot_posl:=radky;
   b:=true;
   end;
if u<>nil then inc(u,poz);
if B then {delame uplne novy radek}
   begin
   if u=nil then Exit;
   v:=New(PEdRadek,Init);
   v^.Vloz(u,1);
   v^.smezerou:=ukoncena;
   if ukoncena then
      begin
      if konverze_tagu then EP_PridejVetsi(v);
      v^.gd:=Sirka_FN(v^.p,nil,v^.spp-1);
      end;
   if jednotna_vyska_radku=true
      then k:=RychlaVyskaRadky('')
      else k:=RychlaVyskaRadky(v^.p);
   v^.y1:=y1;
   v^.y2:=y1+k-1{?};
   v^.yy:=yy;
   inc(PocetRadku);
   tot_posl:=tot_posl^.InitNext(v);   {Doplnim posledni radku}
   end
   else begin
   if u<>nil then e^.Vloz(u,e^.spp);
   e^.smezerou:=ukoncena;
   if ukoncena then
      begin
      if konverze_tagu then EP_PridejVetsi(e);
      e^.gd:=Sirka_FN(e^.p,nil,e^.spp-1);
      end;
   end;
end;

Function EditacniPole.NactiZVazniku(p:PVaznik):boolean;
var q,r:PVaznik;
    u:PChar;
    v:PString;
    z:string;
    i:longint;
    e:PEdRadek;
begin
EP_ZavriSoubor; {Odstrani prave nactenou vec}
PocetRadku:=0;
tot_posl:=nil;
u:=p^.vazba;
Move(u^,z,4);
z[0]:=#3;
if z='#*#' then        {pro jednoradkove textiky}
   begin
   v:=pointer(u);
   z:=v^;
   delete(z,1,4);
   i:=Pos('#',z);
   delete(z,1,i+1);
   z:=z+#0;
   u:=@z[1];
   DalsiRadka(u,0,true);
   end
   else begin          {pro viceradkove texty}
   p:=p^.dalsi;
   while p<>nil do
      begin
      v:=p^.vazba;
      z:=v^+#0;
      u:=@z[1];
      DalsiRadka(u,0,true);
      p:=p^.dalsi;
      end;
   end;
SkocNaZacatek;
zalamuj:=true;
NalamejBuffer(pozice.r);
Zobraz;
end;

Function EditacniPole.NactiSoubor(s:string):byte;
var t:TBufStream;
begin
if not ExistFile(s) then Exit(edna_NOFILE);
t.Init(s,stOpenRead,32768);
NactiSoubor:=NactiZeStreamu(t);
byla_zmena:=false;
t.Done;
end;

Function EditacniPole.UlozDoStreamu(var s:TStream):boolean;
var p:pointer;
    r:PVaznik;
    v:PEdRadek;
    m,l,k:longint;
    crlf:word;
    mz:char;
begin
crlf:=$0a0d;
mz:=' ';
MouseSetCursor(UKmysCekej);
r:=radky^.dalsi;
while r<>nil do
   begin
   v:=r^.vazba;
   if v^.spp>1 then
      begin
      if konverze_tagu then EP_UberVetsi(v);
      l:=v^.spp-1;      {nepocitam ukoncovaci #0}
      s.Write(v^.p^,l);
      if konverze_tagu then EP_PridejVetsi(v);
      end;
   if v^.crlf then s.Write(crlf,2) else s.Write(mz,1);
   r:=r^.dalsi;
   end;
MouseSetCursor(UKmys);
UlozDoStreamu:=true;
end;

Function EditacniPole.UlozSoubor(s:string):boolean;
var t:TMemoryStream;
    t2:TBufStream;
    b:byte;
    d1,e2,e3:string;
begin
s:=FExpand(s);
Fsplit(s,d1,e2,e3);     { chceme adresar, jmeno a priponu cile }
if not ExistDir(d1) then
   begin
   b:=MakeDir(d1);  { testneme zacatek cesty }
   if b<>0 then Exit(false);
   end;
t.Init(40000,20000);
UlozSoubor:=UlozDoStreamu(t);
t.seek(0);
t2.Init(s,stCreate,40000);
if t2.ErrorInfo<>0 then
   begin t.Done;t2.Done;Exit(false);end;

t2.CopyFrom(t,t.GetSize);
if t2.ErrorInfo<>0 then
   begin t.Done;t2.Done;Exit(false);end;
t.Done;
t2.Done;
byla_zmena:=false;
UlozSoubor:=true;
end;

Function Editacnipole.ZkontrolujYY:boolean;
var p:Pvaznik;
    v:PEdRadek;
    a:longint;

    s:string;
    yy,_yy,yy_:longint;
begin
ZkontrolujYY:=true;
a:=0;
p:=radky^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   if v^.yy=a+1 then inc(a)
      else begin
      s:=v^.p;
      yy:=v^.yy;
      v:=p^.predchozi^.vazba;
      _yy:=v^.yy;
      v:=p^.dalsi^.vazba;
      _yy:=v^.yy;
      end;
   p:=p^.dalsi;
   end;
end;


Procedure EditacniPole.NastavBodOznaceni(b:byte;poz:TKurPoz);
begin
if (b=1) or (b=2) then
   begin
   poz_ozn[b]:=poz;
   if (poz_ozn[1].y<>0) and (poz_ozn[2].y<>0) then
      if PorovnejPozKurzoru(poz_ozn[1],poz_ozn[2])<>2 then SmazBodyOznaceni;
   end;
end;


Procedure EditacniPole.SmazBodyOznaceni;
begin
NulujBodKurzoru(poz_ozn[1]);
NulujBodKurzoru(poz_ozn[2]);
end;


Function EditacniPole.Zda_oznacen_blok:boolean;
begin
if (poz_ozn[1].y=0) or (poz_ozn[2].y=0)
   then Zda_oznacen_blok:=false
   else Zda_oznacen_blok:=true;
end;


Function EditacniPole.Pocet_radek_bloku:longint;
var i:longint;
    v1,v2:PEdRadek;

begin
if Zda_oznacen_blok=false then Pocet_radek_bloku:=0
   else begin
   v1:=poz_ozn[1].r^.vazba;
   v2:=poz_ozn[2].r^.vazba;
   Pocet_radek_bloku:=v2^.yy-v1^.yy+1;
   end;
end;


Destructor EditacniPole.Done;
begin
kpoz.hoehe:=100;
Kill_VW(kpoz);
Kill_VW(virt^);
EP_ZavriSoubor;
Dispose(radky,done);
end;


Constructor TBlokTextu.Init;
begin
PocetRadku:=0;
radky:=New(PVaznik,Init(nil,nil));
end;


Procedure TBlokTextu.VlozBlok(zac,kon:TKurPoz);
var v1,v2:PEdRadek;
    p1,p2:PVaznik;
    z:PChar;
begin
p1:=zac.r;
v1:=zac.r^.vazba;
p2:=radky;
if zac.x<v1^.spp then
   begin
   inc(PocetRadku);
   z:=v1^.p;
   inc(z,zac.x-1);
   v2:=New(PEdRadek,Init);

   if zac.r=kon.r then  {zacatek i konec vyberu jsou na stejne radce?}
      begin
      v2^.Vloz(z,kon.x-zac.x,1);
      v2^.crlf:=false;
      radky^.InitNext(v2);
      Exit;
      end;

   v2^.Vloz(z,v1^.spp-zac.x,1);
   v2^.crlf:=v1^.crlf;
   p1:=p1^.dalsi;
   p2:=p2^.InitNext(v2);
   end;

while p1<>kon.r do {dokud nejsme na cilove radce tak...}
   begin
   inc(PocetRadku);
   v1:=p1^.vazba;
   v2:=New(PEdRadek,Init);
   v2^.Vloz(v1^.p,v1^.spp-1,1);
   v2^.crlf:=v1^.crlf;
   p2:=p2^.InitNext(v2);
   p1:=p1^.dalsi;
   end;

{A jeste zbyva zpracovat posledni radku}
if kon.x=1 then Exit;
inc(PocetRadku);
v1:=p1^.vazba;
v2:=New(PEdRadek,Init);
v2^.Vloz(v1^.p,kon.x-1,1);
v2^.crlf:=true;
p2:=p2^.InitNext(v2);
end;


Procedure TBlokTextu.SmazObsah;
var v:PEdRadek;
begin
if PocetRadku=0 then Exit;
while radky^.dalsi<>nil do
    begin
    v:=radky^.dalsi^.vazba;
    Dispose(v,Done);
    Dispose(radky^.dalsi,Done);
    end;
PocetRadku:=0;
end;


Destructor TBlokTextu.Done;
begin
SmazObsah;
Dispose(radky,Done);
end;


Procedure TextoveOkno(x,y,sirka,vyska:longint;popis:string;p:PVaznik);
var e:PEditacniPole;
    ok:pokno;
    okt:pTlacitko;
    _o:word;
    i:longint;
begin
_o:=ovbarva;
ovbarva:=tvbarva;
OKokno_mustr(ok,x,y,sirka,vyska,popis,'',okt);
ovbarva:=_o;
i:=okt^.y-2;

e:=New(PEditacniPole,Init(ok^.x+2,ok^.y+ok^.vyska_zahlavi+1,ok^.sirka-2,i-(ok^.y+ok^.vyska_zahlavi),true));
e^.konverze_tagu:=false;
e^.povolene_zmeny:=false;
e^.jednotna_vyska_radku:=false;
e^.po_kl_rozpr:=true;
e^.NactiZVazniku(p);

repeat
okt^.kontrola;
e^.Kontrola;
if xLastKey in [xEnter,xESC] then Break;
until okt^.klik=1;

Dispose(e,Done);
Dispose(ok,done);
Dispose(okt,Done);
end;

end.
