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;


PARAM_UPRAV_SCROL_X = 1;
PARAM_KONTR_MAX_X   = 2;



Procedure NulujPozici(var kur:Tkurpoz);
Procedure NaplnPozici(var kur:TKurPoz;x,y:longint;p:PUzel);
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;
Function PlatnostPozice(var kur:TKurpoz):boolean;
Function LinearniPozice(var kur:TKurPoz):comp;

const
POCET_ZALOZEK_EDIT_POZICE = 5;
ZAKLADNI_EDIT_POZICE = 9;

MAX_EDIT_POZICE = ZAKLADNI_EDIT_POZICE + POCET_ZALOZEK_EDIT_POZICE;

EP_kurzor = 1;           {pozice kurzoru}
EP_spec_bod = 2;         {pozice pro specialni pouziti}

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;
EP_temp_poz_kurz = 9;

EP_blok_zalozek = 10;

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)}


{--------------------------------------------------------}
{nasledujici patri k TEdiAkce.druh}
EDA_zmena_kurzoru   = 0;
EDA_prekresli_1     = 1;
EDA_prekresli_okno  = 2;
EDA_modif_1         = 3;
EDA_modif_okno      = 4;
{--------------------------------------------------------}

{nasledujici k TEdiAkce.akce}
EDA_znak_1          = 1;
EDA_znak_x          = 2;
EDA_tab             = 3;
EDA_pribuzny_znak   = 4;
{--------------------------------------------------------}

type
TEdiAkce = object
akce:longint;  {pro kazdou akci specificky kod}
druh:byte;
{0.bit: 1 = pozice kurzoru zmenena
 1.bit: 1 = nutne prekresleni radku s kurzorem
 2.bit: 1 = nutne prekresleni celeho okna
 3.bit: 1 = zmenena radka s kurzorem
 4.bit: 1 = zmena vice radek}
Procedure Init;
Procedure Vynuluj;

Procedure NastavBit(b:byte);
Procedure NulujBit(b:byte);
Function ZdaBit(b:byte):boolean;
Function ZdaZmenaTextu:boolean;
Function ZdaZadna:boolean;
Function ZdaPouzeZmenaKurzoru:boolean;
Procedure ZmenaRadky;
Procedure ZmenaOkna;
end;



type
PEditacniPole = ^TEditacniPole;
TEditacniPole = object(TPredekPosuvny)
       radky:PVaznik;       {Jsou tam navazany typy PItRadek}
       pozice:array[1..MAX_EDIT_POZICE] of TKurPoz;
       PozText:record
          odz,doz,
          posunv,posunm:longint;
          end;
       konverze_tagu:boolean;
       jednotna_vyska_radku:boolean;

       mod_zobrazeni:byte;
       {0 = vynut prekresleni celeho okna}
       {1 = zakaz zobrazeni}
       {2 = podle <probehla_akce>
            takto se bude volat pres EditacniPole.Kontrola}

       zapnuto_mouse_self_copy:boolean;
       unicode:boolean;
       povolene_zmeny:boolean;
       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}
       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;
       prv_rad,posl_rad:PUzel;         {Prvni a posledni vypsany radek}
       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}


       minula_akce:TEdiAkce;
       probehla_akce:TEdiAkce;

       dbg_prom:boolean;


       byla_zmena_od_ulozeni:boolean;
       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;
       Procedure ZobrazVse;virtual;
       Function Zobrazeni_najdi_zachytnou_radku(var smer:byte):PUzel;
       Procedure Zobraz_vypisuj_odshora_dolu(p:PUzel;var p1,p2:PUzel);
       Procedure Zobraz_vypisuj_odzdola_nahoru(p:PUzel;var p1,p2:PUzel);
       Procedure Zobraz_Od_kotvy(p:PUzel;smer:byte);
       Procedure VymazProstor_pro_zobr_3_radek(vnad,v,vpod:PItRadek);
       Function Jaky_Zpusob_Zobrazeni:byte;
       Procedure Zobraz_3_radky(p:PUzel);
       Procedure Zobraz_Bez_optimalizace_na_1_radek;
       Procedure Zobraz_Optimalizace_na_1_radek;

       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 Ostatni_pozice_navysX(P:PUzel;pzx,dx:longint);
       Procedure Ostatni_pozice_Prilep_na_jinou_radku(p,q:PUzel;kde_x,diff_x,diff_y:longint);
       Procedure Napln_KurPoz(var co:TKurPoz;mode:byte);
       Procedure VypisRadekTextu(ix,korekce_y:longint;p:PUzel;v:PItRadek);virtual;
       Procedure VlastniVypisRadkyTextu(ix,iy:longint;p:PUzel;v:PItRadek);virtual;
       Function ShiftemMenenyBlok:byte;virtual;
       Procedure DodatkyPredZobrazenim;virtual;
       Procedure DodatkyPoZobrazeni;virtual;
       {------------------------}
       procedure DeaktivacniProcedura;virtual;
       Procedure InicializujKurzory;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 Prilep_K_predeslemu(rus:PUzel;smezerou:boolean;var kam_nalepeno:longint):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 PridejTextNaPozici(poz:TKurPoz;kp:PChar;ksd:longint;mode:byte;presun_kurzoru: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;
       Function Je_Radek_na_obrazovce(v:PItRadek;var dy:longint):boolean;
       Procedure PospojujRadky;virtual;
       Procedure PospojujRadky(p:PUzel);virtual;
       Procedure PridelRadky;virtual;
       Procedure JednoduchePreskladaniRadek_od_kurzoru;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_poziceX(ix:longint;parametry:byte);virtual;
       Procedure Nastav_poziceXYR(ix,iy:longint;ir:pointer);virtual;
       Procedure Nastav_poziceXYRP(ix,iy:longint;ir:pointer;parametry:byte);virtual;

       Procedure Korekce_Poc_ZobrY;
       Procedure Korekce_Poc_ZobrX(odskok:boolean);
       Procedure Korekce_Poc_ZobrX_po_Pozice_v_retezci_IT;
       Function Lokalizuj_grafickou_pozici(xx,yy:longint;var kur:TKurPoz):byte;
       Procedure Vypocitej_grafickou_pozici_kurzoru;
       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);
       Function IdentifikujSlovo(kur:TKurPoz;var zac,kon:TKurPoz):byte;
       Procedure SmazSlovo;
       Function OznacSlovo(kur:TKurPoz):byte;virtual;
       Procedure SmazBlokTextu_internal(zac,kon:TKurPoz);virtual;
       Procedure SmazBlokTextu;virtual;
       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 Znak_pobliz_kurzoru(diff_x:longint;var znak:word):boolean;
       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);
       Function ZkontrolujPlatnostOznaceni:boolean;
       Procedure SmazBodyOznaceni;
       Procedure NastavRozsahOznaceni(zac,kon:TKurPoz);
       Function Zda_oznacen_blok:boolean;
       {jsou definovane oba kraje bloku?}
       Function Pocet_radek_bloku:longint;
       Function Zda_pozice_v_bloku(poz:TKurPoz):boolean;
       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;


