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

interface
uses Dos,Objects,vaznik,TEdRadky,Wokna32,VenomGFX,Lacrt,RezKlav,FNfont2;

const

debug_flag:boolean = false;
global_temp_radky:PVaznik = nil; {Navazany <PEdRadek>.}
                                 {Pouziva se jen docasne, behem nahravani}



    edna_OK       = 0;
    edna_NOFILE   = 1;
    edna_CANCELED = 2;


Procedure NulujPozici(var kur:Tkurpoz);
Function PorovnejPozici(kur1,kur2:TKurpoz):byte;
Procedure ZkopirujPozici(var kam,odkud:TKurPoz);
Procedure ProhodPozice(var kur1,kur2:TKurPoz);
Function PorovnejPozici_pro_posl_znak_bloku(poz,konbl:TKurPoz):byte;


const
MAX_EDIT_POZICE = 8;
EP_kurzor = 1;           {pozice kurzoru}
EP_po_kl_pozice = 2;     {sem si ulozim pozici kurzoru pred odjetim posuvnikem}

EP_posl_vyskyt = 3;      {vyskyt v hledani}
EP_oznac1 = 4;           {zacatek oznaceneho bloku textu}
EP_oznac2 = 5;           {konec oznaceneho bloku textu}

EP_temp_oznac1 = 6;
EP_temp_oznac2 = 7;
EP_min_poz_kurz = 8;


nkp_prvni_znak = 1;        {prvni znak dokumentu}
nkp_za_posledni_znak = 2;  {za posledni znak dokumentu}
nkp_kurzor = 3;            {kurzor}
nkp_posl_vyskyt = 4;       {posl. vyskyt po vyhledavacich procedurach}

nkp_za_posl_vyskyt = 5;    {znak za posl. vyskyt (muze byt i na dalsim radku)}


type
PEditacniPole = ^TEditacniPole;
TEditacniPole = object(TPredekPosuvny)
       radky:PVaznik;       {Jsou tam navazany typy PItRadek}
       pozice:array[1..MAX_EDIT_POZICE] of TKurPoz;

       {
       pozice:TKurpoz;
       posledni_vyskyt:TKurPoz;
       poz_ozn:array[1..2] of TKurpoz;}
       PozText:record
          odz,doz,
          posunv,posunm:longint;
          end;
       konverze_tagu:boolean;
       jednotna_vyska_radku:boolean;
       jednorazove_zakazani_zobrazeni:boolean;
       zapnuto_mouse_self_copy:boolean;
       unicode:boolean;
       pouha_zmena_kurzoru:shortint;
       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}
       xm,ym:longint;
       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}
       {vsirka,vvyska:longint;} {sirka a vyska bez posuvniku}
       virt:PVirtualWindow;   {Alokuje se jen docasne, v ramci .Zobraz (a pak se dealokuje)}
       BB_txt_txt,BB_txt_v:word;  {popredi, pozadi -- default: 65535,0}

       rolovaci_odskok:longint;
       edKlavesa:kevent;
       start_poc_zobrX,start_poc_zobrY:longint;
       {poc_zobrX,poc_zobrY:longint;}    {posun virtualni obrazovky (pro rizeni scrollingu)}

       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:PUzel;         {Prvni a posledni vypsany radek}
       po_kl_prv_rad,po_kl_posl_rad:PUzel; {a jejich uschova}
       {py,px:PPosuvnik;}
       puvodni_citac:dword;
       je_kurzor_videt:boolean;      {je zrovna videt kurzor?}
       rychlost_blikani:byte;
       zalamuj:boolean;       {ma zalamovat radky?}
       tab_na_mezery:byte;
       ukoncovac_radku:string[6];  {#13#10, #13, #10}
       byla_zmena:boolean;
       (*ED_key_proc:Function(o:word):word;*)
       Jak_oznacen_blok:byte;
       {0=zadny blok}
       {1=definovan jeden bod bloku}
       {2=napred byl definovan horni bod bloku}
       {3=napred byl definovan dolni bod bloku}
       ukaz_postup_nahravani:Function(i:byte;r:real):boolean;
       mimoradne_osetreni_klavesnice:Function(o:word):string;
       Constructor Init(ix,iy,_sirka,_vyska:longint;iakt:boolean;ivyznam:longint);
       {Blok zobrazovacich rutin}
       Procedure ZobrazMe;virtual;
       Function TK_X:longint;
       Function TK_Y:longint;
       Function TK_R:puzel;
       Procedure ZkopirujPozici_EP(kam,odkud:byte);
       Procedure ZneplatniPozici_EP(kde:byte);
       Procedure StartovniPozice_EP(b:byte);
       Procedure Ostatni_pozice_navysX(v:PItRadek;pzx,dx:longint);
       Procedure Napln_KurPoz(var co:TKurPoz;mode:byte);
       Procedure VypisRadekTextu(ix:longint;p:PUzel;v:PItRadek);virtual;
       Procedure VlastniVypisRadkyTextu(ix,iy:longint;p:PUzel;v:PItRadek);virtual;
       Function ShiftemMenenyBlok:byte;virtual;
       Procedure DodatkyPoZobrazeni;virtual;
       {------------------------}
       procedure DeaktivacniProcedura;virtual;
       Procedure InicializujKurzory;virtual;
       Procedure ZmenPozici(ix,iy:longint);virtual;
       Procedure Priprava_Na_posouvani_mysi;virtual;
       Procedure Zotaveni_Po_posouvani_mysi;virtual;
       Procedure ZpracujZpravu(id_zpravy,param:longint);virtual;
       procedure Kontrola;virtual;
       Function NactiSoubor(s:string):byte;virtual;
       {edna_OK = vse v poradku, edna_NOFILE = neexistujici soubor,
        edna_CANCELED = zrusene nacitani}
       Function UlozSoubor(s:string):boolean;virtual;
       Function NactiZeStreamu(var s:TStream):byte;virtual;
       Function UlozDoStreamu(var s:TStream):boolean;virtual;
       Procedure UlozDoStreamu_hlavicka(var s:TStream);virtual;
       Procedure UlozDoStreamu_paticka(var s:TStream);virtual;
       Function NactiZVazniku(p:PVaznik):boolean;virtual;
       {Na vaznik jsou pripojeny PStringy}

       Procedure ZavriSoubor;virtual;
       Procedure ZkusZrusitRozpr;virtual;
       Function Prilep_K_predeslemu(rus:PUzel;smezerou:boolean):PUzel;virtual;
       Function Ev_prilep_k_predeslemu(rus:PUzel;smezerou:boolean):PUzel;virtual;
       Function Prilep_Nasledujici_radky(p:PUzel):longint;virtual;
       Function Je_delka_radky_k_zalomeni(v:PItRadek):boolean;virtual;
       Function Kde_je_misto_k_zalomeni(v:PItRadek):longint;virtual;
       Function Je_k_prilepeni_nasledujici_radky(p:PUzel):boolean;virtual;
       Procedure NalamejBuffer(pr:PUzel;kdy_stop_analyzu:longint);
       Function PocetRadku:longint;
       Procedure PosunRadek(p:PUzel);virtual;
       Function MoznyPreskokNahoru:boolean;virtual;
       Procedure PridejTextNaPoziciKurzoru(kp:PChar;ksd:longint;mode:byte;presun_kurzoru:boolean);virtual;
       Procedure ZmenZnakNaPozici(Poz:TKurPoz;o:word);
       Procedure Kod_Klavesy_Na_UTF16_retezec(o:word;var u16:string;var u16_d:byte);virtual;
       Procedure NastavRozmeziRadku(v:PItRadek;var yz:longint);virtual;
       Procedure UpravRozmeziRadku(v:PItRadek;var yz:longint);virtual;
       Procedure PospojujRadky;virtual;
       Procedure PospojujRadky(p:PUzel);virtual;
       Procedure PridelRadky;virtual;
       Procedure PreskladejRadky(q:PUzel;komplet_p,m1,m2,m3:boolean);virtual;
       Procedure PreskladejRadky(q:PUzel;komplet_p:boolean);virtual;
       Procedure PreskladejRadky(poz:TKurPoz;komplet_p,m1,m2,m3:boolean);virtual;
       Procedure PreskladejRadky(poz:TKurPoz;komplet_p:boolean);virtual;
       Procedure PreskladejBlokRadek(poz1,poz2:TKurPoz);
       Procedure VycentrujNaKurzor;virtual;
       Procedure horz_VycentrovaniKurzoru;virtual;
       Procedure vert_VycentrovaniKurzoru;virtual;
       Procedure ZmenVychoziFont(s:string);virtual;
       Procedure ZmenVychoziBarvuTextu(w:word);virtual;
       Procedure Nastav_poziceX(ix:longint);virtual;
       Procedure Nastav_poziceXY(ix,iy:longint);virtual;
       Procedure Nastav_poziceXYR(ix,iy:longint;ir:pointer);virtual;
       Procedure Korekce_Poc_ZobrX_po_Pozice_v_retezci_IT;
       Function Lokalizuj_grafickou_pozici(xx,yy:longint;var kur:TKurPoz):byte;
       Function UkazatelNaRadku(n:longint):PUzel;
       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;
       function RozdelRadku(poz:TKurPoz;var posun:longint):PUzel;
       Procedure DalsiRadka(u:PChar;poz,del:longint;var predchozi_blok_ukoncen:boolean;nynejsi_blok_ukoncen:boolean);
       Function Analyza_po_nacteni_a_konverzi:longint;virtual;
       Function Konverze_po_nacteni:boolean;virtual;
       Function Prvotni_analyza_jeste_v_TedRadek:boolean;virtual;
       Procedure Prvotni_konverze_jeste_v_TedRadek(e:PEdRadek);virtual;
       Procedure Konverze_radky_z_PEdRadek_na_PItRadek(e:PEdRadek;i:PItRadek);virtual;
       Procedure Konverze_radky_z_PItRadek_na_PEdRadek(v:PItRadek;var e:PEdRadek;var u:string);virtual;
       Function NactiZeStreamu_hlavicka(var s:TStream):longint;virtual;

       {Procedure SmazRadku(var poz:TKurPoz);
       Procedure SmazRadku(var poz:TKurPoz;moznosunout:boolean);}

       Procedure SmazRadku(u:PUzel);
       Procedure SmazRadku(u:PUzel;moznosunout:boolean);

       Procedure SmazCastRadky(u:PUzel;zac,kon:longint);
       Procedure SmazSlovo;
       Procedure OznacSlovo(kur:TKurPoz);virtual;
       Procedure SmazBlokTextu(zac,kon:TKurPoz);
       Procedure Presun_o_slovo_vpravo;
       Procedure Presun_o_slovo_vlevo;
       Procedure VlozTextNaPozici(blok:PBlokTextu;poz:TKurPoz);
       Procedure SkocNaZacatek;
       Procedure NovySoubor;
       Procedure UvazModifikaci_edKlavesa;virtual;
       Function OsetriSpecialniKlavesy(i:longint):longint;virtual;
       procedure OsetriVstup;virtual;

       Function PredchazejiciZnak(poz:TKurPoz;var newpoz:TKurPoz):byte;
       Function NasledujiciZnak(poz:TKurPoz;var newpoz:TKurPoz):byte;

       Function KrokVpred:longint;virtual;
       Function KrokZpet:longint;virtual;
       Procedure SipkaDoprava;
       Procedure SipkaDoleva;
       Procedure SipkaDolu;
       Procedure SipkaNahoru;
       Procedure BackSpace;
       Procedure KlavesaDel;
       Procedure KlavesaEnter;
       Procedure KlavesaPGDN;
       Procedure KlavesaPGUP;
       Procedure KlavesaCtrlPGUP;
       Procedure KlavesaCtrlPGDN;
       Procedure KlavesaEnd;
       Procedure KlavesaHome;
       Procedure KlavesaTab;
       Procedure ZpracujPraveMysitko(nx,ny:longint;kur:TKurPoz);virtual;
       Procedure ZpracujStredniMysitko(nx,ny:longint;kur:TKurPoz);virtual;
       Procedure ZpracujLeveMysitko(nx,ny:longint;kur:TKurPoz);virtual;
       Procedure ZpracujLeveMysitko_s_shiftem(nx,ny:longint;kur:TKurPoz);virtual;
       Procedure ZmenProsviceniPodlePohybuMysi(kur:tKurPoz);

       Procedure NastavBodOznaceni(b:byte;poz:TKurPoz);
       Procedure SmazBodyOznaceni;
       Procedure NastavRozsahOznaceni(zac,kon:TKurPoz);
       Function Zda_oznacen_blok:boolean;
       {jsou definovane oba kraje bloku?}
       Function Pocet_radek_bloku:longint;

       Destructor Done;virtual;
       end;

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

implementation
{var font:fn;}

Procedure Dummy;begin end;

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


Function porovnejPozici(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);
{je stejny radek - musime se tedy podivat i na sloupec...}

if kur1.x<kur2.x then Exit(2) else
if kur1.x>kur2.x then Exit(1) else porovnejPozici:=0;
end;


Function PorovnejPozici_pro_posl_znak_bloku(poz,konbl:TKurPoz):byte;
var c:byte;
    v:PItRadek;
begin
c:=PorovnejPozici(poz,konbl);
if c=0 then Exit(0);            {bezne pripad}
{problem vznika v situaci, kdy blok konci za posl. znakem radky a POZ je na
 prvnim znaku nove radky. Tyto situace chceme take vyhodnotit, ze jsme presne
 na konci bloku}

if (poz.x=1) and (poz.y=konbl.y+1) then
   begin
   v:=konbl.r^.vazba;
   if konbl.x=v^.up+1 then c:=0;
   end;
PorovnejPozici_pro_posl_znak_bloku:=c;
end;


Procedure ZkopirujPozici(var kam,odkud:TKurPoz);
begin
kam:=odkud;
end;


Procedure ProhodPozice(var kur1,kur2:TKurPoz);
var temp:tKurPoz;
begin
temp:=kur1;
kur1:=kur2;
kur2:=temp;
end;


Constructor TEditacniPole.Init(ix,iy,_sirka,_vyska:longint;iakt:boolean;ivyznam:longint);
var  r:PItRadek;
     a,dummy:longint;
     ofnc:longint;
     offn:pointer;

begin
inherited init;
id:=id_TEditacniPole;
vyznam:=ivyznam;
atributy:=atributy or A_VYHRADNIREZIM;
start_poc_zobrX:=4;    {od ktere X-ove souradnice okna ma zacit vykreslovat radky}
start_poc_zobrY:=0;    {...a od ktere Y-ove}


BB_txt_txt:=BA_txt_txt;
BB_txt_v:=BA_txt_v;

hlavni_font:=AktualniFont;   {vychozi font pro psani}

x:=ix; y:=iy;
radky:=NovyVaznik;   {Ale vytvorime hlavni strukturu}
InicializujKurzory;  {pocatecni poloha textoveho kurzoru a dalsich bodu zajmu}
kx:=start_poc_zobrX;           {pocatecni poloha a delka kurzoru}
kkx:=-1;
ky:=0;
Init_VW(kpoz,1,100,false);  {Udelam si rezervu na kurzor vysoky 100 znaku}

if iakt then
   begin
   stav:=_aktivni;
   xm:=-mouse.last_lpx;
   ym:=-mouse.last_lpy;
   end
   else begin
   stav:=_neaktivni;
   xm:=1;
   ym:=1;
   end;


odz:=0;
doz:=0;          {na aktualnim radku se nam prave zobrazuje nulty az nulty znak :-)}

