unit tedradky;
{$I defines.inc}
interface
uses dos,vaznik;

{------------------------------Pro EditacniPole-----------------------------}
const ED_GRANULARITA = 32;
{Po jak velkych kusech bude alokovat pamet pro retezce. Mela by byt
nasobkem 16. Zvyseni muze praci mirne urychlit, ale zvysi se pametove naroky}

{PEdRadek je myslen jako nahrada typu AnsiString, ktery je pomaly a ve verzi
1.0.10 v nekterych pripadech (v potomcich objektu) blbne.}


TED_ODDELOVACE_SLOV:string[10] = #32;
{oddelovace slov (lze modifikovat)}

UTF8_AUTO     = 0;
UTF8_ALL_CONV = 1;
UTF8_NO_CONV  = 2;

UTF8_KONV:byte = UTF8_AUTO;

NORMAL_NAMALA_PISMENA_MODE:boolean = true;
NORMAL_NAVELKA_PISMENA_MODE:boolean = true;

VYNUT_UNICODE:boolean = false;

type

Pfnatrb = ^Tfnatrb;
Tfnatrb = object
  pozice:longint;          {pozice v textu (od 1), od ktere to plati}
  extra:pstring;           {extra tagy jako treba obrazek, preskok, atd.}

  {atrb:TFAtrb;}             {vlastni soubor vlastnosti fontu}


  font:pointer;            {ukazatel na font ve formatu FN}
  barva:word;              {barva}
  pozadi:longint;
  modifikace:byte;         {bitove pole dalsich priznaku jako treba podrzeni}
      {0.bit = podtrzeni}
      {1.bit = oznaceni (znazorneno jinym pozadim textu)}
      {2.bit = text v bloku (znazorneno inverzi)}

      {3.-4.bit = 00: unicode/non-unicode podle fontu
                  01: nucene unicode
                  10: nucene nonunicode
                  11: nucene nonunicode}

      {5-6.bit = nepouzito}
      {7.bit = rezervovano}


  Constructor Init;
  Procedure DefaultA;
  Function CopyTo(newpos:longint):PFnatrb;
  {POZOR - nekopiruje extratagy}
  Function CopyEx:PFNatrb;
  {Kopiruje vcetne extratagu}
  Function Je_unicode_font:boolean;
  Procedure DoGlobalnichPromennych;
  Procedure Modifikuj(co,jak:longint);
  Function Zkonstruuj_tag(predchozi_tag:PFNatrb):string;
  Function Porovnej_s_jinym_atributem(v:PFNatrb):boolean;
  Destructor Done;
  end;

PEdRadek = ^TEdRadek;
TEdRadek = object
{Polozka P, ktera funguje jako buffer pro znaky je typu PChar, a vlozeny
 retezec je skutecne PChar, tudiz je zachovana zpetna kompatibilita prave s
 PCharem. Predpoklada se, ze TEdRadek muze obsahovat znaky CRLF a ze tedy
 muze byt viceradkovy}
       p:pchar;                  {buffer na znaky radku}
       pp:longint;               {velikost bufferu}
       spp:longint;              {skutecne zaplneny pocet bajtu}
       Constructor Init;
       Procedure Vloz(s:pchar;sd,poz:longint);virtual;
       Procedure Vloz(s:pchar;poz:longint);virtual;
       Function Prvy:longint;
       {pokud je retezec prazdny, tak vrati 0, pokud neni prazdny, tak 1}
       Procedure VlozS(s:string;poz:longint);virtual;
       Procedure VlozKus(s:pchar;poz:longint;s_zac,s_del:longint);virtual;
       Procedure Vyjmi(poz,l:longint);virtual;
       Procedure Zamena(s:pchar);virtual;
       Procedure ZamenaS(s:string);virtual;
       Function Delka:longint;virtual;
       Function Znak(n:longint):word;virtual;
       Function Najdi(s:string;poz:longint):longint;virtual;
       Procedure InternalVratCast(var poz,delk:longint;var buffer:pchar;var bd:longint);virtual;
       Function VratPchar(poz,delk:longint):pchar;virtual;
       Function VratString(poz,delk:longint):string;virtual;
       Function VS:string;virtual;         {vrati string}
       Function VP:pchar;virtual;          {vrati pchar}
       Function VratUsek(poz,del:longint):PEdRadek;virtual;
       Procedure Rozdel(var nv:TEdRadek;pozice,vypust:longint);virtual;
       {rozdeli retezec na dve casti. nedela zadnou realokaci ani presuny pameti}
       {pri tom muze ze zacatku druheho radku vypustit VYPUST znaku}
       Procedure Rozdel(var nv:TEdRadek;pozice:longint);virtual;
       Function ZacatekSlova_na_pozici(poz:longint):longint;virtual;
       Function ZacatekSlova_na_pozici(poz:longint;var odd_znak:word):longint;virtual;
       Function KonecSlova_na_pozici(poz:longint):longint;virtual;
       Function KonecSlova_na_pozici(poz:longint;var odd_znak:word):longint;virtual;
       Procedure Slovo(poz:longint;var zac,kon:longint);virtual;
       Function Znak_oddelovac_slov(poz:longint;var odd_znak:word):boolean;virtual;
       Function Znak_oddelovac_slov(poz:longint):boolean;virtual;
       Function ZacatekMezislovi(poz:longint):longint;virtual;
       Function KonecMezislovi(poz:longint):longint;virtual;
       Procedure Mezislovi(poz:longint;var zac,kon:longint);virtual;
       Function Prazdny:boolean;virtual;
       Function Zjisti_Kolikate_slovo_nebo_mezislovi(a:longint):longint;
       {1.mezislovi = 0; 1.slovo = 1; 2.mezislovi = 2; 2.slovo = 3...}
       Function Zjisti_Pocet_Slov:longint;
       Procedure Odkud_kam_je_slovo(vychozi:longint;var zac,kon:longint);
       Destructor Done;virtual;
       end;

PItRadek = ^TItRadek;
TItRadek = object(TEdRadek)
       {Z duvodu podpory unicode zabira kazdy znak dva bajty. Lhostejno, je-li}
       {to skutecne unicode retezec nebo ne}
       {Vsechny parametry urcujici pozici nebo delku se zadavaji ve znacich,}
       {nikoliv v bytech. Prvni znak ma hodnotu 1, nikoliv hodnotu 0.
       Viceradkove texty (tedy texty se znaky CRLF) v zasade dovoleny jsou,
       ale nejsou doporuceny, protoze procedury a funkce, ktere s TItRadky
       pracuji, je vetsinou nepredpokladaji.
       V pripadech, ze se predpokladaji viceradkove texty, se pouziva spojovy
       seznam PVaznik, jehoz prvky jsou PItRadky (pro kazdy radek vlastni prvek)}
       up:longint;               {je to (spp-1) div 2}
       aa:Pvaznik;               {plody jsou typu Pfnatrb}
       y1,y2:longint;            {Y-ova pozice na pomyslne strance (pocita se od 0)}
       so,su:longint;            {vyska textu nad linkou a pod linkou}
       bu:longint;               {vyska nejvyssiho obrazku}
                                 {(pocita se od zakladni linky)}

       yy:longint;               {cislo radku}
       gd:longint;               {delka radku v pixelech}
       crlf:byte; {0=natvrdo, 1=wordwrap, 2=nucene zalomeni uvnitr slova}
       {je radek ukoncen natvrdo? DEFAULTNE TRUE}
       odz,doz:longint;          {prvni a posledni kompletne vypsane znaky}
       posunm,posunv:longint;
       lch:word;                 {ktery je prvni znak co nebyl vypsan?}

       Constructor Init;
       Constructor Init(s:string);
       Procedure PrvotniPrirazeni;
       Procedure UtvorZakladniUzel;
       Function Delka:longint;virtual;
       Function Vyska:longint;virtual;
       Procedure Prepocitej_gd;
       Function GD_na_Poz(poz:longint):longint;
       Function VratPchar(poz,delk:longint):pchar;virtual;
       Function VratString(poz,delk:longint):string;virtual;
       Function VratUsek(poz,del:longint):PItRadek;
       Function VratPedRadek(poz,delk:longint;tvor_tagy:boolean):PEdRadek;
       Procedure PrevedUsekMeziUzly_na_PChar(zac,kon:longint;u:boolean;var v:PChar;var vd:longint);
       Function ZkopirujUsekVaznikuUzlu(poz,del:longint):PVaznik;

       Procedure Zalohuj_Uzly(var z:PVaznik);
       Procedure Obnov_Uzly(var z:PVaznik);
       Procedure Znic_Vaznik_Uzlu(var z:PVaznik);
       Function HledejExtraAtribut(s:string;var uz:string):longint;
       Function HledejExtraAtribut_na_poz(s:string;poz:longint;var t:string):longint;

       Function Znak(n:longint):word;virtual;
       Procedure InternalVratCast(var poz,delk:longint;var buffer:pchar;var bd:longint);virtual;

       Function ZrusUzly(poz,l:longint):boolean; {zrusi vsechny uzly krome 1.}
       Function VratUzel(poz:longint):Pfnatrb;
       {vrati atributovy uzel platny pro specifikovanou pozici}
       Function VratUzel_Copy(poz:longint):Pfnatrb;
       {jako predchozi, akorat ze uzel alokuje do noveho bloku pameti}
       Function VratUkazatelNaUzel(poz:longint):PUzel;virtual;
       {vraci odkaz na tento uzel}
       Function Atrib_vs(poz:longint):string;
       {hlavne pro debugging - zkonstruuje string popisujici atributy na danem miste}
       Function PocetUseku:longint;
       Function PocetUsekuOdDo(zac,kon:longint):longint;
       Function PocetUzlu:longint;
       Procedure DejRozsahDanehoUseku(i:longint;var zac,kon:longint);
       Procedure PrevezmiUzelOdjinud(kam:longint;zdroj:PItRadek;pozice_ve_zdroji:longint);virtual;
       Function Najdi(s:string;poz:longint):longint;virtual;
       Procedure Vloz(s:pchar;sd,poz:longint);virtual;
       Procedure Vloz(s:pchar;poz:longint);virtual;
       {Proceduru VlozS neni nutne deklarovat, protoze se pres virtualni
        metodu zavola nas Vloz}
       Procedure VlozWS(t:pchar;td,poz:longint;b:boolean);
       Procedure VlozWord(o:word;poz:longint);
       Procedure NahradWord(o:word;poz:longint;prepocet_gd:boolean);
       Procedure NahradWord(o:word;poz:longint);
       Procedure NahradUsekBufferem(bp:pointer;poz,bajtu:longint);
       Procedure Vyjmi(poz,l:longint);virtual;
       Procedure Vyjmiznak(poz:longint);virtual;
       Procedure VyjmiPosl;virtual;    {smaze posledni znak retezce}
       Procedure Smaz;virtual;         {smaze cely retezec}
       Procedure VlozKus(s:pchar;poz:longint;s_zac,s_del:longint);virtual;
       Procedure VlozKusIT(s:PItRadek;poz,s_zac,s_del:longint);
       Procedure Pripoj(s:PItRadek);
       Procedure ZamenaIt(s:PItRadek); {udela duplikat, nejde o predani odkazu}
       Function Shodnost(s:PItRadek):boolean;
       Function Modifikuj_uzel_barvu(i:longint;ibarva:word):boolean;
       Function Prozkoumej_uzel_barvu(i:longint):word;
       Function Modifikuj_uzel_font(i:longint;s:string):boolean;
       Function Prozkoumej_uzel_font(i:longint):string;
       Function Prozkoumej_uzel_Extra(i:longint):string;
       Function Modifikuj_uzel_Extra(i:longint;s:string):boolean;
       Procedure V_useku_zmen_parametr_uzlu(poz,del:longint;co:byte;jak:longint);
       Function Zrus_duplicitni_uzly:longint;
       Procedure PodtrzeniTextu(b:boolean);
       Procedure Na_Unicode(odk,kam:longint;prevodni_tabulka:pointer);
       {<prevodni_tabulka> nemuze byt <pointer> ale <pUTF8conv>}
       Procedure Z_Unicode(odk,kam:longint;prevodni_tabulka,inverzni_prevodni_tabulka:pointer);
       {<prevodni_tabulka> nemuze byt <pointer> ale <pUTF8conv>}
       {<inverzni_prevodni_tabulka> nemuze byt <pointer> ale <pUTF8convinv>}
       Procedure Na_Mala_pismena(prevodni_tabulka:pointer);
       {<prevodni_tabulka> nemuze byt <pointer> ale <pUTF8conv>
        Procedure pracuje tak, ze non-unicode text prevede na unicode, pak
        pomoci univerzelni unicode tabulky provede konverzi na mala pismena a
        pak text vrati zpet do non-unicode podoby.
        Pokud vstupni text byl unicode, tak zadne prevody ASCII<>unicode neprovadi}
       Procedure Na_Velka_pismena(prevodni_tabulka:pointer);
       {dtto}
       Function Copy_and_to_unicode_and_lowcase(prevodni_tabulka:pointer):PItRadek;
       {specialne pro potreby editoru Blocek - udela kopii retezce a pritom ho prevede
        na mala pismena a take do unicode (pokud jiz v unicode neni)}
       Function Copy_and_to_unicode(prevodni_tabulka:pointer):PItRadek;
       {take pro potreby editoru Blocek - udela kopii retezce a pritom ho prevede
        do unicode (pokud jiz v unicode neni). Velikost pismen nemeni}
       Function Copy_and_from_unicode(prevodni_tabulka,inverzni_prevodni_tabulka:pointer):PItRadek;
       {take pro potreby editoru Blocek - udela kopii retezce a pritom ho prevede
        z unicode pryc (jen useky, ktere v unicode jsou). Velikost pismen nemeni}

       Procedure UmistiUzel(u:PFNatrb;poz:longint);
       Procedure PrvniUzel;
       Procedure Rozdel(var nv:TItRadek;pozice:longint);virtual;
       Procedure Rozdel(var nv:TItRadek;pozice,vypust:longint);
       Procedure Rozdel(var nv:PItRadek;pozice:longint);
       Function NajdiPodretezec(text:PItRadek;odkud:longint):longint;
       Function NajdiNedefinovanyZnak(odkud:longint;var jaky:longint):longint;
       Procedure Obnov_BU;
       Function Copy:PItRadek;
       Destructor Done;virtual;
       end;