Procedure NaplnPozici(var kur:TKurPoz;x,y:longint;p:PUzel);
begin
kur.x:=x;
kur.y:=y;
kur.r:=p;
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;


Function PlatnostPozice(var kur:TKurpoz):boolean;
begin
if kur.r=nil then Exit(false);
if kur.r^.vazba=nil then Exit(false);
PlatnostPozice:=true;
end;


Function LinearniPozice(var kur:TKurPoz):comp;
var a,b:comp;
begin
a:=kur.y;
b:=kur.x;
a:=a*maxlongint+b;
LinearniPozice:=a;
end;


Procedure TEdiAkce.Init;
begin
Vynuluj;
end;


Procedure TEdiAkce.Vynuluj;
begin
akce:=0;
druh:=0;
end;

Procedure TEdiAkce.NastavBit(b:byte);
begin
b:=1 shl b;
druh:=druh or b;
end;

Procedure TEdiAkce.NulujBit(b:byte);
begin
b:=not(1 shl b);
druh:=druh and b;
end;


Procedure TEdiAkce.ZmenaRadky;
begin
NastavBit(EDA_modif_1);
NastavBit(EDA_prekresli_1);
end;


Procedure TEdiAkce.ZmenaOkna;
begin
NastavBit(EDA_modif_okno);
NastavBit(EDA_prekresli_okno);
end;


Function TEdiAkce.ZdaBit(b:byte):boolean;
begin
b:=1 shl b;
ZdaBit:=(druh and b)<>0;
end;


Function TEdiAkce.ZdaZmenaTextu:boolean;
begin
ZdaZmenaTextu:=(druh and (8+16))<>0;
{je nastaven 3. nebo 4.bit?}
end;


Function TEdiAkce.ZdaZadna:boolean;
begin
ZdaZadna:=druh=0;
end;

Function TEdiAkce.ZdaPouzeZmenaKurzoru:boolean;
begin
ZdaPouzeZmenaKurzoru:=druh<=1;
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}

dbg_prom:=false;

prv_rad:=nil;
posl_rad:=nil;

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;

vyska:=_vyska;
sirka:=_sirka;

virtvyska:=_vyska;
virtsirka:=_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}

py^.wkoef:=40;    {zvysime citlivost na kolecko mysi}

mod_zobrazeni:=0; {vynutime zobrazeni}

zapnuto_mouse_self_copy:=true;

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;


minula_akce.Init;
probehla_akce.Init;


byla_zmena_od_ulozeni:=false;
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;

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.Vypocitej_grafickou_pozici_kurzoru;
var v:PItRadek;
begin
v:=TK_R^.vazba;
ky:=v^.y1;
kd:=v^.vyska;
kx:=Zjisti_X(TK_X,v)+Poc_ZobrX;
end;


procedure TEditacniPole.DeaktivacniProcedura;
begin
inherited DeaktivacniProcedura;
if Je_kurzor_videt then BlikejKurzorem;  {vypni kurzor}
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};

   Probehla_akce.NastavBit(EDA_zmena_kurzoru);

   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;



   Function ZkontrolujPosuvnik:boolean;
   var g:boolean;
       oph:longint;
   begin
   if py=nil then Exit(false);
   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
         poc_zobrY:=py^.hodnota;
         if poc_zobrY<>oph
            then g:=true;
         end else py^.probehni:=false;

   if g=true then Probehla_akce.NastavBit(EDA_prekresli_okno);

   ZkontrolujPosuvnik:=g;
   {Pokud bude TRUE, tak to znamena, ze se s posuvnikem neco delo}
   end;

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

zmena_bliknuti:=false;

mod_zobrazeni:=2;       {procedura zobraz bude zkouset optimalizovat}

dbg_prom:=false;

if Probehla_akce.ZdaZadna=false then
   Minula_akce:=Probehla_akce;
Probehla_akce.Vynuluj;

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
      bbb:=ZkontrolujPosuvnik;
      if zmena_bliknuti then BlikejKurzorem;
      if Bod_uvnitr_vnitrni_casti(mys_xx,mys_yy) then
         if (mouse.b<>0) and (bbb=false) then
            if (py<>nil) and (py^.tahaci_stav<>true) then
            begin
            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;
            bbb:=true;
            {zobraz;}
            {Vypustil jsem MouseRel a presunul do KlepnutiMysi}
            end;

     {Jsme budto na posuvniku nebo nekde uplne jinde}
     if mouse._wdif<>0 then
        begin
        i:=mouse._wdif;
        inc(poc_zobrY,i*py^.wkoef);
        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;
        Probehla_akce.NastavBit(EDA_prekresli_okno);
        mouse._wdif:=0;        {ne zcela ciste, ale prijatelne}
        bbb:=true;
        {zobraz;}
        {Exit;}
        end;
      if bbb=true then
         begin
         {mod_zobrazeni:=1;} {debug}
         {dbg_prom:=true;}
         Zobraz;
         end;
      end;
end; {case}


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

if Probehla_akce.ZdaZmenaTextu then byla_zmena_od_ulozeni:=true;
mod_zobrazeni:=0;  {vypneme optimalizace pro <EditacniPole.Zobraz>}

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;
    i:longint;
begin
if TK_X<=1 then
   begin
   Nastav_PoziceX(TK_X);
   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);*)

i:=0;
if TK_X<v^.odz then {presahuje tento radek levy okraj obrazovky?}
   begin
   inc(poc_zobrX,v^.posunm);
   i:=1;
   end;
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:=i;
end;


Function TEditacniPole.KrokVpred:longint;
var v:PItRadek;
    i:longint;
begin
v:=TK_R^.vazba;
if TK_X>=v^.delka+1 then
   begin
   {i kdyz jsme na konci radky a nemuzeme pohnout kurzorem, tak mozna budeme
    muset resit naskrolovani obrazovky}
   Nastav_PoziceX(TK_X);
   Exit(0);
   end;
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);*)

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


Function TEditacniPole.Znak_pobliz_kurzoru(diff_x:longint;var znak:word):boolean;
{DIFF_X: kolik znaku pricist (kladne) nebo odecist od polohy kurzoru
 ZNAK: jaky znak je na specifikovanem miste (kdyz zadny, tak da nulu)
 VYSLEDEK: <false>  na specifikovanem miste neni znak (typicky na konci radky)
                    v takovem pripade ignorovat promennou ZNAK
           <true> v danem miste je nejaky znak a promenna ZNAK je tedy platna}

var v:PItRadek;
    i:longint;
begin
v:=TK_R^.vazba;
i:=TK_X+diff_x;
znak:=0;
if (i<1) or (i>v^.up) then Exit(false); {neplatna pozice?}

znak:=v^.Znak(i);
Znak_pobliz_kurzoru:=true;
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
if KrokVpred<>0
   then Probehla_akce.NastavBit(EDA_prekresli_okno);
end;