poc_zobrX:=start_poc_zobrX;
poc_zobrY:=start_poc_zobrY;

po_kl_poc_zobrX:=poc_zobrX;
po_kl_poc_zobrY:=poc_zobrY;

vyska:=_vyska;
sirka:=_sirka;

py:=ZalozVertikalniPosuvnikOkna(x,y,sirka,vyska,vyska,{vsirka}dummy);
{zalozi posuvnik a nastavi promennou VSirka}
px:=ZalozHorizontalniPosuvnikOkna(x,y,vsirka,vyska,vsirka,{vvyska}dummy);
{zalozi posuvnik a nastavi promennou VVyska}

jednorazove_zakazani_zobrazeni:=false;
zapnuto_mouse_self_copy:=true;

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;          {defaultne 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,vsirka,vvyska,false);
virt:=@_virt; ukazalo se, ze alokace pres lokalni promennou je moc vachrlata
Tudiz nebudu delat globalni alokaci, ale buffer budu tvorit vzdy ad hoc pri zobrazovani}

rolovaci_odskok:=vsirka div 4;
if rolovaci_odskok<45 then rolovaci_odskok:=45;

puvodni_citac:=0;
je_kurzor_videt:=false;      {je zrovna videt kurzor?}
rychlost_blikani:=10;
tab_na_mezery:=5;
byla_zmena:=false;
pouha_zmena_kurzoru:=-1;
ukoncovac_radku:=#13#10;  {defaultni format ukonceni radku}

NovySoubor;   {Az ted konecne zinicializuje prvni radku}
              {(a take soucasne nastavi kurzor na 1.sloupec 1.radky)}
end;


Function TEditacniPole.TK_X:longint;
begin
TK_X:=pozice[EP_kurzor].x;
end;


Function TEditacniPole.TK_Y:longint;
begin
TK_Y:=pozice[EP_kurzor].y;
end;


Function TEditacniPole.TK_R:puzel;
begin
TK_R:=pozice[EP_kurzor].r;
end;


Procedure TEditacniPole.ZkopirujPozici_EP(kam,odkud:byte);
begin
ZkopirujPozici(pozice[kam],pozice[odkud]);
end;


Procedure TEditacniPole.ZneplatniPozici_EP(kde:byte);
begin
NulujPozici(pozice[kde]);
end;


Procedure TEditacniPole.Napln_KurPoz(var co:TKurPoz;mode:byte);
var v:PItRadek;
    p:PUzel;
begin
case mode of
nkp_prvni_znak:begin        {prvni znak dokumentu}
   co.x:=1;
   co.y:=1;
   co.r:=radky^.first;
   end;

nkp_za_posledni_znak:begin  {za posledni znak dokumentu}
   p:=radky^.last;
   v:=p^.vazba;
   co.x:=v^.delka+1;
   co.y:=v^.yy;
   co.r:=p;
   end;

nkp_kurzor: co:=pozice[EP_kurzor];        {kurzor}
nkp_posl_vyskyt:begin
                {sem by bylo dobre dat kontroly, zda je <EP_posl_vyskyt> porad validni}
                co:=pozice[EP_posl_vyskyt];
                v:=co.r^.vazba;
                if co.x>v^.up then co.x:=v^.up;
                {alespon kontrola delky radky}
                end;

nkp_za_posl_vyskyt:begin
                   if pozice[EP_posl_vyskyt].r=nil then Napln_KurPoz(co,nkp_prvni_znak)
                   {musime udelat neco definovaneho, pokud <EP_posl_znak> neni platny}
                      else begin
                      co:=pozice[EP_posl_vyskyt];
                      v:=co.r^.vazba;
                      if co.x<v^.up
                         then inc(co.x)
                         else begin  {jsme na poslednim znaku radky?}
                         if co.r^.dalsi<>nil then
                            begin
                            co.r:=co.r^.dalsi;
                            co.x:=1;
                            inc(co.y);
                            end;
                         end;
                      end;

                   end;

end; {case}

end;


Procedure TEditacniPole.StartovniPozice_EP(b:byte);
var co:TKurPoz;
begin
Napln_KurPoz(co,1);
pozice[b]:=co;
end;

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

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


Procedure TEditacniPole.ZpracujLeveMysitko_s_shiftem(nx,ny:longint;kur:TKurPoz);
var a:byte;
begin
if jak_oznacen_blok=0  {oznacujeme teprve prvni blok}
   then begin
   ZkopirujPozici(pozice[ep_oznac1],kur);
   jak_oznacen_blok:=1;
   Exit;
   end;

if jak_oznacen_blok=1  {jeden blok uz oznacen je a ted oznacujeme druhy}
   then begin
   a:=PorovnejPozici(pozice[ep_oznac1],kur);
   {0 = jsou shodne; 1 = pozice[ep_oznac1]>kur; 2 = pozice[ep_oznac1]<kur}
   if a=0 then begin
      jak_oznacen_blok:=1;  {v tomhle stadiu nic nemenme}
      end else
   if a=1 then begin
      jak_oznacen_blok:=3;
      {napred byl definovan dolni bod bloku a az pak horni}
      {t.j. "hlavni bod" bude dolni bod}
      ZkopirujPozici(pozice[ep_oznac2],pozice[ep_oznac1]);
      {puvodni definici proto presuneme jako dolni bod}
      ZkopirujPozici(pozice[ep_oznac1],kur);
      {a redefinujeme horni bod}
      end else
   if a=2 then begin
      jak_oznacen_blok:=2;
      {napred byl definovan horni bod bloku a ted dodelavam dolni}
      {t.j. "hlavni bod" bude horni bod}
      ZkopirujPozici(pozice[ep_oznac2],kur);
      {definujeme dolni bod}
      end;
   Exit;
   end;

if jak_oznacen_blok=2  {"hlavnim bodem" je horni bod}
   then begin
   a:=PorovnejPozici(pozice[ep_oznac1],kur);
   {0 = jsou shodne; 1 = pozice[ep_oznac1]>kur; 2 = pozice[ep_oznac1]<kur}
   if a=0 then begin
      jak_oznacen_blok:=0;  {jeden ze zpusobu jak odznacit blok}
      end else
   if a=1 then begin
      ZkopirujPozici(pozice[ep_oznac2],pozice[ep_oznac1]);
      {z horniho bodu se stane dolni}
      ZkopirujPozici(pozice[ep_oznac1],kur);
      {redefinujeme horni bod}
      jak_oznacen_blok:=3;
      {"hlavni bod" bude nezmenen, ale ted oznacuje ne vrsek, ale spodek}
      end else
   if a=2 then begin
      ZkopirujPozici(pozice[ep_oznac2],kur);
      {zmena dolni hranice bloku}
      end;
   Exit;
   end;


if jak_oznacen_blok=3  {"hlavnim bodem" je dolni bod}
   then begin
   a:=PorovnejPozici(pozice[ep_oznac2],kur);
   {0 = jsou shodne; 1 = pozice[ep_oznac2]>kur; 2 = pozice[ep_oznac2]<kur}
   if a=0 then begin
      jak_oznacen_blok:=0;  {jeden ze zpusobu jak odznacit blok}
      end else
   if a=1 then begin
      ZkopirujPozici(pozice[ep_oznac1],kur);
      {zmena horni hranice bloku}
      end;

   if a=2 then begin
      ZkopirujPozici(pozice[ep_oznac1],pozice[ep_oznac2]);
      {z dolniko bodu se stane horni}
      ZkopirujPozici(pozice[ep_oznac2],kur);
      {redefinujeme horni bod}
      jak_oznacen_blok:=2;
      {"hlavni bod" bude nezmenen, ale ted oznacuje ne spodek, ale vrsek}
      end;
   Exit;
   end;
end;


Procedure TEditacniPole.ZmenProsviceniPodlePohybuMysi(kur:tKurPoz);
{KUR bude vystupovat jako <pozice[ep_oznac2]>}
var a:byte;
begin

{jak_oznacen_blok:=1;
ZpracujLeveMysitko_s_shiftem(0,0,kur);}

if jak_oznacen_blok in [0,1] then
   begin
   a:=PorovnejPozici(pozice[ep_oznac1],kur);
   {0 = jsou shodne; 1 = pozice[ep_oznac1]>kur; 2 = pozice[ep_oznac1]<kur}
   if a=0 then Exit;  {nemelo by nikdy nastat}
   if a=2
      then begin      {zakladame novy blok, ukotveny shora}
      ZkopirujPozici(pozice[ep_oznac2],kur);  {tzn. definujeme dolni okraj}
      jak_oznacen_blok:=2;
      end else
   if a=1 then begin  {zakladame novy blok, ukotveny zdola}
      ZkopirujPozici(pozice[ep_oznac2],pozice[ep_oznac1]);
      ZkopirujPozici(pozice[ep_oznac1],kur);
      jak_oznacen_blok:=3;
      end
   end else

if jak_oznacen_blok=2 then
   begin   {blok, doposud ukotveny shora}
   a:=PorovnejPozici(pozice[ep_oznac1],kur);
   {0 = jsou shodne; 1 = pozice[ep_oznac1]>kur; 2 = pozice[ep_oznac1]<kur}
   if a=0 then
      begin
      jak_oznacen_blok:=0;
      end else
   if a=2 then ZkopirujPozici(pozice[ep_oznac2],kur) else
   if a=1 then
      begin
      ZkopirujPozici(pozice[ep_oznac2],pozice[ep_oznac1]);
      ZkopirujPozici(pozice[ep_oznac1],kur);
      jak_oznacen_blok:=3; {odted blok redefinujeme jako ukotveny zdola}
      end
   end else

if jak_oznacen_blok=3 then
   begin   {blok, doposud ukotveny zdola}
   a:=PorovnejPozici(pozice[ep_oznac2],kur);
   {0 = jsou shodne; 1 = pozice[ep_oznac2]>kur; 2 = pozice[ep_oznac2]<kur}
   if a=0 then
      begin
      jak_oznacen_blok:=0;
      end else
   if a=1 then ZkopirujPozici(pozice[ep_oznac1],kur) else
   if a=2 then
      begin
      ZkopirujPozici(pozice[ep_oznac1],pozice[ep_oznac2]);
      ZkopirujPozici(pozice[ep_oznac2],kur);
      jak_oznacen_blok:=2; {odted blok redefinujeme jako ukotveny zdola}
      end;
   end;


Zobraz;
end;


Procedure TEditacniPole.ZpracujLeveMysitko(nx,ny:longint;kur:TKurPoz);
var oxx,oyy,nxx,nyy:longint;
    okur,nkur:tKurPoz;

begin
if dos_mem_je_shift then
   begin
   ZpracujLeveMysitko_s_shiftem(nx,ny,kur);
   MouseRel;
   Exit;
   end;

SmazBodyOznaceni;
pozice[ep_kurzor]:=kur;
po_kl_rozpr:=false;  {levym mysitkem se odstrani posuvniko-klavesovy rozpor}

ZkopirujPozici(pozice[ep_oznac1],kur); {zaznamenam polohu jako horni bod...}
                                       {vyberu, ale zatim ponecham...}
                                       {<jak_oznacen_blok> jako 0}
okur:=kur;
oxx:=nx;
oyy:=ny;
repeat
  nxx:=mouse.x-x;
  nyy:=mouse.y-y;
  if (nxx<>oxx) or (nyy<>oyy) then
     begin         {zmenila se od minuleho dotazu poloha mysi?}
     if Lokalizuj_grafickou_pozici(nxx,nyy,nkur)<>0 then  {naplnena promenna NKUR}
        if (nkur.x<>okur.x) or (nkur.y<>okur.y) then
           begin
           ZmenProsviceniPodlePohybuMysi(nkur);
           okur:=nkur;
           end;
     oxx:=nxx;
     oyy:=nyy;
     end;
until mouse.b=0;

MouseRel;
end;


Function TEditacniPole.Lokalizuj_grafickou_pozici(xx,yy:longint;var kur:TKurPoz):byte;
{Pokud je XX:YY mimo okno, tak vrati 0 a KUR nemodifikuje.
 Pokud je XX:YY v okne, ale "pod textem", tak vrati 1 a KUR vyplni podle
   posledniho vypsaneho radku.
 Pokud je XX:YY v okne a v textu, tak identifikuje znak, radek a R podle
   graficke souradnice}

var v:PItRadek;
    p:PUzel;

begin
if xx<0 then Exit(0);
if yy<0 then Exit(0);
if xx>sirka-1 then Exit(0);
if yy>vyska-1 then Exit(0);

inc(yy,poc_ZobrY);
{pri hodnoceni pozice mysi musime brat v uvahu odrolovani textu}
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_IT(xx,poc_zobrX,start_poc_zobrX,v,true);
      kur.r:=p;
      Exit(2);  {nalezeno v textu}
      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:=Radky^.last;
v:=p^.vazba;
kur.y:=v^.yy;
kur.x:=Pozice_v_retezci_IT(xx,poc_zobrX,start_poc_zobrX{korig_pzx},v,true);
kur.r:=p;
Lokalizuj_grafickou_pozici:=1; {pod posledni radkou}
end;


procedure TEditacniPole.DeaktivacniProcedura;
begin
inherited DeaktivacniProcedura;
if Je_kurzor_videt then BlikejKurzorem;  {vypni kurzor}
end;


Procedure TEditacniPole.ZmenPozici(ix,iy:longint);
var dx,dy:longint;
begin
dx:=ix-x;
dy:=iy-y;
if py<>nil then py^.ZmenPozici(py^.x+dx,py^.y+dy);
if px<>nil then px^.ZmenPozici(px^.x+dx,px^.y+dy);
x:=ix;
y:=iy;
end;


Procedure TEditacniPole.Priprava_Na_posouvani_mysi;
begin
if stav=_aktivni then
   if Je_kurzor_videt then BlikejKurzorem;  {vypni kurzor}
zapnuto_mouse_self_copy:=false;
end;


Procedure TEditacniPole.Zotaveni_Po_posouvani_mysi;
begin
if stav=_aktivni then
   if Je_kurzor_videt then BlikejKurzorem;
   { jestlize jsme kurzor predtim vypli, tak ted ho zapni}
zapnuto_mouse_self_copy:=true;
end;


Procedure TEditacniPole.ZpracujZpravu(id_zpravy,param:longint);
begin
if id_zpravy=zpr_start_pohybu_mysi then Priprava_Na_posouvani_mysi else
if id_zpravy=zpr_konec_pohybu_mysi then Zotaveni_Po_posouvani_mysi else
end;



procedure TEditacniPole.kontrola;
   Procedure KlepnutiMysi;
   var op,p:pvaznik;
       v:PItRadek;
       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+vsirka,y+vvyska)) 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};

   Lokalizuj_grafickou_pozici(mx,my,kur);  {naplnena promenna 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
   py^.Kontrola;
      if py^.kopozitiv 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_kurzor_videt then BlikejKurzorem;
            po_kl_rozpr:=true;
            end;
         poc_zobrY:=py^.hodnota;
         end{ else else py.probehni:=false};
   end;*)