Function Init_PEdRadek:PEdRadek;
Function Init_PEdRadek(s:string):PEdRadek;
Function Init_PEdRadek(p:pchar):PEdRadek;

Function Init_PItRadek:PItRadek;
Function Init_PItRadek(tagy:boolean):PItRadek;
Function Init_PItRadek(s:string;tagy:boolean):PItRadek;
Function Init_PItRadek(s:string):PItRadek;
Function Init_PItRadek_prealloc(znaku:longint;tagy:boolean):PItRadek;

Procedure Kill_Vaznik_Uzlu(var aa:PVaznik);
Procedure Kill_PEdRadek(var e:PEdRadek);
Procedure Kill_PItRadek(var e:PItRadek);

Function Vaznik_z_PItRadky(v:PItRadek):PVaznik;

implementation
uses FNfont2,Lacrt,VenomGFX;

const ochrana_obrazku:boolean = false;
      global_inv_unitbl_posl_predloha:putf8conv = nil;

var   global_inv_unitbl:utf8convinv;

Constructor Tfnatrb.Init;
begin
extra:=nil;
modifikace:=0;
pozadi:=-1;
barva:=65535;  {bila barva}
pozice:=1;
font:=nil;
end;

Procedure Tfnatrb.DefaultA;
begin
extra:=nil;
font:=AktualniFont_fn;
barva:=FN_color;
pozadi:=FN_pozadi;
modifikace:=byte(FN_podtrh=true);
pozice:=1;
end;

Function Tfnatrb.CopyTo(newpos:longint):PFnatrb;
{POZOR - nebude kopirovat extratagy}
var e:Pfnatrb;
begin
e:=New(PfnAtrb,Init);
e^.font:=font;
e^.barva:=barva;
e^.pozadi:=pozadi;
e^.modifikace:=modifikace;
e^.pozice:=newpos;
CopyTo:=e;
end;

Function Tfnatrb.CopyEx:PFNatrb;
{Zkopiruje vcetne extratagu}
var e:Pfnatrb;
begin
e:=CopyTo(pozice);
if extra<>nil then e^.extra:=NaPstring(extra^);
CopyEx:=e;
end;


Procedure Tfnatrb.Modifikuj(co,jak:longint);
begin
case co of
1: {barva}
  barva:=jak;
2: {pozadi}
  pozadi:=jak;
3: {font}
  font:=pointer(jak);
4: {modifikace-podtrh}
  if jak=0 then modifikace:=modifikace and 254  {zrusi podtrh}
           else modifikace:=modifikace or 1;    {zapne podtrh}
5: {modifikace-zvyrazneni}
  if jak=0 then modifikace:=modifikace and 253  {zrusi zvyrazneni}
           else modifikace:=modifikace or 2;    {zapne zvyrazneni}

6: {modifikace-v bloku (inverzni zobrazeni)}
  if jak=0 then modifikace:=modifikace and 251  {zrusi inverzi}
           else modifikace:=modifikace or 4;    {zapne inverzii}

7: {modifikace-jak unicode: 0: podle fontu; 1:unicode; 2:non-unicode}
  begin
  modifikace:=modifikace and 231;  {napred vycistime 3.-4. bit (t.j. podle fontu)}
  if jak=1 then modifikace:=modifikace or 8 else  {unicode ano}
  if jak=2 then modifikace:=modifikace or 16;     {unicode ne}
  end;

end; {case}
end;


Function Tfnatrb.Zkonstruuj_tag(predchozi_tag:PFNatrb):string;
    Function Tag_Pozadi(pzd:longint):string;
    begin if pzd<0 then Tag_Pozadi:='-' else Tag_Pozadi:=MyStr(pozadi);end;

    Function tag_podtrh(mdf:longint):string;
    begin if (modifikace and 1)<>0 then tag_podtrh:='+' else tag_podtrh:='-';end;

var s,sb,sf,sm,sp,se:string;
    v:PFNatrb;
begin
v:=predchozi_tag;
if (v=nil) or (barva<>v^.barva) then sb:='BARVA='+mystr(barva)+';' else sb:='';
if (v=nil) or (pozadi<>v^.pozadi)
   then sp:='POZADI='+tag_pozadi(pozadi)+';' else sp:='';
if (v=nil) or (font<>v^.font)
   then sf:='FONT='+FNSLR_dej_ID(font)+';' else sf:='';

sm:=''; {modifikace se budou nascitavat zvlast}
if (v=nil) or ((modifikace and 1)<>(v^.modifikace and 1))
   then sm:='PODTRH='+tag_podtrh(modifikace)+';';

if extra<>nil then se:=extra^ else se:='';

s:='<'+sb+sp+sf+sm+se;
if s[length(s)]=';' then dec(byte(s[0]));

if s='<' then Zkonstruuj_tag:='' else Zkonstruuj_tag:=s+'>';
end;


Function Tfnatrb.Porovnej_s_jinym_atributem(v:PFNatrb):boolean;
{pokud je V s nami shodny, tak zhodnoti jako TRUE, jinak jako FALSE}
begin
Porovnej_s_jinym_atributem:=true;
if extra<>nil then Exit(false);
if v^.extra<>nil then Exit(false);
if barva<>v^.barva then Exit(false);
if pozadi<>v^.pozadi then Exit(false);
if font<>v^.font then Exit(false);
if modifikace<>v^.modifikace then Exit(false);
end;


Procedure Tfnatrb.DoGlobalnichPromennych;
var s:string;
begin
FN_color:=barva;
FN_pozadi:=pozadi;
FN_podtrh:=(modifikace and 1)<>0;
s:=FNSLR_dej_ID(font);
NastavAktualniFont(s);
end;



Function TFnAtrb.Je_unicode_font:boolean;
{modifikace: 3.-4.bit = 00: unicode/non-unicode podle fontu
             01: nucene unicode
             10: nucene nonunicode
             11: nucene nonunicode}
var b:byte;
begin
b:=modifikace and (16+8);
if b=0 then Je_unicode_font:=pfont(font)^.unicode else
if b=8 then Je_unicode_font:=true else Je_unicode_font:=false;
end;