Procedure TEditacniPole.SipkaDoleva;
begin
if KrokZpet<>0
   then Probehla_akce.NastavBit(EDA_prekresli_okno);
end;



Procedure TEditacniPole.Korekce_Poc_ZobrY;
var v:PItRadek;
    b:boolean;
    dy:longint;

begin
v:=TK_R^.vazba;
b:=Je_Radek_na_obrazovce(v,dy);

if dy=0 then Exit;  {radek je videt komplet, horni i dolni okraj}

if b=true then      {je videt kus radku, ale ne kompletni radek}
   begin
   inc(Poc_zobrY,dy)
   end
   else             {radek neni vubec videt}
   begin
   if abs(dy)<vvyska div 2
      then inc(Poc_zobrY,dy*2)
      else Poc_ZobrY:=v^.y1-vvyska div 2;

   if Poc_ZobrY<0 then Poc_ZobrY:=0;
   end;
Probehla_akce.NastavBit(EDA_prekresli_okno);
end;


Procedure TEditacniPole.Korekce_Poc_ZobrX(odskok:boolean);
var v:PItRadek;
    i,dx,jx:longint;

begin
jx:=TK_X;

if jx=1 then
   begin
   if Poc_ZobrX<>start_poc_zobrX then
      begin
      Poc_ZobrX:=start_poc_zobrX;
      Probehla_akce.NastavBit(EDA_prekresli_okno);
      end;
   Exit;
   end;

v:=TK_R^.vazba;

i:=Zjisti_X(jx,v);

if i+Poc_ZobrX>vsirka then
   begin
   Poc_ZobrX:=-(i-vsirka+1);
   if odskok then dec(Poc_ZobrX,rolovaci_odskok);
   if Poc_ZobrX>start_poc_zobrX then Poc_ZobrX:=start_poc_zobrX;
   Probehla_akce.NastavBit(EDA_prekresli_okno);
   end;
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;
   Probehla_akce.NastavBit(EDA_prekresli_okno);
   end;
end;


Procedure TEditacniPole.SipkaDolu;
var  v:PItRadek;
     r:PUzel;
     a1,a2:longint;
begin

if povolene_zmeny then
   begin
   if TK_Y>=PocetRadku then Exit;
   r:=TK_R^.dalsi;
   {diky podmince s TK_Y>=PocetRadku by nemelo hrozit, ze se dostaneme na NIL}
   v:=r^.vazba;
   Nastav_poziceXYR(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true),
                    TK_Y+1,
                    r);

   {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}
      begin
      Probehla_akce.NastavBit(EDA_prekresli_okno);
      poc_ZobrY:=v^.y2-vvyska-1+1;
      end;
   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;
   Probehla_akce.NastavBit(EDA_prekresli_okno);
   end;
end;

Procedure TEditacniPole.SipkaNahoru;
var  v:PItRadek;
     r:PUzel;
begin
if povolene_zmeny then
   begin
   if TK_Y<=1 then Exit;

   {diky podmince s TK_Y<=1 by nemelo hrozit, ze se dostaneme na NIL}
   r:=TK_R^.predchozi;
   v:=r^.vazba;
   Nastav_poziceXYR(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},v,true),
                    TK_Y-1,
                    r);

   {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;
      Probehla_akce.NastavBit(EDA_prekresli_okno);
      if poc_zobrX>start_poc_zobrX then poc_zobrX:=start_poc_zobrX;
      end;
   if v^.y1<poc_ZobrY then                      {vertikalni scrolling}
      begin
      Probehla_akce.NastavBit(EDA_prekresli_okno);
      poc_ZobrY:=v^.y1;
      end;
   end
   else begin
   dec(poc_ZobrY,py^.tlacitkovy_skok);
   Probehla_akce.NastavBit(EDA_prekresli_okno);
   if poc_ZobrY<0 then
      poc_ZobrY:=0;
   end;

end;


Function TEditacniPole.Prilep_K_predeslemu(rus:PUzel;smezerou:boolean;var kam_nalepeno:longint):PUzel;
var abs:PUzel;
    kn2: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
   if (abs<>rus) then
      begin
      if TK_R=rus then             {kurzor je na rusenem radku?}
         Nastav_poziceXYRP(kam_nalepeno+TK_X+1,   {nastavime X}
                          TK_Y-1,                 {o jednu snizime Y}
                          abs,                    {a ukazatel na absorbujici radek}
                          PARAM_UPRAV_SCROL_X);   {naschval NEnastavuji omezovac X}

      if smezerou then kn2:=kam_nalepeno-1 else kn2:=kam_nalepeno;
      Ostatni_pozice_Prilep_na_jinou_radku(rus,abs,0,kn2,-1);
      {ABS musime predavat zvlast, protoze vnitrek RUS, tedy RUS^... uz
       neni validni (tedy ani rus^.predchozi)}
      end;
   probehla_akce.ZmenaOkna;
   end;
Prilep_K_predeslemu:=abs;
end;


Function TEditacniPole.Prilep_K_predeslemu(rus:PUzel;smezerou:boolean):PUzel;
var kam:longint;
begin
Prilep_K_predeslemu(rus,smezerou,kam);
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;
    p:PUzel;
    kam:longint;
begin
if rus^.predchozi=nil then Exit(rus)
   else begin
   v:=rus^.predchozi^.vazba;
   if v^.crlf=0 then Exit(rus)
      else begin
      p:=Prilep_k_predeslemu(rus,smezerou,kam);
      Ostatni_pozice_navysX(p,kam,1);
      Ev_prilep_k_predeslemu:=p;
      end;
   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,kam:longint;
    p2,q:PUzel;
    v,v2:PItRadek;
begin
if p=nil then Exit(0);
i:=0;
v:=p^.vazba;
while v^.crlf<>0 do
   begin
   p2:=p^.dalsi;
   if p2<>nil then
      begin
      v2:=p2^.vazba;
      v2^.yy:=v^.yy+1;
      q:=Prilep_K_predeslemu(p2,true,kam);
      Ostatni_pozice_navysX(q,kam,1);
      if q=nil then Exit(i) else inc(i);
      end;
   end;
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:=SirkaUseku_IT(v2,1,i);
DelkaPrvnihoSlova:=j;
end;

Procedure TEditacniPole.BackSpace;
var l,a,b:longint;
    gdho,vs:longint;
    v,v_nad:PItRadek;
    p,p_nad:PUzel;
    n:Pchar;
    lepilo_se_k_hornimu:boolean;
    s:string;
begin
if not povolene_zmeny then Exit;


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  (Jsme na prvnim radku?)}
   p_nad:=TK_R^.predchozi;    {P bude radek nad kurzorem}
   v_nad:=p_nad^.vazba;
   gdho:=v_nad^.gd;           {zapamatujeme si delku pred prilepenim...}
   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}
      vs:=vsirka;                          {sice se X- i Y- scrolling resil...}
      if gdho>vs-1 then                    {...uz v Nastav_poziceX, ale aspon...}
         poc_zobrX:=-(gdho-vs-1)-vs div 4; {X-scrolling si zde upravime podle sveho}
      PosunRadek(p_nad^.dalsi);
      end
      else begin
      Prilep_Nasledujici_radky(p_nad);
      v_nad:=p_nad^.vazba;
      Nastav_PoziceX(TK_X-1); {kompenzace toho, ze jsem vlastne nesmazal...}
                              {...zadny znak - pouze spojil radky}

      {Ostatni_pozice_navysX(v_nad,TK_X,1);} {abychom si udrzeli spravne hranice bloku}

      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}

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

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