Function ZkontrolujPosuvnik:boolean;
   var g:boolean;
       oph:longint;
   begin
   g:=false;
   oph:=py^.hodnota;
   py^.kontrola;
   {if (mouse.b=1) or (mouse._wdif<>0) or (py^.tahaci_stav) then}
      if py^.kopozitiv or (mouse._wdif<>0) then
         begin
         if po_kl_rozpr=false then
            begin
            ZkopirujPozici_ep(EP_po_kl_pozice,ep_kurzor);
            {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_kurzor_videt then BlikejKurzorem;
            po_kl_rozpr:=true;
            (*PutClippedSprite(cil^,kpoz,kkx,kky);  {chvilkove vypnuti kurzoru}*)
            end;

         poc_zobrY:=py^.hodnota;
         if poc_zobrY<>oph then g:=true;
         end else py^.probehni:=false;
   ZkontrolujPosuvnik:=g;
   {Pokud bude TRUE, tak to znamena, ze se s posuvnikem neco delo}
   end;

var i:longint;
    d:dword;
    b:boolean;
    zmena_bliknuti:boolean;
Begin
{napred rizeni blikani kurzoru}
inherited kontrola;

zmena_bliknuti:=false;
{extra_udalost:=0;}

if TimerTicksFrom(puvodni_citac,rychlost_blikani) then
   begin
   je_kurzor_videt:=not(je_kurzor_videt);
   puvodni_citac:=FromTimer;
   zmena_bliknuti:=true;
   end else zmena_bliknuti:=false;

case stav of
   _deaktivace:DeaktivacniProcedura;
   _aktivace:begin
             {debug}d:=d;
             AktivacniProcedura;
             end;

   _aktivni:begin
      b:=ZkontrolujPosuvnik;
      if zmena_bliknuti then BlikejKurzorem;
      if Bod_uvnitr_vnitrni_casti(mys_xx,mys_yy) then
         if (mouse.b<>0) and (py^.tahaci_stav=false) then
            begin                {je zmackle nejake tlacitko}
            stav:=_aktivni;
            {ofn:=FN_default;
            NastavAktualniFont(hlavni_font);}
            PutClippedSprite(cil^,kpoz,kkx,kky);  {chvilkove vypnuti kurzoru}
            KlepnutiMysi;
            je_kurzor_videt:=true;puvodni_citac:=FromTimer;BlikejKurzorem;
            {NastavAktualniFont(ofn);}
            xm:=-mouse.last_lpx;
            ym:=-mouse.last_lpy;
            b:=true;
            zobraz;
            {Vypustil jsem MouseRel a presunul do KlepnutiMysi}
            end;

     {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}
        b:=true;
        {zobraz;}
        {Exit;}
        end;
      if b=true then Zobraz;
      end;
end; {case}

if (stav=_aktivni) {and (mouse.B=0)} then OsetriVstup;
end;


Function TEditacniPole.KrokZpet:longint;
{Puvodne vracelo jako vysledek funkce pocet bajtu zabranych pripadnym tagem.
 Kdyz tag nebyl zadny, tak vracelo 0.
 Puvodnu klicovy kod bylo toto...
 FNznakZpet(v^.p,v^.delka+1,TK_X-1,unicode,j);
 ... a jako vysledek se bralo J
 }
var v:PItRadek;
begin
if TK_X<=1 then begin poc_zobrX:=start_poc_zobrX;Exit(0);end;
v:=TK_R^.vazba;
Nastav_PoziceX(TK_X-1);

(*if PozText.odz<>0 then         {presahuje tento radek levy okraj obrazovky?}
   if TK_X<=PozText.odz then
      inc(poc_ZobrX,-PozText.posunm);*)

if TK_X<v^.odz then {presahuje tento radek levy okraj obrazovky?}
   inc(poc_zobrX,v^.posunm);
if poc_zobrX>start_poc_zobrX then poc_zobrX:=start_poc_zobrX;

{ DEBUG --
Bar(vga,400,0,799,100,25);
OutText(vga,405,5,'TK_X: '+mystr(TK_X)+#13#10+
                  '  v^.odz: '+mystr(v^.odz)+' ('+
                     mystr(v^.znak(v^.odz))+' / '+
                     char(v^.znak(v^.odz))+')'+#13#10+

                  '  v^.doz: '+mystr(v^.doz)+' ('+
                     mystr(v^.znak(v^.doz))+' / '+
                     char(v^.znak(v^.doz))+')',64000);

OutText(vga,405,50,'v^.posunm: '+mystr(v^.posunm)+'  v^.posunv: '+mystr(v^.posunv),64000);
OutText(vga,405,70,'kx: '+mystr(kx),64000);
--}

KrokZpet:=0;
end;


Function TEditacniPole.KrokVpred:longint;
{Puvodne vracelo jako vysledek funkce pocet bajtu zabranych pripadnym tagem.
 Kdyz tag nebyl zadny, tak vracelo 0.
 Puvodnu klicovy kod bylo toto...
 FNznakVpred(v^.p,v^.delka,TK_X-1,unicode,j);
 ... a jako vysledek se bralo J
 }
var v:PItRadek;
    i,j:longint;
begin
v:=TK_R^.vazba;
if TK_X>=v^.delka+1 then Exit(0);
Nastav_PoziceX(TK_X+1);

(*if PozText.doz<>0 then         {presahuje tento radek pravy okraj obrazovky?}
   if TK_X-1>=PozText.doz then dec(poc_zobrX,PozText.posunv);*)

if TK_X-1>v^.doz then{presahuje tento radek pravy okraj okna?}
   begin
   dec(poc_zobrX,v^.posunv);
   if poc_zobrX>start_poc_zobrX then poc_zobrX:=start_poc_zobrX;
   end;
KrokVpred:=0;
end;


Function TEditacniPole.PredchazejiciZnak(poz:TKurPoz;var newpoz:TKurPoz):byte;
{Vysledek funkce:
 0 = jsme na prvnim znaku dokumentu - nelze se soupnout
 1 = prvni znak radky, soupnuto na posl. znak predchozi radky
 2 = soupnuto o znak doleva}
var v:PItRadek;
    i:byte;
begin
newpoz:=poz;
if newpoz.x>1 then begin dec(newpoz.x);i:=2;end
   else
   if newpoz.y=1 then i:=0
      else begin
      dec(newpoz.y);
      newpoz.r:=newpoz.r^.predchozi;
      v:=newpoz.r^.vazba;
      newpoz.x:=v^.up;
      i:=1;
      end;
PredchazejiciZnak:=i;
end;


Function TEditacniPole.NasledujiciZnak(poz:TKurPoz;var newpoz:TKurPoz):byte;
{Vysledek funkce:
 0 = posledni znak dokumentu - nelze se soupnout
 1 = posledni znak radky, soupnuto na prvni znak nasledujici radky
 2 = soupnuto o znak doprava}
var v:PItRadek;
    i:byte;
begin
v:=poz.r^.vazba;
newpoz:=poz;

if newpoz.x<v^.up then begin inc(newpoz.x);i:=2;end
   else
   if newpoz.y=radky^.pocet then i:=0
      else begin
      inc(newpoz.y);
      newpoz.r:=newpoz.r^.dalsi;
      newpoz.x:=1;
      i:=1;
      end;
end;


Procedure TEditacniPole.SipkaDoprava;
begin
pouha_zmena_kurzoru:=1;
KrokVpred;
end;


Procedure TEditacniPole.SipkaDoleva;
begin
pouha_zmena_kurzoru:=1;
KrokZpet;
end;


Procedure TEditacniPole.Korekce_Poc_ZobrX_po_Pozice_v_retezci_IT;
begin
if FN_poz_v_ret_delka_radky<-poc_zobrX then  {horizontalni scrolling}
   begin
   poc_zobrX:=-FN_poz_v_ret_delka_radky+vsirka div 4;
   if poc_zobrX>start_poc_zobrX then poc_zobrX:=start_poc_zobrX;
   end;
end;


Procedure TEditacniPole.SipkaDolu;
var  v:PItRadek;
     a1,a2:longint;
begin
pouha_zmena_kurzoru:=1;
if po_kl_rozpr and po_kl_jsme_mimo then
   begin
   v:=po_kl_prv_rad^.vazba;
   Nastav_PoziceXYR(TK_X,v^.yy,po_kl_prv_rad);
   poc_zobrY:=po_kl_poc_zobrY;
   poc_zobrX:=po_kl_poc_zobrX;
   end;
if povolene_zmeny then
   begin
   if TK_Y>=PocetRadku then Exit;

   pozice[ep_kurzor].r:=pozice[ep_kurzor].r^.dalsi;
   {diky podmince s TK_Y>=PocetRadku by nemelo hrozit, ze se dostaneme na NIL}
   v:=TK_R^.vazba;
   Nastav_poziceXY(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true),TK_Y+1);

   {if TK_X<v^.delka+1 then inc(TK_X);}
   {Bude potreba zascrolovat?}

   Korekce_Poc_ZobrX_po_Pozice_v_retezci_IT;

   if v^.y2>poc_ZobrY+vvyska-1 then     {vertikalni scrolling}
      poc_ZobrY:=v^.y2-vvyska-1+1;
   end
   else begin
   v:=Radky^.last^.vazba;
   inc(poc_ZobrY,py^.tlacitkovy_skok);
   if poc_ZobrY>v^.y2-vvyska then
      poc_ZobrY:=v^.y2-vvyska-1;
   end;
end;

Procedure TEditacniPole.SipkaNahoru;
var  v:PItRadek;
     r:PUzel;
begin
pouha_zmena_kurzoru:=1;
if po_kl_rozpr and po_kl_jsme_mimo then
   begin
   v:=po_kl_posl_rad^.vazba;
   Nastav_PoziceXYR(TK_X,v^.yy,po_kl_posl_rad);
   poc_zobrY:=po_kl_poc_zobrY;
   poc_zobrX:=po_kl_poc_zobrX;
   end;
if povolene_zmeny then
   begin
   if TK_Y<=1 then Exit;
   pozice[ep_kurzor].r:=pozice[ep_kurzor].r^.predchozi;
   {diky podmince s TK_Y<=1 by nemelo hrozit, ze se dostaneme na NIL}
   v:=TK_R^.vazba;
   Nastav_poziceXY(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true),TK_Y-1);

   {Bude potreba zascrolovat?}
   if FN_poz_v_ret_delka_radky<-poc_zobrX then  {horizontalni scrolling}
      begin
      poc_zobrX:=-FN_poz_v_ret_delka_radky+vsirka div 4;
      if poc_zobrX>start_poc_zobrX then poc_zobrX:=start_poc_zobrX;
      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;


Function TEditacniPole.Prilep_K_predeslemu(rus:PUzel;smezerou:boolean):PUzel;
var abs:PUzel;
    abs_v:PItRadek;
    gdho,kam_nalepeno:longint;

begin
abs:=Global_Prilep_K_predeslemu(radky,rus,smezerou,kam_nalepeno);
{ABS je bud radek predchazejici RUS nebo je s nim totozny
 (to v pripade, ze RUS je prvni radek dokumentu)}
if abs<>nil then
   begin
   abs_v:=abs^.vazba;
   if (abs<>rus) then
      begin
      if TK_R=rus then         {kurzor je na rusenem radku?}
         Nastav_poziceXYR(kam_nalepeno+TK_X+1,  {nastavime X}
                          TK_Y-1,             {o jednu snizime Y}
                          abs);                   {a ukazatel na absorbujici radek}
      if pozice[EP_posl_vyskyt].r=rus then
         pozice[EP_posl_vyskyt].r:=nil;
      {zmenilo se rozlozeni radek. Tezko by se to hlidalo poradne, tak aspon zrusim
       zaznam o posl. vyskytu}
      end;
   end;
Prilep_K_predeslemu:=abs;
end;


Function TEditacniPole.Ev_prilep_k_predeslemu(rus:PUzel;smezerou:boolean):PUzel;
{Dela to same jako predchozi, ale napred zkontroluje, zda perdchozejici radek
 neni ukoncen tvrde (CRLF=0). V tom pripade prilepovat nebude}
var v:PItRadek;
begin
if rus^.predchozi=nil then Exit(rus)
   else begin
   v:=rus^.predchozi^.vazba;
   if v^.crlf=0 then Exit(rus)
      else Ev_prilep_k_predeslemu:=Prilep_k_predeslemu(rus,smezerou);
   end;
end;


Function TEditacniPole.Prilep_Nasledujici_radky(p:PUzel):longint;
{Pripoji nasledujici radky (pripojuje tak dlouho, dokud CRLF neni 0 nebo
 dokud nedorazime na konec textu).

Vrati, kolik radku se k nam pripojilo}
var i:longint;
    v:PItRadek;
begin
i:=0;
v:=p^.vazba;
while v^.crlf<>0 do
   if Prilep_K_predeslemu(p^.dalsi,true)=nil then Exit(i) else inc(i);
Prilep_Nasledujici_radky:=i;
end;



Function PrvniVyskytZnaku(v:PItRadek;z:char;od:longint):longint;
var w:word;
    a:longint;
begin
w:=word(z);
for a:=od to v^.Delka do
    if v^.Znak(a)=w then Exit(a);
PrvniVyskytZnaku:=0;
end;


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

Procedure TEditacniPole.BackSpace;
var l,a,b:longint;
    gdho:longint;
    v,v_nad:PItRadek;
    p_nad:PUzel;
    n:Pchar;
    lepilo_se_k_hornimu:boolean;
    s:string;