Destructor Tfnatrb.Done;
var a,xr,yr,xp,yp,clr:longint;
    v:PVirtualWindow;
    n:boolean;
begin
if extra<>nil then                  {Je na tomto miste extratag?}
   begin
   if ochrana_obrazku=false then
      begin
      a:=1;
      repeat
         {n:=VytahniObrazek(extra^,a,v,xr,yr,xp,yp,clr);}n:=false;
         if N then begin Kill_VW(v^);Dispose(v);end;
      until n=false;
      end;
   FreeMem(extra);
   end;
end;

{$IFDEF FPC}
Function PLength(p:pchar):longint;assembler;
asm
xor eax,eax
mov esi,p
@znova:
cmp byte [esi],0
je @konec
inc esi
inc eax
jmp @znova
@konec:
end;

{$ELSE}
Function PLength(p:pchar):longint;
var q:pchar;
    l:longint;
begin
l:=0;
q:=p;
while q^<>#0 do begin inc(q);inc(l);end;
PLength:=l;
end;
{$ENDIF}

Procedure Kill_Pfnatrb(var p:Pointer);
var h:pfnatrb;
begin
h:=p;
Dispose(h,Done);
end;

Constructor TEdRadek.Init;
begin
spp:=1;
pp:=ED_GRANULARITA;
GetMem(p,pp);
p[0]:=#0;
end;

Function TEdRadek.Delka:longint;
begin
Delka:=spp-1;
end;

Function TEdRadek.Prazdny:boolean;
begin
Prazdny:=delka=0;
end;

Function TEdRadek.Znak(n:longint):word;
begin
if n<1 then Znak:=0 else
if n>=spp then Znak:=0 else
   Znak:=word(p[n-1]);
end;

Function TEdRadek.Prvy:longint;
{pokud je retezec prazdny, tak vrati 0, pokud neni prazdny, tak 1}
begin
if spp=1 then Prvy:=0 else Prvy:=1;
end;

Procedure TEdRadek.InternalVratCast(var poz,delk:longint;var buffer:pchar;var bd:longint);
var i:longint;
begin
poz:=poz-1;
i:=delka;
if poz>=i then poz:=i-1;
if poz<0 then poz:=0;
if poz+delk-1>i then delk:=i-poz+1;
bd:=delk+1;     {vsechny znaky useku retezce + ASCII 0}

GetMem(buffer,bd);
for i:=0 to delk-1 do buffer[i]:=p[i+poz];
buffer[delk]:=#0;
end;

Function TEdRadek.VratPchar(poz,delk:longint):pchar;
var t:pchar;
    td:longint;
begin
InternalVratCast(poz,delk,t,td);
VratPChar:=t;
end;

Function TEdRadek.VratString(poz,delk:longint):string;
var t:pchar;
    td:longint;
    i:longint;
    s:string;

begin
InternalVratCast(poz,delk,t,td);
if td>255 then i:=255 else i:=td-1;
s[0]:=char(i);
move(t^,s[1],i);
FreeMem(t);
VratString:=s;
end;


Function TEdRadek.vs:string;
var i:longint;
begin
i:=delka;
if i>255 then i:=255;      {pozor na maximalni delku stringu}
vs:=VratString(1,i);
end;

Function TEdRadek.vp:pchar;
begin
vp:=VratPChar(1,delka);
end;

Function TEdRadek.VratUsek(poz,del:longint):PEdRadek;
var v:PEdRadek;
begin
v:=New(PEdRadek,Init);
v^.VlozKus(p,1,poz,del);
VratUsek:=v;
end;

Function TEdRadek.Najdi(s:string;poz:longint):longint;
var a,b,c:longint;
    ne:boolean;
begin
b:=Length(s);
for a:=poz-1 to delka-b do
   begin
   ne:=false;
   for c:=1 to b do
      if p[a+c-1]<>s[c] then begin ne:=true;Break;end;
   if NE=false then Exit(a+1);
   end;
Najdi:=0;
end;


Procedure TEdRadek.Vloz(s:pchar;sd,poz:longint);
var np:Pchar;
    opp:longint;