Probehla_akce.ZmenaRadky;
Ostatni_pozice_navysX(v,TK_X+1,-1);

if zalamuj then JednoduchePreskladaniRadek_od_kurzoru
   {else Ostatni_pozice_navysX(v,TK_X,-1);} {abychom si udrzeli spravne hranice bloku}

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?}

if v^.crlf=1
   then inc(c,SirkaEvDodatecneMezery(v)); {a po zapocteni mezery?}
d:=vsirka-start_poc_zobrX-v^.gd-1;        {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?}


Function TEditacniPole.MoznyPreskokNahoru:boolean;
var q,p:PUzel;
    v:PItRadek;
    kam:longint;
    b:boolean;

begin
MoznyPreskokNahoru:=false;
if TK_Y<=1 then Exit;    {predchozi radka neni (t.j. jsme na 1.radce?)}
q:=TK_R;
p:=q^.predchozi;         {ukazatel nastavi na predchozi radku}
b:=Je_k_prilepeni_nasledujici_radky(p);  {a lze prvni slovo nasi radky...}
                                         {...nalepit na konec predchozi radky?}

if b=true then
   begin
   Prilep_k_predeslemu(q,true,kam);
   Nastav_poziceX(TK_X-1);
   Ostatni_pozice_navysX(TK_R,kam,1);
   MoznyPreskokNahoru:=true;
   end;
end;



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;
if internal_je_shift(edKlavesa) then
   begin   {kombinace Shift-Del: budeme mazat ne znak, ale cely blok}
   SmazBlokTextu;
   Exit;
   end;

{Prosta klavesa Del (bez Shift) - budeme mazat jeden znak}
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,-1); {poresme hranice bloku}
   v^.VyjmiZnak(TK_X);
   Probehla_akce.ZmenaRadky;
   if (zalamuj=true) {and (v^.crlf<>0) and (TK_R<>Radky^.last)} then
      begin
      JednoduchePreskladaniRadek_od_kurzoru;

      (*
      dal_ne:=false;
      if TK_Y>1 then
         if Je_k_prilepeni_nasledujici_radky(TK_R^.predchozi)
            {muzeme tuto zkracenou radku prilepit k predchozi?}
            then begin
            infokno(200,200,'???');
            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;
Probehla_akce.ZmenaRadky;
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);
Probehla_akce.akce:=EDA_tab;
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
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+posun;
v2^.y2:=v^.y2+posun;
v2^.yy:=v^.yy+1;

RozdelRadku:=p;
end;


Procedure TEditacniPole.KlavesaEnter;
var v,v2:PItRadek;
    p,p2,p3,q:PUzel;
    n:PChar;
    a,b:longint;
begin
if not povolene_zmeny then Exit;
Probehla_akce.ZmenaOkna;

p:=TK_R;
v:=p^.vazba;
p2:=RozdelRadku(pozice[ep_kurzor],a);
{Nyni: P - radka pred zlomem, P2 - nove vznikla radka za zlomem}
b:=pozice[ep_kurzor].x;
Ostatni_pozice_Prilep_na_jinou_radku(p,p2,b,-b+1,1);
Nastav_poziceXYR(1,TK_Y+1,p2);  {budeme na 1.sloupci nasledujici radku}

{Ostatni_pozice_Prilep_na_jinou_radku(p,q:PUzel;kde_x,kam_x,diff_y:longint);}

Poc_ZobrX:=start_poc_zobrX;
v2:=p2^.vazba;

if (zalamuj=false) {or (v^.crlf=true)} then PosunRadek(p)
   else begin

   {Ostatni_pozice_navysX(p,0,1);}

   p3:=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, je P3 bud shodne nebo ruzne od P.
   }
   if p3<>p then Ostatni_pozice_navysX(p3,0,1);

   Prilep_Nasledujici_radky(p2);

   {k mistu za zlomem eventualne prilep nasledujici radky}

   {dbg_prom:=true;}

   NalamejBuffer(p3,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
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 dolu}
   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;

Probehla_akce.NastavBit(EDA_prekresli_okno);

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
if prv_rad=Radky^.first then  {Je vypsany prvni radek, t.j. nebudeme skrolovat nahoru}
   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;

Probehla_akce.NastavBit(EDA_prekresli_okno);
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
Probehla_akce.NastavBit(EDA_prekresli_okno);
SkocNaZacatek;
end;


Procedure TEditacniPole.KlavesaCtrlPGDN;
var v:PItRadek;
begin
Probehla_akce.NastavBit(EDA_prekresli_okno);
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;parametry:byte);
var v:PItRadek;
    r:PUzel;

begin
r:=pozice[EP_kurzor].r;
if r=nil then
   begin
   InfOkno(300,300,'Error (Nastav_poziceX): <pozice[EP_kurzor].r> is NIL!');
   Exit;
   end;
v:=r^.vazba;
if ix<1 then ix:=1;

if ix>v^.up+1 then
   if (parametry and PARAM_KONTR_MAX_X)<>0 then ix:=v^.up+1;



pozice[EP_kurzor].x:=ix;

{A ted automaticky resme, jestli je kurzor na obrazovce. Budeme prespokladat,
 ze pokud menime polohu kurzoru, tak chceme, aby byl videt.}

Probehla_akce.NastavBit(EDA_zmena_kurzoru);
Korekce_Poc_ZobrY;

if (parametry and PARAM_UPRAV_SCROL_X)<>0 then Korekce_Poc_ZobrX(true);
end;


Procedure TEditacniPole.Nastav_poziceX(ix:longint);
begin
Nastav_poziceX(ix,PARAM_UPRAV_SCROL_X+PARAM_KONTR_MAX_X);
end;


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

if iy<1 then iy:=1;
pozice[EP_kurzor].y:=iy;
Nastav_poziceX(ix,parametry);

{Nastav_poziceXY(ix,iy);}
end;


Procedure TEditacniPole.Nastav_poziceXYR(ix,iy:longint;ir:pointer);
begin
Nastav_poziceXYRP(ix,iy,ir,PARAM_UPRAV_SCROL_X+PARAM_KONTR_MAX_X);
end;


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

Procedure TEditacniPole.KlavesaHome;
begin
Nastav_poziceX(1);
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.Ostatni_pozice_navysX(P:PUzel;pzx,dx:longint);
var v:PItRadek;
begin
v:=p^.vazba;
Ostatni_pozice_navysX(v,pzx,dx);
end;