begin
if not povolene_zmeny then Exit;
byla_zmena:=true;
v:=TK_R^.vazba;
if TK_X=1 then if TK_Y=1 then Exit else
   begin  {t.j. TK_X=1 a TK_Y<>1}
   p_nad:=TK_R^.predchozi;    {P bude radek nad kurzorem}
   v_nad:=p_nad^.vazba;
   Prilep_K_predeslemu(p_nad^.dalsi,  {P^.dalsi = radek s kurzorem}
                       false);        {soucasne zhruba upravi kurzor...}
   if (zalamuj=false) then
      begin
      Nastav_poziceX(TK_X-1);         {dorovnani kurzoru v nezalamovacim modu}
      if v^.gd>vsirka-1 then
         poc_zobrX:=-(v^.gd-vsirka-1)-vsirka div 4;
      PosunRadek(p_nad^.dalsi);
      {Bude potreba zascrolovat?}
      if v_nad^.y1<poc_ZobrY then {jo}
         poc_ZobrY:=v_nad^.y1;
      end
      else begin
      while v_nad^.crlf<>0 do Prilep_k_predeslemu(p_nad^.dalsi,true);
      Nastav_PoziceX(TK_X-1); {kompenzace toho, ze jsem vlastne nesmazal...}
                              {...zadny znak - pouze spojil radky}
      NalamejBuffer(p_nad,0);
      end;

   {okokno('2','poc_zobrX: '+mystr(poc_zobrX)+#13#10+'poc_zobrY: '+mystr(poc_zobrY));}

   Exit;
   end;


{Ted poresime variantu, kdy nejsem na prvnim znaku radku}
l:=TK_X;

Ostatni_pozice_navysX(v,l,-1); {abychom si udrzeli spravne hranice bloku}

KrokZpet;  {provedlo dec(tk_x) a poreseni scrollingu}

{s:=v^.VratString(TK_X,l-TK_X);} {co odmazu?}
{b:=SirkaUseku_IT(v,TK_X,l-TK_X);}

v^.Vyjmi(TK_X,l-TK_X);  {v praxi vyjme jeden znak}

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

   {a navic jeste musim zkusit pripojit tento radek k predchazejicimu}
   if TK_R^.predchozi<>nil then
      begin
      p_nad:=TK_R^.predchozi;
      v_nad:=p_nad^.vazba;
      gdho:=v_nad^.gd;
      while v_nad^.crlf<>0 do Prilep_k_predeslemu(p_nad^.dalsi,true);
      lepilo_se_k_hornimu:=v_nad^.gd<>gdho; {zmenila se delka?}
      end
      else lepilo_se_k_hornimu:=false;

   {a ted to vsechno nalamu}
   if lepilo_se_k_hornimu=false then p_nad:=TK_R;
   NalamejBuffer(p_nad,0);
   end;
end;


Function TEditacniPole.Je_k_prilepeni_nasledujici_radky(p:PUzel):boolean;
{Potomci budou asi predefinovavat}
var v,v2:PItRadek;
    a,b,c,d:longint;
    dbgs:string;

begin
if p^.dalsi=nil then Exit(false);
v:=p^.vazba;
if v^.crlf=0 then Exit(false);
v2:=p^.dalsi^.vazba;

v2^.Odkud_kam_je_slovo(1,a,b); {na pozici B konci prvni slovo dalsiho radku}

if b=0 then Exit(false);
c:=SirkaUseku_It(v2,1,b);     {a jak je ten usek graficky dlouhy?}

d:=vsirka-start_poc_zobrX-v^.gd;        {zbyvajici prostor za posl. znakem}

{
dbgs:='slovo: '+mystr(c)+'  -  radka: '+mystr(d);
bar(vga,90,0,330,20,65030);
print_fn(90,15,dbgs);
}

Je_k_prilepeni_nasledujici_radky:=d>c; {volny prostor zvladne pojmout prvni...}
end;                                   {...slovo dalsi radky?}


Procedure TEditacniPole.KlavesaDel;
var l,a,b:longint;
    v,v2:PItRadek;
    p:PUzel;
    dal_ne:boolean;
    s:string;
begin
if not povolene_zmeny then Exit;
byla_zmena:=true;
v:=TK_R^.vazba;
if (TK_X<=v^.delka) then
   begin      {1. varianta - kurzor neni za poslednim znakem}
   Ostatni_pozice_navysX(v,TK_X,-1); {poresme hranice bloku}
   v^.VyjmiZnak(TK_X);
   if (zalamuj=true) and (v^.crlf<>0) and (TK_R<>Radky^.last) then
      begin
      dal_ne:=false;
      if TK_Y>1 then
         if Je_k_prilepeni_nasledujici_radky(TK_R^.predchozi)
            then begin
            PreskladejRadky(TK_R^.predchozi,false);
            dal_ne:=true;
            end;
      if dal_ne=false then
         if Je_k_prilepeni_nasledujici_radky(TK_R)
            then PreskladejRadky(TK_R,false);
      end;
   end else   {2. varianta - kurzor je za poslednim znakem radky}
if TK_R=Radky^.last then Exit else
   begin
   p:=TK_R^.dalsi;
   v2:=p^.vazba;    {V je porad TK_R^.vazba}
   Prilep_K_predeslemu(p,false); {Pozor, muze hybat s promennou POZICE}
   if zalamuj then
      begin
      while v^.crlf<>0 do Prilep_K_predeslemu(TK_R^.dalsi,true);
      NalamejBuffer(TK_R,0);
      end else PosunRadek(TK_R^.dalsi);
   end;
end;


Procedure TEditacniPole.KlavesaTab;
var u:longint;
    s:string;
begin
if not povolene_zmeny then Exit;
byla_zmena:=true;
u:=TK_X mod (tab_na_mezery+1);
u:=tab_na_mezery-u+1;
s:=XMezer(u);
PridejTextNaPoziciKurzoru(@s[1],u,1{mezery jsou ASCII},true);
end;


Function TEditacniPole.RozdelRadku(poz:TKurPoz;var posun:longint):PUzel;
{vysledkem funkce je odkaz na nove vznikly radek}
var v,v2:PItRadek;
    p:PUzel;
begin
byla_zmena:=true;
v:=poz.r^.vazba;
v2:=Init_PItRadek;                  {novy prazdy PItRadek - dokonce bez atributu}
v2^.PrevezmiUzelOdjinud(1,v,poz.x); {dodame atributy z mista, kde bude zlom}

p:=Radky^.InsertNew(poz.r,v2); {clanek vazniku zapojim do retezu}

v^.Rozdel(v2^,poz.x,0);
v2^.crlf:=v^.crlf;         {Jak jsme byli zalomeni na konci radky?}
v^.crlf:=0;                {Kazdopadne, v miste zlomu je tvrde zalomeni}
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;
RozdelRadku:=p;
end;


Procedure TEditacniPole.KlavesaEnter;
var v,v2:PItRadek;
    p,p2,q:PUzel;
    n:PChar;
    a:longint;
begin
if not povolene_zmeny then Exit;
byla_zmena:=true;

p:=TK_R;

v:=p^.vazba;

p2:=RozdelRadku(pozice[ep_kurzor],a);

Nastav_poziceXYR(1,TK_Y+1,p2);  {budeme na 1.sloupci nasledujici radku}
Poc_ZobrX:=start_poc_zobrX;

v2:=p2^.vazba;

if (zalamuj=false) {or (v^.crlf=true)} then PosunRadek(p)
   else begin
   p:=ev_prilep_k_predeslemu(p,true);
   {Prozkoumej, zda cast pred zlomem lze prilepit k predchazejici radce.
    (pokud ta radka konci s CRLF, tak nelze, jinak lze)
    (jo, a pokud jsme na prvni radce, tak to taky nejde)

    Podle toho, zda to klaplo, nebo ne, se ev. upravi P.
   }

   Prilep_Nasledujici_radky(p2);
   {k mistu za zlomem eventualne prilep nasledujici radky}

   NalamejBuffer(p,1);
   {vime, ze P^ se mozna bude mekce lamat, pak je URCITE tvrdy zlom a pak
    znovu mozna mekke lamani.
    Tedy oblast k lamani radek neni spojita, ale je v ni jeden zlom, pres
    ktey musime prejit}
   end;

v2:=TK_R^.vazba;

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

zablokovani_signalu_enter:=true;
end;

Procedure TEditacniPole.KlavesaPGDN;
var v:PItRadek;
    p,op:PUzel;
    l:longint;
    b:boolean;
begin
pouha_zmena_kurzoru:=1;
if po_kl_rozpr and po_kl_jsme_mimo then begin SipkaNahoru;Exit;end;
b:=false;
if posl_rad=Radky^.last then b:=true else
   begin
   v:=posl_rad^.dalsi^.vazba;
   if v^.y2-poc_ZobrY<vvyska then b:=true;
   posl_rad:=posl_rad^.dalsi;
   end;
if B then  {situace, kdy neni treba skrolovat}
   if TK_R=Radky^.last then begin KlavesaEnd;Exit;end
   else begin
   v:=posl_rad^.vazba;
   Nastav_poziceXYR(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true)-1,
                    v^.yy,
                    posl_rad);

   Exit;
   end;
posl_rad:=posl_rad^.predchozi;{znovu se nasmerujeme na posl. vypsanou radku}
{ta ale nemusi byt vypsana cela (muze to byt treba jen prvni radek pixelu)}

v:=posl_rad^.vazba;

if v^.y2-poc_ZobrY>=vvyska then  {tento radek neni videt cely?}
   if posl_rad<>radky^.first  {to snad nikdy nebude}
      then begin
      posl_rad:=posl_rad^.predchozi;  {...tak se presuneme o radek vys}
      v:=posl_rad^.vazba;
      end;

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
      Nastav_poziceXYR(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true)-1,
                       v^.yy,
                       p);
      Exit;
      end;
   op:=p;
   p:=p^.dalsi;
   end;
{sem bychom se nikdy nemeli dostat, nicmene sem neco napisu...}
Nastav_poziceXYR(1,v^.yy,op);
end;

Procedure TEditacniPole.KlavesaPGUP;
var l,m:longint;
    v:PItRadek;
    p,op:PUzel;
begin
pouha_zmena_kurzoru:=1;
if po_kl_rozpr and po_kl_jsme_mimo then begin SipkaDolu;Exit;end;

if prv_rad=Radky^.first then  {Je vypsany prvni radek, t.j. nebudeme skrolovat}
   if TK_Y=1 then begin KlavesaHome;poc_ZobrY:=0;Exit;end
   else begin
   poc_ZobrY:=0;
   v:=TK_R^.vazba;
   l:=Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true);
   Nastav_poziceXYR(l,1,radky^.first);
   Korekce_Poc_ZobrX_po_Pozice_v_retezci_IT;
   Exit;
   end;