begin
if sd=0 then Exit;      {diskutabilni. snad je to OK}
if poz<1 then poz:=1;
if poz>spp then poz:=spp;
dec(poz);              {pozici budu cislovat od 1, tak jako u typu string}
if spp+sd>pp then       {bude treba provest realokaci pameti}
   begin
   opp:=pp;
   pp:=((spp+sd) div ED_GRANULARITA+1)*ED_GRANULARITA;
   GetMem(np,pp);      {pripravim novy buffer}
   Move(p[0],np[0],poz);    {cast stareho pred vlozenim noveho}
   (*Move(s[0],np[poz],sd+1); {novy kus dam za stary a zkopiruju i #0}*)

   Move(s[0],np[poz],sd);  {novy kus dam za stary. Nelze se spolehat, ze... }
                           {...obsahuje #0}
   np[poz+sd]:=#0;       {znak #0 proto pridam manualne}

   {***********}

   if spp-1>poz then
      Move(p[poz],np[poz+sd],spp-poz+1); {cast stareho, ktera ted bude}
                                             {za novym. Znovu kupiruju i s #0}
   inc(spp,sd);
   FreeMem(p,opp);
   p:=np;
   end
   else begin          {realokace pameti nebude treba}
   Move(p[poz],p[poz+sd],spp-poz); {posun textu vpravo od vlozeneho}
   Move(s[0],p[poz],sd);          {a vlozeni S}
   inc(spp,sd);
   end;
end;

Procedure TEdRadek.Vloz(s:pchar;poz:longint);
var i:longint;
begin
i:=PLength(s);
Vloz(s,i,poz);
end;

Procedure TEdRadek.VlozS(s:string;poz:longint);
var qq:pchar;
    i:longint;
begin
i:=Length(s);
if i=0 then Exit;
s:=s+#0;
qq:=@s[1];
Vloz(qq,i,poz);
end;

Procedure TEdRadek.VlozKus(s:pchar;poz:longint;s_zac,s_del:longint);
var c:char;
begin
dec(s_zac);
inc(s,s_zac);
c:=s[s_del];
s[s_del]:=#0;
Vloz(s,s_del,poz);
s[s_del]:=c;
end;

Procedure TEdRadek.Vyjmi(poz,l:longint);
var t1,t2:Pchar;
    np:longint;
begin
if poz>spp-1 then exit;
if poz<1 then begin dec(l,-(poz-1));poz:=1;end;
{jako pocatecni pozice zadana 0 nebo zaporne cislo?}

if l<1 then exit;
{chceme smazat nulovy nebo zaporny pocet znaku?}

if poz+l>spp then l:=spp-poz;
dec(poz);
t1:=p;inc(t1,poz);
t2:=p;inc(t2,poz+l);
Move(t2^,t1^,spp-poz-1);
dec(spp,l);
np:=(spp div ED_GRANULARITA+1)*ED_GRANULARITA;
if np<>pp then ReAllocMem(p,np);  {P uz ale muze ukazovat jinam (obsah P se muze zmenit)}
pp:=np;
end;

Procedure TEdRadek.Zamena(s:pchar);
begin
Vyjmi(1,delka);
Vloz(s,1);
end;

Procedure TEdRadek.ZamenaS(s:string);
begin
s:=s+#0;
Zamena(@s[1]);
end;

Procedure TEdRadek.Rozdel(var nv:TEdRadek;pozice,vypust:longint);
var n:pchar;
    i:longint;
begin
n:=p;
dec(pozice);
inc(n,pozice+vypust);
i:=spp-pozice-1;
nv.Vloz(n,i-vypust,1);
Vyjmi(pozice+1,i);
end;

Procedure TEdRadek.Rozdel(var nv:TEdRadek;pozice:longint);
begin
Rozdel(nv,pozice,0);
end;

Function TEdRadek.Znak_oddelovac_slov(poz:longint;var odd_znak:word):boolean;
var a,b:byte;
begin
b:=Length(TED_ODDELOVACE_SLOV);
for a:=1 to b do
    if Znak(poz)=word(TED_ODDELOVACE_SLOV[a]) then
       begin
       odd_znak:=Znak(poz);
       Exit(true);
       end;
odd_znak:=0;
Znak_oddelovac_slov:=false;
end;


Function TEdRadek.Znak_oddelovac_slov(poz:longint):boolean;
var dummy:word;
begin
Znak_oddelovac_slov:=Znak_oddelovac_slov(poz,dummy);
end;


Function TEdRadek.ZacatekSlova_na_pozici(poz:longint;var odd_znak:word):longint;
begin
while not Znak_oddelovac_slov(poz,odd_znak) do  {dokud neni mezera}
   if poz=1 then begin odd_znak:=0;Exit(0);end else dec(poz);
ZacatekSlova_na_pozici:=poz;
end;


Function TEdRadek.ZacatekSlova_na_pozici(poz:longint):longint;
var dummy:word;
begin
ZacatekSlova_na_pozici:=ZacatekSlova_na_pozici(poz,dummy);
end;


Function TEdRadek.KonecSlova_na_pozici(poz:longint;var odd_znak:word):longint;
var r:longint;
begin
r:=delka;
while (not Znak_oddelovac_slov(poz,odd_znak)) and (poz<=r) do inc(poz);
KonecSlova_na_pozici:=poz;
end;


Function TEdRadek.KonecSlova_na_pozici(poz:longint):longint;
var dummy:word;
begin
KonecSlova_na_pozici:=KonecSlova_na_pozici(poz,dummy);
end;


Procedure TEdRadek.Slovo(poz:longint;var zac,kon:longint);
begin
zac:=ZacatekSlova_na_pozici(poz);
kon:=KonecSlova_na_pozici(poz);
end;


Function TEdRadek.ZacatekMezislovi(poz:longint):longint;
var dummy:word;
begin
while Znak_oddelovac_slov(poz,dummy) do
   if poz=1 then Exit(1) else dec(poz);
ZacatekMezislovi:=poz+1;
end;


Function TEdRadek.KonecMezislovi(poz:longint):longint;
var r:longint;
    dummy:word;
begin
r:=delka;
while (Znak_oddelovac_slov(poz,dummy)) and (poz<=r) do inc(poz);
KonecMezislovi:=poz;
end;


Procedure TEdRadek.Mezislovi(poz:longint;var zac,kon:longint);
begin
zac:=ZacatekMezislovi(poz);
kon:=KonecMezislovi(poz);
end;


Function TEdRadek.Zjisti_Kolikate_slovo_nebo_mezislovi(a:longint):longint;
{1.mezislovi = 0; 1.slovo = 1; 2.mezislovi = 2; 2.slovo = 3...}
var b,c,d,e:longint;
    uo,un:boolean;
begin
uo:=Znak_oddelovac_slov(1);
c:=0;
e:=delka;
if (uo=false) and (e>0) then inc(c);
for b:=1 to e do
    begin
    d:=Znak(b);
    un:=Znak_oddelovac_slov(b);
    if un<>uo then  {zmena?}
       begin
       inc(c);
       uo:=un;
       end;
    if b=a then Exit(c);
    end;
Zjisti_Kolikate_slovo_nebo_mezislovi:=c;
end;


Function TEdRadek.Zjisti_Pocet_Slov:longint;
var i,j:longint;
begin
i:=Zjisti_Kolikate_slovo_nebo_mezislovi(delka);
if i<2 then Zjisti_Pocet_Slov:=i
   else begin
   j:=i div 2;
   if odd(i) then inc(j);  {koncime slovem? Tak pricti. Mezerou? nepricitej.}
   Zjisti_Pocet_Slov:=j;
   end;
end;


Procedure TEdRadek.Odkud_kam_je_slovo(vychozi:longint;var zac,kon:longint);
{pokud bude analyzovat prvni slovo, tak VYCHOZI bude 1}
var a,b,d:longint;
begin
d:=delka;
if delka=0 then
   begin
   zac:=0;
   kon:=0;
   Exit;
   end;
if vychozi<1 then vychozi:=1;
if vychozi>delka then vychozi:=delka;
if znak_oddelovac_slov(vychozi)=true then zac:=KonecMezislovi(vychozi) else zac:=ZacatekSlova_na_pozici(vychozi);
kon:=KonecSlova_na_pozici(zac)-1;
if kon<zac then
   begin
   zac:=0;
   kon:=0;
   end;
end;


Destructor TEdRadek.Done;
begin
if p<>nil then FreeMem(p);
pp:=0;
spp:=0;
end;


Constructor TItRadek.Init;
begin
inherited Init;
PrvotniPrirazeni;
end;

Constructor TItRadek.Init(s:string);
begin
inherited Init;
PrvotniPrirazeni;
PrvniUzel;
if s<>'' then VlozS(s,1);
end;

Procedure TItRadek.PrvotniPrirazeni;
begin
crlf:=0; {zalomeni natvrdo, nikoliv zadny wordwrap}
up:=0;
gd:=0;
aa:=nil;
so:=-1;
su:=-1;
bu:=0;
odz:=0;
doz:=0;
posunm:=0;
posunv:=0;
yy:=1;
end;

Function TItRadek.Delka:longint;
begin
Delka:=up;
end;

Function TItRadek.Vyska:longint;
begin
if aa=nil then Vyska:=Vyska_FN_aktual else Vyska:=so+su;
end;


Procedure TItRadek.Prepocitej_gd;
begin
gd:=Sirka_it(@self);
end;


Function TItRadek.GD_na_Poz(poz:longint):longint;
begin
GD_na_Poz:=Zjisti_X(poz,@self);
end;


Function TItRadek.Znak(n:longint):word;
var t:pchar;
begin
n:=n*2-2;
if n<0 then Znak:=0 else
if n>spp-1 then Znak:=0 else
   Znak:=word(p[n])+word(p[n+1])*256;
end;


Procedure TItRadek.InternalVratCast(var poz,delk:longint;var buffer:pchar;var bd:longint);
{bude vracet v UTF8 nebo v ASCII}
var g:pchar;
    w:word;
    v:PFNatrb;
    b:boolean;

begin
if poz<1 then poz:=1;
if poz>up then poz:=up;
if poz+delk-1>up then delk:=up-poz+1;

v:=VratUzel(poz);
if UTF8_konv = UTF8_AUTO
   then if v=nil then b:=false else b:=PFont(v^.font)^.unicode
   else
if UTF8_konv = UTF8_ALL_CONV then b:=true
   else
   b:=false;

g:=p;
inc(g,(poz-1)*2);      {jsem nastaven na pozici POZ v bajtech}

WidePChar2Pchar(g,delka*2,b,buffer,bd);
end;


Function TItRadek.PocetUseku:longint;
begin
if aa=nil then PocetUseku:=1 else PocetUseku:=aa^.Pocet;
end;


Function TItRadek.PocetUzlu:longint;
begin
if aa=nil then PocetUzlu:=0 else PocetUzlu:=aa^.Pocet;
end;


Function TItRadek.PocetUsekuOdDo(zac,kon:longint):longint;
var a:PfnAtrb;
    osu,oku,onu:PUzel;
    i:longint;

begin
if (aa=nil) or (up=0) then PocetUsekuOdDo:=1 else
   begin
   if zac<1 then zac:=1;
   if kon<1 then kon:=1;
   if zac>up then zac:=up;
   if kon>up then kon:=up;

   if kon<=zac then PocetUsekuOdDo:=1
      else
      begin
      osu:=VratUkazatelNaUzel(zac);
      oku:=VratUkazatelNaUzel(kon);
      i:=1;
      while osu<>oku do
         begin
         inc(i);
         osu:=osu^.dalsi;
         end;
      PocetUsekuOdDo:=i;
      end;
   end;
end;


Procedure TItRadek.DejRozsahDanehoUseku(i:longint;var zac,kon:longint);
var pu:longint;
    u1,u2:PUzel;
    a1,a2:PfnAtrb;
begin
if (aa=nil) or (i<1) then begin zac:=Prvy;kon:=up;Exit;end;
pu:=PocetUseku;
if i>pu then i:=pu;
if pu=1 then begin zac:=1;kon:=up;Exit;end;

u1:=aa^.Uzel(i);
a1:=u1^.vazba;

zac:=a1^.pozice;

u2:=u1^.dalsi;
if u2=nil then kon:=up
   else begin
   a2:=u2^.vazba;
   kon:=a2^.pozice-1;
   end;
end;


Procedure TItRadek.PrevedUsekMeziUzly_na_PChar(zac,kon:longint;u:boolean;var v:PChar;var vd:longint);
var b:boolean;
    q:pchar;
    delk:longint;

begin
if kon=-1 then {nastane treba  pri pokusu o prevod prazdneho retezce}
   begin
   v:=nil;
   vd:=0;
   Exit;
   end;

if utf8_konv = UTF8_AUTO then b:=u else
if utf8_konv = UTF8_ALL_CONV then b:=true else b:=false;

q:=p;
if zac<1 then zac:=1;
if kon<zac then kon:=zac;
inc(q,(zac-1)*2);
delk:=(kon-zac+1)*2;
WidePchar2Pchar(q,delk,b,v,vd);
end;


Function TItRadek.VratPedRadek(poz,delk:longint;tvor_tagy:boolean):PEdRadek;
var e:PEdRadek;
    osu,onu:PUzel;
    au,oau,anu:PFnAtrb;
    u,konec:boolean;
    kon,i,vd:longint;
    p1,p2:longint;
    ts:string;
    v:PChar;

begin

if poz<1 then poz:=1;
if poz>up then poz:=up;
if poz+delk-1>up then delk:=up-poz+1;
kon:=poz+delk-1;
e:=Init_PedRadek;
oau:=nil;
osu:=VratUkazatelNaUzel(poz);          {prvni uzel}
if osu=nil then   {zadny uzel?}
   begin
   u:=AktualniFont_FN^.unicode;
   PrevedUsekMeziUzly_na_PChar(poz,kon,u,v,vd);
   e^.Vloz(v,vd-1,e^.delka+1);
   FreeMem(v);
   end
   else begin     {jsou uzly?}
   p1:=poz;
   konec:=false;
   repeat
   onu:=osu^.dalsi;                       {nasledujici uzel}
   if onu=nil then
      begin
      p2:=kon;
      konec:=true;
      end
      else begin
      anu:=onu^.vazba;
      p2:=anu^.pozice-1;
      if p2>=kon then begin p2:=kon;konec:=true;end;
      end;

   au:=osu^.vazba;

   u:=au^.Je_unicode_font;
   PrevedUsekMeziUzly_na_PChar(p1,p2,u,v,vd);

   if tvor_tagy=true then
      begin
      ts:=au^.Zkonstruuj_tag(oau);
      e^.VlozS(ts,e^.delka+1);
      oau:=au;
      end;

   if v<>nil then
      begin
      e^.Vloz(v,vd-1,e^.delka+1);
      FreeMem(v);
      end;

   p1:=p2+1;
   osu:=onu;
   until konec=true;
   end;

VratPEdRadek:=e;
end;


Function TItRadek.VratPchar(poz,delk:longint):pchar;
var e:PEdRadek;
    q:pchar;
begin
e:=VratPedRadek(poz,delk,false);
q:=e^.p;
e^.p:=nil;
dispose(e,done);
VratPchar:=q;
end;


Function TItRadek.VratString(poz,delk:longint):string;
var q:pchar;
begin
q:=VratPchar(poz,delk);
VratString:=q;
freemem(q);
end;


Function TItRadek.Najdi(s:string;poz:longint):longint;
var a,b,c:longint;
    ne:boolean;
begin
if (poz<1) or (poz>up) then Exit(0);
dec(poz);
b:=Length(s);
for a:=poz to delka-b do
   begin
   ne:=false;
   for c:=0 to b-1 do
      if p[(a+c)*2]<>s[c+1] then begin ne:=true;Break;end;
   if NE=false then Exit(a+1);
   end;
Najdi:=0;
end;


Procedure SmazUzel(var p:pointer);
var f:PfnAtrb;
begin
f:=p;
Dispose(f,Done);
p:=nil;
end;


Function TItRadek.ZrusUzly(poz,l:longint):boolean;
var zmenauzlu:boolean;
    s,q,r:PUzel;
    v:PFNatrb;

begin
s:=VratUkazatelNaUzel(poz);
if s=nil then q:=nil else q:=s^.dalsi; {1.uzel necha byt}
zmenauzlu:=false;
while q<>nil do
   begin
   v:=q^.vazba;
   r:=q^.dalsi;
   if v^.pozice<poz+l then {kdyz je uvnitr mazaneho useku uzel,}
      begin                {tak ho musim zrusit}
      Dispose(v,Done);
      aa^.ZrusUzel(q);
      zmenauzlu:=true;
      end
      else dec(v^.pozice,l); {kdyz je uzel az za usekem, tak jenom upravim jeho polohu}
   q:=r;
   end;
end;


Procedure TItRadek.Vyjmi(poz,l:longint);
var i,_p_:longint;
    zmenauzlu:boolean;
begin
if poz>up then Exit;
if poz+l>up+1 then l:=up-poz+1;
zmenauzlu:=ZrusUzly(poz,l);
i:=SirkaUseku_IT(@self,poz,l);
inherited vyjmi(poz*2-1,l*2);     {predek nepouziva wordy, ale bajty}
if zmenauzlu then                 {odmazal jsem nejake uzly?}
   begin                          {v tom pripade prepocitam vysku radky}
   so:=-1;                        {"resetuju" aktualni stav}
   VyskaRadky_IT(@self,_p_,so,su);{a vypocitam novy stav}
   end;
dec(gd,i);
up:=(spp-1) div 2;
Obnov_BU;
end;


Procedure TItRadek.VyjmiPosl;
{smaze posledni znak}
begin
Vyjmi(up,1);
end;


Procedure TItRadek.VyjmiZnak(poz:longint);
{smaze jeden znak (na libovolne pozici}
begin
Vyjmi(poz,1);
end;


Procedure TItRadek.Smaz;
begin
Vyjmi(1,up);
end;


Procedure TItRadek.VlozKus(s:pchar;poz:longint;s_zac,s_del:longint);
var c:char;
begin
if s_del<1 then Exit;
if s_zac<1 then s_zac:=1;
dec(s_zac);
inc(s,s_zac);
c:=s[s_del];
s[s_del]:=#0;
Vloz(s,s_del,poz);
s[s_del]:=c;
end;


Procedure TItRadek.VlozWS(t:pchar;td,poz:longint;b:boolean);
{zapisuje PChar z Widecharu. TD je mereno ne v bajtech, ale ve WideCharech}
var i,l:longint;
    q:PUzel;
    v:PFNatrb;
begin
l:=poz*2-1;
q:=VratUkazatelNaUzel(poz);
inherited vloz(t,td*2,l);
if b then
   begin
   i:=SirkaUseku_IT(@self,q,poz,td);
   inc(gd,i);
   end;
if q<>nil then q:=q^.dalsi;
while q<>nil do
   begin
   v:=q^.vazba;
   inc(v^.pozice,td);     {musim upravit polohu vsech uzlu, ktere budou lezet}
   q:=q^.dalsi;           {za vlozenym usekem}
   end;
up:=(spp-1) div 2;
end;

Procedure TItRadek.VlozWord(o:word;poz:longint);
var a:array[1..3] of byte;
begin
a[1]:=Lo(o);
a[2]:=Hi(o);
a[3]:=0;
VlozWS(@a,1,poz,true);
end;


Procedure TItRadek.NahradWord(o:word;poz:longint;prepocet_gd:boolean);
{Nahradi jeden WideChar jinym. Muze a nemusi resit zmenu GD}
var z:word;
    a:Pfnatrb;
    f:pfont;
    i,j:longint;

begin
if aa=nil then prepocet_gd:=false;

if prepocet_gd then
   begin
   z:=Znak(poz);
   a:=VratUzel(poz);
   f:=a^.font;
   i:=SirkaZnaku(f,z);
   j:=SirkaZnaku(f,o);
   dec(gd,i);
   inc(gd,j);
   end;

poz:=(poz-1)*2;
p[poz]:=char(lo(o));
p[poz+1]:=char(hi(o));
end;


Procedure TItRadek.NahradWord(o:word;poz:longint);
begin
NahradWord(o,poz,false);
end;


Procedure TItRadek.NahradUsekBufferem(bp:pointer;poz,bajtu:longint);
{Nahradi kus PItRadky blokem bajtu. Nedela zadne kontroly a nemeni zadne
 promenne.
 Pozice POZ je pocitane ne v bajtech, ale ve znacich}
begin
Move(bp^,p[(poz-1)*2],bajtu);
end;


Procedure TItRadek.Vloz(s:pchar;sd,poz:longint);
var t_bajtu:longint;
    b:boolean;
    v:PFNatrb;
    t:pchar;
begin
if sd=0 then Exit;
if poz<1 then poz:=1;
v:=VratUzel(poz);

if UTF8_konv = UTF8_AUTO
   then if v=nil then b:=false else b:=PFont(v^.font)^.unicode
   else
if UTF8_konv = UTF8_ALL_CONV then b:=true
   else
   b:=false;

Pchar2WidePchar(s,sd,B,t,t_bajtu);  {T je S rozepsane na WideChary}
{Tato procedura si poradi jak s ASCII textem, tak s textem v UTF8}

VlozWS(t,(t_bajtu-1) div 2,poz,true);
{Problem je, ze pokud byl puvodni text v UTF8, tak nemuzeme jako pocet znaku
 brat puvodni SD, protoze v UTF8 muze byt povet bajtu na znak variabilni.
 Proto delku retezce odvodime z delky bufferu.}
FreeMem(t,t_bajtu);
end;


Procedure TItRadek.Vloz(s:pchar;poz:longint);
var d:longint;
begin
d:=PLength(s);
if d>0 then Vloz(s,d,poz);
end;


Procedure TItRadek.UtvorZakladniUzel;
var v:PFNatrb;
begin
v:=New(PFNatrb,Init);
aa:=NovyVaznik;
aa^.InitNext(v);
end;

Function PFNshoda(a,b:PFNatrb):boolean;
var i:boolean;
begin
PFNshoda:=((a^.font=b^.font) and (a^.pozadi=b^.pozadi) and (a^.extra=b^.extra) and
           (a^.modifikace=b^.modifikace) and (a^.barva=b^.barva));
end;

Procedure UpravPozice(p:PVaznik;poz:longint);
var e:PFnAtrb;
begin
p^.Reset;
while not p^.Konec do
   begin
   e:=p^.Nacti;
   inc(e^.pozice,poz-1);
   end;
end;

Procedure TItRadek.VlozKusIT(s:PItRadek;poz,s_zac,s_del:longint);
var c:char;
    m,n:PChar;
    p1,p2,q2:PUzel;
    v1,v2,v:PFNatrb;
    retez:PVaznik;
    mame_uzly,zmena:boolean;

    i,s_kon,cv,hv,dv:longint;
begin
i:=up+1;
if poz>i then poz:=i;             {lze max 1 znak za aktualni konec retezce}
if s_zac>s^.up then s_zac:=s^.up;
if s_zac=0 then s_zac:=1;         {nejak musime osetrit prazdne retezce}
if s_zac+s_del-1>s^.up then s_del:=s^.up-s_zac+1;

mame_uzly:=aa<>nil; {kdyz prijimajici nema zalozene uzly, tak s uzly vubec}
                    {nebudeme pracovat}

retez:=s^.ZkopirujUsekVaznikuUzlu(s_zac,s_del);
if retez=nil then p2:=nil else p2:=retez^.first;
                              {zjisti aktualni uzel pro zacatek vkladaneho}
                              {kdyz nema zadne uzly, tak P2 je NIL}
                              {to nevadi}

inc(gd,SirkaUseku_IT(s,p2,s_zac,s_del)); {pripocti sirku vkladaneho textu}

if mame_uzly then   {jestlize prijimaci ma uzly, tak zpracujeme i uzly}
   begin            {vkladaneho}
   if retez<>nil then    {a vkladany uzly ma? Jestli ne, tak taky nic}
      begin              {delat nebudeme}
      VyskaUsekuRadky_IT(s,s_zac,s_del,cv,hv,dv);
      if hv>so then so:=hv;
      if dv>su then su:=dv;

      UpravPozice(retez,poz);
      p1:=VratUkazatelNaUzel(poz);   {jaky je uzel prijimajiciho v pozici POZ?}
      v1:=p1^.vazba;


      v2:=p2^.vazba;

      if poz=up+1 then   {kdyz vkladame na konec tak za vlozenym usekem uz nebudou}
         begin           {zadne uzly puvodniho}
         if v1^.pozice=poz then     {primo na vkladanem miste je uzel?}
            begin {muze jit o predpripraveny uzel prazdneho retezce nebo o}
                  {uzel nastaveny az jedno misto za posledni znak}
            Dispose(v1,Done); {Takovy uzel kazdopadne smaz}
            aa^.ZrusUzel(p1); {i odkaz na nej}
            end;
         aa^.AbsorbujVaznik(aa^.last,retez);  {a na konec pripoj vkladany}
         end;
      end;
   end;

Obnov_BU;

m:=s^.p;
inc(m,(s_zac-1)*2);         {pozice, od ktere vkladat}
inherited vloz(m,s_del*2,poz*2-1);
up:=(spp-1) div 2;
end;


Function TItRadek.HledejExtraAtribut(s:string;var uz:string):longint;
var i:longint;
    pf:pfnatrb;
    u:string;
begin
uz:='';
i:=0;
if aa=nil then Exit(0);
s:=Convert_up(s);
aa^.reset;
while not aa^.konec do
   begin
   pf:=aa^.nacti;
   if pf^.extra<>nil then
      begin
      u:=pf^.extra^;
      i:=Pos(s,u);
      if i<>0 then
         begin
         delete(u,1,i-1);
         i:=pos(';',u);
         if i=0 then uz:=u
            else uz:=system.Copy(u,1,i-1);
         Exit(pf^.pozice);
         end;
      end;
   end;
HledejExtraAtribut:=0;
end;


Function TItRadek.HledejExtraAtribut_na_poz(s:string;poz:longint;var t:string):longint;
{v T bude cele zneni S vcetne rovnase a vyrazu za nim}
var e:PFnatrb;
    i:longint;
    u:PUzel;

begin
t:='';
u:=VratUkazatelNaUzel(poz);
if u=nil then Exit(0);
s:=Convert_Up(s);
e:=u^.vazba;
if e^.pozice<poz then u:=u^.dalsi;
while u<>nil do
   begin
   e:=u^.vazba;
   if e^.extra<>nil then
      begin
      i:=Pos(s,e^.extra^);
      if i<>0 then
         begin
         t:=e^.extra^;
         delete(t,1,i-1);
         i:=Pos(';',t);
         if i<>0 then t:=system.Copy(t,1,i-1);
         Exit(e^.pozice);
         end;
      end;
   u:=u^.dalsi;
   end;
HledejExtraAtribut_na_poz:=0;
end;



Procedure TItRadek.Pripoj(s:PItRadek);
begin
VlozKusIT(s,spp,1,s^.spp-1);
crlf:=s^.crlf;
end;


Procedure TItRadek.ZamenaIt(s:PItRadek); {udela duplikat, nejde o predani odkazu}
var u:PItRadek;
begin
if s=nil then Exit;
if s<>@self then
   begin
   Smaz;
   u:=s^.Copy;
   self:=u^;
   end;
end;


Function TItRadek.Shodnost(s:PItRadek):boolean;
var i:longint;
begin
if up<>s^.up then Exit(false);
if up=0 then Exit(true);
i:=CompareByte(p^,s^.p^,up);
Shodnost:=i=0;
end;


Function TItRadek.VratUkazatelNaUzel(poz:longint):PUzel;
var v:PFnatrb;
    q:PUzel;
begin
if aa=nil then Exit(nil);
if poz<2 then Exit(aa^.First);
if poz>=up then Exit(aa^.Last);

q:=aa^.First;
while q<>nil do
   begin
   v:=q^.vazba;
   if v^.pozice>poz then
      begin
      if q<>aa^.first then Exit(q^.predchozi); {podminka by mela platit vzdy}
      Break;
      end;
   q:=q^.dalsi;
   end;
VratUkazatelNaUzel:=aa^.Last;
end;

Procedure TItRadek.UmistiUzel(u:PFNatrb;poz:longint);
var e:PUzel;
    w:PFNatrb;
    s:Pstring;
    yd:longint;
begin
if poz<1 then poz:=1;         {osetri nesmyslne rozsahy: moc male}
if poz>up+1 then poz:=up+1;   {moc velke}
u^.pozice:=poz;
if aa=nil then           {zadny uzel zatim neexistuje?}
   begin
   poz:=1;               {v tom pripade jsme prvni}
   aa:=NovyVaznik;       {musime kvuli tomu zalozit vaznik}
   aa^.InitNext(u);      {...a priradit}
   end
   else begin
   e:=VratUkazatelNaUzel(poz);
   w:=e^.vazba;               {nejaky uzel uz tedy existuje...}
   if w^.pozice=poz then      {a nesedi nektery presne na nasi pozici?}
      begin
      if w^.extra<>nil then   {jestli ma nejaky extra tag, tak ho musime}
         begin                {zachovat}
         if u^.extra=nil then     {kdyz novy uzel zadny extraatribut nema,}
            begin
            u^.extra:=w^.extra;   {tak si ho pretahnu k some}
            w^.extra:=nil;        {a v puvodnim uzlu ho zrusim}
            end
            else begin        {novy uzel ma rovnez jakysi extraatribut}
            s:=NaPstring(w^.extra^+';'+u^.extra^); {tak ho spoj dohromady}
            ZrusPstring(u^.extra); {s uzlem puvodniho uzlu}
            u^.extra:=s;
            end;
         end;
      Dispose(w,Done);        {v tom pripade ten stavajici zrusim}
      e^.vazba:=u;            {a namisto nej soupnu novy}
      end
      else begin         {primo na nasi pozici zadny uzel nesedi...}
      aa^.InsertNew(e,u);{tak zaloz novy uzel s pozadovanymi vlastnostmi}
      end;
   end;

if PFont(u^.font)^.so>so then so:=PFont(u^.font)^.so;
if PFont(u^.font)^.su>su then su:=PFont(u^.font)^.su;

if u^.extra<>nil then
   begin
   yd:=NajdiKritickyObrazek(u^.extra^);
   if yd>bu then bu:=yd;
   end;

u^.pozice:=poz;
end;


Procedure NahradUzel(poz:longint;sablona:PFNatrb);
begin

end;



Procedure TItRadek.V_useku_zmen_parametr_uzlu(poz,del:longint;co:byte;jak:longint);
var u,u2:PFNatrb;
    a:longint;
    e,f,z:PUzel;
begin
if poz<1 then poz:=1;         {osetri nesmyslne rozsahy: moc male}
if poz>up+1 then poz:=up+1;   {moc velke}
if aa=nil then           {zadny uzel zatim neexistuje?}
   begin
   poz:=1;               {v tom pripade jsme prvni}
   aa:=NovyVaznik;       {musime kvuli tomu zalozit vaznik}
   u:=New(PFNATRB,Init);
   u^.DefaultA;
   aa^.InitNext(u);      {...a priradit}
   end;

e:=VratUkazatelNaUzel(poz);
u:=e^.vazba;
if u^.pozice<poz then
   begin  {zde jeste uzel neni, takze ho zalozime}
   u2:=u^.CopyTo(poz);
   e:=aa^.InsertNew(e,u2);
   end;

del:=poz+del;
if del>up+1 then del:=up+1;

f:=VratUkazatelNaUzel(del);
u:=f^.vazba;
if u^.pozice<del then
   begin  {zde jeste uzel neni, takze ho zalozime}
   u2:=u^.CopyTo(del);
   f:=aa^.InsertNew(f,u2);
   end;

z:=e;
repeat
u:=z^.vazba;
u^.Modifikuj(co,jak);
{if z=f then z:=nil else z:=z^.dalsi;}
z:=z^.dalsi;
until (z=f) or (z=nil);

Zrus_duplicitni_uzly;
end;


Function TItRadek.Zrus_duplicitni_uzly:longint;
var q1,q2:puzel;
    v,w:pfnatrb;
    b:boolean;
begin
if aa=nil then exit;
q1:=aa^.first;
v:=q1^.vazba;

repeat
q2:=q1^.dalsi;
if q2=nil then Exit;
w:=q2^.vazba;
b:=v^.Porovnej_s_jinym_atributem(w);
if b=false then begin q1:=q2;v:=q1^.vazba;end  {uzly jsou ruzne?}
   else begin   {atributy jsou stejne?}
   Dispose(w,done);   {v tom pripade ten druhy zrusime}
   aa^.ZrusUzel(q2);   {zrusime uzel pro atribut a s prvotnim nehybame}
   end;
until 1=2;
end;


Procedure TItRadek.PrevezmiUzelOdjinud(kam:longint;zdroj:PItRadek;pozice_ve_zdroji:longint);
var e,f:PFNatrb;
begin
e:=zdroj^.VratUzel(pozice_ve_zdroji);
f:=e^.CopyTo(kam);
UmistiUzel(f,kam);
end;


Procedure TItRadek.Obnov_BU;
var v:PFNAtrb;
    a,b:longint;
begin
if aa=nil then Exit;
a:=0;
aa^.Reset;
while not aa^.Konec do
   begin
   v:=aa^.Nacti;
   if v^.extra<>nil then
      begin
      b:=NajdiKritickyObrazek(v^.extra^);
      if b>a then a:=b;
      end;
   end;
bu:=a;
end;


Procedure TItRadek.PrvniUzel;
var v:PFNAtrb;
begin
v:=New(Pfnatrb,Init);
v^.DefaultA;
UmistiUzel(v,1);
end;


Function TItRadek.VratUzel(poz:longint):PfnAtrb;
var q:PUzel;
begin
q:=VratUkazatelNaUzel(poz);
if q=nil then VratUzel:=nil else VratUzel:=q^.vazba;
end;


Function TItRadek.VratUzel_Copy(poz:longint):Pfnatrb;
var e:PFNatrb;
begin
e:=VratUzel(poz);
VratUzel_Copy:=e^.CopyTo(e^.pozice);
end;


Function TItRadek.Atrib_vs(poz:longint):string;
var e:PFNatrb;
    f:pfont;
begin
e:=VratUzel(poz);
if e=nil then Exit('')
   else begin
   f:=e^.font;
   Atrib_vs:=f^.rez+#13#10+mystr(e^.barva);
   end;
end;


Function TItRadek.ZkopirujUsekVaznikuUzlu(poz,del:longint):PVaznik;
var u:PVaznik;
    q:PUzel;
    poz2:longint;
    d,e:PFnatrb;
begin
if aa=nil then Exit(nil);
poz2:=poz+del-1;
if poz<1 then poz:=1;
if poz2<1 then poz2:=1;        {nastava u prazdnych retezcu}
u:=NovyVaznik;
q:=VratUkazatelNaUzel(poz);
while q<>nil do
   begin
   d:=q^.vazba;
   if d^.pozice<=poz2 then
      begin
      if d^.pozice<poz then
         begin
         e:=d^.CopyTo(1);
         end
         else begin
         e:=d^.CopyEx;
         e^.pozice:=e^.pozice-poz+1;
         end;
      u^.InitNext(e);
      end else Break;
   q:=q^.dalsi;
   end;
ZkopirujUsekVaznikuUzlu:=u;
end;


Procedure TItRadek.Zalohuj_Uzly(var z:PVaznik);
begin
z:=ZkopirujUsekVaznikuUzlu(1,up);
end;


Procedure TItRadek.Obnov_Uzly(var z:PVaznik);
begin
if z<>nil then
   begin
   Kill_Vaznik_uzlu(aa);
   aa:=z;
   z:=ZkopirujUsekVaznikuUzlu(1,up);
   end;
end;


Procedure TItRadek.Znic_Vaznik_Uzlu(var z:PVaznik);
begin
Kill_Vaznik_Uzlu(z);
end;


Function TItRadek.Copy:PItRadek;
var n:PItRadek;
begin
if up=0 then n:=Init_PItRadek
   else n:=VratUsek(1,up); {vyplni i polozky SO a SU}
n^.gd:=gd;
n^.crlf:=crlf;
Copy:=n;
end;


Function TItRadek.VratUsek(poz,del:longint):PItRadek;
var v:PItRadek;
    cv,hv,dv:longint;
    r:PVaznik;
    q:pchar;
begin
if poz>up then Exit(nil);
if del<1 then Exit(nil);
if poz<1 then poz:=1;
if poz+del-1>up then del:=up-poz+1;

v:=New(PItRadek,Init);
q:=p;
inc(q,(poz-1)*2);
v^.VlozWS(q,del,1,true);
r:=ZkopirujUsekVaznikuUzlu(poz,del);
v^.aa:=r;
if r<>nil then
   begin
   VyskaRadky_IT(v,cv,hv,dv);
   v^.so:=hv;
   v^.su:=dv;
   end;
VratUsek:=v;
end;

Procedure TItRadek.Rozdel(var nv:TItRadek;pozice,vypust:longint);
{Do POZICE-1 zustanou znaky v SELF, od POZICE v <NV>}
{POZOR - neresi typ zakonceni (neresi promennou CRLF)}
begin
nv.VlozKusIT(@self,1,pozice+vypust,up-pozice-vypust+1);
Ochrana_obrazku:=true;      {Opatreni, aby TfnAtrb.Done nevymazal z pameti}
Vyjmi(pozice,up-pozice+1);  {obrazek. My ho totiz nechceme smazat, ale jen}
Ochrana_obrazku:=false;     {presunout do jineho TItRadku.}
end;

Procedure TItRadek.Rozdel(var nv:TItRadek;pozice:longint);
begin
Rozdel(nv,pozice,0);
end;

Procedure TItRadek.Rozdel(var nv:PItRadek;pozice:longint);
begin
nv:=Init_PItRadek(false);
Rozdel(nv^,pozice,0);
end;


Function TItRadek.Modifikuj_uzel_barvu(i:longint;ibarva:word):boolean;
{Kdyz je I v platnem rozsahu, tak vrati TRUE, kdyz v neplatnem, tak si ho
 upravi a vrati FALSE}
var n:longint;
    a:Pfnatrb;
    b:boolean;
begin
if aa=nil then Exit(false);
b:=true;
n:=PocetUzlu;
if i>n then begin i:=n;b:=false;end;
if i<1 then begin i:=1;b:=false;end;
a:=aa^.Uzel(i)^.vazba;
if a<>nil then  {nikdy by nemelo byt NIL}
   a^.barva:=ibarva;
Modifikuj_uzel_barvu:=b;
end;


Function TItRadek.Prozkoumej_uzel_barvu(i:longint):word;
var n:longint;
    a:pfnatrb;
    w:word;
begin
if aa=nil then Exit(0);
n:=PocetUzlu;
if i>n then i:=n;
if i<1 then i:=1;
a:=aa^.Uzel(i)^.vazba;
if a<>nil {nikdy by nemelo byt NIL}
   then w:=a^.barva
   else w:=0;
Prozkoumej_uzel_barvu:=w;
end;



Function TItRadek.Modifikuj_uzel_font(i:longint;s:string):boolean;
{Kdyz je I v platnem rozsahu, tak vrati TRUE, kdyz v neplatnem, tak si ho
 upravi a vrati FALSE}
var n:longint;
    a:Pfnatrb;
    b:boolean;

begin
if aa=nil then Exit(false);
b:=true;
n:=PocetUzlu;
if i>n then begin i:=n;b:=false;end;
if i<1 then begin i:=1;b:=false;end;
a:=aa^.Uzel(i)^.vazba;
if a<>nil then  {nikdy by nemelo byt NIL}
   a^.font:=Nacti_FNSLR(s);
Modifikuj_uzel_font:=b;
end;


Function TItRadek.Prozkoumej_uzel_Extra(i:longint):string;
var n:longint;
    a:pfnatrb;
    s:string;
begin
if aa=nil then Exit('');
n:=PocetUzlu;
if i>n then i:=n;
if i<1 then i:=1;
a:=aa^.Uzel(i)^.vazba;
if a<>nil {nikdy by nemelo byt NIL}
   then begin
   if a^.extra=nil then Exit('');
   Prozkoumej_uzel_Extra:=a^.extra^;
   end
   else Prozkoumej_uzel_Extra:='';
end;



Function TItRadek.Modifikuj_uzel_Extra(i:longint;s:string):boolean;
var n:longint;
    a:pfnatrb;
begin
if aa=nil then Exit(false);
n:=PocetUzlu;
if i>n then i:=n;
if i<1 then i:=1;

a:=aa^.Uzel(i)^.vazba;
if a<>nil {nikdy by nemelo byt NIL}
   then begin
   if a^.extra<>nil then ZrusPstring(a^.extra);
   a^.extra:=NaPstring(s);
   Exit(true);
   end
   else Exit(false);
end;


Function TItRadek.Prozkoumej_uzel_font(i:longint):string;
var n:longint;
    a:pfnatrb;
    s:string;
begin
if aa=nil then Exit('');
n:=PocetUzlu;
if i>n then i:=n;
if i<1 then i:=1;
a:=aa^.Uzel(i)^.vazba;
if a<>nil {nikdy by nemelo byt NIL}
   then s:=FNSLR_dej_ID(a^.font)
   else s:='';
Prozkoumej_uzel_font:=s;
end;


Procedure TItRadek.PodtrzeniTextu(b:boolean);
{B=true ->  podtrhne text
 B=false -> zlikviduje pripadne podtrzeni textu}
var v:PfnAtrb;
begin
if aa=nil then Exit;
aa^.reset;
while not aa^.konec do
   begin
   v:=aa^.nacti;
   if B=true then v^.modifikace:=v^.modifikace or 1
             else v^.modifikace:=v^.modifikace and 254
   end;
end;



Procedure Priprav_inverzni_tabulku_unicode_ascii(p:putf8conv);
begin
{todo - nachystani globalni promenne}
if p<>global_inv_unitbl_posl_predloha then
   begin
   pUTF8conv_to_pUTFconvinv(p,@global_inv_unitbl);
   global_inv_unitbl_posl_predloha:=p;
   end;
end;


Procedure TItRadek.Na_Mala_pismena(prevodni_tabulka:pointer);
{<prevodni_tabulka> nemuze byt <pointer> ale <pUTF8conv>
 Procedure pracuje tak, ze non-unicode text prevede na unicode, pak
 pomoci univerzelni unicode tabulky provede konverzi na mala pismena a
 pak text vrati zpet do non-unicode podoby.
 Pokud vstupni text byl unicode, tak zadne prevody ASCII<>unicode neprovadi}
   Procedure Preved_Usek_Na_mala_pismena(odk,kam:longint;unic:boolean;unitbl:putf8conv);
   var j:longint;
       o,o2,ou,oa:word;
       err:boolean;
   begin
   if unic=true then
      begin
      for j:=odk to kam do
          begin
          o:=Znak(j);
          o2:=Uni_Convert_up_or_down(UNI_velke_na_male,o);
          NahradWord(o2,j);
          end;
      end
      else begin
      for j:=odk to kam do
          begin
          o:=Znak(j);
          ou:=Preklad_ascii_2_unicode(o,unitbl); {prevod ASCII->unicode}
          o2:=Uni_Convert_up_or_down(UNI_velke_na_male,ou); {na male}

          if NORMAL_NAMALA_PISMENA_MODE {norm. mod: prevod zpet unicode->ascii}
             then oa:=Preklad_unicode_2_ascii(o2,unitbl,
                                              @global_inv_unitbl,
                                              err)  {unicode->ASCII}
             else  {nebo alter. mod - zustane v unicode}
             begin oa:=o2;err:=false;end;

          if err=true then oa:=o;
          NahradWord(oa,j);
          end;
      end;
   end;

var i:longint;
    uni:boolean;
    a1,a2:PUzel;
    atr1,atr2:PFNAtrb;
    u1,u2:longint;

begin
if delka=0 then Exit;

if (NORMAL_NAMALA_PISMENA_MODE=true) and (VYNUT_UNICODE=false)
   then Priprav_inverzni_tabulku_unicode_ascii(prevodni_tabulka);

if aa=nil then Preved_Usek_Na_mala_pismena(1,delka,false,nil)
   else begin
   a1:=aa^.first;
   repeat
      a2:=a1^.dalsi;
      atr1:=a1^.vazba;
      if a2=nil then atr2:=nil else atr2:=a2^.vazba;
      u1:=atr1^.pozice;
      if u1>delka then Break; {muze se stat, kdyz je za retezcem jeste uzel}
      if atr2=nil then u2:=delka else u2:=atr2^.pozice-1;
      uni:=VYNUT_UNICODE or atr1^.je_unicode_font;
      Preved_Usek_Na_mala_pismena(u1,u2,uni,prevodni_tabulka);
      a1:=a2;
   until a1=nil;
   end;
Prepocitej_gd;
end;


Procedure TItRadek.Na_Velka_pismena(prevodni_tabulka:pointer);
   Procedure Preved_Usek_Na_velka_pismena(odk,kam:longint;unic:boolean;unitbl:putf8conv);
   var j:longint;
       o,o2,ou,oa:word;
       err:boolean;
   begin
   if unic=true then
      begin
      for j:=odk to kam do
          begin
          o:=Znak(j);
          o2:=Uni_Convert_up_or_down(UNI_male_na_velke,o);
          NahradWord(o2,j);
          end;
      end
      else begin
      for j:=odk to kam do
          begin
          o:=Znak(j);
          ou:=Preklad_ascii_2_unicode(o,unitbl); {prevod ASCII->unicode}
          o2:=Uni_Convert_up_or_down(UNI_male_na_velke,ou); {na velke}

          if NORMAL_NAVELKA_PISMENA_MODE {norm. mod: prevod zpet unicode->ascii}
             then oa:=Preklad_unicode_2_ascii(o2,unitbl,
                                              @global_inv_unitbl,
                                              err)  {unicode->ASCII}
             else    {nebo alter. mod - zustane v unicode}
             begin oa:=o2;err:=false;end;
          if err=true then oa:=o;
          NahradWord(oa,j);
          end;
      end;
   end;

var i:longint;
    uni:boolean;
    a1,a2:PUzel;
    atr1,atr2:PFNAtrb;
    u1,u2:longint;

begin
if delka=0 then Exit;

if (NORMAL_NAMALA_PISMENA_MODE=true) and (VYNUT_UNICODE=false)
   then Priprav_inverzni_tabulku_unicode_ascii(prevodni_tabulka);

if aa=nil then Preved_Usek_Na_velka_pismena(1,delka,false,nil)
   else begin
   a1:=aa^.first;
   repeat
      a2:=a1^.dalsi;
      atr1:=a1^.vazba;
      if a2=nil then atr2:=nil else atr2:=a2^.vazba;
      u1:=atr1^.pozice;
      if u1>delka then Break; {muze se stat, kdyz je za retezcem jeste uzel}
      if atr2=nil then u2:=delka else u2:=atr2^.pozice-1;
      uni:=VYNUT_UNICODE or atr1^.je_unicode_font;
      Preved_Usek_Na_velka_pismena(u1,u2,uni,prevodni_tabulka);
      a1:=a2;
   until a1=nil;
   end;
Prepocitej_gd;
end;


Function TItRadek.Copy_and_to_unicode_and_lowcase(prevodni_tabulka:pointer):PItRadek;
var n:PItRadek;
    b:boolean;
begin
n:=self.Copy;
b:=NORMAL_NAMALA_PISMENA_MODE;
NORMAL_NAMALA_PISMENA_MODE:=false;
n^.Na_mala_pismena(prevodni_tabulka);
Copy_and_to_unicode_and_lowcase:=n;
NORMAL_NAMALA_PISMENA_MODE:=b;
end;


Procedure TItRadek.Na_Unicode(odk,kam:longint;prevodni_tabulka:pointer);
var pt:putf8conv;
    j:longint;
    o,o2:word;
begin
pt:=prevodni_tabulka;
if pt=nil then Exit;
for j:=odk to kam do
       begin
       o:=Znak(j);
       o2:=Preklad_ascii_2_unicode(o,pt); {prevod ASCII->unicode}
       NahradWord(o2,j);
       end;
end;


Procedure TItRadek.Z_Unicode(odk,kam:longint;prevodni_tabulka,inverzni_prevodni_tabulka:pointer);
var pt:putf8conv;
    ipt:putf8convinv;
    j:longint;
    o,o2:word;
    err:boolean;
begin
pt:=prevodni_tabulka;
ipt:=inverzni_prevodni_tabulka;
if pt=nil then Exit;
for j:=odk to kam do
       begin
       o:=Znak(j);
       o2:=Preklad_unicode_2_ascii(o,pt,ipt,err);
       {Prevod Unicode -> ASCII}
       NahradWord(o2,j);
       end;
end;



Function TItRadek.Copy_and_to_unicode(prevodni_tabulka:pointer):PItRadek;
var n:PItRadek;
    a1,a2:PUzel;
    atr1,atr2:PFNAtrb;
    u1,u2:longint;
    uni:boolean;
begin
n:=self.Copy;
if prevodni_tabulka<>nil then
   if up>0 then
      begin
      if n^.aa=nil then n^.Na_Unicode(1,delka,prevodni_tabulka)
         else begin
         a1:=n^.aa^.first;
         repeat
            a2:=a1^.dalsi;
            atr1:=a1^.vazba;
            if a2=nil then atr2:=nil else atr2:=a2^.vazba;
            u1:=atr1^.pozice;
            if u1>n^.delka then Break; {muze se stat, kdyz je za retezcem jeste uzel}
            if atr2=nil then u2:=n^.delka else u2:=atr2^.pozice-1;
            uni:=atr1^.je_unicode_font;
            if not uni then n^.Na_Unicode(u1,u2,prevodni_tabulka);
            a1:=a2;
         until a1=nil;
         end;
      end;
Copy_and_to_unicode:=n;
end;


Function TItRadek.Copy_and_from_unicode(prevodni_tabulka,inverzni_prevodni_tabulka:pointer):PItRadek;
var n:PItRadek;
    a1,a2:PUzel;
    atr1,atr2:PFNAtrb;
    u1,u2:longint;
    uni,invnil:boolean;
begin
invnil:=false;
n:=self.Copy;
if prevodni_tabulka<>nil then
   if up>0 then
      begin
      if inverzni_prevodni_tabulka=nil then
         begin
         invnil:=true;
         New(putf8convinv(inverzni_prevodni_tabulka));
         pUTF8conv_to_pUTFconvinv(prevodni_tabulka,inverzni_prevodni_tabulka);
         end;

      if n^.aa=nil then n^.Z_Unicode(1,delka,prevodni_tabulka,inverzni_prevodni_tabulka)
         else begin
         a1:=n^.aa^.first;
         repeat
            a2:=a1^.dalsi;
            atr1:=a1^.vazba;
            if a2=nil then atr2:=nil else atr2:=a2^.vazba;
            u1:=atr1^.pozice;
            if u1>n^.delka then Break; {muze se stat, kdyz je za retezcem jeste uzel}
            if atr2=nil then u2:=n^.delka else u2:=atr2^.pozice-1;
            uni:=atr1^.je_unicode_font;
            if uni then n^.Z_Unicode(u1,u2,prevodni_tabulka,inverzni_prevodni_tabulka);
            a1:=a2;
         until a1=nil;
         end;
      end;
if invnil=true then Dispose(putf8convinv(inverzni_prevodni_tabulka));
Copy_and_from_unicode:=n;
end;


Function TItRadek.NajdiPodretezec(text:PItRadek;odkud:longint):longint;
var i,a,b:longint;
    h:boolean;
begin
i:=text^.up;            {delka podretezce}
if up<i then Exit(0);   {jsme kratsi nez hledany rezetec?}
if i=0 then Exit(0);    {hledany retezec je prazdny?}
if (odkud<1) then Exit(0);  {chybny parametr odkud?}

for a:=odkud to up-i+1 do
    begin
    h:=true;
    for b:=1 to i do
        if text^.Znak(b)<>Znak(a+b-1) then begin h:=false;Break;end;
    if H then Exit(a);
    end;
NajdiPodretezec:=0;
end;


Function TItRadek.NajdiNedefinovanyZnak(odkud:longint;var jaky:longint):longint;
var a,dp:longint;
    r,q:PUzel;
    b:PFNatrb;
    f:pfont;
    w:word;
begin
jaky:=-1;
if (odkud<1) then Exit(0);  {chybny parametr odkud?}
if aa=nil then Exit(0);  {pokud nejsou atributove uzly, tak chybi info o fontu...}

r:=VratUkazatelNaUzel(odkud);
b:=r^.vazba;
f:=b^.font;     {s jakym fontem se pracuje na pozici ODKUD?}

q:=r^.dalsi;
if q<>nil then dp:=PFNatrb(q^.vazba)^.pozice {a kde bude pristi zmena atributu?}
          else dp:=-1;      {...a nebo se uz menit nebude}

for a:=odkud to up do    {...a tedy o definovanych a nedefinovanych znacich}
    begin
    if a=dp then
       begin
       b:=q^.vazba;
       f:=b^.font;
       q:=q^.dalsi;
       if q<>nil then dp:=PFNatrb(q^.vazba)^.pozice {a dalsi zmena?}
          else dp:=-1;      {...nebo uz nic?}
       end;

    w:=Znak(a);
    if Nedef_bitmapa_znaku(f,w) and (w<>32 {mezera}) then
       begin
       jaky:=w;
       Exit(a);
       end;
    end;
NajdiNedefinovanyZnak:=0;
end;


Destructor TItRadek.Done;
begin
Kill_Vaznik_Uzlu(aa);
inherited Done;
end;


Procedure Kill_Vaznik_Uzlu(var aa:PVaznik);
begin
if aa<>nil then
   begin
   Vaznik_Done_all(aa,@Kill_pfnatrb);
   aa:=nil;
   end;
end;


Function Init_PEdRadek:PEdRadek;
begin
Init_PEdRadek:=New(PEdRadek,Init);
end;


Function Init_PEdRadek(s:string):PEdRadek;
var e:PedRadek;
begin
e:=Init_PEdRadek();  {pozor, ty prazdne zavorky jsou nutne, jinak...}
                        {...FPC nepochopi nas overloading}
e^.VlozS(s,1);
Init_PEdRadek:=e;
end;


Function Init_PEdRadek(p:pchar):PEdRadek;
var e:PedRadek;
begin
e:=Init_PEdRadek();  {pozor, ty prazdne zavorky jsou nutne, jinak...}
                        {...FPC nepochopi nas overloading}
e^.Vloz(p,1);
Init_PEdRadek:=e;
end;


Function Init_PItRadek(tagy:boolean):PItRadek;
var i:PItRadek;
begin
i:=New(PItRadek,Init);
Init_PItRadek:=i;
if tagy=true then i^.PrvniUzel;
end;


Function Init_PItRadek:PItRadek;
begin
Init_PItRadek(false);
end;


Function Init_PItRadek(s:string;tagy:boolean):PItRadek;
var i:PItRadek;
begin

if tagy=true then
   begin
   s:=s+#0;
   Exit(Tagy_Na_Vaznik(@s[1],nil))
   end
   else begin
   i:=Init_PItRadek();  {pozor, ty prazdne zavorky jsou nutne, jinak...}
                        {...FPC nepochopi nas overloading}
   i^.VlozS(s,1);
   end;
Init_PItRadek:=i;
end;


Function Init_PItRadek(s:string):PItRadek;
begin
Init_PItRadek:=Init_PItRadek(s,true);
end;


Function Init_PItRadek_prealloc(znaku:longint;tagy:boolean):PItRadek;
{Vytvori novy PItRadek a prealokuje do nej prostor, ktery pak muzeme bodove
 modifikovat pomoci metody NahradWord}
var i,j:PItRadek;
begin
i:=Init_PItRadek(tagy);
if znaku*2>i^.pp then
   begin
   FreeMem(i^.p);
   i^.pp:=(((znaku*2)+1) div ED_GRANULARITA+1)*ED_GRANULARITA;
   GetMem(i^.p,i^.pp);
   end;
i^.spp:=znaku*2+1;
i^.up:=znaku;
Init_PItRadek_prealloc:=i;
end;


Procedure Kill_PEdRadek(var e:PEdRadek);
begin
if e<>nil then
   begin
   Dispose(e,Done);
   e:=nil;
   end;
end;

Procedure Kill_PItRadek(var e:PItRadek);
begin
if e<>nil then
   begin
   Dispose(e,Done);
   e:=nil;
   end;
end;


Function Vaznik_z_PItRadky(v:PItRadek):PVaznik;
var p:PVaznik;
begin
p:=NovyVaznik;
p^.InitNext(v);
Vaznik_z_PItRadky:=p;
end;

end.