Procedure TEditacniPole.Ostatni_pozice_Prilep_na_jinou_radku(p,q:PUzel;kde_x,diff_x,diff_y:longint);
var i:longint;
    v:PItRadek;
begin
v:=p^.vazba;
for i:=2 to MAX_EDIT_POZICE do
    if (pozice[i].y=v^.yy) and (pozice[i].x>{>=}kde_x
                                {">=" by asi bylo "cistsi", ale treba
                                 FP IDE se take chova takto
                                 (zde ovlivnuje hlavne Enter pred oznac. blokem)}
                                ) then
       begin       {POZICE je na rusenem radku?}
       pozice[i].r:=q;
       inc(pozice[i].y,diff_y);
       inc(pozice[i].x,diff_x);
       end
       else begin  {Co kdyz je pozice pod rusenym radkem?}
       if pozice[i].y>v^.yy then
          inc(pozice[i].y,diff_y);
       end;
end;



Procedure TEditacniPole.PridejTextNaPozici(poz:TKurPoz;kp:PChar;ksd:longint;mode:byte;presun_kurzoru:boolean);
var v:PItRadek;
    ogd,dgd,rods,oup,dup:longint;
    b:boolean;
    vmode:byte;
    dbgs:string;

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

Probehla_akce.ZmenaRadky;
v:=poz.r^.vazba;

vmode:=UTF8_konv;
ogd:=v^.gd;
oup:=v^.up;

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

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

if mode=2   {vynutime text v UTF8}
   then begin UTF8_konv:=UTF8_ALL_CONV;v^.Vloz(kp,ksd,poz.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,poz.x,true);
   end;

dgd:=v^.gd-ogd;        {o kolik pixelu jsme prodlouzili retezec?}
dup:=v^.up-oup;        {a o kolik to bylo znaku?}

if dup=1
   then probehla_akce.akce:=EDA_znak_1  {zaznamename pridani 1 znaku}
   else probehla_akce.akce:=EDA_znak_x; {zaznamename pridani X znaku}


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

Ostatni_pozice_navysX(v,poz.x,ksd); {abychom si udrzeli spravne hranice bloku}

if presun_kurzoru then
   if (poz.r=TK_R) and (poz.x>=TK_X)
      then Nastav_PoziceX(TK_X+ksd,PARAM_KONTR_MAX_X);



{
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
   begin {upravu skrolovani nenechavam na <Nastav_PoziceX>, ale poresim zde}
   dec(poc_ZobrX,rods);
   Probehla_akce.NastavBit(EDA_prekresli_okno);
   end;


(*
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
      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.PridejTextNaPoziciKurzoru(kp:PChar;ksd:longint;mode:byte;presun_kurzoru:boolean);
begin
PridejTextNaPozici(pozice[ep_kurzor],kp,ksd,mode,presun_kurzoru);
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,true);
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;

Probehla_akce.NastavBit(EDA_prekresli_okno);

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
jek:=Je_Klavesa;
if jek=false then
   begin
   if py^.probehni then Zobraz;
   Exit;
   end;

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 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 (Probehla_akce.ZdaZmenaTextu=false) and (Internal_Je_Shift(edKlavesa)=true)
   then begin
   {beep;}
   j:=ShiftemMenenyBlok;
   end;

ZkontrolujPlatnostOznaceni;

if j<>0 then
   begin
   if povolene_zmeny then
   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,w: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;   {BUG! V prubehu ruseni radek prestava byt v^.YY aktualni}
if PocetRadku=1 then NovySoubor
   else begin
   if u^.dalsi<>nil
      then begin
      w:=u^.dalsi^.vazba;
      w^.yy:=yy;
      end;

   Kill_PitRadek(v);  {zrusime odkazovanou radku}

   if yy=TK_Y then b:=0 else  {rusime radku s kurzorem?}
   if yy>TK_Y then b:=1       {pod kurzorem?}
              else b:=2;      {nad kurzorem?}

   if u=Radky^.last then        {jsme na posledni radce?}
      begin
      u:=u^.predchozi;
      if b=0 then
         Nastav_PoziceXYR(TK_X,TK_Y-1,u);
      {Jsme na rusene radce a na te radce je kurzor? Tak ho soupneme vys.}
      Radky^.ZrusUzel(u^.dalsi);
      sunout:=false;
      end
      else begin                {nejsme na posledni radce}
      u:=u^.dalsi;
      if b=0 then                        {kdyz rusime radek s kurzorem...}
         Nastav_PoziceXYR(TK_X,TK_Y,u);  {...tak ho musime posunout}
      Radky^.ZrusUzel(u^.predchozi);
      sunout:=true;
      end;

   if b=0 then                          {kurzor je na mazanem radku}
      begin
      w:=u^.vazba;
      Nastav_PoziceX(Pozice_v_retezci_IT(kx,poc_zobrX,0 {mozna radeji: start_poc_zobrX},w,true));
      end else
   if b=2 then
      Nastav_PoziceXYR(TK_X,TK_Y-1,TK_R);     {kurzor je pod mazanym radkem}

probehla_akce.ZmenaRadky;

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);
Probehla_akce.ZmenaRadky;
if zalamuj=true then
   begin
   t.x:=zac;
   t.y:=v^.yy;
   t.r:=u;
   PreskladejRadky(t,false);
   end;
end;


Function TEditacniPole.IdentifikujSlovo(kur:TKurPoz;var zac,kon:TKurPoz):byte;
var v:PItRadek;
    a,b:longint;
    k:byte;

begin
if kur.r=nil then Exit(0);
v:=kur.r^.vazba;
if v^.delka=0 then Exit(1);
zac:=kur;
kon:=kur;
if kur.x>v^.up then dec(kur.x);  {kurzor za posl. znakem?}

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;
  k:=2;
  end
  else begin     {kurzor je na slove?}
  v^.Slovo(kur.x,a,b);
  zac.x:=a+1;
  kon.x:=b;
  k:=3;
  end;
IdentifikujSlovo:=k;
end;


Function TEditacniPole.OznacSlovo(kur:TKurPoz):byte;
var h:byte;
    zac,kon:TKurPoz;
begin
h:=IdentifikujSlovo(kur,zac,kon);
if (h=0) or (h=1) then Exit(h);
if {a<>b} zac.x<>kon.x
   then NastavRozsahOznaceni(zac,kon)
   else h:=h+10;
OznacSlovo:=h;
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;
Probehla_akce.ZmenaRadky;
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 poslednim vypsanym znakem?}
   if (v^.doz<v^.up) or ((v^.doz=v^.up) and (v^.posunv<>0)) then
      begin
      a:=SirkaUseku_IT(v,1,b);     {tak to zamer...}
      poc_zobrX:=-(a-vsirka-1);    {...a zaskroluj}
      Probehla_akce.NastavBit(EDA_prekresli_okno);
      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;
   Probehla_akce.NastavBit(EDA_prekresli_okno);
   end
   else
   if v^.odz=1 then
      begin
      poc_zobrX:=start_poc_zobrX;
      Probehla_akce.NastavBit(EDA_prekresli_okno);
      end;