v:=prv_rad^.vazba;
l:=ky-poc_zobrY;
dec(poc_zobrY,vvyska-(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
         Nastav_poziceXYR(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true)-1,
                          v^.yy,
                          p);
         Exit;
         end;
      p:=p^.predchozi;
      end;
   end;

{Nasledujici kod by se mel vykonat jenom v pasivnim modu}
Nastav_poziceXYR(1,1,radky^.first);
end;

Procedure TEditacniPole.KlavesaCtrlPGUP;
begin
pouha_zmena_kurzoru:=1;
SkocNaZacatek;
end;


Procedure TEditacniPole.KlavesaCtrlPGDN;
var v:PItRadek;
begin
pouha_zmena_kurzoru:=1;
v:=radky^.last^.vazba;
Nastav_poziceXYR(1,v^.yy,radky^.last);
VycentrujNaKurzor;
end;


Procedure TEditacniPole.InicializujKurzory;
var a:byte;
begin
pozice[ep_kurzor].x:=1;        {textovy krzor nastavime na prvni radku}
pozice[ep_kurzor].y:=1;
pozice[ep_kurzor].r:=radky^.first;
for a:=2 to MAX_EDIT_POZICE do {a ostatni ukazovadla zneplatnime}
    begin
    pozice[a].x:=0;
    pozice[a].y:=0;
    pozice[a].r:=nil;
    end;
Jak_oznacen_blok:=0;  {nemame oznacen zadny kraj bloku}
end;



Procedure TEditacniPole.Nastav_poziceX(ix:longint);
begin
if ix<1 then ix:=1;
pozice[EP_kurzor].x:=ix;
end;


Procedure TEditacniPole.Nastav_poziceXY(ix,iy:longint);
begin
if iy<1 then iy:=1;
pozice[EP_kurzor].y:=iy;
Nastav_poziceX(ix);
end;


Procedure TEditacniPole.Nastav_poziceXYR(ix,iy:longint;ir:pointer);
begin
if ir=nil then
   InfOkno(300,300,'Error: Argument for "TK_R" cannot be NIL!');
pozice[EP_kurzor].r:=ir;
Nastav_poziceXY(ix,iy);
end;


Procedure TEditacniPole.KlavesaEND;
var v:PItRadek;
begin
pouha_zmena_kurzoru:=1;
v:=TK_R^.vazba;
Nastav_poziceX(v^.delka+1);

Poc_ZobrX:=-(v^.gd-vsirka+1);
if Poc_ZobrX>start_poc_zobrX then Poc_ZobrX:=start_poc_zobrX;

{if v^.gd>vsirka-1 then
   Poc_ZobrX:=-(v^.gd-vsirka-1+start_poc_zobrX);
if Poc_ZobrX}
end;

Procedure TEditacniPole.KlavesaHome;
begin
pouha_zmena_kurzoru:=1;
Nastav_poziceX(1);
Poc_ZobrX:=start_poc_zobrX;
end;

Function TEditacniPole.MoznyPreskokNahoru:boolean;
var v:PItRadek;
    p:PUzel;
    i,j:longint;
begin
MoznyPreskokNahoru:=false;
if TK_Y<=1 then Exit;
p:=TK_R^.predchozi;
v:=p^.vazba;
if v^.crlf=0 then Exit;

i:=DelkaPrvnihoSlova(TK_R,j);
if j<>TK_X-1 then Exit;
j:=vsirka-1-v^.gd-start_poc_zobrX;
if i<j then
   begin
   Prilep_k_predeslemu(p^.dalsi,true);
   {v^.gd:=sirka;}
   MoznyPreskokNahoru:=true;
   end;
end;


Procedure TEditacniPole.Ostatni_pozice_navysX(v:PItRadek;pzx,dx:longint);
var i:longint;
begin
for i:=2 to MAX_EDIT_POZICE do
    if v^.yy=pozice[i].y then
       if pzx<=pozice[i].x then inc(pozice[i].x,dx);
end;


Procedure TEditacniPole.PridejTextNaPoziciKurzoru(kp:PChar;ksd:longint;mode:byte;presun_kurzoru:boolean);
var v:PItRadek;
    dgd,rods:longint;
    b:boolean;
    vmode:byte;
    dbgs:string;

begin
if povolene_zmeny=false then Exit;
if ksd<1 then Exit;

byla_zmena:=true;
v:=TK_R^.vazba;

vmode:=UTF8_konv;
dgd:=v^.gd;

if mode=0   {text v ASCII nebo UTF8}
   then v^.Vloz(kp,ksd,TK_X) else

if mode=1   {vynutime text v ASCII}
   then begin UTF8_konv:=UTF8_NO_CONV;v^.Vloz(kp,ksd,TK_X);UTF8_konv:=vmode;end else

if mode=2   {vynutime text v UTF8}
   then begin UTF8_konv:=UTF8_ALL_CONV;v^.Vloz(kp,ksd,TK_X);UTF8_konv:=vmode;end else

if mode=3   {text rozepsany ve widecharech (t.j. UTF16)}
   then
   begin
   {if byte(kp[0])>127 then beep;}
   {debug}
   {dbgs:=mystr(byte(kp[0]))+'+'+mystr(byte(kp[1]));
   bar(vga,90,0,130,20,65030);
   print_fn(90,15,dbgs);}
   {/debug}
   v^.VlozWS(kp,ksd,TK_X,true);
   end;

dgd:=v^.gd-dgd;            {o kolik jsme prodlouzili retezec?}

if dgd>rolovaci_odskok then rods:=dgd else rods:=rolovaci_odskok;

Ostatni_pozice_navysX(v,TK_X,ksd); {abychom si udrzeli spravne hranice bloku}
if presun_kurzoru then Nastav_PoziceX(TK_X+ksd);



{
Bar(vga,400,0,799,130,25);
OutText(vga,405,5,'TK_X: '+mystr(TK_X)+#13#10+
                  'v^.gd: '+mystr(v^.gd)+#13#10+
                  'dgd: '+mystr(dgd)+#13#10+
                  'v^.delka: '+mystr(v^.delka)+#13#10+
                  'poc_zobrX: '+mystr(poc_zobrX)+#13#10+
                  '  v^.doz: '+mystr(v^.doz)+' ('+
                     mystr(v^.znak(v^.doz))+' / '+
                     char(v^.znak(v^.doz))+')',64000);
}
{OutText(vga,405,60,'v^.posunm: '+mystr(v^.posunm)+'  v^.posunv: '+mystr(v^.posunv),64000);}

{
OutText(vga,405,110,'kx: '+mystr(kx),64000);
}


if kx+dgd>vsirka-1 then dec(poc_ZobrX,rods);


(*
if TK_X=v^.delka then          {piseme na konci radku?}
   begin
   inc(dgd,kx);
   if dgd>vsirka-1 then dec(poc_zobrX,rods);
   end
   else if PozText.doz<>0 then {presahuje tento radek pravy okraj obrazovky?}
           if TK_X-1>=PozText.doz then dec(poc_zobrX,{PozText.posunv}rods);
*)

if zalamuj then
   begin
   poc_zobrX:=start_poc_zobrX;
   if kp^=' ' then b:=MoznyPreskokNahoru else b:=false;
   v:=TK_R^.vazba;

   if Je_delka_radky_k_zalomeni(v) then
   {if v^.gd>vsirka-1-start_poc_zobrX then}
      begin
      while v^.crlf<>0 do Prilep_k_predeslemu(TK_R^.dalsi,true{false});
      NalamejBuffer(TK_R,0);
      end;
   {if B then
       begin
       Nastav_poziceX(1);
       inc(TK_Y);
       TK_R:=TK_R^.dalsi;
       end;}
   end;

end;


Procedure TEditacniPole.ZmenZnakNaPozici(Poz:TKurPoz;o:word);
var v:PItRadek;
begin
if not povolene_zmeny then Exit;
v:=poz.r^.vazba;
v^.Nahradword(o,poz.x);
v^.Prepocitej_GD;
end;



Procedure TEditacniPole.ZkusZrusitRozpr;
var p:PUzel;
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 TEditacniPole.Kod_Klavesy_Na_UTF16_retezec(o:word;var u16:string;var u16_d:byte);
var s:string;
begin
if (unicode=true) or (((o<256) and (o>31))=true) {ochrana proti CTRL-neco a ALT-neco}
   then begin
   u16:=Word2string(o)+#0;
   u16_d:=1;
   end
   else
   begin
   u16:='';
   u16_d:=0;
   end;
end;


Procedure TEditacniPole.UvazModifikaci_edKlavesa;
begin
end;


Function TEditacniPole.OsetriSpecialniKlavesy(i:longint):longint;
begin
if i=0 then OsetriSpecialniKlavesy:=3 else OsetriSpecialniKlavesy:=1;
end;


Function TEditacniPole.ShiftemMenenyBlok:byte;
var a,b,c,d:byte;
    z:boolean;
begin
b:=PorovnejPozici(pozice[ep_kurzor],pozice[EP_min_poz_kurz]);
{0 = jsou shodne; 1 = kur1>kur2; 2 = kur2>kur1}
if b=0 then Exit(0);
z:=false;

{debug}
 if Internal_Je_numlock(edklavesa) then
   b:=b;


if zda_oznacen_blok=true then
   begin  {nejaky blok uz mame - jdeme ho modifikovat}
   c:=PorovnejPozici_pro_posl_znak_bloku(pozice[EP_min_poz_kurz],pozice[EP_oznac2]);
   if c=0 then  {byl kurzor na posl. znaku bloku?}
      begin
      NastavRozsahOznaceni(pozice[EP_oznac1],pozice[EP_kurzor]);
      {jestli jo, tak uprav hranice bloku podle nynejsiho kurzoru}
      z:=true;
      end;

   d:=PorovnejPozici(pozice[EP_min_poz_kurz],pozice[EP_oznac1]);
   if d=0 then  {byl kurzor na prvnim znaku bloku?}
      begin
      NastavRozsahOznaceni(pozice[EP_kurzor],pozice[EP_oznac2]);
      {jestli jo, tak uprav hranice bloku podle nynejsiho kurzoru}
      z:=true;
      end;
   if z=true then
      begin
      a:=PorovnejPozici(pozice[EP_oznac2],pozice[EP_oznac1]);
      if a=0 then SmazBodyOznaceni else
      if a=2 then ProhodPozice(pozice[EP_oznac2],pozice[EP_oznac1]);
      Exit(1);
      end;
   {zbyva moznost, ze C<>0 a soucasne D<>0}
   SmazBodyOznaceni;
   Exit(1);
   end;

{Konec variant s upravovanim existujicich bloku. Ted utvorime uplne novy blok}
SmazBodyOznaceni;
if b=1 then NastavRozsahOznaceni(pozice[EP_min_poz_kurz],pozice[ep_kurzor]) else
            NastavRozsahOznaceni(pozice[ep_kurzor],pozice[EP_min_poz_kurz]);
ShiftemMenenyBlok:=1;
end;


Procedure TEditacniPole.OsetriVstup;
var o:longint;
    i,j:longint;
    u16:string[63];
    u16_d:byte;
    r:char;
    jek:boolean;

begin
pouha_zmena_kurzoru:=-1;
jek:=Je_Klavesa;
if jek=false then
   begin
   if py^.probehni then Zobraz;
   Exit;
   end;

pouha_zmena_kurzoru:=0;  {pripravme se na to, ze se bude dit neco vic nez}
                         {jen zmena polohy kurzoru}
edKlavesa:=xKlavesa;   {udelame kopii klavesovych informaci, protoze mozna...}
                       {...budeme fejkovat}

pozice[EP_min_poz_kurz]:=pozice[EP_kurzor];

UvazModifikaci_edKlavesa;  {potomkum dame moznost prebit zachycene klavesy}



{Ted zpracujeme zakladni "konzervativni" klavesy}
if po_kl_rozpr and (edKlavesa.ASCII<>0) then ZkusZrusitRozpr;

if Internal_Je_CTRL(edKlavesa) then
   begin
   i:=1;
   case edKlavesa.ASCII of
   xCtrlPgUp,xCtrlHome:KlavesaCtrlPGUP;
   xCtrlPgDn,xCtrlEnd:KlavesaCtrlPGDN;
   else i:=0;
   end; {case}
   end
   else begin
   i:=1;
   {if (Internal_Je_Shift(edKlavesa)=true) then okokno(mystr(edklavesa.ascii));}
   case edKlavesa.ASCII of
          xLsipka:SipkaDoleva;
          xPsipka:SipkaDoprava;
          xDSipka:SipkaDolu;
          xHsipka:SipkaNahoru;
          xDel:KlavesaDel;
          xEnter:KlavesaEnter;
          xEndk:KlavesaEnd;
          xHome:KlavesaHome;
          xPGDN:KlavesaPGDN;
          xPGUP:KlavesaPGUP;
          xESC:stav:=_deaktivace;
          xBackSpace:BackSpace;
          xTab:KlavesaTab;
          else i:=0;
   end; {case}
   end; {if Internal_Je_CTRL...}
{-----------------------------------------------}

j:=OsetriSpecialniKlavesy(i);
{Zmacklou klavesu jsme nezpracovali ve vseobecne casti?...}
{...Tak to zkusime ve specialni}

{if edklavesa.ascii=43 then
   i:=i;}

if j=3 then   {zapisovani znaku?}
   if (povolene_zmeny=true) then
      if edKlavesa.psaci=true then
         begin
         if unicode
            then o:=edKlavesa.Uni
            else o:=edKlavesa.ASCII;
         if (o<>0) and (o<>xPREFIX_KEY) then
            begin
            Kod_Klavesy_Na_UTF16_retezec(o,u16,u16_d);
            PridejTextNaPoziciKurzoru(@u16[1],u16_d,3,true);
            {Word znaku je prelozeny do retezce v UTF16. Proto ukladame v modu 3}
            end;
         end;

if (pouha_zmena_kurzoru=1) and (Internal_Je_Shift(edKlavesa)=true)
   then j:=ShiftemMenenyBlok;

if j<>0 then
   begin
   if povolene_zmeny then
   if po_kl_rozpr then po_kl_rozpr:=false;
   zobraz;
   end;
End;


Function TEditacniPole.UkazatelNaRadku(n:longint):PUzel;
begin
UkazatelNaRadku:=radky^.Uzel(n);
end;


Procedure TEditacniPole.OverPoziciKurzorovehoBodu(var kur:TKurPoz);
var v:PItRadek;
begin
if kur.y>PocetRadku then
   begin
   kur.y:=PocetRadku;
   kur.r:=Radky^.last;
   v:=radky^.last^.vazba;
   kur.x:=v^.delka+1;
   Exit;
   end;

v:=kur.r^.vazba;
if kur.x>v^.delka+1 then kur.x:=v^.delka+1;
end;


Procedure TEditacniPole.SmazRadku(u:PUzel);
begin
SmazRadku(u,true);
end;


Procedure TEditacniPole.SmazRadku(u:PUzel;moznosunout:boolean);
var v:PItRadek;
    a,b,yy,y1,y2:longint;
    sunout:boolean;
    p:Pvaznik;
begin
if not povolene_zmeny then Exit;
v:=u^.vazba;
y1:=v^.y1;
y2:=v^.y2;
yy:=v^.yy;
if PocetRadku=1 then NovySoubor
   else begin
   Kill_PitRadek(v);  {zrusime odkazovanou radku}
   if yy=TK_Y then b:=0 else
   if yy>TK_Y then b:=1 else b:=2;

   if u=Radky^.last then        {jsme na posledni radce?}
      begin
      {???}
      dec(pozice[ep_kurzor].y);
      {dec(TK_Y);}       {kurzor popojede z rusene posl. radky nahoru}
      {???}
      if u=TK_R then pozice[ep_kurzor].r:=u^.predchozi;
      u:=u^.predchozi;
      Radky^.ZrusUzel(u^.dalsi);
      sunout:=false;
      end
      else begin
      if u=TK_R then pozice[ep_kurzor].r:=u^.dalsi;
      u:=u^.dalsi;
      Radky^.ZrusUzel(u^.predchozi);
      sunout:=true;
      end;

   if b=0 then
      begin
      v:=u^.vazba;
      Nastav_PoziceX(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true));
      end else   {kurzor je na mazanem radku}
   if b=2 then dec(pozice[ep_kurzor].y);     {kurzor je pod mazanym radkem}

   if sunout and moznosunout then
      begin
      v:=u^.vazba;
      if (zalamuj=false) or (v^.yy=1)
         then PosunRadek(u)
         else PreskladejRadky(u,false);
      end;
   end;
end;


Procedure TEditacniPole.SmazCastRadky(u:PUzel;zac,kon:longint);
var v:PItRadek;
    t:TkurPoz;
begin
if not povolene_zmeny then Exit;
if u=nil then Exit else v:=u^.vazba;
if kon<=zac then Exit;
if v^.delka<zac then Exit;
v^.Vyjmi(zac,kon-zac);
if TK_Y=v^.yy then
   if TK_X>kon then Nastav_PoziceX(TK_X-(kon-zac+1))
      else if (TK_X>zac) and (TK_X<=kon) then Nastav_PoziceX(zac);
if zalamuj=true then
   begin
   t.x:=zac;
   t.y:=v^.yy;
   t.r:=u;
   PreskladejRadky(t,false);
   end;
end;



Procedure TEditacniPole.OznacSlovo(kur:TKurPoz);
var v:PItRadek;
    a,b,n,tkx:longint;
    p,p2:pchar;
    c:char;
    zac,kon:TKurPoz;
begin
if kur.r=nil then Exit;
v:=kur.r^.vazba;
if v^.delka=0 then Exit;
zac:=kur;
kon:=kur;

if v^.Znak_oddelovac_slov(kur.x) then
  begin          {kurzor je v prostoru mezi slovy?}
  v^.Mezislovi(kur.x,a,b);
  zac.x:=a;
  kon.x:=b;
  {v^.Vyjmi(a,b-a);}
  end
  else begin     {kurzor je na slove?}
  v^.Slovo(kur.x,a,b);
  zac.x:=a+1;
  kon.x:=b;
  {v^.Vyjmi(a+1,b-a);}
  end;

if a<>b then
   begin
   NastavRozsahOznaceni(zac,kon);
   end;
end;



Procedure TEditacniPole.SmazSlovo;
var v:PItRadek;
    a,b,n,tkx:longint;
    p,p2:pchar;
    c:char;
begin
if not povolene_zmeny then Exit;
v:=TK_R^.vazba;
if v^.delka=0 then Exit;

tkx:=TK_X;
if v^.Znak_oddelovac_slov(tkx) then
  begin          {kurzor je v prostoru mezi slovy?}
  v^.Mezislovi(tkx,a,b);
  v^.Vyjmi(a,b-a);
  end
  else begin     {kurzor je na slove?}
  v^.Slovo(tkx,a,b);
  v^.Vyjmi(a+1,b-a);
  end;

if a<>b then
     begin
     Nastav_PoziceX(a);
     if zalamuj=true then PreskladejRadky(pozice[ep_kurzor],false);
     end;
end;


Procedure TEditacniPole.Presun_o_slovo_vpravo;
var v:PItRadek;
    a,b,c,d:longint;
    tkx:longint;
begin
v:=TK_R^.vazba;
if v^.delka=0 then Exit;  {prazdny radek?}

{Pokud jsme pred prvnim slovem nebo na prvnim slove vyjma    posledniho znaku,
 tak skoci na posledni znak prvniho slova.
 Pokud jsme na poslednim slove (ale ne na jeho poslednim znaku), tak skoci
 na posledni znak posl. slova.
 Pokud jsme na poslednim znaku posl. slova, tak skoci na prvni znak prvniho
 slova nasledujiciho radku.
 Ve vsech ostatnich pripadech skoci na prvni znak nasledujiciho slova.}

tkx:=TK_X;
a:=v^.Zjisti_kolikate_slovo_nebo_mezislovi(tkx);
{1.mezislovi = 0; 1.slovo = 1; 2.mezislovi = 2; 2.slovo = 3...}

if a=0 then      {jsme jeste pred prvnim slovem}
   begin
   c:=v^.KonecMezislovi(tkx);
   Nastav_PoziceX(c);
   Exit;
   end;

if a=1 then      {uvnitr prvniho slova}
   begin
   c:=v^.KonecSlova_na_pozici(tkx);
   Nastav_PoziceX(c);
   Exit;
   end;

{Vsechny ostatni varianty znamenaji, ze se pokusim skocit na prvni znak...
 ...nasledujiciho slova.
 Eventualne, pokud jiz v poslednim slove jsme, tak na posledni znak posledniho slova}

d:=tkx;
if odd(a)=true then   {kurzor je na slove}
   begin
   d:=v^.KonecSlova_na_pozici(tkx); {v tom pripade se presuneme tesne za slovo}
   end;

{jsme predchozim slovem}
c:=v^.KonecMezislovi(d);
Nastav_PoziceX(c);


b:=v^.KonecSlova_na_pozici(TK_X);  {a ted se jeste podivam, kde konci slovo,}
                                   {kam jsme prave preskocili kurzorem}


if b>v^.doz then  {je to az za pravym okrajem okna?}
   begin
   a:=SirkaUseku_IT(v,1,b);     {tak to zamer...}
   poc_zobrX:=-(a-vsirka-1);    {...a zaskroluj}
   end;
end;


Procedure TEditacniPole.Presun_o_slovo_vlevo;
var v:PItRadek;
    a,b,c,d:longint;
    tkx:longint;
begin
v:=TK_R^.vazba;
tkx:=TK_X;
if v^.delka=0 then Exit;
if tkx=1 then Exit;

a:=v^.Zjisti_kolikate_slovo_nebo_mezislovi(tkx-1);
{1.mezislovi = 0; 1.slovo = 1; 2.mezislovi = 2; 2.slovo = 3...}