end;



Procedure TEditacniPole.SmazBlokTextu_internal(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  {kdyz je ZAC pred KON}
   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;       {debug, jiny vyznam to nema}
          dec(kon.y);             {tato radka se smaze, takze posunume i konec}
          SmazRadku(temp.r,false);
          end;
   {zbyva pocatecni radek a koncovy radek}
   if zac.x=1 then
      begin
      temp:=zac;
      zac.r:=zac.r^.predchozi; {Pozor, v pripade, ze jsme na 1.radku, tak...}
      v:=temp.r^.vazba;        {...bude obsahovat NIL}
      SmazRadku(temp.r,false);
      if zac.r=nil {muze se stat, viz vyse}
         then zac.r:=radky^.first;
      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;     {Pozor, hrozi, ze bude za posl. radkem a tedy NIL}
      v:=temp.r^.vazba;
      SmazRadku(temp.r,false);
      if kon.r=nil then kon.r:=radky^.last;
      if zac.r=temp.r
         then
         begin
         zac.r:=kon.r;
         end;

      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;

Probehla_akce.ZmenaOkna;
end;


Procedure TEditacniPole.SmazBlokTextu;
var b:byte;
    zac,kon:TKurPoz;
begin
if Zda_oznacen_blok=false then Exit;
OverPoziciKurzorovehoBodu(pozice[ep_oznac1]);
OverPoziciKurzorovehoBodu(pozice[ep_oznac2]);
b:=PorovnejPozici(pozice[ep_oznac1],pozice[ep_oznac2]);
if b=0 then Exit;
if b=1 then begin zac:=pozice[ep_oznac2];kon:=pozice[ep_oznac1];end else
            begin zac:=pozice[ep_oznac1];kon:=pozice[ep_oznac2];end;
zac.r:=UkazatelNaRadku(zac.y);
kon.r:=UkazatelNaRadku(kon.y);
SmazBlokTextu_internal(zac,kon);
SmazBodyOznaceni;
Zobraz;
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...}
                                    {...budeme pripraveni na celkove prelamani}
Probehla_akce.ZmenaOkna;
end;


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;
Probehla_akce.NastavBit(EDA_prekresli_okno);
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;
Probehla_akce.NastavBit(EDA_prekresli_okno);
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,korekce_y:longint;p:PUzel;v:PItRadek);
var f:byte;
    d:longint;
begin
if zda_oznacen_blok=false then VlastniVypisRadkyTextu(ix,v^.y1-Poc_ZobrY-korekce_y,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-korekce_y,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;



Function TEditacniPole.Zobrazeni_najdi_zachytnou_radku(var smer:byte):PUzel;
var v:PItRadek;
    i,j,a,ab:longint;
    dyp:array[1..5] of longint;
    p:PUzel;


begin
smer:=0;

{for a:=1 to 5 do dyp[a]:=0;}{debug}

if prv_rad<>nil then
   if Probehla_akce.ZdaBit(EDA_prekresli_okno)=false
      then Exit(prv_rad);    {lze pouzit prvni radku obrazovky od minula?}

v:=TK_R^.vazba;   {radka s kurzorem}
if Je_radek_na_obrazovce(v,dyp[1])
   then Exit(TK_R);          {odpichneme se od radky s kurzorem?}


v:=radky^.first^.vazba;  {prvni radka souboru}
if Je_radek_na_obrazovce(v,dyp[2])
   then Exit(radky^.first);  {odpichneme se od prvni radky souboru?}


{dyp[3]:=100;} {debug}
v:=radky^.last^.vazba;   {posledni radka souboru}
if Je_radek_na_obrazovce(v,dyp[3])
   then Exit(radky^.first);  {odpichneme se od posledni radky souboru?}


{if dbg_prom=true then
   begin writeln('za dyp3');readln;end;}

if Zda_oznacen_blok then
   begin
   v:=pozice[ep_oznac1].r^.vazba;
   if Je_radek_na_obrazovce(v,dyp[4])
      then Exit(pozice[ep_oznac1].r);
   v:=pozice[ep_oznac2].r^.vazba;
   if Je_radek_na_obrazovce(v,dyp[5])
      then Exit(pozice[ep_oznac2].r);
   end
   else begin
   {pokud neni definovan blok, tak do dyp[4] a dyp[5] zadame velmi velka cisla}
   dyp[4]:=maxlongint;
   dyp[5]:=maxlongint;
   end;

{Hm..., pokud jsme se dostali az sem, tak to znamena, ze zadny zkouseny
 zachytny bod neni na obrazovce. Vybereme z nich tedy ten nejblizsi}

{if dbg_prom=true then
   begin writeln('pred cyklem');readln;end;}

a:=maxlongint;
for i:=1 to 5 do
    begin
    ab:=abs(dyp[i]);
    if ab<a then begin j:=i;a:=ab;end;
    end;

{if dbg_prom=true then
   begin writeln('po cyklu');readln;end;}

if dyp[j]<0 then smer:=1 else smer:=2;

if dbg_prom=true then
   begin writeln(j);readln;end;

case j of
 1:p:=TK_R;
 2:p:=radky^.first;
 3:p:=radky^.last;
 4:p:=pozice[ep_oznac1].r;
 5:p:=pozice[ep_oznac2].r;
end;{case}

if dbg_prom=true then
   begin writeln(longint(p),' : ',j);readln;end;

Zobrazeni_najdi_zachytnou_radku:=p;
end;


Procedure TEditacniPole.Zobraz_vypisuj_odshora_dolu(p:PUzel;var p1,p2:PUzel);
var v:PItRadek;
begin
repeat
  v:=p^.vazba;
  if v^.y2-Poc_zobrY>0 then
     begin
     p1:=p;
     repeat
       v:=p^.vazba;
       if v^.y1-Poc_zobrY<vvyska
          then begin VypisRadekTextu(poc_zobrX,0,p,v);p2:=p;end
          else Exit;
       p:=p^.dalsi;
     until p=nil;
     Exit;
     end;
  p:=p^.dalsi;
until p=nil;
end;


Procedure TEditacniPole.Zobraz_vypisuj_odzdola_nahoru(p:PUzel;var p1,p2:PUzel);
var v:PItRadek;
begin
repeat
  v:=p^.vazba;
  if v^.y1-Poc_zobrY<vvyska then
     begin
     p2:=p;
     repeat
       v:=p^.vazba;
       if v^.y2-Poc_zobrY>0
          then begin VypisRadekTextu(poc_zobrX,0,p,v);p1:=p;end
          else Exit;
       p:=p^.predchozi;
     until p=nil;
     Exit;
     end;
  p:=p^.predchozi;
until p=nil;
end;


Procedure TEditacniPole.Zobraz_Od_kotvy(p:PUzel;smer:byte);
var p2:PUzel;

begin
if smer=1 then Zobraz_Vypisuj_odshora_dolu(p,prv_rad,posl_rad) else
if smer=2 then Zobraz_Vypisuj_odzdola_nahoru(p,prv_rad,posl_rad) else
   begin {t.j. smer=0}
   Zobraz_Vypisuj_odshora_dolu(p,prv_rad,posl_rad);
   if p^.predchozi<>nil then
      Zobraz_Vypisuj_odzdola_nahoru(p^.predchozi,prv_rad,p2)
   end;
end;



Procedure TEditacniPole.VymazProstor_pro_zobr_3_radek(vnad,v,vpod:PItRadek);
var hy1,hy2:longint;
begin
if vnad=nil then hy1:=v^.y1 else hy1:=vnad^.y1;
if vpod=nil then hy2:=v^.y2 else hy2:=vpod^.y2;
Bar(virt^,0,hy1-Poc_ZobrY,virt^.breite-1,hy2-Poc_ZobrY,BB_txt_v);
end;


Procedure TEditacniPole.Zobraz_3_radky(p:PUzel);
var i,j:longint;
    q:PUzel;
    v:PItRadek;

begin
q:=p^.predchozi;
if q<>nil then
   begin
   v:=q^.vazba;
   VypisRadekTextu(poc_zobrX,0,q,v);
   end;

v:=p^.vazba;
VypisRadekTextu(poc_zobrX,0,p,v);

q:=p^.dalsi;
if q<>nil then
   begin
   v:=q^.vazba;
   VypisRadekTextu(poc_zobrX,0,q,v);
   end;

end;



Procedure TEditacniPole.Zobraz_Bez_optimalizace_na_1_radek;
var p:PUzel;
    tempvw:virtualwindow;
    smer:byte;

begin

{if dbg_prom=true then
begin writeln('Zobraz_Bez_optimalizace_na_1_radek');readln;end;}

p:=Zobrazeni_najdi_zachytnou_radku(smer);

{if dbg_prom=true then
begin writeln('Zobraz_Bez_optimalizace_na_1_radek  po Zobrazeni_najdi_zachytnou_radku');readln;end;}

{if p<>prv_rad then begin writeln('ok');readln;end;}

if radky^.pocet>3 then
   smer:=smer;

Init_VW(tempvw,vsirka,vvyska,false);
Clr(tempvw,BB_txt_v);

virt:=@tempvw;

NastavVystup(virt);

{if zda_oznacen_blok then
   p:=p;}

{
if poc_zobrY<>0 then
   begin
   writeln('ooo');
   readln;
   Exit;
   end;
}

Zobraz_Od_kotvy(p,smer);

{if dbg_prom=true then
begin writeln('po Zobraz_od_kotvy');readln;end;}

MouseLock;
if zapnuto_mouse_self_copy=true then MouseSelfCopy(virt^,x,y);
PutClippedSprite(cil^,virt^,x,y);
{PutSprite_and_clear(cil^,virt^,x,y,BB_txt_v);}
MouseUnLock;
Kill_VW(tempvw);
NastavVystup(cil);
end;


Procedure TEditacniPole.Zobraz_Optimalizace_na_1_radek;
{Provede se, pokus se zmeni jen jeden radek (ten s kurzorem) a pokud neni
 potreba skrolovat. Pro jistotu ale vypise i radek nad a radek pod.}

var p:PUzel;
    v,vpod,vnad:PItRadek;
    tempvw:virtualwindow;
    smer:byte;
    h,hy1,hy2,zhy1,zhy2:longint;
    {dbgs:string;}

begin

{dbgs:='cas: '+mystr(FromTimer);
bar(vga,90,0,330,20,65030);
print_fn(90,15,dbgs);}

p:=TK_R;
v:=p^.vazba;
h:=v^.Vyska;
if p^.predchozi<>nil
   then begin vnad:=p^.predchozi^.vazba;inc(h,vnad^.vyska);hy1:=vnad^.y1;end
   else begin vnad:=nil;hy1:=v^.y1;end;

if p^.dalsi<>nil
   then begin vpod:=p^.dalsi^.vazba;inc(h,vpod^.vyska);hy2:=vpod^.y2;end
   else begin vpod:=nil;hy2:=v^.y2;end;


Init_VW(tempvw,vsirka,vvyska,false);

virt:=@tempvw;


{Bar(virt^,0,0,virt^.breite-1,virt^.hoehe-1,64000);} {debug}

zhy1:=hy1-Poc_ZobrY;
zhy2:=hy2-Poc_ZobrY;

MouseLock; {Musime uz zde, pred MouseSelfCopy_Background a pred Bar(virt^...)}


MouseSelfCopy_Background(virt^,x,y);
{aktualni pozadi mysi prokopirujeme do sprajtu VIRT}

Bar(virt^,0,zhy1,virt^.breite-1,zhy2,BB_txt_v);
NastavVystup(virt);
Zobraz_3_radky(p);

if zapnuto_mouse_self_copy=true then MouseSelfCopy(virt^,x,y);
{mys se prokopiruje do sprajtu VIRT}

PutSpriteRegion(cil^,virt^,0,zhy1,virt^.breite-1,zhy2,x,y+zhy1);
{Na obrazovku zkupirujeme nikoliv cely sprajt, ale jen zajmovou oblast}

MouseUnLock;
Kill_VW(tempvw);
NastavVystup(cil);
end;



Function TEditacniPole.Jaky_Zpusob_Zobrazeni:byte;
{Rekne, jakym zpusobem vykreslovat}
begin
if mod_zobrazeni=0 then Exit(0);  {kompletni prekresleni}
if Probehla_akce.ZdaBit(EDA_prekresli_okno)=true then Exit(0); {to same}
if Probehla_akce.ZdaBit(EDA_prekresli_1)=true then Exit(1); {zobraz jen 1. radek}
Jaky_Zpusob_Zobrazeni:=2;  {jen presune kurzor}
end;



Procedure TEditacniPole.ZobrazMe;
var v:PItRadek;
    ofnzl:boolean;

begin
if mod_zobrazeni=1 {zakaz zobrazeni}
   then begin
   mod_zobrazeni:=0;
   Exit;
   end;

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

DodatkyPredZobrazenim;


case Jaky_Zpusob_zobrazeni of
0: Zobraz_Bez_optimalizace_na_1_radek; {Je treba prekreslit cele okno? Prekresli.}
1: Zobraz_Optimalizace_na_1_radek; {Staci prekreslit jeden radek?}
2: ZhasniKurzor;  {Neni treba prekreslovat nic, resp. jen presunout kurzor?}
end; {case}


Vypocitej_grafickou_pozici_kurzoru;

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;

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);
--}
end;


Procedure TEditacniPole.ZobrazVse;
begin
mod_zobrazeni:=0;
Zobraz;
end;


Procedure TEditacniPole.DodatkyPredZobrazenim;
begin {Defaultne prazdne} 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_od_ulozeni:=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;


Function TEditacniPole.Je_Radek_na_obrazovce(v:PItRadek;var dy:longint):boolean;
{Pokud je radka videt kompletne, tak vrati TRUE a DY=0
 Pokud castecne, tak taky TRUE, ale DY=pocet pixelu,
 ktere chybi nahore (DY<0) ci dole (DY>0).
 Kdyz radka neni videt ani castecne, tak vrati FALSE a v DY je pocet vert.
 pixelu od prvniho (horniho ci dolniho) okraje radku}