if a=0 then           {jsme jeste pred prvnim slovem}
   begin
   Nastav_PoziceX(1);
   Exit;
   end;

d:=tkx;
if odd(a)=false then  {jsem v prostoru mezi slovy?}
   begin
   d:=v^.ZacatekMezislovi(tkx-1);
   end;

c:=v^.ZacatekSlova_na_pozici(d-1)+1;
Nastav_PoziceX(c);

if TK_X<v^.odz then{presahuje tento radek pravy okraj okna?}
   begin
   if TK_X=1
      then a:=-2
      else a:=SirkaUseku_IT(v,1,TK_X-1);

   poc_zobrX:=-a+start_poc_zobrX+2;
   if poc_zobrX>start_poc_zobrX then poc_zobrX:=start_poc_zobrX;
   end
   else
   if v^.odz=1 then poc_zobrX:=start_poc_zobrX;
end;



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

begin
if not povolene_zmeny then Exit;

{debug}{if internal_je_numlock(edklavesa) then
   b:=b;}

v:=zac.r^.vazba;

if PorovnejPozici(zac,kon)=2 then
   if zac.x>v^.up then
      if zac.x>1 then
         begin
         NasledujiciZnak(zac,zac);
         v:=zac.r^.vazba;     {znovu si musim vytahnout V}
         end;

if zac.y=kon.y then
   begin
   if (zac.x<=1) and (kon.x>=v^.delka+1)
      then begin SmazRadku(zac.r);Exit;end
      else begin SmazCastRadky(zac.r,zac.x,kon.x);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.r,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.r,false);
      dec(kon.y);
      end
      else begin
      temp:=zac;
      v:=temp.r^.vazba;
      temp.x:=v^.delka+1;
      SmazCastRadky(temp.r,zac.x,temp.x);
      end;

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

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

   if zalamuj=true then PreskladejRadky(zac,false,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 TEditacniPole.VlozTextNaPozici(blok:PBlokTextu;poz:TKurPoz);
begin
if not povolene_zmeny then Exit;
blok^.PrehrajBlok(radky,poz);
if zalamuj=false
   then PosunRadek(poz.r^.dalsi)
   else PreskladejRadky(poz,true);  {nezname usporadani bloku, proto...}
end;                                {...budeme pripraveni na celkove prelamani}


Procedure TEditacniPole.vert_VycentrovaniKurzoru;
var v:PItRadek;
    a,b:longint;
begin
v:=TK_R^.vazba;

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

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

Procedure TEditacniPole.horz_VycentrovaniKurzoru;
var v:PItRadek;
    xx:longint;
begin
v:=TK_R^.vazba;

if TK_X>v^.up
   then xx:=v^.gd
   else xx:=SirkaUseku_IT(v,1,TK_X);

if zalamuj=false then
   begin
   poc_ZobrX:=-(xx-vsirka div 2);
   if poc_ZobrX>-100 then poc_ZobrX:=start_poc_zobrX;
   end;
end;

Procedure TEditacniPole.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 TEditacniPole.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+vvyska-1);
if b=false then Exit;

if je_kurzor_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,BB_txt_txt);
   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 TEditacniPole.ZhasniKurzor;
begin
if je_kurzor_videt then
   begin
   je_kurzor_videt:=false;
   BlikejKurzorem;
   end;
end;

Procedure TEditacniPole.RozsvitKurzor;
begin
if je_kurzor_videt=false then
   begin
   je_kurzor_videt:=true;
   BlikejKurzorem;
   end;
end;


Procedure TEditacniPole.VlastniVypisRadkyTextu(ix,iy:longint;p:PUzel;v:PItRadek);
begin
print_it(ix,iy,v);
end;




Procedure TEditacniPole.VypisRadekTextu(ix:longint;p:PUzel;v:PItRadek);
var f:byte;
    d:longint;
begin
if zda_oznacen_blok=false then VlastniVypisRadkyTextu(ix,v^.y1-Poc_ZobrY,p,v)
   else begin
   if (v^.yy>pozice[ep_oznac1].y) and (v^.yy<pozice[ep_oznac2].y)
      then begin  {radka zcela uvnitr bloku}
      v^.V_useku_zmen_parametr_uzlu(1,v^.up,6,1);
      f:=1;
      end else

   if (v^.yy=pozice[ep_oznac1].y) and (v^.yy=pozice[ep_oznac2].y)
      then begin  {blok na stejne radce zacina i konci}
      d:=pozice[ep_oznac2].x-pozice[ep_oznac1].x;
      if d>0 then v^.V_useku_zmen_parametr_uzlu(pozice[ep_oznac1].x,d,6,1);
      f:=2;
      end else

   if v^.yy=pozice[ep_oznac1].y
      then begin  {prvni radek bloku}
      v^.V_useku_zmen_parametr_uzlu(pozice[ep_oznac1].x,v^.up,6,1);
      f:=3;
      end else
   if v^.yy=pozice[ep_oznac2].y
      then begin  {posledni radek bloku}
      d:=pozice[ep_oznac2].x-1;
      if d>0 then v^.V_useku_zmen_parametr_uzlu(1,d,6,1);
      f:=4;
      end else f:=0; {uplne mimo blok}

   VlastniVypisRadkyTextu(ix,v^.y1-Poc_ZobrY,p,v);
   if f=1 then v^.V_useku_zmen_parametr_uzlu(1,v^.up,6,0) else
   if f=2 then v^.V_useku_zmen_parametr_uzlu(pozice[ep_oznac1].x,d,6,0) else
   if f=3 then v^.V_useku_zmen_parametr_uzlu(pozice[ep_oznac1].x,v^.up,6,0) else
   if f=4 then v^.V_useku_zmen_parametr_uzlu(1,pozice[ep_oznac2].x-1,6,0);
   end;
end;


Procedure TEditacniPole.ZobrazMe;
   Procedure EdPrint_Vaznik_ROZPR;
   {VOLA SE V PRIPADE POSUVNIKO-KLAVESOVEHO ROZPORU - NEOPTIMALIZOVANO}
   var v,kv:PItRadek;
       p:PUzel;
   begin
   po_kl_jsme_mimo:=true;
   p:=radky^.first;
   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>=vvyska then Break;   {jsme pod vyrezem? tak konec}
      if p=pozice[ep_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:PItRadek;
       i:longint;
       b:boolean;
       p:PUzel;

       debug_s:string;

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

   FN_poloha[0].N:=TK_X;     {(stejne jako jeste dalsi podobne veci)}


   {SetBasicLine(v^.y1-poc_ZobrY);}

   VypisRadekTextu(poc_zobrX,p,v);
   {Print_FN(poc_zobrX,AUTO_LINE,v^.p,v^.delka,nil);}

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

   ky:=v^.y1;
   if TK_X=1 then
      kx:=poc_zobrX else kx:=FN_poloha[0].x; {polohu zname, takze tam umistime kurzor}
   kd:=v^.vyska;

   {
   debug_s:=v^.vs;
   if kd=0 then
      kd:=kd;
   }

   {
   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:=TK_R^.dalsi;
   while p<>nil do
      begin
      v:=p^.vazba;
      if v^.y1-poc_ZobrY<vvyska then
         begin
         VypisRadekTextu(poc_zobrX,p,v);
         posl_rad:=p;             {je tato radka alespon castecne videt?}
         end
         else begin
         posl_rad:=p^.predchozi;  {aha, tato uz neni, posledni tedy byla ta predchozi}
         Break;
         end;
      p:=p^.dalsi;
      end;

   {a nad kurzorem - zase jenom ty, co se vejsou na obrazovku}
   p:=TK_R^.predchozi;
   while p<>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^.delka,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:PItRadek;
    ofnzl:boolean;
    tempvw:virtualwindow;

begin
if jednorazove_zakazani_zobrazeni=true then
   begin
   jednorazove_zakazani_zobrazeni:=false;
   Exit;
   end;

{ZkontrolujYY;}
ofnzl:=FN_z_linky;
FN_z_linky:=false;

Init_VW(tempvw,vsirka,vvyska,false);
Clr(tempvw,BB_txt_v);
{Bar(tempvw,0,0,tempvw.breite-1,15,64000);}
virt:=@tempvw;

NastavVystup(virt);

if po_kl_rozpr then EdPrint_Vaznik_ROZPR
               else EdPrint_Vaznik_NORM;

MouseLock;
if zapnuto_mouse_self_copy=true then MouseSelfCopy(virt^,x,y);
PutSprite_and_clear(cil^,virt^,x,y,BB_txt_v);
MouseUnLock;

if (stav=_aktivni) then
   begin
   je_kurzor_videt:=true;
   puvodni_citac:=FromTimer;
   BlikejKurzorem;
   end;

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

FN_z_linky:=ofnzl;

DodatkyPoZobrazeni; {Prilezitost pro aplikaci zobrazit si doplnky}


{--DEBUG
Bar(vga,0,0,200,100,20);
OutText(vga,5,5,'poc_zobrX: '+mystr(poc_ZobrX),64000);
OutText(vga,5,25,'poc_zobrY: '+mystr(poc_ZobrY),64000);
--}

Kill_VW(tempvw);
end;


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


Procedure TEditacniPole.ZmenBarvuPozadi(w:word);
begin
BB_txt_v:=w;
{Clr(virt^,BB_txt_v);}
end;


Procedure TEditacniPole.ZavriSoubor;
var v:PItRadek;
    debug_i:dword;

begin
debug_i:=0;
while radky^.pocet<>0 do {Pracuj tak dlouho, dokud nezrusime vsechny radky}
    begin
    inc(debug_i);
    v:=radky^.first^.vazba;
    Kill_PitRadek(v);
    radky^.ZrusUzel(radky^.first);
    end;
end;

Procedure TEditacniPole.NovySoubor;
var v:PItRadek;
    i:longint;
    os:string;
    ofnc:longint;


begin
ZavriSoubor;         {vysledkem by mel byt prazdny vaznik <Radky>}
v:=Init_PItRadek;

os:=AktualniFont;
NastavAktualniFont(hlavni_font);
ofnc:=FN_color;
FN_color:=BB_txt_txt;

radky^.InitNext(v);      {prvni radek...}
v^.PrvniUzel;            {...i s atributovym uzlem}
v^.y1:=0;
v^.y2:=v^.y1+v^.Vyska-1;
v^.yy:=1;

kd:=v^.vyska;

FN_color:=ofnc;
NastavAktualniFont(os);

InicializujKurzory;
SkocNaZacatek;
byla_zmena:=false;
end;



Procedure TEditacniPole.NastavRozmeziRadku(v:PItRadek;var yz:longint);
begin
v^.y1:=yz;
v^.y2:=v^.y1+v^.vyska-1;
yz:=v^.y2+1;
end;


Procedure TEditacniPole.UpravRozmeziRadku(v:PItRadek;var yz:longint);
begin
v^.y2:=v^.y1+v^.Vyska-1;
yz:=v^.y2+1;
end;



Procedure TEditacniPole.PridelRadky;
var p:PUzel;
    v:PItRadek;
    pryy,i:longint;

begin
i:=0;
pryy:=0;
p:=radky^.first;
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^.delka);
   }
   p:=p^.dalsi;
   end;
if zalamuj then NalamejBuffer(radky^.first,-1);
end;


Function TEditacniPole.PocetRadku:longint;
begin
PocetRadku:=Radky^.PocetUzlu;
end;


Procedure TEditacniPole.PosunRadek(p:PUzel);
{Nesnazi se zjistovat vysku radek, ale proste upravi jejich Y1 a Y2 a YY aby
 na sebe navazovaly}
var v,w:PItRadek;
begin
if p=nil then Exit;
if p^.predchozi=nil then Error('Error in TEditacniPole.PosunRadky!','');
{jsme na nultem radku? Tak to je chyba.}
if p=Radky^.first then  {jsme na prvnim radku? To muze byt.}
   begin
   v:=p^.vazba;
   v^.yy:=1;
   v^.y1:=0;
   v^.y2:=v^.Vyska-1;
   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^.y1:=w^.y2+1;
   v^.y2:=v^.y1+v^.vyska-1;
   p:=p^.dalsi;
   end;
end;


Procedure TEditacniPole.PreskladejRadky(q:PUzel;komplet_p,m1,m2,m3:boolean);
{Q je odkaz na aktualni radek, ktery se nejak zmenil a muze se nyni
 prilepit k predchazejicimu ci naslednemu radku.

To, zda se pripoji ci nepripoji bere podle CRLF. Delky radek neresi}

var p:PUzel;
    v:PItRadek;
    a:longint;
    o:word;
    c:char;
begin
if q=radky^.first then p:=q
   else begin
   p:=q^.predchozi;     {co predchozi radek?}
   v:=p^.vazba;
   if v^.crlf<>0        {ma mekke zakonceni?}
      then Prilep_k_predeslemu(p^.dalsi,m1)
                     {v tom pripade nas radek spoj s tim hornim}
      else p:=q; {v opacnem pripade nic nemen}
   end;

v:=p^.vazba;
if v^.crlf<>0 then Prilep_k_predeslemu(p^.dalsi,m2);
while v^.crlf<>0 do Prilep_k_predeslemu(p^.dalsi,m3);

if p<>radky^.first then p:=p^.predchozi;

if komplet_p=false then
   begin
   v:=p^.vazba;
   o:=v^.Znak(1);
   c:=char(o);
   if v^.crlf=0 then a:=1 else a:=0;
   end else a:=-1;
NalamejBuffer(p,a);
end;


Procedure TEditacniPole.PreskladejRadky(poz:TKurPoz;komplet_p,m1,m2,m3:boolean);
begin
PreskladejRadky(poz.r,komplet_p,m1,m2,m3);
end;


Procedure TEditacniPole.PreskladejRadky(poz:TKurPoz;komplet_p:boolean);
begin
PreskladejRadky(poz.r,komplet_p,true,true,true);
end;

Procedure TEditacniPole.PreskladejRadky(q:PUzel;komplet_p:boolean);
begin
PreskladejRadky(q,komplet_p,true,true,true);
end;


Procedure TEditacniPole.PreskladejBlokRadek(poz1,poz2:TKurPoz);
{Resi problem, kdy procedura PreskladejRadky ukonci praci v pripade, ze prvni
 prochazeny radek je natvrdo ukoncen. To je nekdy zadouci, jindy ne.
 Tato procedura prochazi oblast od POZ1 do POZ2 nize a pokud najde mekky zlom,
 tak odtud odstartuje PreskladejRadky}
var p:PUzel;
    v:PItRadek;
begin
p:=poz1.r;
repeat
  v:=p^.vazba;
  if v^.crlf<>0 then
     begin
     PreskladejRadky(p,true);
     Break;
     end;
  if p=poz2.r then Break else p:=p^.dalsi;
until p=nil;
end;



Function TEditacniPole.Je_delka_radky_k_zalomeni(v:PItRadek):boolean;
{potomci predefinovavaji}
begin
Je_delka_radky_k_zalomeni:=v^.gd>vsirka-start_poc_zobrX-1;
end;


Function TEditacniPole.Kde_je_misto_k_zalomeni(v:PItRadek):longint;
{potomci predefinovavaji}
begin
Kde_je_misto_k_zalomeni:=Pozice_v_retezci_IT(vsirka-1,Poc_ZobrX,0 {mozna radeji: start_poc_zobrX},v,false);
end;