var y1z,y2z:longint;
    ddbg:boolean;

begin
ddbg:=false;
if dbg_prom=true then
   if dy=100 then ddbg:=true;

if v=nil then begin writeln('Je_Radek_na_obrazovce: V=nil!');readln;end;

if ddbg=true then
   begin
   writeln('krit.faze: ',longint(v));readln;
   end;


y2z:=v^.y2-Poc_zobrY;
if ddbg=true then
   begin
   writeln(v^.y1,' : ',v^.y2,' : ',poc_zobrY);readln;
   end;

if y2z>0 then       {je spodek radky od horniho okraje okna nize?}
   begin
   y1z:=v^.y1-poc_ZobrY;

   if y1z<vvyska    {a je vrsek radky od dolniho okraje okan vyse?}
      then
           begin
           if y2z>=vvyska     {horni okraj v okne, ale dolni ne?}
              then dy:=y2z-vvyska+1
              else
              if y1z<0        {dolni okraj v okne, ale horni ne?}
                 then dy:=y1z
                 else dy:=0;  {zobrazeno komplet vse?}
           Exit(true);
           end      {jo, oboje splneno, jsme v okne}
      else begin dy:=y1z-vvyska;
                 Exit(false);              {ne, jsme pod oknem}
           end;
   end
   else begin                   {spodek radky je od horniho okraje okna vyse}
   dy:=y2z;
   Exit(false);
   end;
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!','');}
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;
probehla_akce.ZmenaOkna;
end;


Procedure TEditacniPole.JednoduchePreskladaniRadek_od_kurzoru;
var p,p_nad:PUzel;
begin
{napred ke stavajicimu radku pripojim radky nasledujici}
Prilep_Nasledujici_radky(TK_R);
{a navic jeste musim zkusit pripojit tento radek k predchazejicimu}
p:=TK_R;
p_nad:=ev_prilep_k_predeslemu(p,true);
if p_nad<>p then Nastav_PoziceX(TK_X-1);
NalamejBuffer(p_nad,0);
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
probehla_akce.ZmenaOkna;
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);

v:=p^.vazba;
a:=v^.y2-v^.y1;
if p=radky^.first then
   begin
   v^.y1:=0;
   v^.y2:=v^.y1+a;
   end
   else begin
   p:=p^.predchozi;
   end;

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;


{zobraz;
readln;}

NalamejBuffer(p,a);

{zobraz;
readln;}
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,start_poc_zobrX,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.}

{kdy_stop_analyzu:
 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,yz_,vrad:longint;
    {d1,d2,d3,d4:longint;}
    probehlo_zalomeni:boolean;
    vkladat_mezeru:boolean;

begin
if pr=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);    {odseknutim kusu radku se mohlo v^.Y3 zmensit}
         yz_:=yz;
         NastavRozmeziRadku(nv,yz_); {alespon provizorne nastavime Y1 a Y2...}
         {nove vznikleho, aby nam to pak neblblo procedury pro scrolling}

         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 {zde nemuze byt >=}
               begin
               {if dbg_prom then
                  l:=l;}

               Nastav_PoziceXYR(TK_X-i-1,
                                TK_Y+1,
                                novy);
               {Tato procedura by mela poresit i pripadny scrolling}
               end;

            end;



         Ostatni_pozice_Prilep_na_jinou_radku(p,novy,i,-i-1,1);
         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;

dbg_prom:=false;

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}

Poc_ZobrX:=start_poc_zobrX;
{Mozna by bylo lepe resit to pres <Korekce_Poc_ZobrX>, ale zatim takto...}

end;


Procedure TEditacniPole.PospojujRadky(p:PUzel);
var q:PUZel;
    v,v2:PItRadek;
    yz:longint;
begin
if p=nil then p:=radky^.first;
repeat
Prilep_Nasledujici_radky(p);
v:=p^.vazba;
p:=p^.dalsi;
if p<>nil then
   begin
   v2:=p^.vazba;
   v2^.yy:=v^.yy+1;
   yz:=v^.y2+1;
   NastavRozmeziRadku(v2,yz);
   end;
until p=nil;
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);
probehla_akce.ZmenaOkna;
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;
begin
pozice[ep_temp_poz_kurz]:=pozice[ep_kurzor];

zalamuj:=false;
PospojujRadky;


Nastav_poziceXYR(pozice[ep_temp_poz_kurz].x,
                 pozice[ep_temp_poz_kurz].y,
                 pozice[ep_temp_poz_kurz].r);

{VycentrujNaKurzor;}
end;

Procedure TEditacniPole.ZalamovaciRezim;
begin
pozice[ep_temp_poz_kurz]:=pozice[ep_kurzor];

{i:=DejLinearniPozici;}
zalamuj:=true;
NalamejBuffer(radky^.first,-1);

Nastav_poziceXYR(pozice[ep_temp_poz_kurz].x,
                 pozice[ep_temp_poz_kurz].y,
                 pozice[ep_temp_poz_kurz].r);
{NastavLinearniPozici(i);}
{SkocNaZacatek;}
{VycentrujNaKurzor;}
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^.DefaultA;
   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;}64;
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}e^.delka+1);
   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_od_ulozeni:=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_od_ulozeni:=false;
UlozSoubor:=o;
end;


Function TEditacniPole.ZkontrolujPlatnostOznaceni:boolean;
var b:boolean;
begin
b:=true;
if (pozice[EP_oznac1].y<>0) and (pozice[EP_oznac2].y<>0) then
   if porovnejPozici(pozice[EP_oznac1],pozice[EP_oznac2])<>2 then
      begin
      SmazBodyOznaceni;
      b:=false;
      end;
ZkontrolujPlatnostOznaceni:=b;
end;


Procedure TEditacniPole.NastavBodOznaceni(b:byte;poz:TKurPoz);
var c:byte;
begin
Probehla_akce.ZmenaOkna;
if (b=1) or (b=2) then
   begin
   if b=1 then c:=EP_oznac1 else c:=EP_oznac2;
   pozice[c]:=poz;
   ZkontrolujPlatnostOznaceni;
   end;
end;


Procedure TEditacniPole.SmazBodyOznaceni;
begin
Probehla_akce.ZmenaOkna;
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);}

Probehla_akce.ZmenaOkna;
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;



Function TEditacniPole.Zda_pozice_v_bloku(poz:TKurPoz):boolean;
var p1,p2,pz:comp;
{vp,v1,pp:PItRadek;}

begin
if Zda_oznacen_blok=false then Exit(false);

pz:=LinearniPozice(poz);
p1:=LinearniPozice(pozice[EP_oznac1]);
p2:=LinearniPozice(pozice[EP_oznac2]);

Zda_pozice_v_bloku:=((pz>=p1) and (pz<p2));
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;

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.