Procedure TEditacniPole.NalamejBuffer(pr:PUzel;kdy_stop_analyzu:longint);
{Predpokladame, ze jiz probehlo spojovani radek. Ted provede jejich rozdeleni.}

{vzdy_vse:
 0  = skonci analyzu jakmile najde radek s CRLF
 <0 = ve vsech pripadech pokracuj v analyze
 >0 = toleruj N prvnich radku s CRLF
}

var v,v2,nv:PItRadek;
    p,novy:PUzel;
    a,i,l,j,oi,pryy,yz,vrad:longint;
    {d1,d2,d3,d4:longint;}
    probehlo_zalomeni:boolean;
    vkladat_mezeru:boolean;

begin
if p=nil then Exit;   {pojistka}
p:=pr;
v:=p^.vazba;
yz:=v^.y1;
pryy:=v^.yy;       {vytahneme Y1 a YY z prvniho zpracovavaneho radku}
if kdy_stop_analyzu>=0 then inc(kdy_stop_analyzu);
while p<>nil do
   begin
   v:=p^.vazba;
   probehlo_zalomeni:=false;
   NastavRozmeziRadku(v,yz); {nastavi Y1 a Y2 a automaticky inkrementuje YZ}
   v^.yy:=pryy;              {jeste YY}
   if Je_delka_radky_k_zalomeni(v) then
      begin
      probehlo_zalomeni:=true;
      oi:=Kde_je_misto_k_zalomeni(v);
      if oi<v^.delka+1 then
         begin               {dlouha radka - bude treba zalamovat}
                             {zname presny znak zalomeni, jenze my chceme...}
                             {...zalamovat podle slov, ne podle znaku}
         vkladat_mezeru:=true;
         i:=v^.ZacatekSlova_na_pozici(oi);     {proto najdeme, kde slovo zacina}
         if i=0 then      {mezera nenalezena, slovo tedy musime rozdelit nasilne}
            begin
            i:=oi;
            vkladat_mezeru:=false;
            l:=0;           {rozdeleni uvnitr slova - nelze vypustit zadny znak}
            end else l:=1;  {rozdeleni mezi slovy - vypustime mezeru}

         nv:=Init_PItRadek;
         nv^.PrvniUzel; {nutne, jinak v^.Rozdel bude ignorovat atributy}
         v^.Rozdel(nv^,i,l);  {doufejme, ze radne prevede i textove atributy}
                              {taky by se mel automaticky nastavit v^.gd}

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

         if vkladat_mezeru then v^.crlf:=1 else v^.crlf:=2;
         {radek uz neni ukoncen natvrdo pomoci CRLF, ale je ukoncen pruzne
          (a to bud s mezerou, nebo bez)}
         dec(i,l);

         novy:=Radky^.InsertNew(p,nv);
         if TK_Y=v^.yy then
            begin
            if TK_X>i then {nemuze tu byt >=}
               begin
               v2:=posl_rad^.vazba;
               j:=v^.Vyska;
               if v^.y2+j-Poc_ZobrY>vvyska-1
                  then inc(poc_ZobrY,j+1);
               Nastav_PoziceXYR(TK_X-i-1,
                                TK_Y+1,
                                novy);
               end;
            end;

         if pozice[ep_posl_vyskyt].y=v^.yy then
            pozice[ep_posl_vyskyt].r:=nil;
         end
         else begin          {radka se na obrazovku preci jen vejde - nebudu zalamovat}
         if v^.crlf=0 {tvrde zalomeni?}
            then dec(kdy_stop_analyzu);
         end;
      end;
   inc(pryy);
   p:=p^.dalsi;
   if (probehlo_zalomeni=false) and (kdy_stop_analyzu=0) then Break;
   end;

if p<>nil then PosunRadek(p);
{optimalizace pro pripady, kdy vime, ze v nizsich castech je uz vse...}
{...srovnane a bude stacit pouhy posun radek}

if TK_X=0 then Nastav_PoziceX(1); {vojeb, spravne by nemelo nikdy nastat}


SmazBodyOznaceni;   {BOHUZEL, dokud neosetrim hlidani bloku, tak takhle :-(}
end;


Procedure TEditacniPole.PospojujRadky(p:PUzel);
{TODO: poresit prozpusobeni bloku}
var q:PUZel;
    v:PItRadek;
    i,j:longint;
begin
i:=0;
if p=nil then p:=radky^.first;
{obvyklejsi postup s radky^.Reset... neprovadim, protoze nektere radky
 rusim a nechci riskovat neplatne ukazatele}
while p<>nil do
   begin
   v:=p^.vazba;
   while v^.crlf<>0 do
      begin
      q:=Prilep_k_predeslemu(p^.dalsi,true); {druhy radek prilepi k prvnimu}
      if q=nil then Break;
      end;
   v^.y1:=i;
   j:=v^.so+v^.su;
   v^.y2:=i+j-1;
   inc(i,j);
   p:=p^.dalsi;
   end;
end;


Procedure TEditacniPole.PospojujRadky;
begin
PospojujRadky(radky^.first);
end;


Procedure TEditacniPole.ZmenVychoziFont(s:string);
var ok:boolean;
    i:PItRadek;
    c:longint;
    y1:longint;

begin
i:=radky^.first^.vazba;
if i^.Prozkoumej_uzel_font(1)=s then Exit;
{pokud uz font nastaven je, tak neni treba nic menit}

y1:=0;
hlavni_font:=s;
if zalamuj then PospojujRadky;
radky^.reset;
while not radky^.konec do
   begin
   i:=radky^.nacti;   {budeme hledat jednotlive radky...}
   for c:=1 to maxlongint do
       begin   {pro vsechny uzly zmenime font na S}
       ok:=i^.Modifikuj_uzel_font(c,s);
       if not OK then Break;
       end;
   VyskaRadky_IT(i,c,i^.so,i^.su);   {updatujeme polozky ohledne vysky...}
   i^.gd:=Sirka_IT(i);                {...a graficke sirky}
   i^.y1:=y1;
   i^.y2:=i^.y1+i^.Vyska-1;
   y1:=i^.y2+1;
   end;

if zalamuj then NalamejBuffer(radky^.first,-1);
end;


Procedure TEditacniPole.ZmenVychoziBarvuTextu(w:word);
var konec:boolean;
    i:PItRadek;
    pw:word;
    bb,cb:Pfnatrb;

begin
konec:=false;
bb_txt_txt:=w;
i:=radky^.first^.vazba;

bb:=i^.VratUzel(1);           {atributy 1.znaku na 1.radku}
pw:=bb^.barva;                {o jakou se jedna barvu?}
if pw=w then Exit;  {pokud uz barva nastavena je, tak neni treba nic menit}

radky^.reset;
while not radky^.konec do
   begin
   i:=radky^.nacti;   {budeme hledat jednotlive radky...}
   if konec=false then
      begin
      i^.aa^.reset;      {...a v nich vazniky atributovych uzlu}
      while not i^.aa^.konec do
         begin           {bude postupne prochazet vsechny atributove uzly radky}
         cb:=i^.aa^.nacti;
         if cb^.barva=pw then cb^.barva:=w
                        else begin konec:=true;Break;end;
         end;
      end else Break;
   end;
end;



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

Function TEditacniPole.DejLinearniPozici:longint;
var p:PUzel;
    v:PItRadek;
    i:longint;
begin
i:=0;
p:=radky^.first;
while p<>TK_R do
   begin
   v:=p^.vazba;
   i:=i+v^.delka;
   p:=p^.dalsi;
   if p=nil then Break;  {vojeb, nemelo by nikdy nastat}
   end;
i:=i+TK_X;
DejLinearniPozici:=i;
end;

Procedure TEditacniPole.NastavLinearniPozici(i:longint);
var v:PItRadek;
    dosazeno:boolean;
begin
dosazeno:=false;
Radky^.Reset;
while not Radky^.konec do
   begin
   v:=Radky^.nacti;
   dec(i,v^.delka);
   if i<1 then
      begin
      inc(i,v^.delka);
      dosazeno:=true;
      break;
      end;
   end;

if dosazeno=false then  {pokud jsme na konci souboru a stale se nedosahlo I}
   i:=v^.delka+1;

Nastav_poziceXYR(i,v^.yy,radky^.nacteny);
end;

Procedure TEditacniPole.PosouvaciRezim;
var i:longint;
begin
i:=DejLinearniPozici;
zalamuj:=false;
PospojujRadky;
SrovnejYYradek(radky^.first);
NastavLinearniPozici(i);
{SkocNaZacatek;}
VycentrujNaKurzor;

SmazBodyOznaceni;  {bohuzel - procedura PospojujRadky si neporadi s bloky}
end;

Procedure TEditacniPole.ZalamovaciRezim;
var i:longint;
begin
i:=DejLinearniPozici;
zalamuj:=true;
NalamejBuffer(radky^.first,-1);
NastavLinearniPozici(i);
{SkocNaZacatek;}
VycentrujNaKurzor;

SmazBodyOznaceni;  {bohuzel - procedura PospojujRadky si neporadi s bloky}
end;


Procedure TEditacniPole.SkocNaZacatek;
begin
poc_ZobrX:=start_poc_zobrX;
poc_ZobrY:=start_poc_zobrY;
StartovniPozice_ep(ep_kurzor);
end;


Function TEditacniPole.Prvotni_analyza_jeste_v_TedRadek:boolean;
{Defaultne prevede tabulatory na mezery. Potomci si ale mohou tuto metodu
 prenastavit treba tak, aby delala ruzne analyzy textu jeste predtim, nez se
 spusti konverze na PItRadek}
var e:PEdRadek;
    z_timeru,z_timeru2:dword;
    byl_zobrazen_postup_nahravani:boolean;
    dokonceno:boolean;
    i:longint;
begin
z_timeru:=FromTimer;
byl_zobrazen_postup_nahravani:=false;
Global_Temp_radky^.Reset;
i:=0;
dokonceno:=true;
while not Global_Temp_radky^.Konec do
   begin
   inc(i);
   e:=Global_Temp_Radky^.Nacti;
   Prvotni_konverze_jeste_v_TedRadek(e);
   z_timeru2:=FromTimer;
   if ukaz_postup_nahravani<>nil then
      if TimerTicksFrom(z_timeru,15)=true then
         begin
         byl_zobrazen_postup_nahravani:=true;
         if not Ukaz_Postup_Nahravani(1,i/Global_Temp_Radky^.pocet*100) then
            begin
            MouseSetCursor(UKmys);
            dokonceno:=false;
            Break;
            end;
         z_timeru:=FromTimer;
         end;
   end;
if byl_zobrazen_postup_nahravani=true then Ukaz_Postup_Nahravani(1,-1);

Prvotni_analyza_jeste_v_TedRadek:=dokonceno;
end;


Procedure TEditacniPole.Prvotni_konverze_jeste_v_TedRadek(e:PEdRadek);
var k,u,n:longint;
    r:real;
    tbm:string;

begin
k:=1;
n:=e^.delka;
while k<=n do
   begin
   if e^.znak(k)=9 then {rozklad tabulatoru na mezery}
      begin
      e^.Vyjmi(k,1);
      u:=K mod (tab_na_mezery+1);
      u:=tab_na_mezery-u+1;
      tbm:=XMezer(u);
      e^.vlozS(tbm,k);
      inc(n,u-1);
      end
      else inc(k);
   end;
end;



Procedure TEditacniPole.Konverze_radky_z_PEdRadek_na_PItRadek(e:PEdRadek;i:PItRadek);
{Zasadni procedura pro nacitani souboru}
{V potomcich se znovy mohou delat vselijake konverze jak na urovni E, tak i I}
begin
i^.Vloz(e^.p,e^.delka,1);    {automaticky se nastavi i^.gd}
{podle i^.aa^.atributy.font se ridi, jestli bude E vkladat v modu UTF-8 nebo normalne}
end;



Function TEditacniPole.Konverze_po_nacteni:boolean;
var e:PEdRadek;
    i:PItRadek;
    yy,y1:longint;
    offs:string;
    ofnc:word;
    ab,bb:PFnatrb;
    temp_u:PUzel;
    z_timeru:dword;
    byl_zobrazen_postup_nahravani:boolean;
    dokonceno:boolean;

begin
dokonceno:=Prvotni_analyza_jeste_v_TedRadek;
{Pro kazdou radku vola <Prvotni_konverze_jeste_v_TedRadek>. Tam se postupne
provadi rozklad tabulatoru na mezery. (a potomci take mohou uz zde
 hledat skvence  UTF-8)

Pro skonceni pruchodu si jeste mohou potomci prodat jeste nejake vlastni akce}


{Pozor, muze se stat, ze zmeni napr. promennou <self.hlavni_font>}

if dokonceno=false then  {v druhe fazi nahravani zmacknuto ESC?}
   begin
   SmazVaznikPEdRadku(Global_temp_radky);
   Exit(false);
   end;

offs:=AktualniFont;NastavAktualniFont(hlavni_font);
ofnc:=FN_color;FN_color:=BB_txt_txt;
z_timeru:=FromTimer;
byl_zobrazen_postup_nahravani:=false;
temp_u:=Global_temp_radky^.first;
if temp_u<>nil then
   begin
   bb:=New(Pfnatrb,Init);      {vyrvori uzel s defaultnimi param. textu}
   bb^.Default;
   end;

yy:=1;
y1:=0;
while temp_u<>nil do
    begin
    e:=temp_u^.vazba;
    i:=Init_PItRadek;
    i^.UmistiUzel(bb,1);         {alespon prvni uzel at je vzdy definovany}

    i^.yy:=yy;

    Konverze_radky_z_PEdRadek_na_PItRadek(e,i);

    i^.y1:=y1;
    i^.y2:=i^.y1+i^.Vyska-1;
    i^.crlf:=0;                {??? TODO ???}
    y1:=i^.y2+1;
    inc(yy);
    Kill_PEdRadek(e);

    Radky^.InitNext(i);
    temp_u:=temp_u^.dalsi;

    if temp_u<>nil then
       begin
       ab:=i^.VratUzel(i^.delka);    {Jaky ma posledni znak radky atributy?}
       bb:=ab^.CopyTo(1);            {Prekopirujeme je do prvniho znaku...}
       end;                          {...nasledujiciho radku}


    if ukaz_postup_nahravani<>nil then
      if TimerTicksFrom(z_timeru,15)=true then
         begin
         byl_zobrazen_postup_nahravani:=true;
         if not Ukaz_Postup_Nahravani(2,yy/Global_temp_radky^.Pocet*100) then
            begin
            MouseSetCursor(UKmys);
            SmazVaznikPEdRadku(Global_temp_radky);
            dokonceno:=false;
            Break;
            end;
         z_timeru:=FromTimer;
         end;

    end;

if byl_zobrazen_postup_nahravani=true then Ukaz_Postup_Nahravani(2,-1);
NastavAktualniFont(offs);
FN_color:=ofnc;

Vaznik_done_all(Global_temp_radky);
Analyza_po_nacteni_a_konverzi;
Konverze_po_nacteni:=dokonceno;
end;


Function TEditacniPole.Analyza_po_nacteni_a_konverzi:longint;
begin
{Defaultne prazdne, ale muze byt predefinovano potomky}
end;


Function TEditacniPole.NactiZeStreamu_hlavicka(var s:TStream):longint;
{1=ASCII nebo UTF-8}
{2=UTF16LE}
{3=UTF16BE}
begin
NactiZeStreamu_hlavicka:=1;
end;


Function Hledej_Konec_Radku(buffer:pchar;poz,bajtu:longint;utfm:byte;znak:char):longint;
var w:word;
    l,p:longint;
begin
p:=bajtu-poz+1;
if utfm=1 then
   begin
   Hledej_Konec_Radku:=IndexByte(buffer[poz],p,byte(znak));
   end
   else
   begin
   w:=byte(znak);
   if utfm=3 then w:=w shl 8;
   l:=IndexWord(buffer[poz],p div 2,w);
   if l<0 then l:=-1
      else begin
      l:=l*2;
      if utfm=3 then inc(l);
      end;
   Hledej_Konec_Radku:=l;
   end;
end;


Function TEditacniPole.NactiZeStreamu(var s:TStream):byte;
{Funguje tak, ze napred nacte cely soubor do provizorniho vazniku Temp_Radky,
 ktery spojuje promenne typu PEdRadek. Pote se prochazi jednotlive polozky
 docasneho vazniku (t.j. jednotlive radky), provadi se konverze na PItRadky,
 ktere se pospojuji do finalniho vazniku Radky}

const VEL_BUFFER = 65536;
var l,m,k,kk:longint;
    dbg_i:longint;
    utfm:byte;
    p:pchar;
    r:PVaznik;
    v:PEdRadek;
    pokracovat,byl_zobrazen_postup_nahravani:boolean;
    ukoncen_predchozi_blok:boolean;
    posl_znak_predchoziho_bloku:longint;
    oddelovac:byte;
    z_timeru:dword;

begin
posl_znak_predchoziho_bloku:=-1;
l:=s.GetSize;
if l=0 then
   begin
   NovySoubor;
   NactiZeStreamu:=edna_OK;
   Exit;
   end;

MouseSetCursor(UKmysCekej);
MyGetMem(p,VEL_BUFFER+1);
ZavriSoubor;         {Odstrani prave nactenou vec}
pokracovat:=true;
ukoncen_predchozi_blok:=true;
byl_zobrazen_postup_nahravani:=false;
z_timeru:=FromTimer;

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

Global_temp_radky:=NovyVaznik;

utfm:=NactiZeStreamu_hlavicka(s);

repeat
l:=s.GetPos;                  {zaznamenam pozici ve streamu pred ctenim}
s.Read(p^,VEL_BUFFER);        {pokusim se precist VEL_BUFFER 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   {CRLF=#13#10}
   if (p[0]=#10) and (posl_znak_predchoziho_bloku=13)
      then m:=1 else m:=0;  {kdyz minuly blok skoncil #13...}
                            {...a na zacatku tohodle by z CRLF zustalo #10}
   posl_znak_predchoziho_bloku:=byte(p[l-1]);

   dbg_i:=0;

   repeat
   {Ted budu prohledavat nacteny blok a hledat v nem konce radek.}
   {Rutina by si mela poradit s formaty #13#10, s #10 i s #13.}

   inc(dbg_i);

   if dbg_i=6 then
      l:=l;

      k:=Hledej_Konec_Radku(p,m,l,utfm,#13); {budu hledat #13}
      if k=-1 then
         begin                    {v bloku jsme nenasli #13 (CR)?}
         k:=Hledej_Konec_Radku(p,m,l,utfm,#10); {tak co alespon #10 (LF)?}
         if k=-1 then    {ani LF?}
            begin
            DalsiRadka(p,m,l-m+1,ukoncen_predchozi_blok,false);
            m:=l;
            oddelovac:=0;
            end else oddelovac:=10;
         end else oddelovac:=13;


      if k<>-1 then  {byl nalezen bud #13 nebo #10}
         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;  {!!! SPORNE !!!}         {znak #13 nahradim znakem #0}*)



         if utfm=3 then kk:=k-1 else kk:=k;

         p[m+k]:=#0;  {Zajistime, aby vysledny PEdRadek koncil znakem #0}
                      {Je to vhodne kvuli zpetne kompatibilite s PChar}

         DalsiRadka(p,m, kk,  ukoncen_predchozi_blok,true);
         inc(m,k+1);
         if utfm>1 then inc(m);
         if oddelovac=13 then
            begin
            case utfm of
            1:if p[m]=#10 then inc(m,1);
            2:if (p[m]=#10) and (p[m+1]=#0) then inc(m,2) else inc(m,0);
            3:if (p[m]=#10) and (p[m-1]=#0) then inc(m,1) else dec(m,1);
            end; {case}
            end
            else begin      {oddelovac=#10}
            case utfm of
            3:dec(m,1);     {pri UTF16BE o jednu zpet}
            end; {case}
            end;
         end;
   until m>=l;
   if ukaz_postup_nahravani<>nil then
      if TimerTicksFrom(z_timeru,15)=true then
         begin
         byl_zobrazen_postup_nahravani:=true;
         pokracovat:=Ukaz_Postup_Nahravani(3,s.GetPos/s.GetSize*100);
         if pokracovat=false then
            begin
            NovySoubor;
            MouseSetCursor(UKmys);
            SmazVaznikPEdRadku(Global_temp_radky);
            FreeMem(p,VEL_BUFFER+1);
            NactiZeStreamu:=edna_CANCELED;
            Exit;
            end;
         z_timeru:=FromTimer;
         end;
   end;




until l<>VEL_BUFFER;
if byl_zobrazen_postup_nahravani=true then Ukaz_Postup_Nahravani(3,-1);

DalsiRadka(nil,0,0,ukoncen_predchozi_blok,true);
{ukoncime pripadnou rozdelanou radku}
FreeMem(p,VEL_BUFFER+1);
{V tento okamzik mame nacteno do Temp_Radky, jenz svazuje radky typu PedRadek}
MouseSetCursor(UKmys);
if not Konverze_po_nacteni then
   begin
   NovySoubor;
   NactiZeStreamu:=edna_CANCELED;
   Exit;
   end;
{A ted jsme data preklopili do definitivniho vazniku Radky a jeho PItRadek}
SkocNaZacatek;
MouseSetCursor(UKmys);
NactiZeStreamu:=edna_OK;
if zalamuj then NalamejBuffer(TK_R,-1);
end;

Procedure TEditacniPole.DalsiRadka(u:PChar;poz,del:longint;var predchozi_blok_ukoncen:boolean;nynejsi_blok_ukoncen:boolean);
var v,e:PEdRadek;
    b:boolean;
begin
if Global_temp_radky^.pocet>0 then b:=predchozi_blok_ukoncen else b:=true;
if u<>nil then inc(u,poz);
if B then {delame uplne novy radek}
   begin
   v:=Init_PEdRadek;
   if u<>nil then v^.Vloz(u,del,1);
   Global_Temp_radky^.InitNext(v);   {zaradime vytvorenou radku do vazniku}
   end
   else begin  {pripojovani na konec posledni existujici radky}
   e:=Global_Temp_radky^.last^.vazba;
   if u<>nil then e^.Vloz(u,del,e^.delka);
   end;
predchozi_blok_ukoncen:=nynejsi_blok_ukoncen;
end;

Function TEditacniPole.NactiZVazniku(p:PVaznik):boolean;
var q:PUzel;
    u:PChar;
    v:PString;
    z:string;
    i:longint;
    e:PItRadek;
    predchozi:boolean;

begin
ZavriSoubor; {Odstrani prave nactenou vec}
if p^.PocetUzlu=0 then Exit(false);
predchozi:=true;
u:=p^.first^.vazba;
if u=nil then Exit(false);
Global_Temp_Radky:=NovyVaznik;
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,Length(z) {NUTNO OVERIT},predchozi,true);
   end
   else begin          {pro viceradkove texty}
   q:=p^.first;
   while q<>nil do
      begin
      v:=q^.vazba;
      z:=v^+#0;
      u:=@z[1];
      DalsiRadka(u,0,Length(z) {NUTNO OVERIT},predchozi,true);
      q:=q^.dalsi;
      end;
   end;
{V tento okamzik mame nacteno do Temp_Radky, jenz svazuje radky typu PedRadek}
Konverze_po_nacteni;
{A ted jsme data preklopili do definitivniho vazniku Radky a jeho PItRadek}
SkocNaZacatek;
NactiZVazniku:=true;
end;

Function TEditacniPole.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;


Procedure TEditacniPole.Konverze_radky_z_PItRadek_na_PEdRadek(v:PItRadek;var e:PEdRadek;var u:string);
begin
e:=v^.VratPEdRadek(1,v^.up,false);
{if v^.crlf=0 then u:=#13#10 else u:=' ';}
if v^.crlf=0 then u:=ukoncovac_radku else
if v^.crlf=1 then u:=' ' else u:='';
end;


Procedure TEditacniPole.UlozDoStreamu_hlavicka(var s:TStream);
begin
{dummy}
end;


Procedure TEditacniPole.UlozDoStreamu_paticka(var s:TStream);
begin
{dummy}
end;


Function TEditacniPole.UlozDoStreamu(var s:TStream):boolean;
{Predpoklad: Uz mame otevreny proud S.}
var v:PItRadek;
    e:PEdRadek;
    u:string[6];
    kr:boolean;
    i:longint;

begin
MouseSetCursor(UKmysCekej);
Radky^.Reset;

UlozDoStreamu_hlavicka(s);  {ev. ulozeni zahlavi, napr. BOM}

while not Radky^.konec do
   begin
   v:=radky^.Nacti;
   Konverze_radky_z_PItRadek_na_PEdRadek(v,e,u);  {E se alokuje uvnitr}
   i:=e^.delka;
   s.Write(e^.p^,i);

   if radky^.nacteny<>radky^.last then kr:=true
      else kr:=i=0;

   if (kr=true) and (u<>'') then
      s.Write(u[1],Length(u));     {zpusob ukonceni radky: CRLF, #32,...}
   Kill_PEdRadek(e);
   end;

UlozDoStreamu_paticka(s);   {ev. doulozeni neceho po radkach (napr. kontrolni soucet)}

MouseSetCursor(UKmys);
UlozDoStreamu:=true;
end;

Function TEditacniPole.UlozSoubor(s:string):boolean;
var {t:TMemoryStream;}
    t2:TBufStream;
    b:byte;
    o:boolean;
    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;

t2.Init(s,stCreate,40000);
if t2.ErrorInfo<>0 then
   begin t2.Done;Exit(false);end;

o:=UlozDoStreamu(t2);
t2.Done;

if o=true then byla_zmena:=false;
UlozSoubor:=o;
end;


Procedure TEditacniPole.NastavBodOznaceni(b:byte;poz:TKurPoz);
var c:byte;
begin
if (b=1) or (b=2) then
   begin
   if b=1 then c:=EP_oznac1 else c:=EP_oznac2;
   pozice[c]:=poz;
   if (pozice[EP_oznac1].y<>0) and (pozice[EP_oznac2].y<>0) then
      if porovnejPozici(pozice[EP_oznac1],pozice[EP_oznac2])<>2 then SmazBodyOznaceni;
   end;
end;


Procedure TEditacniPole.SmazBodyOznaceni;
begin
NulujPozici(pozice[EP_oznac1]);
NulujPozici(pozice[EP_oznac2]);
jak_oznacen_blok:=0;
end;


Function Bod_na_prazdne_radce(poz:TKurPoz):boolean;
var v:PItRadek;
begin
v:=poz.r^.vazba;
Bod_na_prazdne_radce:=v^.up=0;
end;



Procedure TEditacniPole.NastavRozsahOznaceni(zac,kon:TKurPoz);
var b:byte;
    zp,kp:boolean;
begin
{zp:=Bod_na_prazdne_radce(zac);
kp:=Bod_na_prazdne_radce(kon);}

pozice[ep_oznac1]:=zac;
pozice[ep_oznac2]:=kon;
jak_oznacen_blok:=2;
end;


Function TEditacniPole.Zda_oznacen_blok:boolean;
begin
Zda_oznacen_blok:=Jak_oznacen_blok>1;  {definovane oba okraje bloku?}
end;


Function TEditacniPole.Pocet_radek_bloku:longint;
var i:longint;
begin
if Zda_oznacen_blok=false then Pocet_radek_bloku:=0
   else begin
   i:=abs(pozice[ep_oznac2].y-pozice[ep_oznac1].y)+1;
   Pocet_radek_bloku:=i;
   end;
end;


Destructor TEditacniPole.Done;
begin
kpoz.hoehe:=100;
Kill_VW(kpoz);
ZavriSoubor;
Dispose(radky,done);
Dispose(py,Done);
Dispose(px,Done);
end;




Procedure Redef_proc(ja:pointer;var r:longint);
var pok:Pokno_s_tlacitky;
    e:PEditacniPole;
    z:Pzatrzitka;
begin
pok:=ja;
if r=10 then
   begin
   e:=pok^.Najdi_dle_vyznam(2)^.vazba;
   z:=pok^.Najdi_dle_vyznam(10)^.vazba;
   if z^.id=id_TZatrzitko then
      begin
      if z^.VratHodnotu='1' then e^.ZalamovaciRezim else e^.PosouvaciRezim;
      e^.zobraz;
      end;
   end;
end;


Procedure InternalTextoveOkno(x,y,sirka,vyska:longint;popis,soubor:string;p:PVaznik);
var e:PEditacniPole;
    f:PTextovePole;
    ok:Tokno_s_tlacitky;
    z:PZatrzitka;
    _o:word;
    i:longint;
    k:virtualwindow;
    znovu:boolean;
    ppp:pointer;

begin
_o:=BA_okn_v;
BA_okn_v:=BA_tla_v;


ok.init(x,y,sirka,vyska,popis,w_OK);


ok.proceduralni_promenna_z_run_akce:=@Redef_proc;

{ppp:=@Redef_proc;
move(ppp^,ok.proceduralni_promenna_z_run_akce,4);}


{ok.proceduralni_promenna_z_run_akce:=@Redef_proc;}

BA_okn_v:=_o;

i:=ok.vyska-25;

e:=New(PEditacniPole,Init(ok.x+2,ok.y+ok.vyskazahlavi+1,ok.sirka-2,i-ok.vyskazahlavi-30,true,2));
e^.konverze_tagu:=false;
{e^.povolene_zmeny:=false;}
e^.jednotna_vyska_radku:=false;
{e^.po_kl_rozpr:=true;}

if p=nil
   then e^.NactiSoubor(soubor)
   else e^.NactiZVazniku(p);

{
zalamuj:=true;
NalamejBuffer(TK_R);
}


z:=New(PZatrzitka,Init(ok.x+4,ok.y+ok.vyska-25,'zalamuj','0',10));
ok.Pridej(z);

f:=New(PTextovePole,Init(ok.x+340,ok.y+ok.vyska-25,100,'test',true,0));
ok.Pridej(f);

ok.Pridej(e);
ok.Retez^.Aktivuj(e);
ok.Zobraz;

repeat
ok.Retez^.Aktivuj(e);
znovu:=false;
ok.Run;
if xklavesa.ascii=xEnter then begin znovu:=true;end;
until znovu=false;

ok.Done;
end;


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


Procedure TextoveOkno(x,y,sirka,vyska:longint;popis:string;soubor:string);
begin
InternalTextoveOkno(x,y,sirka,vyska,popis,soubor,nil);
end;



end.
