(* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *)
(*  Jenotka pro graficke uzivatelske rozhrani: WOKNA-32                    *)
(*  Obsah: soubor objektu, funkci a procedur tvorici kompletni, snadno     *)
(*         pouzitelne graficke uzivatelske rozhrani                        *)
(*         Pracuje v 16ti bitovych grafickych rezimech                     *)
(*  Autori: Laaca(laaca@seznam.cz) & Mircosoft                             *)
(*     Dale je v baliku prilozena sada utilit pro FN fonty od D.menta      *)
(*  Posledni uprava: 27.7.2012                                             *)
(*  Pro kompilaci: WOKNA32.INC, DEFINES.INC, VENOMGFX.PAS, FNFONT2.PAS,    *)
(*                 FNFONT2.PAS, VAZNIK.PAS, LACRT.PAS, DISKY, (DOS.PPU)    *)
(*                 LACRT_VM.INC, LACRT_MV.INC, VENOMGIF.INC, VENOMPNG.GIF  *)
(*                 TEDRADKY.PAS a v release mode jeste knihovna PasJPEG    *)
(*  Pro spusteni: nic (Omnia mea mecum porto)                              *)
(*                ovsem je mozne pouzivat vlastni obrazky, fonty a         *)
(*                prekladove tabulky kodu klavesnice                       *)
(*  Upozorneni: tyto zdrojove kody pouzivate na vlastni nebezpeci          *)
(*      Tato jednotka a pouzite podjednotky smi byt sireny pouze pod       *)
(*      podminkami GNU/GPL                                                 *)
(* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *)

{
==========-------HISTORIE:--=========================================
+ nova funkce
- oprava chyby
* zmena
x ostraneni funkce

1.73
     * prepsan a snad vylepsen objekt TVWokno

1.72
     * odstranena zavislost na stare procedure PutChar_FN, tzn. ted pouziva
       novou proceduru na vystup znaku

1.71
     * adaptovano na zmeny ve VenomGFX

1.70 * predelan a vylepsen cely system hlasek a textu
     * oddelovac radek uz neni znak '|' ale klasicky #13#10
     + funkce Fileselector, ktera umoznuje vyber vice nez jednoho souboru
     + Listboxy take umoznuji vyber vice polozek
     + funkce DvojlistBox
     * objekt TEdRadek odsunut do samostatne jednotky TEdRadky
     * Blocek 1.33
     x zrusena funkce nabidka

1.62 - opraveno dost chyb
     * adaptovano na zmeny ve VenomGFX
     * Blocek 1.32
     + pridan editor unicode fontu Kasmar
     + pridan tag PODTRH
     * jednotka FNfont2 prekopana, aby pracovala primarne s PChary

1.61 * Infokno zcela predelano
     + objekt TLista
     + nekolik novych vymozenosti u tlacitek

1.60 * vetsina objektu ted ma spolecneho predka
     x zrusen objekt CiselnaOsa
     * do VenomGFX pridany nektere procedury a nekolik nesmyslnych odebrano
     + objekty se daji retezit
     *- mnoho vnitrnich zmen a oprav zejmena v tPrepinac a TextovePole
     * prepsany procedury AnoNeOkno a OKokno. Ted jsou mnohem pruznejsi.
     * posuvniky ted funguji jako ve windows
     + ctecky obrazku overuji format dat
     * Blocek v1.3c

1.54 + ctecka formatu PNG
     + VenomGFX umi zobrazovat mys v bankovych rezimech
     + PutSpriteRegion ve VenomGFX
     + do VyberSouborOkno je mozne zadat dve skupiny zvlast znacenych pripon
     * ruzne upravy objektu VWokno

1.53 * predelana textova pole. Ted umi skrolovat a tim padem muzes zadat text
       delsi nez okenko.
     * u textovych poli se nyni sirka zadava v pixelech a nikoliv ve znacich
     - vodorovne posuvniky byly nekdy nepresne
     - za nekterych podminek kurzor mysi nechaval smouhy
     + funkce NamixujBarvu a jeji propojeni s VyberHicolorBarvuOkno
     + tag POZADI
     * objekt TStrom/PStrom z jednotky Vaznik je vylepsen o promennou SKOK
     * Blocek v1.1.2

1.52 + ctecka formatu GIF
     * pridan druhy unicode font a vyrazne redukovana velikost unicode formatu
     * FN fonty se udrzuji v pameti v komprimovane podobe (stejne jako unicode)
     * vylepsen system aktivnich klaves (provadi se pomoci tagu KLAVESY v popisu tlacitka)
     - opraveno nekolik malych chyb u editacnich poli

1.51 - ve VyberSouborOkno prezivala zradna chyba
     - opraveno ukladani obrazku BMP
     + pridana moznost nacitani 8 bitovych BMP
     + definitivne vyreseno zpracovavani fontu z VGA generatoru (8x16,8x14,8x8)
     + objekt TSeznam
     + priklad Sedemo
     * dalsi zmeny v Tlacitko2
     + automaticke zalamovani radek v editacnich polich
     + autodetekce textu v unicode
     + Menustav umi exportovat vytvorena menu do pascalovskeho zapisu
     * Blocek v1.1

1.44 + Textove pole umi unicode
     * prilozene fonty jsou v kodovani Latin2
     + blikajici kurzor
     + VyberSouborOkno zna klavesu TAB
     * predelana a vylepsena jednotka Konfig
     + umoznen zapis souradnic ve formatu NA_STRED +- hodnota
       (vystredeni objektu do centra +- odchylka hodnota)
     * zmeny v procedurach VyberBarvuOkno a VyberHicolorBarvuOkno
     * prekopano Tlacitko2 a Posuvnik (zase)
     * drobne upravy VyberSouborOkno
     + textova direktiva SKOK
     + podpora obrazu VGA fontu (mivaji koncovku .CH) v rozliseni 8x8
     + EditacniPole obsahuje vertikalni posuvnik
     * Blocek v1.0.3

1.43 - odstranena chybicka klaves PageUP a PageDown u Listboxu
     - EditacniPole.UlozDoStreamu divne ukladalo konce radek
     * mala zmena vykreslovani tlacitek
     * malinka zmena vykreslovani zatrzitek
     + lepsi podpora unicode
     + Blocek v1.0

1.42 - znak '<' matl Textove pole
     + podpora kodovani unicode UTF-8
     + Blocek castecne podporuje unicode texty
     + ListBox umoznuje definovat uzivatelskou reakci na stisk praveho mysitka
     + funkce ListBox_retezcovy (viz LBdemo)
     + podpora lokalizace do jinych jazyku (zatim je hotova cestina,
       anglictina a rustina)
     - TDialog nepredaval defaultni text
     + objekt TVWokno a nadstavova procedura VWOkno
     + demicka LBdemo a VWdemo
     - nekolik chybek u editacnich poli

1.4  - opraveno nekolik chybek u Editacnich poli
     + pridan ListBox (scrolovaci menu)
     + totalne predelan a znacne vylepsen fileselector
     + nove funkce a opravy chyb v editoru Blocek
     - opraveno nekolik zavaznych chyb v jednotce Vaznik
     * zcela predelan posuvnik (take se i jinak pouziva)

1.3  * prepsan objekt Tlacitko2
     + objekt EditacniPole
     + pridan priklad na EditacniPole BLOCEK.PAS
     + moznost zmeny kurzoru mysi
     + v duchu hesla "Omnia mea mecum porto" pridan do kodu kurzor presypaci hodiny
     + wokna32 lze pouzivat i v prekladaci FPC 2.0.0 a novejsich
     * procistena jednotka FnFont2
     * trosicku pozmeneno prvni demo
     * uz nepotrebuje soubor OBRAZKY.PAS
     - D.mentova utilita FNED uz pri kliknuti ceka na uvolneni mysitka
     - opraveny male chybky ve vybernicku

1.22 - _box se nyni radne vykresli, i kdyz je uzsi nez 3 pixely
       (kvuli tomuto se hroutil fileselector u adresaru s velmi mnoha soubory)
     + VyberHicolorBarvuOkno lze ukoncit stiskem Enteru ci Escape
     - soubory s malymi pismeny na zacatku uz nejsou zarazovany na konec
     * velmi urychleno trideni (nova metoda TVaznik.Setrid)
     * velke zmeny kodu u VyberSouborOkno a procedur z jednotky Disk

1.21 - opravena chyba pri cteni obrazku BMP a JPG s lichou sirkou
     - jeste jedna chybka v Textovepole.kontrola
     * na trech mistech vylepsen kod

1.2  * O zobrazovani mysi se stara callback. Neni potreba volat MousePoll
     - oprava metody Dialog.Zobraz
     - textovepole.kontrola
     + objekt Vybernicek pro stromova menu
     + pridan podpurny program Menustav
     + pridan novy tag <VYSKA> (viz FN_FONT2.PAS)
     - oprava chyby u tagu <SF>
     + pridana sada utilit na FN fonty od D.menta


1.1  + Orezavani pri psani
     * Zmeneny kody pro zmeny fontu(a barvy a podobne) za letu. Nyni se
       podobaji HTML


1.0    Zakladni verze
}


unit Wokna32;
{$INCLUDE defines.inc}
{$I-,B-,R-}
interface
uses
objects,   {I/O operace}
venomgfx,  {graficka knihovna. stara se i o mys}
fnfont2,   {funkce ohledne psani a fontu}
ovaznik,   {vazane linearni seznamy a stromy}
tedradky,  {objekt TEdRadek}
Lacrt;     {ruzne pomocne funkce}

var
{barvy: (lze bez obav menit, ale pozor, aby se pak treba nepsalo bile na bile)}
tlhbarva,        {barva leveho a horniho okraje tlacitek}
tpdbarva,        {barva praveho a dolniho okraje tlacitek}
tvbarva,         {barva vnitrku tlacitek}
txtbarva,        {barva textu, kterym se pise v oknech a na tlacitkach (tj. obvykle cerna na sede)}
ttxtbarva,       {barva textu na tlacitkach}
ttxtextra1barva,  {barva textu zvlast duleziteho}
ttxtextra2barva,  {barva jineho textu zvlast duleziteho}
txtpolevbarva,   {barva textovych poli, zatrzitek a prepinacu}
txtpoleinvbarva, {barva textovychpole, pokud jsou oznacena}

txtpolelhbarva,  {barva leveho a horniho okraje textovych poli}
txtpolepdbarva,  {barva praveho a dolniho okraje textovych poli}
txtpoletbarva,   {barva textu v textovych polich, zatrzitek a puntiku}
txttextinvbarva, {barva textu v textovych polich, pokud je oznacen}
olhbarva,        {barva leveho a horniho okraje oken}
opdbarva,        {barva praveho a dolniho okraje oken}
ovbarva,         {barva vnitrku oken}
oobdbarva,       {barva prouzku pod nadpisem okna (obvykle modra)}
obarvanadpisu,   {barva nadpisu okna}
iolhbarva,       {barva leveho a horniho okraje pro proceduru Infokno}
iopdbarva,       {barva praveho a dolniho okraje pro proceduru Infokno}
iovbarva,        {barva vnitrku Infokna}
iobarvatextu,    {barva textu v Infokne}
posbarva,        {barva stredni casti posuvniku}
ramobrbarva,           {ramecek ohranicujici obrazek}
vedleobrbarva:word;    {okoli obrazku}

lboznbarva,      {oznacena polozka v Listboxu}
lbmultioznbarva, {polozky Listboxu oznacene insertem pri multivyberu}
mlhbarva,        {levy a horni okraj okna menu}
mpdbarva,        {pravy a dolni okraj}
mvbarva,         {vypln okna menu}
mtxtbarva,       {barva textu nad tlacitky}
minlhbarva,      {levy a horni okraj neaktivnich tlacitek}
minpdbarva,      {pravy a dolni okraj neaktivnich tlacitek}
minvbarva,       {vypln neaktivnich tlacitek}
mintxtbarva,     {barva textu v neaktivnich tlacitkach}
mialhbarva,      {levy a horni okraj aktivnich tlacitek}
miapdbarva,      {pravy a dolni okraj aktivnich tlacitek}
miavbarva,       {vypln aktivnich tlacitek}
miatxtbarva,     {barva textu v aktivnich tlacitkach}
mislhbarva,      {levy a horni okraj stisknutych tlacitek}
mispdbarva,      {pravy a dolni okraj stisknutych tlacitek}
misvbarva,       {vypln stisknutych tlacitek}
mistxtbarva:word;{barva textu ve stisknutych tlacitkach}

WhatAboutMouse:procedure; {pokud chces delat s mysi neco, co neobsluhuje callback}
                          {defaultne prazdna proc. (o vsechno se stara callback)}
Lsipka_obrazek,
Psipka_obrazek,
Hsipka_obrazek,
Dsipka_obrazek:VirtualWindow; {budou pouzity na posuvniky}

const dbg:boolean=false;
type
Point2StrFunc = Function(p:pointer):string;
VaznikProc    = Procedure(p:PVaznik);

(************************ objektove ovladaci prvky: *************************)
{Vsechny funguji skoro stejne:
 Inicializace: Init(...); a spol. Priradi se pocatecni hodnoty a cele zarizeni
 se vykresli(o pripadne vypnuti kurzoru se postara, na konci ho necha zapnuty).
 Ovladaci prvek se vzdy musi vejit na obrazovku, na vycuhovani neni staveny!
Souradnice x,y znamenaji obvykle neco kolem leveho horniho rohu.
 Opetovne zobrazeni: metoda Zobraz;.
 Cteni stavu: primo z polozky Hodnota (u tlacitek take pres funkci Klik, ktera
po skonceni Hodnotu vynuluje, aby bylo tlacitko pouzitelne i v dalsim cyklu).
 Zruseni: destruktorem Done;
 Pokud nejake rozmery zavisi na rozmerech textu, prizpusobi se mu vzdy v
okamziku zobrazeni. Nastaveni velikosti fontu je tedy libovolne.}

(********************** pokrocila sprava ovladacich prvku *******************)
{Prvky vychazejici z TWoknaZaklad se mozne "retezit" a pro cely retez vykonat
nekterou z podporovanych operaci. Wokna uz zajisti, aby danou funkci vykonaly
vsechny objekty v retezu. Retezit muzes pomoci funkci
SVAZEJ a UZEL z VAZNIK.PAS

Priklad:
var Tlacidla:PVaznik;
begin
Tlacidla:=Svazej(
          Uzel(New(PTlacitko,Init(10,10,'prvni','',100,2)),
          Uzel(New(PTlacitko,Init(10,30,'druhe','',100,2)),
          Uzel(New(PTlacitko,Init(10,50,'treti','',100,2)),
          Uzel(New(PTlacitko,Init(10,70,'ctvrte','',100,2)),nil))))
                );
repeat
Vse_Kontrola(Tlacidla);
until Vse_zda_aktivni(Tlacidla)<>nil;
Vse_zlikviduj(Tlacidla);
}

const PLUS_K_TLACITKU = 6;

{Konstanty pro promennou STAV-------------------------------------------}
      _Neaktivni=0; {chova se inertne, nic nedela, kurzor neni videt}
      _Enterem=1;   {byl stisknut enter, pole je ted neaktivni}
      _Aktivni=2;   {kurzor je videt, lze psat}
      _Escapem=3;   {byl stisknut escape, pole je aktivni, cely text je oznacen}
      _Odkliknutim=4; {bylo kliknuto mimo pole pole je neaktivni}
      _Tabulatorem=5; {byl stisknut tabulator, pole je neaktivni}
      _Aktivace=6;    {prechodny stav. Pouziva se interne pri prepnuti tabulatorem}
      _Deaktivace=7;  {dtto}

      _Uvolnene=0;  {plati pro tlacitka}
      _Stiskle=1;   {tedy pro Tlacitko i Tlacitko2}
      _ExtraAkce=8; {pokud je na tlacitku zmackle leve i prave mysitko zaroven}
type
PWoknaZaklad = ^TWoknaZaklad;
TWoknaZaklad = object
           x,y:longint;         {pozice leveho horniho rohu}
           xm,ym:longint;       {pozice posledniho klepnuti mysi}
           sirka,vyska:longint;
           mys_uvnitr:boolean;
           mys_klikla_uvnitr:boolean;
           stav:byte;     {jestli je aktivni, neaktivni,... Ne vzdy vyuzito}
           hlavni_font,ofn:string[12];
           automys:boolean;
           Constructor Init;           {jedine co udela, zaznamena aktualni font}
           procedure kontrola;virtual; {abstraktni metoda - potomci si ji predefinuji}
           procedure zobraz;virtual;   {abstraktni metoda - zobrazi objekt}
           function MysZde:boolean;    {testuje, je-li mys v aktivni oblasti}
           procedure ufon;             {ofn:=FN_default;NastavFont(hlavni_font)}
           procedure ofon;             {NastavFont(ofn)}
           Destructor Done;virtual;
           end;

Function Vse_zda_aktivni(p:PVaznik):PVaznik;
{ve vazbach P jsou objekty vychazejici z TWoknaZaklad. Jestlize je u nektereho
STAV roven _aktivni, vrati odkaz na dany PVaznik. Jinak vrati nil.}
Function Vse_kontrola(p:PVaznik):Pvaznik;
{Pro vsechny objekty zavola proceduru Kontrola}
Procedure Vse_Zobraz(p:PVaznik);
{Vykresli vsechny objekty ve vazniku}
Procedure Vse_zlikviduj(var p:PVaznik);
{Zlikviduje vsechny navazane objekty pomoci destructoru Done a pak zlikviduje
i vaznik}

type
PTlacitko = ^Tlacitko;
Tlacitko = object(TWoknaZaklad)
           vyska_textu,
           stextu,
           pridavek:word;{vyska tlacitka je urcena vyskou textu plus Pridavek nad nim a pod nim}
           napis:string[60];{napis na tlacitku}
           popis:string;{zobrazi se v okenku po kliknuti pravym mysitkem. Kdyz je '', da se pravym mysitkem normalne kliknout.}
           hodnota:byte;{cim bylo kliknuto: 0 - nic, 1,2,4 - l.,p.,str. mysitko. Uchovava se do nejblizsiho zavolani metod
                         Kontrola (ta ji nastavi podle aktualni situace) nebo Klik (ta ji vynuluje).}
                        {DULEZITE: HODNOTA se kopituje do i promenne STAV}
           Aklavesy:string[5];     {seznam horkych klaves, ktere mohou aktivovat tlacitko}
           neviditelny:boolean;
           constructor init(ix,iy:integer;inapis,ipopis:string;_sirka,ipridavek:longint);
           procedure zobraz;virtual;
           procedure kontrola;virtual;
           function klik:byte;{vraci cislo tlacitka mysi, kterym bylo stisknuto, jestli bylo. Pak vynuluje Hodnotu.}
           destructor done;virtual;
           end;
{klasicke tlacitko s textem. Funkci Kontrola je potreba volat v cyklu po
Cekej (pri automaticke obsluze mysi neni cekani na klik nutne), vyhodnoceni
stavu bud pres Klik nebo Hodnotu. Pokud zadate _SIRKA=0, je sirka tlacitka
urcena rozmery napisu. V opacnem pripade je sirka rovna parametru _SIRKA.
Ipridavek = o kolik zvetsit tlacitko oproti vypocitane vysce a sirce
Pokud potrebujete, aby tlacitko nejak zpracovalo i klik pravym mysitkem, dejte
Popis='', jinak se v takovem pripade ten popis jen zobrazi a kliknuti bude
ignorovano.}

PTlacitko2 = ^Tlacitko2;
Tlacitko2 = object(TWoknaZaklad)
            hodnota:byte; {DULEZITE: HODNOTA se kopituje do i promenne STAV}
            popis:string;
            obr1,obr2:Pvirtualwindow;{obr1 pro norm. zobr., obr2 pro stisknute}
            pruhledne:boolean;
            barva_pruhlednosti:word;
            nepotrebny:boolean;
            neviditelny:boolean;
            Constructor init(ix,iy:integer;ipopis:string;o1,o2:PVirtualwindow;prbarva:word);
            Constructor init(ix,iy:integer;ipopis,o1,o2:string);
            procedure zobraz;virtual;
            procedure kontrola;virtual;
            function klik:byte;
            destructor Done;virtual;
            end;
{Graficke tlacitko. Vidite, ze metoda Init ma dva mozne tvary. Budto v parametrech
O1 a O2 urcite soubor, ze ktereho se maji nacist dva obrazky nebo to udelate
manualne a sami. V tom pripade pouzijete druhou verzi.
Obrazek O1 je videt za normalniho stavu, O2 pri zmacknuti. Oboje muze byt budto
obycejny PCX obrazek (napr. 'KOCKA.PCX') nebo to muze byt PCX obrazek umisteny
v knihovne obrazku. Zde je pouzit stejny format knihovny obrazku jako pouziva
jednotka FNfont2. V takovem pripade bude argument vypadat napr. ZVIRATA.KKH:1
-To pred dvojteckou je nazev knihovny a to za ni je poradove cislo obrazku v knihovne

Funkcni stranka je uplne stejna jako u textoveho tlacitka.}

PZatrzitko = ^Zatrzitko;
Zatrzitko = object(TWoknaZaklad)
            textik:string[60];{text vedle zatrzitka}
            popis:string;{zobrazi se po kliknuti pravym mysitkem}
            hodnota:boolean;{zatrzeno = true}
            okraj:longint;
            bylo_klepnuto:boolean;
            constructor init(ix,iy:integer;itextik,ipopis:string;izatr:boolean);
            procedure zobraz;virtual;
            procedure kontrola;virtual;
            destructor done;virtual;
            end;
{Bily zatrhavaci ctverecek s jednim radkem textu vedle. Kliknout se da bud do
bileho ctverecku nebo na text, rozmery oblasti pro kliknuti na text jsou
urceny rozmery textu v okamziku zobrazeni (podle aktualniho nastaveni pisma).
Na prave mysitko reaguje bud zobrazenim popisu nebo, pokud je popis prazdny,
vubec.}

pPrepinac = ^Tprepinac;
tPrepinac = object(TWoknaZaklad)
           nadpis:string;{radek zobrazeny nad polozkami prepinace}
           popis:string;
           PocetRadku:byte;{pocet polozek prepinace}
           zahlavi:longint;
           Hodnota:byte;{0 = nevybrano nic, 1..PocetRadku = cislo prislusneho radku}
           texty:PVaznik;{texty polozek}
           Constructor init(ix,iy:integer;inadpis,idata,ipopis:string;ivyb:byte);
           procedure zobraz;virtual;
           procedure kontrola;virtual;
           Destructor Done;virtual;
           end;
{Nekolik radku, u kazdeho je bile kolecko. Kliknutim vyberete vzdy jednu
moznost. Text polozky max. 31 znaku. Cislo vybrane polozky urcite z promenne
Hodnota. Polozky jsou cislovany od 1; pokud je hodnota=0, neni vybrano nic.}

const poVERT = 0;
      poHORZ = 1;

Function sirka_pos:longint;  {sirka vertikalniho posuvniku}
Function vyska_pos:longint;  {vyska horizontalniho posuvniku}

type
PPosuvnik = ^Posuvnik;
Posuvnik = object(TWoknaZaklad)
           {sirka a vyska jsou zde mysleny bez posuvniku}
           virtvyska,{virtualni vyska}
           hodnota,{aktualne nastavena poloha, pocitano od 0}
           VelSoupatka,{o kolik pixelu se soupne pri stisku tlacitka}
           cistavyska:longint;  {vyska bez tlacitek}
           ciste_y:longint;
           ciste_y2:longint;
           tlacitkovy_skok:longint;
           smer:byte; {poVERT=svisly posuvnik; poHORZ=vodorovny posuvnik}
           nahoruT,doluT:tlacitko2;
           tahaci_stav:boolean;
           mxx,myy:longint;
           stara:longint;
           probehni:boolean;
           constructor Init(ix,iy:integer;idelka,vdelka,iHodnota,iskok:longint;ismer:byte);
           procedure zobraz;virtual;
           function kontrola:boolean;
           Function DejHodnotu:longint;
           destructor done;virtual;
           end;{posuvnik}
{Svisly nebo vodorovny posuvnik. Parametry konstruktoru:
X,Y je pozice na obrazovce
iDelka je vyska (sirka) posuvniku na obrazovce
vDelka je vyska (sirka) virtualni obhospodarovane plochy
iHodnota - pocatecni pozice posuvniku
iSkok - o kolik pixelu se plocha soupne po klepnuti na sipku posuvniku
iSmer - poVERT: vertikalni posuvnik, poHORZ: horizontalni posuvnik}


PTextovepole = ^Textovepole;
TextovePole = object(TWoknaZaklad)
              MaxZnaku:longint;{max. delka retezce}
              pozice:longint;{poloha kurzoru v textu, 0 = pred prvnim znakem, -1 = vybran cely text}
              Hodnota:string;{text - NECIST PRIMO, NA CTENI POUZIJ FCI}
                             {VRATHODNOTU}
              pHodnota:pointer; {pHodnota:=@Hodnota}
              default:string;{puvodni text, obnovi se pri stisku Esc}
              ProSoubor:boolean;{true => zakazou se znaky, ktere nejdou pouzit v nazvu souboru}
              unicode:boolean;
              TX_key_proc:Function(o:word):word;
              mimoradne_osetreni_klavesnice:Function(o:word):string;
              puvodni_citac:dword;
              je_videt:boolean;      {je zrovna videt kurzor?}
              poc_zobrX:longint;
              gd:longint;            {"graficka" delka retezce}
              virt,kpoz:virtualwindow;
              rychlost_blikani:byte;
              odz,doz,posunv,posunm,kx,kd,kkx,kky:longint;
              constructor init(ix,iy:integer;idelka:longint;itext:string;iakt,iprosoubor:boolean);
                               {idelka - kolik pixelu (nikoliv znaku) ma byt dlouhe}
                               {iakt - jestli ma byt pole po inicializaci hned aktivni}
              procedure BlikejKurzorem;
              procedure zobraz;virtual;
              procedure kontrola;virtual;
              Function VratHodnotu(dekoduj:boolean):string;
              {Vrati hodnotu Textoveho pole}
              {jestlize DEKODUJ=true tak dekoduje sekvence >> na > }
              procedure KrokVpred;
              procedure KrokZpet;
              Procedure KlavesaBackSpace;
              Procedure KlavesaDel;
              Procedure KlavesaEnd;
              Procedure KlavesaHome;
              procedure OsetriVstup;
              destructor done;virtual;
              end;
{Pole pro zadavani textu (1 radek). Kurzor se presouva pomoci mysi nebo
klavesami home, end a sipkami. Funguji delete a backspace. Esc rusi zadany
text a nahradi ho puvodnim (itext pri inicializaci) a necha pole aktivni.
Enter nebo klik mysi mimo pole pole deaktivuji a napsany text nechaji. Pole se
opet aktivuje kliknutim mysi. Neaktivni pole neovlivnuje klavesnici ani mys,
lze ho kontrolovat spolu s jinymi ovladacimi prvky. Jako aktivni si zabira
klavesnici pro sebe (pokud neni kontrolovano jako uplne posledni).
Pro urceni, jakym zpusobem bylo ukonceno psani do pole, slouzi polozka Stav,
ktera muze nabyvat techto hodnot:}
const
      PRAVY_OKRAJ = 2;
      LEVY_OKRAJ = 4;

type
       {**************************************************************}
       { OBJEKT TEDRADEK BYL PRESUNUT DO SAMOSTATNE JEDNOTKY TEDRADKY }
       {**************************************************************}

       {**************************************************************}
       { EDITACNI POLE BYLA PRESUNUTA DO SAMOSTATNE JEDNOTKY EDITPOLE }
       {**************************************************************}


{----------------------------------------------------------------------------}

PPolozka = ^TPolozka;
TPolozka = object
       text:pstring;
       help:pstring;
       id:longint;       {jedinecne identifikacni cislo.}
       povoleno:boolean;
       x1,y1,x2,y2:longint;
       Constructor Init(_text,_help:string;_id:longint;_povoleno:boolean);
       Destructor Done;
       end;


{Jednotlive bity parametru MOZNOSTI maji nasledujici vyznam
bit0 : 0=vybernicek defaultne skryt/1=defaultne zobrazen
bit1 : 0=hlavni moznosti pod sebou/1=hlavni moznosti vedle sebe
bit2 : 0=nedovol vybrat zakazane polozky/1=dovol vsechny polozky

pro pohodlne pouziti mate tyto konstanty:}
const vbZOBRAZ    = 1;         {po inicializaci se ihned zobrazi}
      vbVEDLESEBE = 2;         {menu bude horizontalne (jinak je vertikalne)}
      vbPODSEBOU  = 0;
      vbDOVOLVSE  = 4;         {umozni vybrat i zakazane polozky}
      vbROZTAHNI  = 8;         {menu se roztahne do cele sirky(vysky) obrazovky}
      vbAKTIVACEPREJETIM = 16; {menu se aktivuje pouhym najetim mysi, bez klikani}

      Roztec_horiz_pol_vybernicku:longint = 40;
type
PVybernicek = ^TVybernicek;
TVybernicek = object
       x1,y1,x2,y2:longint;    {souradnice objektu na obrazovce}
       data:PStrom;   {plody stromu jsou typu PPolozka}
       pozice:PStrom; {do jake vetve se prave koukame. Defaultne na kmen}
       moznosti:byte; {viz konstanty nahore}
       rychly_konec:longint;
       {ma smysl pri presmerovani obsluhy mysi ci klavesnice
        - pokud ho vase obsluha nastavu necha na 0, nestane se nic
        - pokud bude kladny, tak ma stejny ucinek jako stisk Enteru
        - pokud bude zaporny, tak vyskoci s hodnotou NIL}
       pozadi:Pvirtualwindow;  {tady se uchova to, co bude prekryto}
       dosah_kontroly:longint;
       VB_Mouse_R_proc:Function(s:PStrom):longint; {vola se pri stisku jakehokoliv mysitka}
       VB_Key_proc:Function(s:Pstrom;o:word;var i:longint):word;  {to same, akorat obsluhuje klavesnici}
       Constructor Init(_x,_y:longint;_moznosti:byte;_data:PStrom);
       Procedure Zobraz;
       Procedure Schovej;
       Procedure UrovenZobrazeni(p:PStrom);
       {umoznuje predvybrat defaultni polozku. ta se
        muze nachazet v jakekoli miste stromu.
        defaultne je to koren.}
       Function Vyber:Pstrom;
       {Tohle je oc tu bezi. Necha vas vybrat polozky}
       Function Kontrola:longint;
       {Testuje, jestli mys klikla do pracovniho prostoru vybernicku}
       Function AktivujMenu(i:longint):PStrom;
       {Doporucene uziti:
        begin
        i:=v^.Kontrola;if i<>0 then v^.AktivujMenu(i)
        if xKeyPressed then
           case xReadKey of
           klMENU:AktivujMenu(0);
           end;
        ...
        end;
        }
       Destructor Done;
       private
          trasa:PVaznik;
          _omx,_omy:longint;
          Procedure ZobrazHoriz;
       end;

PLBpol = ^TLBpol;
       TLBpol = object
       y1,y2:longint;   {poloha polozky ve virtualnim okne}
       ozn:boolean;     {je pri multivyberu onzacena?}
       s:pstring;       {retezec S vygeneruje proc. promenna LB_dej_retezec}
       end;

PListBox = ^TListBox;
TListBox = object(TWoknaZaklad)
       py:Posuvnik;
       popredi,pozadi:word;      {barvicky}
       virt:VirtualWindow;       {vystupni buffer}
       kresli_posuvnik:boolean;
       LB_dej_retezec:Point2StrFunc;   {konverze Vaznik^.vazba na string}
       LB_Mouse_R:VaznikProc;          {Co delat pri stisku praveho mysitka. Defaultne je NIL}
       klPrekladKlaves:Function(o:word;lb:PListbox):word;
       uschovany_pvaznik:PVaznik;
       koren,posledni,hodnota:Pvaznik; {jejich plody budou PLBpol}
       poc_ZobrY:longint;        {Y-pozice scrollingu}
       kpocY:longint;            {hodnota poc_Zobr dana klavesnici. Ma vyssi prioritu nez dana mysi}
       prv_rad,posl_rad:PVaznik;       {Prvni a posledni vypsany radek}
       kprv_rad,kposl_rad:PVaznik;     {jejich zalohy}
       kurzor_v_rozsahu:boolean; {norm TRUE. Je FALSE kdyz posuvnikem odskolujeme tak daleko, ze neni videt kurzor}
       VYBRANO:boolean; {az bude TRUE, tak to bude znacit, ze uzivatel uz neco vybral}
       Kod_navratu:longint;
       multi:boolean;            {povolen vyber vice polozek?}
       pocetmulti:longint;       {kolik polozek mame multiselektovanych}
       Constructor init(ix,iy,isirka,ivyska:integer;p:Pvaznik;proc:Point2StrFunc;_multi,iakt:boolean);
       Procedure Zobraz;virtual;
       Procedure Aktivuj;
       Procedure OsetriVstup;
       Procedure OdznacVse;
       Procedure Kontrola;virtual;
       Function VratHodnotu:Pvaznik;     {vrati polozku na ktere je kurzor}
       Function VratMultiHodnotu:PVaznik;{vrati seznam vybranych polozek, kdyz}
       {multiselektem neni nic vybrano, tak se chova jako VratHodnotu, jen s
        tim rozdilem, ze udela zcela novy vaznik i s hlavickou - ne prosty
        ukazatel do existujiciho}
       Destructor Done;virtual;
       end;
{ListBox je menu s moznosti scrollingu. Pri vybirani muzete pouzivat klavesnici i mys
a pokud mate ovladac CTMOUSE (napr. z distribuce FreeDOSu), tak muzete pouzivat i scrolovaci kolecko.
Vstupni data musi byt zapojena do spojoveho seznamu VAZNIK. Jejich format neni predepsan,
ale musite napsat funkci, ktera z techto dat vykonstruuje retezec STRING. Odkaz
na tuto funkci pak predate jako parametr PROC. Pokud zadate NIL, tak se pouzije
defaultni funkce POINT2PSTRING.
Priklady muzete videt napr ve funkcich
   VyberSokno_disk nebo VyberSokno_2_adresar
obhospodarovaci cyklus by mel vypadat priblizne takto:
    -----------------------------
       lb.init(100,50,500,400,data,@data_vazba_2_string,true);

       repeat
       if xKeyPressed then xReadkey;
       lb.kontrola;
       until lb.vybrano;

       p:=lb.VratHodnotu
    -----------------------------
VratHodnotu vrati PVaznik na vybranou polozku, ktery je zapojen do vstupniho
pvazniku.

Parametr IAKT ma stejny vyznam jako u textoveho nebo editacniho pole.
}

PSeznam = ^TSeznam;
TSeznam = object(TWoknaZaklad)
       maxvyska:longint;
       popis:string;
       _yy,virtvyska:longint;
       lb:TListBox;
       tla:Tlacitko2;
       uschova:Virtualwindow;
       LB_dej_retezec:Point2StrFunc;   {konverze Vaznik^.vazba na string}
       prvky:PVaznik;
       mojebarva:word;
       hodnota:PVaznik;
       bylo_vybrano:boolean;
       Constructor Init(ix,iy,isirka,imaxv:longint;p,default:PVaznik;proc:Point2StrFunc);
       Procedure Zobraz;virtual;       {zobrazi zakladni zatazenou formu}
       Procedure Kontrola;virtual;
       Procedure RozbalSeznam;virtual;
       Destructor Done;virtual;
       end;

Pokno = ^okno;
okno = object(TWoknaZaklad)
       vyska_zahlavi:longint;
       PozadiOkna:virtualwindow;
       _data:PVaznik;
       _akce:Actiontype;
       constructor init(ix,iy,isirka,ivyska:longint;nadpis:string);
       Function Volne_y:longint; {rekne, kam az saha text vypsany pri inicializaci}
                                 {pomoci mustrovych funkci (jako OKokno_mustr apod.)}
       destructor done;virtual;
       end;
{Viz Windows :-). Init okno zobrazi (a necha vypnuty kurzor), Zrus ho zase
zrusi (vrati puvodni pozadi a jestli vrati kurzor do stavu, v jakem byl pred
Initem). Vyska modre listy je urcena aktualnim nastavenim pisma, sirka okna
muze byt automaticky zvetsena, pokud by se do nej nadpis nevesel. Pokud zadate
nadpis='', zadna modra lista se nezobrazi.}


PVWokno = ^TVWOkno;
TVWOkno = object(TWoknaZaklad)
       xx,yy:longint;
       zdroj:virtualwindow;
       zobr_sirka,zobr_vyska:longint;
       {v:virtualwindow;}
       poc_ZobrX,poc_ZobrY:longint;
       je_videt:boolean;
       px,py:Posuvnik;
       akce_posuvniku:byte;
       kresli_ramecek:boolean;
       ob_my_key_proc:Function(o:word):word;
       Constructor Init(ix,iy,isirka,ivyska:longint;plocha:virtualwindow;iramecek:boolean;iakt:boolean);
       Procedure Zobraz;virtual;
       Procedure OsetriVstup;
       procedure kontrola;virtual;
       Destructor Done;virtual;
       end;

Plista = ^TLista;
TLista = object(TWOknaZaklad)
       sir_tlac,prid_tlac:longint;
       zadane,stz,prvni:longint;
       kliknuto:boolean;
       posledni_ve_hre:boolean;
       barva_stiskleho:word;
       objektiky:PVaznik;
       Lis_dej_retezec:Point2StrFunc;
       Lis_dej_retezec2:Point2StrFunc;
       Lis_akce_pri_zadani:Procedure(i:longint;p:PLista);
       nahoruT,doluT:tlacitko2;
       Constructor Init(ix,iy,isirka,ivyska,isir_tlac,iprid_tlac:longint;proc:Point2StrFunc;iprvky:PVaznik);
       Procedure NatahniPrvky(iprvky:PVaznik);
       Procedure PridejPosouvatka;
       Procedure SrovnejListu;
       Procedure Zobraz;virtual;
       Procedure Kontrola;virtual;
       Destructor Done;virtual;
       end;

PCiselnik = ^TCiselnik;
TCiselnik = object(TWoknaZaklad)
       nahorut,dolut:Tlacitko2;
       tpole:TextovePole;
       min,max:longint;
       hodnota:longint;
       kliknuto:boolean;
       popis:string;
       Constructor Init(ix,iy,ihodnota,imin,imax:longint;ipopis:string);
       Procedure Zobraz;virtual;
       Procedure VlozHodnotu(i:longint);
       Procedure Kontrola;virtual;
       Destructor Done;virtual;
       end;

{Rodinu objektu Dialog lze volat budto primo, nebo neprimo pomoci funkci}
{VlozCisloOkno a VlozTextOkno}
Pdialog = ^Dialog;
dialog = object
       {mysleno jako verejne}
       hodnota,nadpis,defaulttext:string;

       {mysleno jako soukrome}
       okynko:Okno;
       okt,cancelt:Tlacitko;
       tp:textovepole;
       sirka_tlacitek,delka,delkaradky:longint;
       bylo_cancel:boolean;

       Constructor Init(_nadpis:string;idelka:longint;_defaulttext:string);
       Destructor Done;
       Procedure Zobraz;virtual;
       Function Validator:boolean;virtual;
       end;

PCiselny_dialog = ^Ciselny_Dialog;
ciselny_dialog = object(dialog)
       __od,__do:longint;
       Constructor Init(_nadpis:string;_od,_do,_defaulttext:longint);
       Destructor Done;
       Function Validator:boolean;virtual;
       end;

PSouborovy_dialog = ^Souborovy_dialog;
souborovy_dialog = object(dialog)
       Function Validator:boolean;virtual;
       end;

const obv_sta_x:longint = 800;
      obv_sta_y:longint = 600;
Procedure ObvyklyStart;   {obvykla sekvence prikazu pro nastaveni videorezimu
                           800x600, zapnuti mysi a podobne  }
Procedure ObvyklyKonec;   {odstrani ovladac mysi a vrati se do textoveho modu}

Function PrunikMysi(x1,y1,x2,y2:longint):boolean;
                          {zjisti, zda se kurzor prekryva s vyrezem}

Function ProvedClippingVertikalniCary(var k1,k2:longint;y1,y2:longint):boolean;

Function ZeStreduX(i,sirka:longint):longint;
Function ZeStreduY(i,vyska:longint):longint;

Procedure OpravVycuhovani(var ix,iy:longint;sirka,vyska:longint);
{opravi souradnice obdelnika, aby byl cely zobrazen na obrazovce}

Procedure _box(x1,y1,x2,y2,m1,m2,m3:longint);
{procedurka, ktera vykresli jakoby tlacitko. Jenom vykresli, nic neumi}

Procedure _prazdnybox(x1,y1,x2,y2,m1,m2:longint);
{vykresli jenom okraje tlacitka}

Procedure _print(x,y,barva:longint;textik:string);
{Vypise text - narozdil od Print_FN se Y souradnici mysli vrsek fontu, ne
zakladni linka}

Function _SirPos:longint; {vraci sirku vertikalniho posuvniku}

Procedure SmazVaznikPStringu(var p:PVaznik); {tyto dve procedury}
Procedure Fileselector_smaz(var p:PVaznik);  {jsou identicke}

Procedure SmazVaznikPEdRadku(var p:PVaznik);

Procedure PosunVaznikuPEdRadek(p:pvaznik;a,j:longint);

{*************** rutiny spolupracujici s objekty typu Vybernicek ************}
Function VytvorPolozku(test,help:string;id:longint;povoleno:boolean):pointer;
{Vytvori polozku ve vybernicku. Vytvori ovsem pouze "plod" stromu, nikoliv vetev}
{Zapis linearniho menu vypada napriklad takto:}
{
var staty:PStrom;
begin
staty:=StromDef(UzelS(VytvorPolozku('Slovensko: ','',1,true),
                UzelS(VytvorPolozku('Portugalsko','',2,true),
                UzelS(VytvorPolozku('Ukrajina','neni clenem NATO',3,true),nil
                )))
               );
}

Function NajdiPolozku_po_ID(s:PStrom;i:longint):Pstrom;
{vrati primy ukazatel na polozku, u ktere zname ID}
Procedure OdstranPolozky(var p:PStrom);
{smaze cely strom polozek}
Function VybranyText(p:Pstrom):string;
{z vybrane polozky vytahne pole "text"}
Function VybraneID(p:PStrom):longint;
{z vybrane polozky vytahne pole "id"}

Procedure UlozVybernicek(p:PStrom;s:string);
{ulozi nabidkovy strom na disk (v binarnim tvaru)}
Function NactiVybernicek(var p:PStrom;s:string):longint;
{nahraje nabidkovy strom z disku. parametr P uz musi byt inicializovany}


const
    NA_STRED = -1000000; {v nekterych procedurach, ktere chteji zadat pozici,
                        muzes misto X a Y souradnic zadat tuto konstantu a
                        okno se automaticky vystredi}
    {Je dovolen i zapis typu NA_STRED+50 nebo NA_STRED-200}
    {(Takto se zadava odchylka od stredove pozice)}

(************************** globalni promenne: ******************************)

var cil:Pvirtualwindow;      {Kam budeme kreslit? Defaultne nastaven na obrazovku}
    hned_vykresluj:boolean;  {Ma metoda <objekt>.Init hned volat <objekt>.Zobraz?}
    utf8_tbl:Putf8conv;
    VyberBarvuOkno_Zruseno:boolean;  {pro VyberBarvuOkno}
    aktivniokno:Pokno;
    UKmys,UKmysCekej:PVirtualwindow;

(*********************** verejne procedury a funkce: ************************)
{Pokud jde o nejake okno a souradnice se mu nezadavaji rucne, zobrazi se vzdy
nekde pobliz stredu obrazovky, ktery si samo spocita.}

Function NejsirsiText(p:PVaznik):longint;
{Plody vazniku jsou PStringy. Funkce najde ten graficky nejdelsi z vazniku}

Procedure ZjistiRozmeryTextu(texty:string;var sirka,vyska:longint;p:PVaznik);
Procedure ZjistiRozmeryTextu(texty:pchar;var sirka,vyska:longint;p:PVaznik);
{Zjisti sirku a vysku plochy zabrane textem. Jednotlive radky textu se
oddeluji znakem klasicky #13#10. Pokud ti jde jen o toto, tak parametr P nech
jako NIL. Pokud to neni NIL, tak do vazniku P rozseparuje jednotlive radky}

const infokno_sirka:longint = 160;
      info_okno_presna_sirka:boolean = false;
      {pri FALSE muze byt skutecna sirka trochu mensi, tak aby odpovidala
      nejsirsi radce textu. Pri TRUE presne dodrzi zadanou sirku}

procedure InfOkno(ix,iy:longint;hlaska:string;resb:boolean);
procedure infOkno(ix,iy,isirka:longint;hlaska:string;resb:boolean);
{male zlute informacni okenko s textem, odklikne se cimkoli. Text Hlaska
se automaticky rozklada do vice radku (slova se nedeli). Ix a iy je stred
okna, ne levy horni roh. Pokud je resb true, pocka se na konci procedury
na uvolneni vsech tlacitek na mysi a klavesnici (procedura Resetuj), jinak ne.
Rozmery okna jsou urceny rozmery textu, ktery se ma zobrazit.}


function polohovane_AnoNeOkno(xpoz,ypoz:longint;texty:string):boolean;
function AnoNeOkno(texty:string):boolean;
{okno s otazkou a tlacitky Ano a Ne. Retezec Texty obsahuje text otazky.
Radky oddelujte znaky #13#10 (u delsich textu je to nutne, protoze radky se
nedeli automaticky). Pozor na max. delku retezce - 255 znaku.
"Ano" se da zvolit i klavesami A a Enter, "ne" klavesami N a Esc.
Funkce vraci true, pokud bylo zvoleno Ano.
Sirka okna je urcena sirkou nejdelsiho radku, vyska poctem radku.}
     procedure anoneokno_mustr(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;popis,texty,tla1,tla2:string;var anot,net:ptlacitko);
     procedure anoneokno_mustr(var ok:pokno;idelka,ivyska:longint;popis,texty,tla1,tla2:string;var anot,net:ptlacitko);
     {vykresli to same jako predchozi procedura, ale potom ihned skonci. Smysl
     je ten, ze ti usnadni tvorbu vselijakych oken se dvema tlacitky}

function polohovane_anonezrusokno(xpoz,ypoz:longint;texty:string):byte;
     {vykresli dialogove okno Ano, Ne, Zrus}

procedure Okokno(titulek,texty:string);
Procedure OKokno(titulek:string;texty:pchar);
{okno s titulkem, zpravou a tlacitkem OK. Texty funguji stejne jako u AnoNeOkna.
Odklepnout se da mysi (tlacitko OK), Enterem, mezernikem nebo klavesou O.}
     procedure okokno_mustr(var ok:pokno;idelka,ivyska:longint;titulek,texty:string;var oukej:ptlacitko);
     procedure okokno_mustr(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;titulek,texty:string;var oukej:ptlacitko);
     procedure okokno_mustr(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;titulek:string;texty:pchar;var oukej:ptlacitko);
     procedure okokno_mustr(var ok:pokno;idelka,ivyska:longint;titulek:string;texty:pchar;var oukej:ptlacitko);

     {vykresli to same jako predchozi procedura, ale potom ihned skonci. Smysl
     je ten, ze ti usnadni tvorbu vselijakych oken s jednim OK tlacitkem}
     procedure mustr_bez_tlacitek(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;popis,texty:string);
     procedure mustr_bez_tlacitek(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;popis:string;texty:pchar);
     {to same jako predchozi, ale nevykresli zadna tlacitka}

function VlozTextOkno(nadpis:string;idelka:longint;defaulttext:string;prosoubor:boolean):string;
{Okno,do ktereho se zada nejaky text.
 nadpis - bude zobrazen v horni modre liste okna. Pokud zadate '', zobrazi
          se 'Vlo§ text:'
 idelka - delka zadavaciho policka

 defaulttext - text, ktery je v okne zobrazen na zacatku a funkce ho vraci v
               pripade,ze je zadavani zruseno (tlacitko Zrus nebo klavesa Esc)
 prosoubor - true => zakaze psani diakritiky, interpunkce a mezer, vhodne pro
             bezpecne psani jmen souboru}
function VlozCisloOkno(nadpis:string;_od,_do,default:longint):longint;
{Okno, do ktereho se pise cislo.
 nadpis - viz vyse, pokud je '', pak se vypise 'Vloz cislo:'
 _od,_do - rozsah pozadovaneho cisla (Val asi uklada vysledek do integeru,
           takze radsi rozsah neprehanejte)
 default - cislo, ktere je v okne zobrazeno na zacatku a funkce ho vraci v
           pripade, ze je zadavani zruseno
Pokud napisete nejakou kravinu (pismena misto cisel apod.), bude automaticky
smazana a cislo zustane v okne, abyste ho mohli pripadne jeste opravit.}
function VyberBarvuOkno(nadpis:string;default:byte):word;
{Okno s vyberem barvy pro 256 barev, vraci cislo te vybrane. Ovlada se mysi
nebo klavesnici (sipky, Home, End, Enter/O, Esc/Z).
 nadpis - je zobrazen v horni liste okna, mel by mit max. 19 znaku (jestli
          bude delsi, okno se automaticky rozsiri, ale uz nebude vypadat tak
          hezky). Pokud zadate '', zobrazi se 'Vyber barvu:'.
 default - vychozi barva, ktera je vybrana na zacatku a kterou vraci
           v pripade zruseni
 Pokud uzivatel klepnul na Zrusit, vrati fce. vychozi barvu a nastavi globalni
 promennou VyberBarvuOkno_Zruseno na TRUE (jinak bude FALSE)}
function vyberhicolorbarvuokno(nadpis:string;default:word):word;
{To samy, ale vybira se z celeho spektra sestnactibitovych barev
 Pokud uzivatel klepnul na Zrusit, vrati fce. vychozi barvu a nastavi globalni
 promennou VyberBarvuOkno_Zruseno na TRUE (jinak bude FALSE)}

function NamixujBarvu(nadpis:string;default:word):word;

procedure ZjistujSouradnice;
{zobrazi zamerovaci kriz, se kterym se pohybuje pomoci mysi, a male okenko s
jeho aktualnimi souradnicemi. Velmi uzitecna a casto pouzivana vecicka.
Pravym mysitkem se prepina barva krize mezi bilou a cernou, levym mysitkem
nebo libovolnou klavesou se konci.}

Function Listbox_retezcovy(x,y,sirka,vyska:longint;s:string;Pmysitko:VaznikProc;multi:boolean;p:PVaznik):PVaznik;
{Ze scrolovaciho menu necha vybirat retezce. Plody PVazniku jsou typu PString
 Patrne je budete vytvaret takto: p^.InitNext(NaPstring('retezec'))
 PMysitko je proceduralni promenna typu PointProc. Zavola se pri klepnuti praveho mysitka
 na nejakou z polozek. Muze byt i NIL. V tom pripade to nevyvola zadnou akci
 Pokud je MULTI true, tak umozni vybrat vice polozek - v takovem pripade vygeneruje
 novy spojovy seznam, ktery je zadouci pozdeji dealokovat. Kdyz je MULTI false,
 tak vrati proste ukazatel na polozku stavajiciho spojoveho seznamu}

Function ListboxOkno(x,y,sirka,vyska:longint;hlaska:string;p:PVaznik;proc:Point2StrFunc):PVaznik;
{Podobne predchazejici funkci. Plody ovsem nemusi byt nutne retezce.}

function Dvojlistbox(nadpis:string;sirka,vyska:longint;proc:Point2StrFunc;p,_q:PVaznik):PVaznik;
var dvojlistbox_vsepol,dvojlistbox_vybpol:pchar;


Procedure VWOkno(x,y,sirka,vyska:longint;s:string;zdroj:Virtualwindow);

function Fileselector(nadpis,maska,koncovky:string;vyska:longint;moznosti:byte):PVaznik;
function VyberSouborOkno(nadpis,maska,koncovky:string;vyska:longint;moznosti:byte):string;

const VSNORMAL = 0;
      VS_BEZ_A = 1;
      VS_S_N   = 2;
      VS_BEZMULTI = 128;
{Necha uzivatele vybrat soubor a vrati jeho jmeno.
 nadpis - zobrazi se v horni liste okna
 maska - druh souboru, ktery se ma zobrazovat. Muze obsahovat cestu
         napr. "C:\HRY\*.* nebo "..\*.TXT"
         na velikosti pismen nezalezi
 koncovky - muzete specifikovat, ktere soubory maji byt zvyrazneny (jinu barvou)
            uvedte jednu nebo vice pripon. Oddeluji se znakem |
            napr. "MP3" nebo "EXE|COM|BAT". Od verze 1.54 je mozne definovat i
            druhou skupinu. Dela se to pomoci dalsiho znaku |
            Priklad: "EXE|COM|BAT|JPG||PNG||GIF|"

 vyska - vyska okna v pixelech
 moznosti - moznost zobrazeni. Vyuziva se 0. a 1.bit.
    0.bit - 0: zobrazuj adresare
               Vysledek fce. se pak vraci i s cestou: napr. "C:\TP\AHOJ.PAS"
            1: nezobrazuj adresare
               Vysledek fce. se pak vraci bez cesty: napr. "AHOJ.PAS"

    1.bit - 0: nezobrazuj tlacitko "novy"
            1: zobrazuj tlacitko "novy"

    7.bit - 0: povol mnohonasobny vyber
            1: zakaz mnohonasobny vyber

Pri pouziti tlacitka Novy se novy soubor fyzicky nevytvori, jen se vrati
zadane jmeno. Jmeno se zadava s koncovkou. Pozor, je to dost nebezpecna funkce,
pouzivejte ji s rozmyslem.
Pri pouziti tlacitka Zrus (nebo klavesy Esc) funkce vraci NIL ci ''(prazdny retezec).

FileSelector dovoli vybrat vice souboru, kdezto
VyberSouborOkno dovoli vybrat jen jeden soubor, ale zato to mas rovnou se stringu
}

procedure NastavFont(s:string);
{Nastavi font. Nadale lze pouzivat zmenu "za letu", ale je na tobe, aby ses}
{vzdycky vratil do puvodniho stavu}

Function NastavenyFont:fn;
{Opak predchoziko - zjisti, jaky font je prave nastaveny.
(toto lze rovnez zjistit z krkolomnejsiho String2FN(FN_default))}

Procedure NactiHlasky_ze_souboru(s:string);
{Nacte hlasky z externiho souboru. Velmi uzitecne pro lokalizace}
{POZOR - Je definovana v souboru WOKNA32.INC}

procedure Cekej;

implementation
uses
dos,          {kvuli funkci VyberSouborOkno}
odisk,        {sprava souboru}
vnm_PCX,      {loader formatu PCX}
laklv,        {klavesnice}
clanky;       {nacitani souboru s lokalizacnimi retezci}

{$INCLUDE wokna32.inc}
const MAGIC_VYBERNICKOVEHO_STROMU = '®VB¯';

var font:fn;
    __o:word;
    vybersoubor_priv_koncovky:string; {privilegovane koncovky pro VyberSoubor}

Procedure Dummy;begin end;

procedure Cekej;
begin
repeat
WhatAboutMouse;
until xKeyPressed or (mouse.b<>0);
end;

procedure CekejNaCokoli;
var x,y:longint;
begin
x:=mouse.x;
y:=mouse.y;
repeat
WhatAboutMouse;
if (mouse.x<>x) or (mouse.y<>y) then Break;
until xKeyPressed or (mouse.b<>0);
end;

Function _MaxX:longint;
begin
_MaxX:=cil^.breiteminus1;
end;

Function _MaxY:longint;
begin
_MaxY:=cil^.hoeheminus1;
end;

Function ChceNaStred(i:longint):boolean;
begin
ChceNaStred:=abs(i-NA_STRED)<5000;
end;

Function ZeStreduX(i,sirka:longint):longint;
begin
i:=i-NA_STRED;
ZeStreduX:=cil^.breite div 2-sirka div 2+i;
end;

Function ZeStreduY(i,vyska:longint):longint;
begin
i:=i-NA_STRED;
ZeStreduY:=cil^.hoehe div 2-vyska div 2+i;
end;

Procedure OpravVycuhovani(var ix,iy:longint;sirka,vyska:longint);
{Zajisti, aby bylo okno na obrazovce cele}
begin
if ix<0 then ix:=0; if (ix+sirka)>_maxx then ix:=_maxx-sirka;
if iy<0 then iy:=0; if (iy+vyska)>_maxy then iy:=_maxy-vyska;
end;

Procedure InicializaceBarev;
{Emulace palety VGA}
begin
tlhbarva:={vga2word(15)}50744;
tpdbarva:=vga2word(8);
tvbarva:=vga2word(7);
txtbarva:=vga2word(16);
ttxtbarva:=vga2word(16);
ttxtextra1barva:=vga2word(9);
ttxtextra2barva:=vga2word(12);
txtpolevbarva:=vga2word(15);
txtpolelhbarva:=vga2word(8);
txtpolepdbarva:=vga2word(28);
txtpoletbarva:=vga2word(16);
olhbarva:=vga2word(15);
opdbarva:=vga2word(8);
ovbarva:=vga2word(7);
oobdbarva:=vga2word(1);
lboznbarva:=vga2word(1);
lbmultioznbarva:=vga2word(8);
obarvanadpisu:=vga2word(15);
iolhbarva:=vga2word(27);
iopdbarva:=vga2word(24);
iovbarva:=vga2word(14);
iobarvatextu:=vga2word(16);
posbarva:=vga2word(26);
txttextinvbarva:=vga2word(7);
txtpoleinvbarva:=vga2word(1);
ramobrbarva:=65535;
vedleobrbarva:=0;

mvbarva:=vga2word(7);
mlhbarva:=vga2word(15);
mpdbarva:=vga2word(8);
mtxtbarva:=vga2word(0);
minlhbarva:=vga2word(8);
minpdbarva:=vga2word(8);
minvbarva:=vga2word(7);
mintxtbarva:=vga2word(8);
mialhbarva:=vga2word(15);
miapdbarva:=vga2word(8);
miavbarva:=vga2word(15);
miatxtbarva:=vga2word(0);
mislhbarva:=vga2word(8);
mispdbarva:=vga2word(15);
misvbarva:=vga2word(22);
mistxtbarva:=vga2word(15);
end;

Function PrunikMysi(x1,y1,x2,y2:longint):boolean;
begin
PrunikMysi:=Prunik(x1,y1,x2,y2,
             mouse.x-mouse.hotspot_x,
             mouse.y-mouse.hotspot_y,
             mouse.x-mouse.hotspot_x+mouse.cursor.breite-1,
             mouse.y-mouse.hotspot_y+mouse.cursor.hoehe-1
            );
end;


Function ProvedClippingVertikalniCary(var k1,k2:longint;y1,y2:longint):boolean;
begin
if k2<y1 then Exit(false);
if k1>y2 then Exit(false);
if k1<y1 then k1:=y1;
if k2>y2 then k2:=y2;
ProvedClippingVertikalniCary:=true;
end;


Procedure _prazdnybox(x1,y1,x2,y2,m1,m2:longint);
begin
LineClipped(cil^,x1,y1,x2,y1,m1);
LineClipped(cil^,x1,y2,x2,y2,m2);
LineClipped(cil^,x1,y1,x1,y2,m1);
LineClipped(cil^,x2,y1,x2,y2,m2);
end;

Procedure _box(x1,y1,x2,y2,m1,m2,m3:longint);
begin
if (m3<>0) and (y2-y1>2) then Bar(cil^,x1+1,y1+1,x2-1,y2-1,m3);
_prazdnybox(x1,y1,x2,y2,m1,m2);
end;

Procedure _print(x,y,barva:longint;textik:string);
var hv:longint;
    fo:word;
begin
fo:=FN_color;
FN_color:=barva;
hv:=RychlaVyskaSO(textik);
inc(y,hv);
Print_FN(x,y,textik,font);
FN_color:=fo;
end;

Procedure _hline(x1,x2,y,barva:longint);
begin
LineHorz(cil^,x1,x2,y,barva);
end;

Procedure _vline(x,y1,y2,barva:longint);
begin
LineVert(cil^,x,y1,y2,barva);
end;

Procedure _bar(x1,y1,x2,y2,barva:longint);
begin
if x1<0 then x1:=0;
if y1<0 then y1:=0;
if x2>cil^.breite-1 then x2:=cil^.breite-1;
if y2>cil^.hoehe-1 then y2:=cil^.hoehe-1;
Bar(cil^,x1,y1,x2,y2,barva);
end;

Function _sirkatextu(s:string):longint;
begin
_sirkatextu:=Sirka_FN(s,font);
end;

Function _sirkatextu2(l:longint):longint;
begin
_sirkatextu2:=_sirkatextu(xchar(l,'Z'));
end;

Procedure _TrojuhelnicekP(x,y1,y2,barva:longint);
begin
  repeat
  LineVert(cil^,x,y1,y2,barva);
  inc(x);
  inc(y1);
  dec(y2);
  until y1>=y2;
end;

Procedure _TrojuhelnicekL(x,y1,y2,barva:longint);
begin
  repeat
  LineVert(cil^,x,y1,y2,barva);
  dec(x);
  inc(y1);
  dec(y2);
  until y1>=y2;
end;

Procedure _TrojuhelnicekH(x1,x2,y,barva:longint);
begin
  repeat
  LineHorz(cil^,x1,x2,y,barva);
  dec(y);
  inc(x1);
  dec(x2);
  until x1>=x2;
end;

Procedure _TrojuhelnicekD(x1,x2,y,barva:longint);
begin
  repeat
  LineHorz(cil^,x1,x2,y,barva);
  inc(y);
  inc(x1);
  dec(x2);
  until x1>=x2;
end;

Procedure _maskedline(x1,y1,x2,y2:longint;barva,maska:word);
begin
LineWithMask(cil^,x1,y1,x2,y2,barva,maska);
end;

Procedure _PushText;begin end;
Procedure _PopText;begin end;

Procedure _nastavfont(f:fn);
begin
font:=f;
end;

Procedure NastavFont(s:string);
var b:byte;
begin
b:=Nacti_FNSLR(s);
font:=FN_selector^[b].font;
FN_DEFAULT:=s;
end;


Function NastavenyFont:fn;
begin
NastavenyFont:=font;
end;


procedure _napis(x,y:integer;bt,bo:word;hlaska:string);
Begin
_bar(x-2,y-1,x+_sirkatextu(hlaska),y+Vyska_FN_default,bo);
_print(x,y,bt,hlaska);
End;{napis}


Function MyBar(var dest:virtualwindow;x1,y1,x2,y2:longint;c:word):boolean;
begin
if (x2<x1) or (y2<y1) then Exit(false);
if (x2<0) or (y2<0) or (x1>dest.breite-1) or (y1>dest.hoehe-1) then Exit(false);
Bar(dest,x1,y1,x2,y2,c);
MyBar:=true;
end;



Function shiftpressed:boolean;
var j:boolean;
begin
asm
mov ah,12h;int 16h;test al,3;jz @ano;mov j,0;jmp @ko;
@ano:
mov j,1
@ko:
end;
shiftpressed:=not j;
end;

Function VB_SizeOf(p:pointer):longint;
var v:PPolozka;
begin
v:=p;
VB_SizeOf:=Length(v^.text^)+1+Length(v^.help^)+1+SizeOf(v^.id)+SizeOf(v^.povoleno);
end;

Function VB_CompData(p,q:pointer):boolean;
var b:^longint;
    v1:PPolozka;
begin
if p=nil then Exit(false);
v1:=p;
b:=q;
VB_CompData:=v1^.id=b^;
end;

Function NajdiPolozku_po_ID(s:PStrom;i:longint):Pstrom;
var ocp:pointer;
      q:pointer;
begin
move(procCompMyData,ocp,4);
procCompMyData:=@VB_CompData;
q:=@i;
NajdiPolozku_po_ID:=s^.Search_Offsprings(q);
Move(ocp,procCompMyData,4);
end;

Procedure VB_SaveHeader(f:PBufStream);
var s:string;
begin
s:=MAGIC_VYBERNICKOVEHO_STROMU;
f^.write(s[1],Length(MAGIC_VYBERNICKOVEHO_STROMU));
end;

Function VB_CheckHeader(f:PBufStream):boolean;
var s:string;
    i:byte;
begin
i:=Length(MAGIC_VYBERNICKOVEHO_STROMU);
s[0]:=char(i);
f^.read(s[1],i);
VB_CheckHeader:=s=MAGIC_VYBERNICKOVEHO_STROMU;
end;

Procedure VB_SaveData(f:PBufStream;p:pointer;j:longint);
var q:pchar;
    s:string;
    v:PPolozka;
begin
if p<>nil then
   begin
   f^.write(j,4);
   v:=p;
   q:=@s;inc(q);
   s:=v^.text^+#0;
   f^.write(q^,Length(s));
   s:=v^.help^+#0;
   f^.write(q^,Length(s));
   f^.write(v^.id,SizeOf(v^.id));
   f^.write(v^.povoleno,SizeOf(v^.povoleno));
   end
   else
   begin
   j:=0;
   f^.write(j,4);
   end;
end;

Function VB_LoadData(f:PBufStream):pointer;
var velikost_polozky:longint;
    q:pchar;
    v:PPolozka;
    w:pointer;
    _text,_help:string;
    _id:longint;
    _povoleno:boolean;
begin
f^.read(velikost_polozky,4);
if velikost_polozky=0 then
   begin
   v:=nil;
   end
   else
   begin
   GetMem(w,velikost_polozky);
   f^.read(w^,velikost_polozky);
   q:=w;
   _text:=q;
   inc(q,Length(_text)+1);
   _help:=q;
   inc(q,Length(_help)+1);
   move(q^,_id,sizeof(_id));
   inc(q,sizeof(_id));
   move(q^,_povoleno,sizeof(_povoleno));
   v:=New(PPolozka,Init(_text,_help,_id,_povoleno));
   FreeMem(w,velikost_polozky);
   end;
VB_LoadData:=v;
end;

Function Vse_zda_aktivni(p:PVaznik):PVaznik;
var q:PVaznik;
    v:PWoknaZaklad;
begin
q:=p^.dalsi;
while q<>nil do
   begin
   v:=q^.vazba;
   if v^.stav=_aktivni then Exit(q);
   q:=q^.dalsi;
   end;
Vse_zda_aktivni:=nil;
end;

Procedure Vse_zobraz(p:PVaznik);
var q:PVaznik;
    v:PWoknaZaklad;
begin
q:=p^.dalsi;
while q<>nil do
   begin
   v:=q^.vazba;
   v^.zobraz;
   q:=q^.dalsi;
   end;
end;

Function Vse_kontrola(p:PVaznik):Pvaznik;
var q:PVaznik;
    v:PWoknaZaklad;
begin
Vse_kontrola:=nil;
q:=p^.dalsi;
while q<>nil do
   begin
   v:=q^.vazba;
   v^.Kontrola;
   if v^.stav in [_stiskle,_extraakce] then Vse_kontrola:=q;
   if v^.stav=_tabulatorem then
      begin
      if q^.dalsi<>nil then PWoknaZaklad(q^.dalsi^.vazba)^.stav:=_aktivace
                       else PWoknaZaklad(p^.dalsi^.vazba)^.stav:=_aktivace;
      v^.stav:=_deaktivace;
      end;
   q:=q^.dalsi;
   end;
end;

Procedure Vse_zlikviduj(var p:PVaznik);
var q:Pvaznik;
    v:PWoknaZaklad;
begin
q:=p^.dalsi;
while q<>nil do
   begin
   v:=q^.vazba;
   Dispose(v,Done);
   q:=q^.dalsi;
   end;
Vaznik_Done_All(p,nil);
end;

Procedure Zrus_Pstring(var p:pointer);
begin
ZrusPString(PString(p));
end;

Procedure SmazVaznikPStringu(var p:PVaznik);
begin
Vaznik_Done_all(p,@Zrus_PString);
end;

Procedure Fileselector_smaz(var p:PVaznik);
begin
Vaznik_Done_all(p,@Zrus_PString);
end;

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

Procedure Mustr_SmazData(var p:pointer);
var v:PEdRadek;
begin
v:=p;
Dispose(v,Done);
end;

Procedure SmazVaznikPEdRadku(var p:PVaznik);
begin
Vaznik_Done_all(p,@Mustr_SmazData);
end;

{Constructor TPolozka.Init(_text,_help:string;_povoleno:boolean);}
Constructor TPolozka.Init(_text,_help:string;_id:longint;_povoleno:boolean);
begin
text:=NaPstring(_text);
help:=NaPstring(_help);
id:=_id;
povoleno:=_povoleno;
x1:=0;
y1:=0;
x2:=0;
y2:=0;
end;

Destructor TPolozka.Done;
begin
end;

Function VybranyText(p:Pstrom):string;
var v:PPolozka;
begin
v:=p^.vazba;
VybranyText:=v^.text^;
end;

Function VybraneID(p:PStrom):longint;
var v:PPolozka;
begin
v:=p^.vazba;
VybraneID:=v^.id;
end;


Procedure __OdstranPolozky(var p:pointer);
var v:PPolozka;
begin
v:=p;
ZrusPstring(v^.text);
ZrusPString(v^.help);
Dispose(v,Done);
end;

Procedure OdstranPolozky(var p:PStrom);
begin
Strom_Done_All(p,@__OdstranPolozky);
end;

Function VytvorPolozku(test,help:string;id:longint;povoleno:boolean):pointer;
begin
VytvorPolozku:=New(PPolozka,Init(test,help,id,povoleno));
end;

Procedure UlozVybernicek(p:PStrom;s:string);
var p1,p2,p3,p4,p5:pointer;
begin
p1:=procMySizeOf;
p2:=procSaveMyData;
p3:=procLoadMyData;
p5:=procSaveHeaderOfMyData;
p5:=procLoadHeaderOfMyData;
procMySizeOf:=@VB_SizeOf;
procSaveMyData:=@VB_SaveData;
procLoadMyData:=@VB_LoadData;
procSaveHeaderOfMyData:=@VB_SaveHeader;
procLoadHeaderOfMyData:=@VB_CheckHeader;
p^.Save(s);
move(p1,procMySizeOf,4);
move(p2,procSaveMyData,4);
move(p3,procLoadMyData,4);
move(p4,procSaveHeaderOfMyData,4);
move(p5,procLoadHeaderOfMyData,4);
end;

Function NactiVybernicek(var p:PStrom;s:string):longint;
var p1,p2,p3,p4,p5:pointer;
    i:longint;
begin
p1:=procMySizeOf;
p2:=procSaveMyData;
p3:=procLoadMyData;
p4:=procSaveHeaderOfMyData;
p5:=procLoadHeaderOfMyData;
procMySizeOf:=@VB_SizeOf;
procSaveMyData:=@VB_SaveData;
procLoadMyData:=@VB_LoadData;
procSaveHeaderOfMyData:=@VB_SaveHeader;
procLoadHeaderOfMyData:=@VB_CheckHeader;
i:=p^.Load(s);
move(p1,procMySizeOf,4);
move(p2,procSaveMyData,4);
move(p3,procLoadMyData,4);
move(p4,procSaveHeaderOfMyData,4);
move(p5,procLoadHeaderOfMyData,4);
NactiVybernicek:=i;
end;

Function _SirPos:longint;
begin
_SirPos:=Hsipka_obrazek.breite;
end;

Constructor TWoknaZaklad.Init;
begin
hlavni_font:=FN_default;
automys:=true;
xm:=-mouse.last_lpx;
ym:=-mouse.last_lpy;
end;

function TWoknaZaklad.MysZde:boolean;
var i,j:longint;
begin
i:=Mouse.X;
j:=Mouse.Y;
MysZde:=(i>=x) and (j>=y) and (i<=x+sirka-1) and (j<=y+vyska-1);
end;

Procedure TWoknaZaklad.Ufon;
begin
ofn:=FN_default;
NastavFont(hlavni_font);
if automys then if PrunikMysi(x,y,x+sirka-1,y+vyska-1) then MouseHide;
end;

Procedure TWoknaZaklad.Ofon;
begin
NastavFont(ofn);
if automys then if PrunikMysi(x,y,x+sirka-1,y+vyska-1) then MouseShow;
end;

Procedure TWoknaZaklad.kontrola;
begin
mys_uvnitr:=mouseinarea(x,y,x+sirka-1,y+vyska-1);
mys_klikla_uvnitr:=Uvnitr(mouse.last_lpx,mouse.last_lpy,x,y,x+sirka-1,y+vyska-1);
if mys_klikla_uvnitr then
   if (xm=-mouse.last_lpx) and (ym=-mouse.last_lpy) then mys_klikla_uvnitr:=false
   else begin
   xm:=-mouse.last_lpx;
   ym:=-mouse.last_lpy;
   end;
end;

Procedure TWoknaZaklad.zobraz;
begin
end;

Destructor TWoknaZaklad.Done;
begin
end;

Constructor tlacitko.init(ix,iy:integer;inapis,ipopis:string;_sirka,ipridavek:longint);
var s:string;
Begin
inherited init;
x:=ix; y:=iy;
napis:=inapis;
popis:=ipopis;
pridavek:=ipridavek;
neviditelny:=false;
if napis<>'' then
   begin
   stextu:=Sirka_FN(napis,font);
   if _sirka=0 then sirka:=stextu+PLUS_K_TLACITKU else sirka:=_sirka;
   vyska_textu:=RychlaVyskaRadky(napis);
   vyska:=vyska_textu+pridavek div 2+1;
   end;  {DEJ SI POZOR - JESTLI JE '' TAK SI MUSIS PORADIT SAM}
hodnota:=0;
stav:=0;
NajdiTag(inapis,'KLAVESY',s);   {instalace aktivnich klaves. Vezmu je z tagu}
if s='' then Aklavesy:='' else  {KLAVESY parametru inapis}
   begin
   s:=SkipAllSpaces(s);
   Aklavesy:=Copy(s,9,Length(s));
   end;
if hned_vykresluj then zobraz;
End;{tlacitko.init}

procedure tlacitko.zobraz;
var jy,i:longint;
    ow:word;
    s:string;
    z:VirtualWindow;

Begin
if neviditelny then Exit;
ufon;
ow:=tvbarva;
NajdiTag(napis,'POZADI_OKOLI',s);   {alternativni pozadi tlacitka?}
if s<>'' then
   begin
   s:=SkipAllSpaces(s);
   s:=Copy(s,14,Length(s));
   tvbarva:=MyVal(s);
   end;
_box(x,y,x+sirka,y+vyska,tlhbarva,tpdbarva,tvbarva);

jy:=y+(vyska shr 1)-(vyska_textu shr 1)+1;

i:=x+sirka div 2;
i:=i-stextu div 2+1;
if i<x+pridavek+1 then i:=x+pridavek+1;

if (sirka>2) and (vyska>2) then
   begin
   NastavVystup(z);
   i:=i-x;
   Init_VW(z,sirka-2,vyska-2,false);
   Clr(z,tvbarva);
   _print(i,jy-y,ttxtbarva,napis);
   PutClippedSprite(cil^,z,x+1,y+1);
   Kill_VW(z);
   NastavVystup(cil^);
   end;

tvbarva:=ow;
ofon;
End;{tlacitko.zobraz}

procedure tlacitko.kontrola;
var a:byte;
Begin
if neviditelny then Exit;
inherited kontrola;
{writeln('x :',self.x,'   y:',self.y,'    sirka:',self.sirka,'    vyska:',self.vyska);debug;}
if mouseinarea(x,y,x+sirka,y+vyska) then
  begin
  hodnota:=mouse.b;{ulozeni, cim bylo kliknuto}
  if mouse.b<>0 then
     begin{animace kliknuti tlacitka}
     mousehide;
     _box(x,y,x+sirka,y+vyska,tpdbarva,tlhbarva,0);{stisknute - obracene stinovany ramecek}
     mouseshow;

     while mouse.b<>0 do
        if mouse.b=3 then {zmackle leve i prave najednou}
           begin
           mouserel;
           hodnota:=_ExtraAkce;
           Break;
           end;
     mouserel;{pockani na uvolneni mysi}
     mousehide;
     _box(x,y,x+sirka,y+vyska,tlhbarva,tpdbarva,0);{pusteno - normalni ramecek}
     {zobraz;}
     mouseshow;
     end;
  if (hodnota=2) then
     if (popis<>'') then
        begin{kdyz je zadany nejaky popis, zobrazi se a nebere se to jako kliknuti}
        infokno(mouse.x,mouse.y,popis,true);
        hodnota:=0;
        end else
     else
  end
 else hodnota:=0;{mys je mimo tlacitko}
if (aKlavesy<>'') and (xKeyLock=false) and (xLastKey>0) and (xLastKey<256) then
   begin
   a:=Pos(char(xLastKey),aKlavesy);
   if a<>0 then
      begin
      hodnota:=1;  {simulace stisku mysitka pri zmacknuti aktivni klavesy}
      xLastKey:=0;
      end;
   end;
stav:=hodnota;
End;{tlacitko.kontrola}

function tlacitko.klik:byte;
Begin
klik:=hodnota;
hodnota:=0;
stav:=0;
End;{tlacitko.klik}

Destructor tlacitko.done;
begin end;

Constructor tlacitko2.init(ix,iy:integer;ipopis:string;o1,o2:PVirtualwindow;prbarva:word);
Begin
inherited init;
x:=ix; y:=iy;
popis:=ipopis;
hodnota:=0;
stav:=0;
obr1:=o1;
obr2:=o2;
nepotrebny:=false;
neviditelny:=false;
pruhledne:=true;
barva_pruhlednosti:=prbarva;
sirka:=o1^.breite;
vyska:=o2^.hoehe;
if hned_vykresluj then zobraz;
End;{init}

Constructor tlacitko2.init(ix,iy:integer;ipopis,o1,o2:string);
var a:byte;
begin
inherited init;
x:=ix; y:=iy;
popis:=ipopis;
pruhledne:=false;
barva_pruhlednosti:=0;
hodnota:=0;
stav:=0;
obr1:=nil;
obr2:=nil;
nepotrebny:=true;
neviditelny:=false;
if o1<>'' then
   begin
   a:=Pos(':',o1);
   New(obr1);
   if a=0 then Load_PCX(o1,obr1^);
   sirka:=obr1^.breite;
   vyska:=obr1^.hoehe;
   end else begin sirka:=10;vyska:=10;end;
if o2<>'' then
   begin
   a:=Pos(':',o2);
   New(obr2);
   if a=0 then Load_PCX(o2,obr2^);
   end;
if hned_vykresluj then zobraz;
end;

procedure tlacitko2.zobraz;
Begin
if neviditelny then Exit;
ufon;
(*with obrazky do _putimage(x,y,sirka,vyska,data^[1]);*)
if pruhledne then
   begin
   _box(x,y,x+sirka,y+vyska,tlhbarva,tpdbarva,tvbarva);
   PutHCSprite(cil^,obr1^,x,y,barva_pruhlednosti);
   end else PutSprite(cil^,obr1^,x,y);
ofon;
End;{tlacitko2.zobraz}

procedure tlacitko2.kontrola;
Begin
if neviditelny then Exit;
inherited kontrola;
if mouseinarea(x,y,x+sirka-1,y+vyska-1) then
   begin
   hodnota:=mouse.b;
   if mouse.b<>0 then
      begin{animace kliknuti}
      mousehide;
      if pruhledne then
         begin
         _box(x,y,x+sirka,y+vyska,tlhbarva,tpdbarva,tvbarva);
         if obr2<>nil then
            PutHCSprite(cil^,obr2^,x,y,barva_pruhlednosti) else
            PutHCSprite(cil^,obr1^,x,y,barva_pruhlednosti);
         end else              {stisknute - druhy obrazek}
             if obr2<>nil then Putsprite(cil^,obr2^,x,y) else
                               Putsprite(cil^,obr1^,x,y);
      mouseshow;
      mouserel;{pockani na uvolneni mysi}
      mousehide;
      if pruhledne then
         begin
         _box(x,y,x+sirka,y+vyska,tlhbarva,tpdbarva,0);
         PutHCSprite(cil^,obr1^,x,y,barva_pruhlednosti);
         end else Putsprite(cil^,obr1^,x,y);{stisknute - druhy obrazek}
      mouseshow;
      end;
   if (hodnota=2)and(popis<>'') then
      begin{kdyz je zadany nejaky popis, zobrazi se a nebere se to jako kliknuti}
      infokno(mouse.x,mouse.y,popis,true);
      hodnota:=0;
      end;
   end else hodnota:=0;{mys je mimo tlacitko}
stav:=hodnota;
End;{tlacitko2.kontrola}

function tlacitko2.klik:byte;
Begin
if hodnota=1 then
   hodnota:=hodnota;
klik:=hodnota;
hodnota:=0;
stav:=0;
End;{tlacitko2.klik}

Destructor tlacitko2.done;
Begin
if obr1<>nil then begin Kill_VW(obr1^);if nepotrebny then Dispose(obr1);end;
if obr2<>nil then begin Kill_VW(obr2^);if nepotrebny then Dispose(obr2);end;
End;{tlacitko2.zrus}

Constructor zatrzitko.init(ix,iy:integer;itextik,ipopis:string;izatr:boolean);
Begin
inherited init;
x:=ix; y:=iy;
textik:=itextik; popis:=ipopis;
hodnota:=izatr;
if hned_vykresluj then zobraz;
End;{zatrzitko.init}

procedure KresliZatrzitko(_x,_y:word;jo:boolean);
Begin
if jo then begin                       {Bill Gates by se citil jako doma :-)}
           PutPixel(cil^,_x+2,_y+4,0);
           Bar(cil^,_x+2,_y+5,_x+3,_y+6,0);
           line(cil^,_x+3,_y+7,_x+8,_y+2,txtbarva);
           line(cil^,_x+4,_y+7,_x+8,_y+3,txtbarva);
           line(cil^,_x+4,_y+8,_x+8,_y+4,txtbarva);
           end
      else Bar(cil^,_x+1,_y+1,_x+9,_y+9,txtpolevbarva);
End;{kreslizatrzitko}

procedure zatrzitko.zobraz;
var hv,dv,cv:longint;
    p:pchar;
Begin
ufon;
textik:=textik+#0;
p:=@textik[1];
sirka:=sirka_fn(p,font)+14;
VyskaRadky(p,cv,hv,dv);
dec(textik[0]);
vyska:=cv; if vyska<10 then vyska:=10;
okraj:=y+hv-10;
_box(x,okraj,x+10,y+hv{-1},txtpolelhbarva,txtpolepdbarva,txtpolevbarva);
kreslizatrzitko(x,okraj,hodnota);
_print(x+14,y+1,txtbarva,textik);
ofon;
End;{zatrzitko.zobraz}

procedure zatrzitko.kontrola;
Begin
inherited kontrola;
bylo_klepnuto:=false;
if mys_uvnitr then
 begin
 if mouse_l then
    begin
    hodnota:=not hodnota;
    mousehide;
    kreslizatrzitko(x,okraj,hodnota);
    mouseshow;
    mouserel;
    bylo_klepnuto:=true;
    end
  else if mouse_r then
          if (popis<>'') then
             infokno(mouse.x,mouse.y,popis,true) else MouseRel;
  end;
End;{zatrzitko.kontrola}

Destructor zatrzitko.done;
begin
inherited done;
end;

Constructor tprepinac.init(ix,iy:integer;inadpis,idata,ipopis:string;ivyb:byte);
var i,j:longint;
    radek:pstring;
    n:longint;
Begin
inherited init;
x:=ix; y:=iy;
nadpis:=inadpis;
popis:=ipopis;
zahlavi:=RychlaVyskaRadky(nadpis)+5;
texty:=New(PVaznik,Init(nil,nil));
ZjistiRozmeryTextu(idata,sirka,vyska,texty);
vyska:=vyska+zahlavi;
pocetradku:=texty^.PocetPrvku;
inc(sirka,12);       {pridam prostor na puntik}
{pocatecni hodnota:}
if ivyb>pocetradku then hodnota:=pocetradku
                   else hodnota:=ivyb;
{zobrazeni:}
if hned_vykresluj then zobraz;
i:=vyska;
End;{prepinac.init}

procedure puntik(x,y:longint;barva:word);{nakresli puntik do kolecka prepinace}
Begin
FilledCircle(cil^,x+4,y,2,barva,barva);
End;{puntik}

procedure tprepinac.zobraz;
{}procedure kolecko(y:longint);{nakresli stinovane bile kolecko, x = x celeho prepinace}
{}Begin
{}FilledCircle(cil^,x+4,y,3,txtpolevbarva,txtpolevbarva);
{}Circle(cil^,x+4,y,4,txtbarva);
{}End;{kolecko}
var i,j:longint;
    h:byte;
    p:PVaznik;
    v:PEdRadek;
Begin{prepinac.zobraz}
ufon;
{vypocet rozmeru podle nastaveni textu:}
{zobrazeni nadpisu:}
_print(x,y,txtbarva,nadpis);
{vykresleni jednotlivych polozek:}
i:=zahlavi;
h:=0;
p:=texty^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   inc(h);
   j:=y+i+RychlaVyskaSO(v^.p) div 2;
   kolecko(j);
   if h=hodnota then puntik(x,j,txtbarva);
   _print(x+13,y+i,txtbarva,v^.p);
   inc(i,v^.y2-v^.y1+1);
   p:=p^.dalsi;
   end;
ofon;
End;{prepinac.zobraz}

procedure tprepinac.kontrola;
var p:PVaznik;
    v:PEdRadek;
    i,j,k,oh,y1,y2:longint;
Begin
inherited kontrola;
if mouse_r then
   if mouseinarea(x,y+zahlavi,x+sirka-1,y+vyska+zahlavi-1) then
      begin
      infokno(mouse.x,mouse.y,popis,true);
      Exit;
      end;
if mouse_l then
   if mouseinarea(x,y+zahlavi,x+sirka-1,y+{zahlavi+}vyska-1) then
begin
i:=zahlavi;
oh:=hodnota;
k:=0;
p:=texty^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   j:=v^.y2-v^.y1+1;
   inc(k);
   y1:=y+i;
   y2:=y+i+j-1;
   inc(i,j);
   if k=oh then
      begin
      MouseHide;
      if hodnota<>0 then puntik(x,y1+RychlaVyskaSO(v^.p)-7,txtpolevbarva);{vymazani puv. puntiku}
      MouseShow;
      end;
   if (mouse.y>=y1) and (mouse.y<=y2) then
      begin
      MouseHide;
      puntik(x,y1+RychlaVyskaSO(v^.p)-7,txtbarva);{nakresleni noveho}
      MouseShow;
      hodnota:=k;
      end;
   p:=p^.dalsi;
   end;
mouserel;{cekani na pusteni mysi}
end;
End;{prepinac.kontrola}

Destructor tprepinac.done;
Begin
SmazVaznikPEdRadku(texty);
End;{prepinac.zrus}

Function NejsirsiText(p:PVaznik):longint;
var s:pchar;
    i,j:longint;
begin
i:=0;
p:=p^.dalsi;
while p<>nil do
   begin
   s:=p^.vazba;
   j:=Sirka_FN(s,font);
   if j>i then i:=j;
   p:=p^.dalsi;
   end;
NejsirsiText:=i;
end;


Function Sirka_pos:longint;
{sirka vertikalniho posuvniku}
begin
Sirka_pos:=DSipka_obrazek.breite;
end;


Function Vyska_pos:longint;  {vyska horizontalniho posuvniku}
begin
Vyska_pos:=PSipka_obrazek.hoehe;
end;


Constructor posuvnik.init(ix,iy:integer;idelka,vdelka,iHodnota,iskok:longint;ismer:byte);
var _hned_v:boolean;
Begin
inherited init;
x:=ix; y:=iy;
smer:=ismer;
if vdelka<idelka then vdelka:=idelka;
hodnota:=ihodnota;
virtvyska:=vdelka;
tlacitkovy_skok:=iskok;
_hned_v:=hned_vykresluj;hned_vykresluj:=false;
tahaci_stav:=false;
if smer=poVERT then
   begin
   nahorut.init(x,y,'',@HSipka_obrazek,@HSipka_obrazek,$FFFF);
   vyska:=idelka;
   sirka:=Hsipka_obrazek.breite;
   dolut.init(x,y+vyska-DSipka_obrazek.hoehe-1,'',@DSipka_obrazek,@DSipka_obrazek,$FFFF);
   cistavyska:=vyska-HSipka_obrazek.hoehe-DSipka_obrazek.hoehe;
   ciste_y:=y+HSipka_obrazek.hoehe;
   ciste_y2:=y+vyska-DSipka_obrazek.hoehe-1;
   end
   else begin
   nahorut.init(x,y,'',@LSipka_obrazek,@LSipka_obrazek,$FFFF);
   sirka:=idelka;
   vyska:=LSipka_obrazek.hoehe;
   dolut.init(x+sirka-PSipka_obrazek.breite-1,y,'',@PSipka_obrazek,@Psipka_Obrazek,$FFFF);
   cistavyska:=sirka-LSipka_obrazek.breite-PSipka_obrazek.breite;
   ciste_y:=x+LSipka_obrazek.breite;
   ciste_y2:=x+sirka-PSipka_obrazek.breite-1;
   end;

hned_vykresluj:=_hned_v;
if hned_vykresluj then zobraz;
End;{posuvnik2._init}

procedure posuvnik.zobraz;
var k:real;
    i,j:longint;
    n:boolean;
Begin
{horni tlacitko - urci rozmery posuvniku:}
MouseLock;
WaitRetrace;
dolut.zobraz;                   {zobrazeni dolni sipky}
nahorut.zobraz;                 {zobrazeni horni sipky}
n:=PrunikMysi(x,y,x+sirka-1,y+vyska-1);
if N then MouseHide;
if smer=poVERT then
   begin
   k:=vyska/virtvyska;              {kolik % virtualni vysky se vejde na obrazovku?}
   k:=k*cistavyska;
   VelSoupatka:=Round(k);           {velikost soupatka}
   _bar(x,ciste_y,x+sirka,ciste_y2-1,posbarva);  {stredni cast posuvniku}
   if virtvyska>vyska then
      begin
      k:=hodnota/virtvyska*cistavyska;
      j:=Round(k);
      i:=ciste_y+j;
      if i<ciste_y then i:=ciste_y;
      if i+VelSoupatka>ciste_y2 then i:=ciste_y2-VelSoupatka;
      _box(x,i,x+sirka,i+VelSoupatka,tlhbarva,tpdbarva,tvbarva); {posuvny ramecek:}
      end;
   end
   else begin
   k:=sirka/virtvyska;              {kolik % virtualni vysky se vejde na obrazovku?}
   k:=k*cistavyska;
   VelSoupatka:=Round(k);           {velikost soupatka}
   _bar(ciste_y,y,ciste_y2,y+vyska,posbarva);  {stredni cast posuvniku}
   if virtvyska>sirka then
      begin
      k:=hodnota/virtvyska*cistavyska;
      j:=Round(k);
      i:=ciste_y+j;
      if i<ciste_y then i:=ciste_y;
      if i+VelSoupatka>ciste_y2 then i:=ciste_y2-VelSoupatka;
      _box(i,y,i+VelSoupatka,y+vyska,tlhbarva,tpdbarva,tvbarva); {posuvny ramecek:}
      end;
   end;
if N then MouseShow;
MouseUnlock;
End;{posuvnik2.zobraz}

Function posuvnik.dejhodnotu:longint;
begin
dejhodnotu:=hodnota;
end;

Function posuvnik.kontrola:boolean;
var b:boolean;
    my,i,j,l:longint;
    k:real;
Begin{posuvnik.kontrola}
inherited kontrola;
kontrola:=false;
probehni:=false;
dolut.kontrola; nahorut.kontrola;
if smer=poVERT then
   begin
   b:=mouseinarea(x,ciste_y,x+nahorut.sirka,ciste_y2);
   my:=mouse.y-ciste_y;
   i:=virtvyska-vyska;
   if B and (tahaci_stav=false) and (mouse.b=1) then
      begin
      {Ted musim detekovat, jestli jsem klepnul do prostredniho soupatka}
      k:=hodnota/virtvyska*cistavyska;
      j:=Round(k);
      l:=ciste_y+j;
      if l<ciste_y then l:=ciste_y;
      if l+VelSoupatka>ciste_y2 then l:=ciste_y2-VelSoupatka;
      if (mouse.y>=l) and (mouse.y<=l+VelSoupatka) then
         begin
         Tahaci_stav:=true;
         stara:=hodnota;
         mxx:=-1;
         myy:=-1;
         end;
      {-----------------------------------------------------------------}
      end;
   end
   else begin
   b:=mouseinarea(ciste_y,y,ciste_y2,y+nahorut.vyska);
   my:=mouse.x-ciste_y;
   i:=virtvyska-sirka;
   if B and (tahaci_stav=false) and (mouse.b=1) then
      begin
      {Ted musim detekovat, jestli jsem klepnul do prostredniho soupatka}
      k:=hodnota/virtvyska*cistavyska;
      j:=Round(k);
      l:=ciste_y+j;
      if l<ciste_y then l:=ciste_y;
      if l+VelSoupatka>ciste_y2 then l:=ciste_y2-VelSoupatka;
      if (mouse.x>=l) and (mouse.x<=l+VelSoupatka) then
         begin
         Tahaci_stav:=true;
         stara:=hodnota;
         mxx:=-1;
         myy:=-1;
         end;
      {-----------------------------------------------------------------}
      end;
   end;

if tahaci_stav=true then
   if mouse.b=1 then
      if (mouse.x<>mxx) or (mouse.y<>myy) then
         begin
         probehni:=true;
         mxx:=mouse.x;
         myy:=mouse.y;
         end else
      else begin {tahaci_stav=true, mouse.b=0}
      tahaci_stav:=false;
      probehni:=true;
      if B=false then hodnota:=stara;
      end;

if B then
   if tahaci_stav=false then
      if mouse.b=1 then probehni:=true;

if probehni then
       begin
       kontrola:=true;
       my:=my-VelSoupatka div 2;
       if my<0 then my:=0;
       k:=my/cistavyska*virtvyska;
       hodnota:=round(k);
       if hodnota<0 then hodnota:=0;
       if hodnota>i then hodnota:=i;
       Zobraz;
       end;

if tahaci_stav=false then
   begin
   probehni:=false;

   if (dolut.hodnota=_stiskle) then
      begin
      inc(hodnota,tlacitkovy_skok);
      if hodnota>i then hodnota:=i;
      Zobraz;
      probehni:=true;
      kontrola:=true;
      end;

   if (nahorut.hodnota=_stiskle) then
      begin
      probehni:=true;
      kontrola:=true;
      dec(hodnota,tlacitkovy_skok);
      if hodnota<0 then hodnota:=0;
      Zobraz;
      end;
   end;

End;{posuvnik.kontrola}

Destructor posuvnik.done;
begin end;

Constructor textovepole.init(ix,iy:integer;idelka:longint;itext:string;iakt,iprosoubor:boolean);
Begin
inherited init;
{automys:=false;}
x:=ix; y:=iy;
maxznaku:=256;
mimoradne_osetreni_klavesnice:=nil;
TX_key_proc:=@Default_ed_key_proc;
if Length(itext)>maxznaku then SetLength(itext,maxznaku);{oriznuti retezce, pokud je moc dlouhy}
hodnota:=itext;
default:=itext;
pHodnota:=@hodnota;
unicode:=AktualniFont^.unicode;
hlavni_font:=FN_DEFAULT;
if iakt then
   begin
   stav:=_aktivni;
   xm:=-mouse.last_lpx;
   ym:=-mouse.last_lpy;
 (*mouse.last_px:=x;  {straslive programatorske zverstvo :-( }
   mouse.last_py:=y;*)
   end
   else begin
   stav:=_neaktivni;
   xm:=1;
   ym:=1;
   end;
gd:=Sirka_FN(itext,font);
poc_zobrX:=0;
kx:=0;
kd:=Vyska_FN_default+2;
rychlost_blikani:=10;
puvodni_citac:=0;
je_videt:=false;
prosoubor:=iprosoubor;
sirka:=idelka;
vyska:=Vyska_FN_default+5;
Init_VW(virt,sirka{-LEVY_OKRAJ-PRAVY_OKRAJ}-1,vyska-1,false);
Init_VW(kpoz,1,100,false);
KlavesaEnd;   {naskroluju nakonec}
if itext<>'' then
   pozice:=-1;   {pro zacatek oznacime cely text}
Clr(virt,txtpolevbarva);
if hned_vykresluj then zobraz;
End;{textovepole.init}

procedure textovepole.BlikejKurzorem;
var n:boolean;
begin
if pozice=-1 then Exit;
kpoz.hoehe:=kd;
kkx:=kx+x+1;
if kkx<x+1 then kkx:=x+1;
kky:=y+2;

if je_videt then
   begin
   n:=PrunikMysi(kkx,kky,kkx,kky+kd-1);
   if N then mousehide;
   GetClippedSprite(cil^,kpoz,kkx,kky);
   LineClipped(cil^,kkx,kky,kkx,kky+kd-1,txtpoletbarva);
   if N then mouseshow;
   end
   else begin
   n:=Prunik(kkx,kky,kkx,kky+kd-1,
             mouse.x-mouse.hotspot_x,
             mouse.y-mouse.hotspot_y,
             mouse.x-mouse.hotspot_x+mouse.cursor.breite-1,
             mouse.y-mouse.hotspot_y+mouse.cursor.hoehe-1
            );
   if N then mousehide;
   PutClippedSprite(cil^,kpoz,kkx,kky);
   if N then mouseshow;
   end;
end;

procedure textovepole.zobraz;
var c2:pvirtualwindow;
Begin
ufon;
NastavFont(hlavni_font);
FN_poloha._odz:=0;
FN_poloha._doz:=0;
NastavVystup(virt);
if (stav=_aktivni)and(pozice>=0) then
   begin
   FN_poloha.B:=URCIZNAK;     {budu chtit znam polohu aktualniho znaku na obrazovce}
   FN_poloha.N:=pozice;     {(stejne jako jeste dalsi podobne veci)}
   _print(poc_zobrX,3,txtpoletbarva,hodnota);{text}
   end
   else
   if (stav=_escapem)or((stav=_aktivni)and(pozice=-1)) then
      begin
      c2:=cil;
      cil:=@virt;
      _napis(poc_zobrX,3,txttextinvbarva,txtpoleinvbarva,hodnota);{oznaceny text}
      cil:=c2;
      end
      else _print(poc_zobrX,3,txtpoletbarva,hodnota);{text bez kurzoru}
if pozice=0 then kx:=poc_ZobrX else kx:=FN_poloha.x;
NastavVystup(cil^);
odz:=FN_poloha._odz;
doz:=FN_poloha._doz;
posunv:=FN_poloha._posunv;
posunm:=FN_poloha._posunm;
PutSprite_and_clear(cil^,virt,x+1,y+1,txtpolevbarva);
_prazdnybox(x,y,x+sirka,y+vyska,txtpolelhbarva,txtpolepdbarva);
if (stav=_aktivni) then
   begin
   je_videt:=true;
   puvodni_citac:=FromTimer;
   BlikejKurzorem;
   end;
ofon;
End;{textovepole.zobraz}

procedure textovepole.kontrola;
var i:longint;
    d:dword;
    zmena_bliknuti:boolean;
    p:pchar;

Begin
inherited kontrola;
zmena_bliknuti:=false;
d:=FromTimer;
if d>puvodni_citac+rychlost_blikani then
   begin
   je_videt:=not(je_videt);
   puvodni_citac:=d;
   zmena_bliknuti:=true;
   end;
if stav=_deaktivace then
   begin
   stav:=_odkliknutim;
   zobraz;
   end;
if stav=_aktivace then
   begin
   stav:=_aktivni;
   xm:=-mouse.last_lpx;
   ym:=-mouse.last_lpy;
   zmena_bliknuti:=true;
   if pozice=-1 then pozice:=0;
   end;
if not ((stav=_aktivni)or(stav=_escapem)) then
  if mys_klikla_uvnitr{Uvnitr(Mouse.last_px,Mouse.last_py,x,y,x+sirka,y+vyska)}
     then
     begin {aktivace v pripade kliknuti mysi do pole}
     pozice:=-1;
     BufferOff;
     stav:=_aktivni;
     zobraz;
     mouserel;
     xm:=-mouse.last_lpx;
     ym:=-mouse.last_lpy;
     end else
  else
  begin       {stav=AKTIVNI, ESCAPEM}
  xKeyLock:=true;         {zrusim moznost aktivace tlacitek stiskem horke}
                          {klavesy, aby to nenastalo nahodne pri psani}
  if Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska) or
     (mouse.last_lpx=-xm) and (mouse.last_lpy=-ym) then
     begin
     if mouse.b<>0 then
        begin
        BufferOff;
        stav:=_aktivni;
        i:=Length(hodnota);
        hodnota:=hodnota+#0;
        p:=@hodnota[1];
        pozice:=pozice_v_retezci(mouse.x,mouse.y,x+4,y+3,p,i,font);
        dec(hodnota[0]);
        if pozice<0 then pozice:=0
                    else begin
                    KrokZpet;
                    if pozice>i then pozice:=i;
                    end;
        xm:=-mouse.last_lpx;
        ym:=-mouse.last_lpy;
        zobraz;
        mouserel;
        end;
     if zmena_bliknuti then BlikejKurzorem;
     end {ne uvnitr}
     else begin
     if stav in [_aktivni,_escapem] then
        begin
        stav:=_odkliknutim;
        xKeyLock:=false;   {umoznim aktivaci tlacitek horkou klavesou}
        zobraz;
        end;
     xm:=mouse.last_lpx;
     ym:=mouse.last_lpy;
     Exit;
     end;   {else begin :: uvnitr}
  OsetriVstup;
  end;   {else begin :: not ((stav=_akt...}
{OsetriVstup;}
end;

Procedure TextovePole.KrokVpred;
var i,j:longint;
begin
i:=Length(hodnota);
if pozice=i then Exit;
if pozice=-1 then
   begin
   KlavesaEnd;
   Exit;
   end
   else if pozice<Length(hodnota) then
        inc(pozice,FNznakVpred(pHodnota,i,pozice+1,unicode,j));

if doz<>0 then         {presahuje tento radek pravy okraj obrazovky?}
   if pozice>=doz then
      begin
      {i:=Sirka_FN(copy(hodnota,1,pozice),font);
      poc_zobrX:=-(i-virt.breite)+4;}

      dec(poc_zobrX,posunv);
      if poc_zobrX>0 then poc_zobrX:=0;
      end;

end;

Procedure TextovePole.KrokZpet;
var i,j,k:longint;
begin
if pozice>0 then
   begin
   i:=Length(hodnota);
   j:=FNznakZpet(pHodnota,i+1,pozice{+1},unicode,k);
   dec(pozice,j);
   end
   else
   begin
   KlavesaHome;
   Exit;
   end;

if odz<>0 then         {presahuje tento radek levy okraj obrazovky?}
   if pozice<=odz then
      inc(poc_zobrX,posunm);
if poc_zobrX>0 then poc_zobrX:=0;
end;

Procedure TextovePole.KlavesaBackSpace;
var a:longint;
begin{backspace}
if pozice>0 then
   begin
   a:=pozice;
   KrokZpet;
   delete(hodnota,pozice+1,a-pozice);
   end
   else begin
   hodnota:='';
   pozice:=0;
   end;
end;

Procedure TextovePole.KlavesaDel;
var a:longint;
begin
if pozice=-1 then begin hodnota:='';pozice:=0;end
   else begin
   a:=pozice;
   KrokVpred;
   delete(hodnota,a+1,pozice-a);
   pozice:=a;
   end;
end;

Procedure TextovePole.KlavesaEnd;
var i:longint;
begin
i:=sirka_fn(hodnota,font);
poc_ZobrX:=virt.breite-i;
if poc_ZobrX>0 then poc_ZobrX:=0;
pozice:=Length(hodnota);
end;

Procedure TextovePole.KlavesaHome;
begin
poc_ZobrX:=0;
pozice:=0;
end;


Procedure TextovePole.OsetriVstup;
   Function MyLength:longint;
   begin
   if unicode then MyLength:=UniLengthS(hodnota)
              else MyLength:=Length(hodnota);
   end;

const povoleneznaky=[word('A')..word('Z'),word('a')..word('z'),word('0')..word('9'),word('.'),word('_'),word('\'),word('~'),word('-'),word(':'){,'*','?'}];{znaky povolene v nazvech souboru}
var o,o2:word;
    i,j:longint;
    pomstr:string[4];{kvuli unicode a kvuli vlozeni retezce "<<" pri jednom stiknuti "<"}
    sf:string;
begin
  if xKeyPressed then
    begin
    dec(virt.breite,0);
    je_videt:=true;
    puvodni_citac:=FromTimer;
    o2:=xReadKey;
    o:=TX_key_proc(o2);
    if o2>255 then
       begin         {kurzorove klavesy}
          case o of
          xLsipka:KrokZpet;
          xPsipka:KrokVpred;
          xDel:KlavesaDel;
          xHome:KlavesaHome;
          xEndk:KlavesaEnd;
          end;
       stav:=_aktivni;
       end
       else
    case o of
    8:KlavesaBackSpace;
    9:stav:=_tabulatorem;{tabulator}
    13:stav:=_enterem;{enter}
    27:begin{escape}
        stav:=_escapem;
        pozice:=-1;
        hodnota:=default;
        xKeyLock:=false;
        end;

    else{case}
    if mimoradne_osetreni_klavesnice=nil then
       begin
       if prosoubor and (not o in povoleneznaky) then o:=0;
       if (o<32) or (o>255) then o:=0;
       if o<>0 then
          if unicode then pomstr:=Word2UTF8(PrelozZnak(o,utf8_tbl^))
                     else pomstr:=char(o)
          else pomstr:='';
       end
       else begin
       pomstr:=mimoradne_osetreni_klavesnice(o);
       if (pomstr<>'') then
          begin
          i:=Length(pomstr); {kdyby rutina pridavala #0 pro moznost konverze na pchar}
          if pomstr[i]=#0 then delete(pomstr,i,1);
          end;
       end;

    if pomstr<>'' then
       begin {ostatni znaky - psani}
       sf:=FN_DEFAULT;
       NastavFont(hlavni_font);
       if pomstr='<' then pomstr:='<<';
       if pomstr='>' then pomstr:='>>';
       if pozice=-1 then
          begin {text je oznaceny, znak ho nahradi}
          hodnota:=char(o);
          pozice:=1;
          stav:=_aktivni;
          end else
          if MyLength<maxznaku then
             begin {pripsani na pozici kurzoru}
             insert(pomstr,hodnota,pozice+1);
             inc(pozice,Length(pomstr));
             if pozice=Length(hodnota) then
                begin
                j:=sirka_fn(hodnota,font)+poc_zobrX;
                if j>virt.breite-1 then
                   dec(poc_zobrX,j-virt.breite+1);
                end
                else begin
                j:=sirka_fn(copy(hodnota,1,pozice),font)+poc_zobrX;
                if j>virt.breite-1 then
                   dec(poc_zobrX,j-virt.breite+1);
                end;
                  {inc(gd,sirka_fn(pomstr,font));}
             end;
          NastavFont(sf);
          end;
    end;{case o}
    zobraz;
    end;{if KeyPressed}
End;

Function TextovePole.VratHodnotu(dekoduj:boolean):string;
var s:string;
    a,l:longint;
begin
if dekoduj=false then Exit(hodnota);
s:=hodnota;
a:=1;
l:=Length(s);
while a<=l do
   begin
   if (s[a]='<') or (s[a]='>') then
      begin
      delete(s,a,1);
      inc(a);
      dec(l);
      end;
   inc(a);
   end;
VratHodnotu:=s;
end;

Destructor textovepole.done;
begin
xKeyLock:=false;
kpoz.hoehe:=100;
Kill_VW(virt);
kill_VW(kpoz);
end;

Function Point2PString(p:pointer):string;
var v:PString;
begin
v:=p;
Point2PString:=v^;
end;

Constructor TListBox.init(ix,iy,isirka,ivyska:integer;p:Pvaznik;proc:Point2StrFunc;_multi,iakt:boolean);
var i:longint;
    q,k:PVaznik;
    v:PLBpol;
    h:boolean;
begin
inherited init;
x:=ix;y:=iy;
sirka:=isirka;
vyska:=ivyska;
multi:=_multi;
Init_VW(virt,isirka,ivyska,false);
if proc=nil then LB_dej_retezec:=@Point2Pstring else LB_dej_retezec:=proc;
i:=0;
koren:=New(PVaznik,Init(nil,nil));
uschovany_pvaznik:=p;
k:=koren;
if p<>nil then
   begin
   q:=p^.dalsi;
   while q<>nil do   {provedu konverzi vazniku P do noveho, kde budou vyznaceny Y souradnice jednotlivych polozek}
      begin
      New(v);
      v^.ozn:=false; {zatim nebyla oznacena multivyberem}
      v^.y1:=i;
      v^.s:=NaPstring(LB_dej_retezec(q^.vazba));
      inc(i,RychlaVyskaRadky(v^.s^));
      v^.y2:=i-1;
      k:=k^.InitNext(v);
      q:=q^.dalsi;
      end;
   end;
LB_Mouse_R:=nil; {Co delat pri stisku praveho mysitka? Defaultne nic}
posledni:=k;
h:=hned_vykresluj;hned_vykresluj:=false;
py.Init(x+sirka,y,vyska,i,0,10,poVERT);
kresli_posuvnik:=true;
hned_vykresluj:=h;
sirka:=sirka+py.sirka;
MouseHide;
MouseShow;
pozadi:=txtpolevbarva;
popredi:=txtbarva;
klPrekladKlaves:=nil;
Kod_navratu:=0;
pocetmulti:=0;
Clr(virt,pozadi);
poc_ZobrY:=0;
kpocY:=0;
if iakt then
   begin
   stav:=_aktivni;
   xm:=-mouse.last_lpx;
   ym:=-mouse.last_lpy;
   end
   else begin
   stav:=_neaktivni;
   xm:=1;
   ym:=1;
   end;
hodnota:=koren^.dalsi;
vybrano:=false;
end;

Procedure TListBox.Zobraz;
   Function Prosvit(x1,y1,x2,y2:longint;barva:word):boolean;
   begin
   if stav=_aktivni then Prosvit:=Mybar(virt,x1,y1,x2,y2,barva)
      else
      if (x2<0) or (y2<0) or (x1>virt.breiteminus1) or (y1>virt.hoeheminus1) then
         Exit(false)
         else begin
         LineClipped(virt,x1,y1,x2,y1,barva);
         LineClipped(virt,x1,y2,x2,y2,barva);
         LineClipped(virt,x1,y1,x1,y2,barva);
         LineClipped(virt,x2,y1,x2,y2,barva);
         Prosvit:=true;
         end;
   end;

var p:PVaznik;
    ofc:longint;
    v:PLBpol;

begin
ufon;
NastavVystup(virt);
SetBasicLine(-poc_ZobrY);
ofc:=FN_Color;
FN_color:=popredi;
kurzor_v_rozsahu:=false;
p:=koren^.dalsi;
prv_rad:=nil;
while p<>nil do
   begin
   v:=p^.vazba;
   if v^.y1-poc_ZobrY>virt.hoeheminus1 then Break;
   if v^.y2-poc_ZobrY>0 then
      begin
      if prv_rad=nil then prv_rad:=p;
      posl_rad:=p;
      if (p=hodnota)
         then kurzor_v_rozsahu:=Prosvit(2,v^.y1-poc_ZobrY+1,sirka-py.sirka-2,v^.y2-poc_ZobrY,lboznbarva)
         {oznaceno?}
         else if v^.ozn then Prosvit(2,v^.y1-poc_ZobrY+1,sirka-py.sirka-2,v^.y2-poc_ZobrY,lbmultioznbarva);
         {multioznaceno?}
      SetBasicLine(v^.y1-poc_ZobrY);
      FN_color:=txtbarva;
      Print_FN(4,AUTO_LINE,v^.s^,font);
      end;
   p:=p^.dalsi;
   end;

if kurzor_v_rozsahu then
   begin
   kposl_rad:=posl_rad;
   kprv_rad:=prv_rad;
   end;

PutSprite_and_clear(cil^,virt,x,y,pozadi);
FN_Color:=ofc;
ofon;
NastavVystup(cil^);
if kresli_posuvnik then py.zobraz;
end;

Procedure TListBox.Aktivuj;
begin
stav:=_aktivni;
mouse.last_lpx:=x;
mouse.last_lpy:=y;
xm:=-mouse.last_lpx;
ym:=-mouse.last_lpy;
end;

Procedure TListBox.Kontrola;
   Procedure VsechnoOdznac;
   var p:PVaznik;
       v:PLBpol;
   begin
   p:=koren^.dalsi;
   while pocetmulti<>0 do
      begin
      v:=p^.vazba;
      if v^.ozn then
         begin
         dec(pocetmulti);
         v^.ozn:=false;
         end;
      p:=p^.dalsi;
      end;
   end;

   Procedure OznacRozsah(p,q:PVaznik);
   var v1,v2:PLBpol;
       r:PVaznik;
       znovu:boolean;
   begin
   v1:=p^.vazba;
   v2:=q^.vazba;
   if v2^.y1<v1^.y1 then begin r:=p;p:=q;q:=r;end;
   r:=p;
   znovu:=true;
   repeat
   v1:=r^.vazba;
   v1^.ozn:=true;
   inc(pocetmulti);
   if r=q then znovu:=false;
   r:=r^.dalsi;
   until znovu=false;
   end;

   Procedure KliknutiDovnitr;
   var p,q:PVaznik;
       v:PLBpol;
       i,j,my:longint;
       s:string;
   begin
   my:=mouse.y-y+poc_zobrY;
   p:=prv_rad;
   while p<>nil do
      begin
      v:=p^.vazba;
      if (my>=v^.y1) and (my<=v^.y2) then
            begin
            if (hodnota=p) and (Mouse_L) then vybrano:=true;
            if v^.y2-poc_ZobrY>virt.hoeheminus1 then
               poc_zobrY:=v^.y2-virt.hoeheminus1;
            if v^.y1-poc_ZobrY<0 then
               poc_zobrY:=v^.y1;
            if (Je_Shift and multi) then
               begin
               VsechnoOdznac;
               OznacRozsah(p,hodnota);
               hodnota:=p;
               end
            else if (Je_CTRL and multi) then
               begin
               if v^.ozn then dec(pocetmulti) else inc(pocetmulti);
               v^.ozn:=not v^.ozn;
               end else hodnota:=p;
            kpocy:=poc_ZobrY;
            if mouse_R and (LB_Mouse_R<>nil) then
               begin
               i:=hodnota^.Kolikaty_ve_vazniku(koren);
               q:=uschovany_pvaznik^.SearchRecord(i);
               LB_Mouse_R(q);

               s:=LB_dej_retezec(q^.vazba);  {co kdyz se retezec zmenil?}
               if s<>v^.s^ then               {bajo, zmenil}
                  begin
                  i:=RychlaVyskaRadky(s);
                  ZrusPString(v^.s);
                  v^.s:=NaPstring(s);
                  j:=v^.y2-v^.y1+1;
                  if i<>j then   {ajaj, a zmenila se i vyska retezce}
                     begin
                     v^.y2:=v^.y1+i-1;   {prepocet Y2 souradnice vybranehi objektu}
                     i:=i-j;
                     p:=p^.dalsi;
                     while p<>nil do
                        begin
                        v:=p^.vazba;     {prepocet Y souradnic vsech nasledujicich}
                        inc(v^.y1,i);    {polozek}
                        inc(v^.y2,i);
                        p:=p^.dalsi;
                        end;
                     inc(py.virtvyska,i);  {o zmene jeste informuju posuvnik}
                     end;
                  end;
               end;
            Exit;
            end;
      p:=p^.dalsi;
      end;
   end;

var i:longint;
Begin
inherited kontrola;
if kresli_posuvnik then
     begin
     if py.kontrola then poc_zobrY:=py.hodnota;
     if py.probehni then Zobraz;
     end;

if not ((stav=_aktivni)or(stav=_escapem)) then
  if Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska) then
     begin {aktivace v pripade kliknuti mysi do pole}
     stav:=_aktivni;
     zobraz;
     mouserel;
     xm:=-mouse.last_lpx;
     ym:=-mouse.last_lpy;
     end else
  else     {tedy stav = _aktivni}
  begin
  if Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska) or
     (mouse.last_lpx=-xm) and (mouse.last_lpy=-ym) then
     begin
     if (mouse.b<>0) and (py.tahaci_stav=false) then
        begin
        stav:=_aktivni;
        if py.probehni=false then KliknutiDovnitr;
        xm:=-mouse.last_lpx;
        ym:=-mouse.last_lpy;
        zobraz;
        mouserel;
        end;
     end {ne uvnitr}
     else begin
     if stav in [_aktivni,_escapem] then
        begin
        stav:=_odkliknutim;
        zobraz;
        end;
     xm:=mouse.last_lpx;
     ym:=mouse.last_lpy;
     Exit;
     end;   {else begin :: uvnitr}
  if (mouse._wdif<>0) and (kresli_posuvnik) then
      begin
      i:={mouse.w-puv_kolecko}mouse._wdif;
      inc(poc_zobrY,i*10);
      if poc_zobrY<0 then poc_zobrY:=0;
      if poc_zobrY>py.virtvyska-py.vyska then poc_zobrY:=py.virtvyska-py.vyska;
      py.hodnota:=poc_zobrY;
      mouse._wdif:=0;        {ne zcela ciste, ale prijatelne}
      zobraz;
      end;
  OsetriVstup;
  end;   {else begin :: not ((stav=_akt...}
{OsetriVstup;}
end;

Procedure TListBox.OsetriVstup;
   Procedure SipkaDolu;
   var v:PLBpol;
   begin
   if hodnota=nil then Exit;          {muze byt - kdyz je prazdny vaznik}
   if hodnota^.dalsi<>nil then
      begin
      hodnota:=hodnota^.dalsi;
      v:=hodnota^.vazba;
      if not kurzor_v_rozsahu then poc_ZobrY:=kpocY;
      if v^.y2-poc_ZobrY>virt.hoeheminus1 then
         begin poc_zobrY:=v^.y2-virt.hoeheminus1;kurzor_v_rozsahu:=false;end;
      if kurzor_v_rozsahu=false then
         begin
         kpocy:=poc_zobrY;
         py.hodnota:=poc_zobrY;
         end;
      end;
   end;

   Procedure SipkaNahoru;
   var v:PLBpol;
   begin
   if hodnota=nil then Exit;          {muze byt - kdyz je prazdny vaznik}
   if hodnota^.predchozi^.predchozi<>nil then
      begin
      hodnota:=hodnota^.predchozi;
      v:=hodnota^.vazba;
      if not kurzor_v_rozsahu then poc_ZobrY:=kpocY;
      if (v^.y1-poc_ZobrY<0) then
         begin poc_zobrY:=v^.y1;kurzor_v_rozsahu:=false;end;
      if kurzor_v_rozsahu=false then
         begin
         kpocy:=poc_zobrY;
         py.hodnota:=poc_zobrY;
         end;
      end;
   end;

   Procedure PageDown;
   var v,v2:PLBpol;
       p,op:pvaznik;
   begin
   if hodnota=nil then Exit;          {muze byt - kdyz je prazdny vaznik}
   if (kurzor_v_rozsahu=false) then
      begin
      poc_zobrY:=kpocy;
      py.hodnota:=kpocy;
      posl_rad:=kposl_rad;
      hodnota:=nil; {ted bude hodnota<>posl_rad takze se splni podminka nize}
      end;
   if (posl_rad=posledni) or (hodnota<>posl_rad) then {jestlize jsme skocili na posledni polozku, tak vime, ze se nebued skrolovat (nebo jen malinko)}
      begin                {preskok na posledni vypsanou radku}
      hodnota:=posl_rad;
      v:=hodnota^.vazba;
      if v^.y2-poc_ZobrY>virt.hoehe{minus1} then
         poc_zobrY:=v^.y2-virt.hoehe{minus1};
      end
      else begin           {skroling}
      v:=posl_rad^.vazba;
      v2:=posledni^.vazba;
      if v2^.y2-v^.y1<virt.hoehe then
         begin poc_zobrY:=v2^.y2-virt.hoeheminus1;hodnota:=posledni;end
         else begin
         poc_zobrY:=v^.y1;
         p:=posl_rad;
         while p<>nil do
            begin
            v2:=p^.vazba;
            if v2^.y1-poc_ZobrY>=virt.hoeheminus1 then
               begin
               op:=p;
               Break;
               end;
            op:=p;
            p:=p^.dalsi;
            end;
         hodnota:=op;
         v2:=op^.vazba;
         if v2^.y2-poc_ZobrY>virt.hoeheminus1 then
            poc_zobrY:=v2^.y2-virt.hoeheminus1;
         end;
      end;
   kpocy:=poc_zobrY;
   py.hodnota:=poc_zobrY;
   end;

   Procedure PageUp;
   var v,v2:PLBpol;
       p,op:PVaznik;
   begin
   if hodnota=nil then Exit;          {muze byt - kdyz je prazdny vaznik}
   if (kurzor_v_rozsahu=false) then
      begin
      poc_zobrY:=kpocy;
      py.hodnota:=kpocy;
      prv_rad:=kprv_rad;
      hodnota:=nil; {ted bude hodnota<>posl_rad takze se splni podminka nize}
      end;
   if (prv_rad=koren^.dalsi) or (hodnota<>prv_rad) then {jestlize jsme skocili na prvni polozku, tak vime, ze se nebued skrolovat (nebo jen malinko)}
      begin                {preskok na posledni vypsanou radku}
      hodnota:=prv_rad;
      v:=hodnota^.vazba;
      if v^.y1-poc_ZobrY<0 then
         poc_zobrY:=v^.y1;
      end
      else begin           {skroling}
      v:=prv_rad^.vazba;
      v2:=koren^.dalsi^.vazba;
      if v^.y2-v2^.y1<virt.hoehe then
         begin poc_zobrY:=0;hodnota:=koren^.dalsi;end
         else begin
         poc_zobrY:=v^.y2-virt.hoeheminus1;
         p:=prv_rad;
         while p^.predchozi<>nil do
            begin
            v2:=p^.vazba;
            if v2^.y1<=poc_ZobrY then
               begin
               op:=p;
               Break;
               end;
            op:=p;
            p:=p^.predchozi;
            end;
         v2:=op^.vazba;
         hodnota:=op;
         poc_ZobrY:=v2^.y1;
         end;
      end;
   kpocy:=poc_zobrY;
   py.hodnota:=poc_zobrY;
   end;

   Procedure KlavesaInsert;
   var v:PLBpol;
   begin
   if multi=false then Exit;
   v:=hodnota^.vazba;
   if v^.ozn then dec(pocetmulti) else inc(pocetmulti);
   v^.ozn:=not v^.ozn;
   SipkaDolu;
   end;

   Procedure KlavesaEscape;
   begin
   stav:=_escapem;
   hodnota:=nil;
   vybrano:=true;
   end;

var o:word;
begin
if xLastKey=0 then Exit;
o:=xLastKey;
xLastKey:=0;
if klPrekladKlaves<>nil then o:=klPrekladKlaves(o,@self);
case o of
   xDSipka:SipkaDolu;
   xHSipka:SipkaNahoru;
   xPGDN:PageDown;
   xPGUP:PageUp;
   xIns:KlavesaInsert;
   xEnter:vybrano:=true;
   xESC:KlavesaEscape;
   else
   xLastKey:=o;
   end;
Zobraz;
end;

Procedure TListbox.OdznacVse;
var v:PLBpol;
    p:Pvaznik;
begin
pocetmulti:=0;
p:=koren^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   v^.ozn:=false;
   p:=p^.dalsi;
   end;
end;

Function TListBox.VratHodnotu:PVaznik;
var i:longint;
    p:Pvaznik;
begin
if hodnota=nil then Exit(nil);
i:=hodnota^.Kolikaty_ve_vazniku(koren);
p:=uschovany_pvaznik^.SearchRecord(i);
VratHodnotu:=p;
end;

Function TListBox.VratMultiHodnotu:PVaznik;
var p,pp,q,r:PVaznik;
    s:string;
    v:PLBpol;
    i,j:longint;
begin
if hodnota=nil then Exit(nil);
p:=New(PVaznik,Init(nil,nil));
if pocetmulti=0 then
   begin
   q:=p^.InitNext(nil);
   q^.vazba:=VratHodnotu^.vazba;
   s:=pstring(q^.vazba)^;
   end
   else begin
   i:=0;
   pp:=p;
   q:=koren^.dalsi;
   r:=uschovany_pvaznik^.dalsi;
   while i<pocetmulti do
      begin
      v:=q^.vazba;
      if v^.ozn then
         begin
         inc(i);
         pp:=pp^.InitNext(r^.vazba);
         end;
      r:=r^.dalsi;
      q:=q^.dalsi;
      end;
   end;
VratMultiHodnotu:=p;
end;

Procedure PLBpol_del(var p:pointer);
var v:PLBpol;
begin
v:=p;
ZrusPString(v^.s);
Dispose(v);
p:=nil;
end;

Destructor TListBox.Done;
begin
Vaznik_Done_All(koren,@PLBpol_del);
Kill_VW(virt);
end;

Constructor TSeznam.Init(ix,iy,isirka,imaxv:longint;p,default:PVaznik;proc:Point2StrFunc);
var hv:boolean;
     i:longint;
     s:string;
     q:PVaznik;
begin
inherited init;
x:=ix;
y:=iy;
sirka:=isirka;
maxvyska:=imaxv;
virtvyska:=0;
if proc=nil then LB_dej_retezec:=@Point2PString else LB_dej_retezec:=proc;
prvky:=p;
q:=p^.dalsi;
while q<>nil do
   begin
   s:=LB_dej_retezec(q^.vazba);
   inc(virtvyska,RychlaVyskaRadky(s));
   q:=q^.dalsi;
   end;

inc(virtvyska,2);

hv:=hned_vykresluj;
hodnota:=default;
hned_vykresluj:=false;
tla.init(x+sirka-dsipka_obrazek.breite,y,'',@dsipka_obrazek,@dsipka_obrazek,$FFFF);
hned_vykresluj:=hv;

if hodnota=nil then i:=dsipka_obrazek.hoehe else
   begin
   s:=LB_dej_retezec(hodnota^.vazba);
   i:=RychlaVyskaRadky(s);
   if i<tla.obr1^.hoehe then i:=tla.obr1^.hoehe;
   end;
mojebarva:=FN_color;
_yy:=y+i+1;
if hned_vykresluj then Zobraz;
end;

Procedure TSeznam.Zobraz;
var s:string;
    p:pchar;
    i:longint;
    hv,dv:longint;
    ob:word;
begin
ufon;
if hodnota=nil then i:=dsipka_obrazek.hoehe else
   begin
   s:=LB_dej_retezec(hodnota^.vazba)+#0;
   p:=@s[1];
   VyskaRadky(p,i,hv,dv);
   dec(s[0]);
   if i<tla.obr1^.hoehe then i:=tla.obr1^.hoehe;
   end;
_yy:=y+i+1;
ob:=FN_color;
FN_color:=mojebarva;
Init_VW(uschova,sirka,i+1,false);
GetSprite(cil^,uschova,x,y);
_box(x,y,x+sirka-tla.obr1^.breite-1,_yy,txtpolelhbarva,txtpolepdbarva,txtpolevbarva);
if hodnota<>nil then print_fn(x+4,y+i-dv+1,s,font);
FN_color:=ob;
tla.zobraz;
ofon;
end;

Procedure TSeznam.RozbalSeznam;
var i:longint;
    b:boolean;
    hv:boolean;
    ob:word;
    vw:virtualwindow;
begin
if virtvyska>maxvyska then
   begin b:=true;i:=maxvyska;end else
   begin b:=false;i:=virtvyska;end;
hv:=hned_vykresluj;
hned_vykresluj:=false;;
Init_VW(vw,sirka,i+2,false);
MouseHide;GetSprite(cil^,vw,x-1,_yy+1);MouseShow;
lb.Init(x,_yy+1,sirka-tla.obr1^.breite-1,i,prvky,LB_dej_retezec,false,true);
lb.kresli_posuvnik:=b;
mouse.last_lpx:=x+1;
mouse.last_lpy:=_yy+2;
hned_vykresluj:=hv;
rectangle(cil^,x-1,_yy+1,x+lb.sirka-Dsipka_obrazek.breite,_yy+i+1,0);
ob:=FN_color;
FN_color:=mojebarva;
lb.Zobraz;
repeat
if xKeyPressed then xReadkey;
lb.kontrola;
until lb.vybrano or (lb.stav<>_aktivni);
if lb.vybrano and (lb.hodnota<>nil) then
   begin
   bylo_vybrano:=true;
   hodnota:=lb.VratHodnotu;
   end else bylo_vybrano:=false;
MouseHide;PutSprite(cil^,vw,x-1,_yy+1);
Kill_VW(vw);
lb.Done;
PutSprite(cil^,uschova,x,y);
MouseShow;
FN_color:=ob;
Kill_VW(uschova);
Zobraz;
end;

Procedure TSeznam.Kontrola;
begin
inherited kontrola;
tla.kontrola;
if tla.klik=1 then RozbalSeznam;
end;

Destructor TSeznam.Done;
begin
PutSprite(cil^,uschova,x,y);
Kill_VW(uschova);
end;
       {**************************************************************}
       { OBJEKT TEDRADEK BYL PRESUNUT DO SAMOSTATNE JEDNOTKY TEDRADKY }
       {**************************************************************}


       {**************************************************************}
       { EDITACNI POLE BYLA PRESUNUTA DO SAMOSTATNE JEDNOTKY EDITPOLE }
       {**************************************************************}

Procedure PosunVaznikuPEdRadek(p:PVaznik;a,j:longint);
var v:PEdRadek;
    i:longint;
begin
if a>0 then i:=1 else i:=-1;
while p<>nil do
   begin
   v:=p^.vazba;
   inc(v^.y1,a);
   inc(v^.y2,a);
   inc(v^.yy,j);
   p:=p^.dalsi;
   end;
end;


Function DelkaNejsirsihoRadku(p:PVaznik):longint;
var v:PEdRadek;
    i:longint;
begin
i:=0;
p:=p^.dalsi;
while p<>nil do
   begin
   v:=p^.vazba;
   if v^.gd>i then i:=v^.gd;
   p:=p^.dalsi;
   end;
DelkaNejsirsihoRadku:=i;
end;

Procedure ZjistiRozmeryTextuPE(texty:PEdRadek;var sirka,vyska:longint;p:PVaznik);
var t:string;
    a,i,j,vy:longint;
    ps:longint;
    v:PEdRadek;
begin
sirka:=0;
vyska:=0;
a:=0;
repeat
inc(a);
i:=pos(#13#10,texty^.p);
if i=0 then j:=texty^.spp-1 else j:=i-1;
t:=texty^.VratString(1,j);
if i<>0 then texty^.Vyjmi(1,j+2);
ps:=Sirka_FN(t,font);
if ps>sirka then sirka:=ps;
vy:=RychlaVyskaRadky(t);
if p<>nil then
   begin
   v:=New(PEdRadek,Init);
   v^.y1:=vyska;
   v^.y2:=vyska+vy-1;
   v^.yy:=a;
   v^.gd:=ps;
   v^.VlozS(t,1);
   p^.InitNext(v);
   end;
inc(vyska,vy);
until i=0;
end;


Procedure ZjistiRozmeryTextu(texty:string;var sirka,vyska:longint;p:PVaznik);
var q:PEdRadek;
begin
q:=New(PEdRadek,Init);
q^.VlozS(texty,1);
ZjistiRozmeryTextuPE(q,sirka,vyska,p);
Dispose(q,Done);
end;

Procedure ZjistiRozmeryTextu(texty:pchar;var sirka,vyska:longint;p:PVaznik);
var q:PEdRadek;
begin
q:=New(PEdRadek,Init);
q^.Vloz(texty,1);
ZjistiRozmeryTextuPE(q,sirka,vyska,p);
Dispose(q,Done);
end;


Procedure PripravText_do_infokna(texty:string;var sirka,vyska:longint;p:PVaznik);
var i,j,k,l,os:longint;
    tt,t:string;
    q:PVaznik;
    v,v2:PEdRadek;
    pp:pchar;
begin
os:=sirka;
ZjistiRozmeryTextu(texty,sirka,vyska,p);  {napred se postaram o hrube rozradkovani}
{totext;}
if sirka<os then Exit;
sirka:=os;
q:=p^.dalsi;
while q<>nil do
   begin
   v:=q^.vazba;
   tt:=SmazMezery_v_tagach(v^.p);
   t:=tt;
   NajdiTag(tt,'MIN_NAP_SIR',t);   {alternativni zadani max. sirky okna}
   if t<>'' then
      sirka:=MyVal(Copy(t,13,Length(t)));
   t:=tt;
   i:=Sirka_FN(t,font);
   v^.gd:=i;
   j:=0;
   if i>sirka then
      begin
      repeat
      j:=BackSearch(t,' ',1);
      if j=0 then
         begin
         t:=t+#0;
         pp:=@t[1];
         k:=pozice_v_retezci(sirka,1,0,0,pp,font);
         dec(t[0]);
         dec(k,FNznakZpet_s(t,k,false,l));
         delete(t,k+1,length(t));
         i:=Sirka_FN(t,font);
         Break;
         end;
      k:=Length(t)-j+1;
      delete(t,k,Length(t));
      i:=Sirka_FN(t,font);
      until (i<=sirka);
      v2:=New(PEdRadek,Init);
      q^.InsertNew(v2);
      v2^.y1:=v^.y1;
      v2^.y2:=v^.y2;
      v2^.yy:=v^.yy;
      v2^.VlozS(Copy(tt,k+1,Length(tt)),1);
      PosunVaznikuPEdRadek(q^.dalsi,v^.y2-v^.y1+1,1);
      v^.gd:=i;
      v^.Vyjmi(1,v^.spp-1);
      v^.VlozS(t,1);
      end;
   q:=q^.dalsi;
   end;
vyska:=v^.y2;
end;

Constructor okno.init(ix,iy,isirka,ivyska:longint;nadpis:string);
Begin
inherited init;
if ChceNaStred(ix) then ix:=ZeStreduX(ix,isirka);
if ChceNaStred(iy) then iy:=ZeStreduY(iy,ivyska);

x:=ix; y:=iy;
sirka:=isirka; vyska:=ivyska;
if (nadpis<>'')and(sirka<_sirkatextu(nadpis)+10) then sirka:=_sirkatextu(nadpis)+10;{rozsireni na sirku nadpisu}
vyska_zahlavi:=RychlaVyskaRadky(nadpis)+4;
mousehide;
init_vw(pozadiokna,sirka+1,vyska+1,false);
getsprite(cil^,pozadiokna,x,y);
_box(x,y,x+sirka,y+vyska,olhbarva,opdbarva,ovbarva);{okno}
if nadpis<>'' then begin
                   _bar(x+2,y+2,x+sirka-3,y+vyska_zahlavi,oobdbarva);{prouzek pro nadpis}
                   _print(x+6,y+4,obarvanadpisu,nadpis);{nadpis}
                   end;
MouseShow;
_data:=nil;
_akce:=nil;
End;{okno.init}

Function okno.Volne_Y:longint;
var p:PVaznik;
    v:PEdRadek;
begin
if _data=nil then Volne_Y:=Vyska_zahlavi+4 else
   begin
   p:=_data^.SearchLast;
   v:=p^.vazba;
   Volne_Y:=vyska_zahlavi+4+v^.y2+1;
   end;
end;

Destructor okno.done;
Begin
mousehide;
inc(sirka);inc(vyska);
PutClippedSprite(cil^,pozadiokna,x,y);
Kill_VW(pozadiokna);
mouseshow;
if _data<>nil then
   Vaznik_Done_all(_data,_akce);
End;

Procedure TextDoOkna(x,y:longint;p:PVaznik);
var s:string;
    vv:PEdRadek;
begin
p:=p^.dalsi;
while p<>nil do
   begin
   vv:=p^.vazba;
   s:=vv^.p;
   _print(x+3,y+vv^.y1,iobarvatextu,s);{vypsani radku}
   p:=p^.dalsi;
   end;
end;

procedure infokno(ix,iy,isirka:longint;hlaska:string;resb:boolean);
var prvni:PVaznik;
    r:virtualwindow;
    sirka,vyska:longint;
    bylkurzor:boolean;{jestli byl pred volanim infokna zapnut kurzor mysi}

begin
if hlaska='' then exit;
sirka:=isirka;          {maximalni sirka okna}
vyska:=100;             {nema vyznam, pozdeji bude prebita}
prvni:=New(PVaznik,Init(nil,nil));

PripravText_do_infokna(hlaska,sirka,vyska,prvni);
if info_okno_presna_sirka=false then
   sirka:=DelkaNejsirsihoRadku(prvni);
inc(sirka,5);
inc(vyska,5);

if ChceNaStred(ix) then ix:=ZeStreduX(ix,sirka)
   else dec(ix,(sirka div 2));{protoze v parametrech ix a iy zadavame stred okna, musi se upravit na levy horni roh}
if ChceNastred(iy) then iy:=ZeStreduY(iy,vyska)
   else dec(iy,(vyska div 2)); {(shr 1 je totez jako div 2, ale je to o trochu rychlejsi)}
OpravVycuhovani(ix,iy,sirka,vyska);

bylkurzor:=mouse.visible;{jestli se ma kurzor po skonceni procedury zapnout}
mousehide;
init_vw(r,sirka+1,vyska+1,false); {alokace}
GetSprite(cil^,r,ix,iy); {nacteni pozadi}
_box(ix,iy,ix+sirka,iy+vyska,iolhbarva,iopdbarva,iovbarva);{vykresleni ramecku}
TextDoOkna(ix,iy+3,prvni);  {vypsani radku}
if bylkurzor then mouseshow;

mouserel; cekej;{ceka se na odkliknuti}
mousehide;
putsprite(cil^,r,ix,iy);
kill_vw(r);
if bylkurzor then mouseshow;

Vaznik_Done_All(prvni,@Mustr_SmazData);
if resb then mouserel;{kdyz resb=false, zustane po odkliknuti okna stale
kliknuto=true. Infokno tak jde pouzit treba na zadani souradnic kliknutim}
End;{infokno}

procedure infokno(ix,iy:longint;hlaska:string;resb:boolean);
begin
infokno(ix,iy,infokno_sirka,hlaska,resb)
end;


procedure mustr_bez_tlacitek(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;popis:string;texty:pchar);
var prvni:PVaznik;
    i,{pomocna}
    maxdelka,{pocet znaku nejdelsiho radku}
    celkova_vyska:longint;

Begin
if texty='' then texty:=' ';{exit;}
{Exit tu uz byt nemuze, protoze se pocita s tim, ze inicializuje okno}
prvni:=New(PVaznik,Init(nil,nil));
ZjistiRozmeryTextu(texty,maxdelka,celkova_vyska,prvni);

if celkova_vyska<ivyska then celkova_vyska:=ivyska;
if maxdelka<idelka then maxdelka:=idelka;

ok:=New(pokno,init(xpoz,
                   ypoz,
        maxdelka+10,{sirka}
        50+celkova_vyska,{vyska}
        popis));{ty mezery tam jsou proto, aby i pri velmi kratkych textech bylo misto na tlacitka}
ok^._akce:=@Mustr_SmazData;

i:=ok^.y+ok^.vyska_zahlavi+2;
MouseHide;
TextDoOkna(ok^.x+5,i,prvni);  {vypsani radku}
MouseShow;
ok^._data:=prvni;
end;

procedure mustr_bez_tlacitek(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;popis,texty:string);
var t:pchar;
begin
texty:=texty+#0;
t:=@texty[1];
mustr_bez_tlacitek(ok,xpoz,ypoz,idelka,ivyska,popis,t);
end;

procedure anoneokno_mustr(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;popis,texty,tla1,tla2:string;var anot,net:ptlacitko);
var x,l:longint;
begin
mustr_bez_tlacitek(ok,xpoz,ypoz,idelka,ivyska,popis,texty);
x:=ok^.x+ok^.sirka div 2;
l:=Sirka_FN(tla1,font)+4;
anot:=New(PTlacitko,init(x-l-20,ok^.y+ok^.vyska-25,tla1,'',0,2));
net:=New(PTlacitko,init(x+20,ok^.y+ok^.vyska-25,tla2,'',0,2));
end;

procedure anonezrusokno_mustr(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;popis,texty,tla1,tla2,tla3:string;var anot,net,zrust:ptlacitko);
var x,l:longint;
begin
if idelka<225 then idelka:=225;
mustr_bez_tlacitek(ok,xpoz,ypoz,idelka,ivyska,popis,texty);
x:=ok^.x+ok^.sirka div 2;
l:=Sirka_FN(tla1,font)+4;
anot:=New(PTlacitko,init(x-l-45,ok^.y+ok^.vyska-25,tla1,'',0,2));

l:=Sirka_FN(tla2,font)+4;
net:=New(PTlacitko,init(x-l div 2,ok^.y+ok^.vyska-25,tla2,'',0,2));

zrust:=New(PTlacitko,init(x+45,ok^.y+ok^.vyska-25,tla3,'',0,2));
end;

function polohovane_anonezrusokno(xpoz,ypoz:longint;texty:string):byte;
var ok:pokno;
    anot,net,zrust:ptlacitko;
    ch:char;
    stav:shortint;{pomocna, pro zaverecny cyklus}
begin
anonezrusokno_mustr(ok,xpoz,ypoz,0,0,_ANONE_DOTAZ,texty,_ANO,_NE,_CANCEL,anot,net,zrust);
ch:=' '; stav:=-1;
 repeat
 mouserel;
 {cekej;}
 if xKeyPressed then begin
                    ch:=char(xreadkey);
                    if ch in [{'a','A',}#13] then stav:=1
                     else if ch in [{'n','N',}#27] then stav:=0;
                    end;
 anot^.kontrola; net^.kontrola; zrust^.kontrola;
 if anot^.hodnota=1 then stav:=1;
 if net^.hodnota=1 then stav:=0;
 if zrust^.hodnota=1 then stav:=2;
 until stav<>-1;
polohovane_anonezrusokno:=stav;
Dispose(anot,done);
Dispose(net,done);
Dispose(ok,done);
mouserel;
End;{anoneokno}



procedure anoneokno_mustr(var ok:pokno;idelka,ivyska:longint;popis,texty,tla1,tla2:string;var anot,net:ptlacitko);
begin
anoneokno_mustr(ok,NA_STRED,NA_STRED,idelka,ivyska,popis,texty,tla1,tla2,anot,net);
end;

function polohovane_anoneokno(xpoz,ypoz:longint;texty:string):boolean;
var ok:pokno;
    anot,net:ptlacitko;
    ch:char;
    stav:(sneurcen,sano,sne);{pomocna, pro zaverecny cyklus}
begin
anoneokno_mustr(ok,xpoz,ypoz,0,0,_ANONE_DOTAZ,texty,_ANO,_NE,anot,net);
ch:=' '; stav:=sneurcen;
 repeat
 mouserel;
 {cekej;}
 if xKeyPressed then begin
                    ch:=char(xreadkey);
                    if ch in [{'a','A',}#13] then stav:=sano
                     else if ch in [{'n','N',}#27] then stav:=sne;
                    end;
 anot^.kontrola; net^.kontrola;
 if anot^.hodnota=1 then stav:=sano;
 if net^.hodnota=1 then stav:=sne;
 until stav<>sneurcen;
polohovane_anoneokno:=stav=sAno;
Dispose(anot,done);
Dispose(net,done);
Dispose(ok,done);
mouserel;
End;{anoneokno}

function anoneokno(texty:string):boolean;
begin
anoneokno:=polohovane_anoneokno(NA_STRED,NA_STRED,texty);
end;

procedure okokno_mustr(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;titulek,texty:string;var oukej:ptlacitko);
begin
mustr_bez_tlacitek(ok,xpoz,ypoz,idelka,ivyska,titulek,texty);
oukej:=new(ptlacitko,init(ok^.x+(ok^.sirka shr 1)-30,ok^.y+ok^.vyska-25,_OK,'',0,2));
end;

procedure okokno_mustr(var ok:pokno;idelka,ivyska:longint;titulek,texty:string;var oukej:ptlacitko);
begin
okokno_mustr(ok,NA_STRED,NA_STRED,idelka,ivyska,titulek,texty,oukej);
end;

procedure okokno_mustr(var ok:pokno;xpoz,ypoz,idelka,ivyska:longint;titulek:string;texty:pchar;var oukej:ptlacitko);
begin
mustr_bez_tlacitek(ok,xpoz,ypoz,idelka,ivyska,titulek,texty);
oukej:=new(ptlacitko,init(ok^.x+(ok^.sirka shr 1)-30,ok^.y+ok^.vyska-25,_OK,'',0,2));
end;

procedure okokno_mustr(var ok:pokno;idelka,ivyska:longint;titulek:string;texty:pchar;var oukej:ptlacitko);
begin
okokno_mustr(ok,NA_STRED,NA_STRED,idelka,ivyska,titulek,texty,oukej);
end;


Procedure OKokno(titulek:string;texty:pchar);
var oukej:PTlacitko;
    ok:Pokno;
    konecb:boolean;
begin
OKokno_mustr(ok,0,0,titulek,texty,oukej);
konecb:=false;
 repeat
 mouserel;cekej;
 oukej^.kontrola;
 if oukej^.hodnota=1 then konecb:=true;
 if xKeyPressed and (xreadkey in [word(' '),word(#13)]) then konecb:=true;
 until konecb;
Dispose(ok,Done);
Dispose(oukej,Done);
mouserel;
End;{okokno}

Procedure OKokno(titulek,texty:string);
var t:pchar;
begin
texty:=texty+#0;
t:=@texty[1];
OKokno(titulek,t);
end;

Constructor Dialog.Init(_nadpis:string;idelka:longint;_defaulttext:string);
begin
defaulttext:=_defaulttext;
sirka_tlacitek:=Sirka_FN(_CANCEL,font)+Sirka_FN(_OK2,font)+20;
if idelka<sirka_tlacitek+60 then idelka:=sirka_tlacitek+60;
delka:=idelka;
nadpis:=_nadpis;
delkaradky:=delka-sirka_tlacitek;
end;

Procedure Dialog.Zobraz;
var okb,cancelb:boolean;
    i,j:longint;
begin
okb:=false;
cancelb:=false;
i:=RychlaVyskaRadky(nadpis)+4;
j:=Vyska_FN_default;
okynko.init(_maxx shr 1-delka div 2,_maxy shr 1-30,delka,{50}i+j+12,nadpis);
with okynko do
   begin
   tp.init(x+2,y+vyska_zahlavi+6,delkaradky,defaulttext,true,false);
   i:=x+delkaradky+4;
   okt.init(i,y+vyska_zahlavi+7,_OK2,_DIALOG_ZOBRAZ_OK,0,1);
   inc(i,sirka_fn(_OK2,font)+8);
   cancelt.init(i,y+vyska_zahlavi+7,_CANCEL,_DIALOG_ZOBRAZ_ZRUS,0,1);
   end;
mouserel;
   repeat
   {cekej;}
   {if xKeyPressed then o:=xreadkey else o:=0;}
   tp.kontrola;
   if tp.stav<>_aktivni then        {normalne se o klavesnici postara}
      if xKeyPressed then xreadkey; {textove pole, ale kdyz neni aktivni, tak to musim udelat sam}
   okt.kontrola; cancelt.kontrola;
   if (okt.hodnota=1)or(tp.stav=_enterem)or(xLastKey=13) then
      begin
      hodnota:=tp.hodnota;
      if Validator then okb:=true;
      end;

   if (cancelt.hodnota=1)or(tp.stav=_escapem)or(xLastKey=27) then cancelb:=true;
   until okb or cancelb;
tp.Done;
if cancelb then hodnota:=defaulttext;
bylo_cancel:=cancelb;
end;

Function Dialog.Validator:boolean;
begin
Validator:=true;
end;

Destructor Dialog.Done;
begin
okynko.done;
end;

Constructor Ciselny_dialog.Init(_nadpis:string;_od,_do,_defaulttext:longint);
var a,b:byte;
begin
a:=PocetRadu(_od);
b:=PocetRadu(_do);
if b>a then a:=b;
inherited Init(_nadpis,a,mystr(_defaulttext));
__od:=_od;
__do:=_do;
end;

Destructor Ciselny_dialog.Done;
begin
inherited Done;
end;

Function Ciselny_dialog.Validator:boolean;
var l:longint;
    i:integer;
begin
Validator:=false;
Val(hodnota,l,i);
if (i=0) and (hodnota<>'') then
   if (l>=__od) and (l<=__do) then Validator:=true;
end;

Function Souborovy_dialog.Validator:boolean;
var a:longint;
begin
Validator:=hodnota<>'';
for a:=1 to Length(hodnota) do
    if byte(hodnota[a])<128 then
       if not (hodnota[a] in pro_nazvy_souboru) then exit(false);
end;


function vloztextokno(nadpis:string;idelka:longint;defaulttext:string;prosoubor:boolean):string;
var d:Pdialog;
Begin
if nadpis='' then nadpis:=_VLOZ_TEXT^;
while byte(nadpis[0])<11 do nadpis:=nadpis+' ';
if prosoubor then d:=New(PSouborovy_dialog,Init(nadpis,idelka,defaulttext)) else
                  d:=New(Pdialog,Init(nadpis,idelka,defaulttext));
d^.Zobraz;
vloztextokno:=d^.hodnota;
Dispose(d,Done);
end;

function vlozcislookno(nadpis:string;_od,_do,default:longint):longint;
var d:ciselny_dialog;
Begin
d.init(nadpis,_od,_do,default);
d.Zobraz;
d.Done;
End;{vlozcislookno}

function NamixujBarvu(nadpis:string;default:word):word;
  Procedure ObnovObdelnik(x,y:longint;rh,gh,bh:byte);
  var mix:word;
      ff:word;
  begin
  mix:=RGB2word(rh,gh,bh);
  MouseHide;
  Bar(cil^,x+71,y,x+250,y+59,ovbarva);
  Bar(cil^,x+1,y+5,x+69,y+39,mix);
  Print_FN(x+155,y+15,Mystr(rh),font);
  Print_FN(x+155,y+31,Mystr(gh),font);
  Print_FN(x+155,y+47,Mystr(bh),font);
  ff:=FN_color;
  FN_color:=65535;
  Rectangle(cil^,x+182,y+15,x+248,y+32,0);
  Print_FN(x+185,y+31,'= '+Mystr(mix),font);
  FN_color:=ff;
  rh:=round(rh/31*255);
  gh:=round(gh/63*255);
  bh:=round(bh/31*255);
  Print_FN(x+80,y+15,Mystr(rh),font);
  Print_FN(x+80,y+31,Mystr(gh),font);
  Print_FN(x+80,y+47,Mystr(bh),font);
  Print_FN(x+110,y+15,'(#'+dec2hex(rh)+')',font);
  Print_FN(x+110,y+31,'(#'+dec2hex(gh)+')',font);
  Print_FN(x+110,y+47,'(#'+dec2hex(bh)+')',font);
  MouseShow;
  end;

const SIRKA=350;
      VYSKA=150;
var ok:okno;
    okt,zrt:Tlacitko;
    hotovo,rk,gk,bk:boolean;
    r,g,b:Posuvnik;
    x,y,s:longint;
    rh,gh,bh:byte;
    o,otv,mix:word;
begin
ok.init(NA_STRED,NA_STRED,SIRKA,VYSKA,nadpis);{okno}
x:=ok.x+2;
y:=ok.y+ok.vyska_zahlavi+1;
s:=SIRKA-4;
mix:=default;
okt.init(x+s-2-60,y+4,_OK,'',60,1);
zrt.init(x+s-2-60,y+24,_CANCEL,'',60,1);
hotovo:=false;
word2RGB(default,rh,gh,bh);
ObnovObdelnik(x,y,rh,gh,bh);
otv:=tvbarva;
tvbarva:=64000;r.Init(x,y+60,s,32*s,rh*(s),s,poHORZ);
tvbarva:=1728;g.Init(x,y+80,s,64*s,gh*(s),s,poHORZ);
tvbarva:=30;b.Init(x,y+100,s,32*s,bh*(s),s,poHORZ);
Rectangle(cil^,x,y+4,x+70,y+40,0);
repeat
if xKeypressed then o:=xReadkey;
okt.kontrola;
zrt.kontrola;
tvbarva:=64000;rk:=r.kontrola;
tvbarva:=1728;gk:=g.kontrola;
tvbarva:=30;bk:=b.kontrola;
tvbarva:=otv;
if rk or gk or bk then
   begin
   rh:=r.hodnota div s;
   gh:=g.hodnota div s;
   bh:=b.hodnota div s;
   ObnovObdelnik(x,y,rh,gh,bh);
   end;
if (o=xEnter) or (okt.hodnota=1) then
   begin
   mix:=Rgb2word(rh,gh,bh);
   hotovo:=true;
   end;
if (o=xESC) or (zrt.hodnota=1) then begin mix:=default;hotovo:=true;end;
until hotovo;
ok.done;
NamixujBarvu:=mix;
end;

function vyberbarvuokno(nadpis:string;default:byte):word;
const SIRT = 50;
var ok:okno;
    vybrana,vybrana2:word;
    okt,cancelt:tlacitko;
    hotovo:boolean;
    i,j:word;
    lhx,lhy,sirka,vyska:longint;
    h,n:longint;
    s:string;
Begin
mouserel;
if nadpis='' then nadpis:=_VYBER_BARVU;
vybrana:=default; vybrana2:=vybrana; hotovo:=false;
s:=_OK;
s:=s+_CANCEL;
s:=s+_PALETA;
h:=RychlaVyskaRadky(s);
n:=16*10+RychlaVyskaRadky(nadpis)+4+8;
sirka:=164;
vyska:=n+h;
ok.init(NA_STRED,NA_STRED,SIRKA,VYSKA,nadpis);{okno}
with ok do begin
           lhx:=x+2;
           lhy:=y+vyska_zahlavi+2;
           h:=y+ok.vyska-h-4;
           MouseHide;
           for i:=0 to 15 do for j:=0 to 15 do {barvy}
             _bar(lhx+10*j,lhy+10*i,lhx+10*j+9,lhy+10*i+9,vga2word(i shl 4+j));
           MouseShow;
           okt.init(ok.x+2,h,_OK2,_VYBER_BARVU_POTVRD,SIRT,1);   {tlacitka}
           cancelt.init(ok.x+sirka-SIRT-2,h,_CANCEL,_VYBER_BARVU_ZRUS,SIRT,1);
           end;
MouseHide;
 repeat
 {znacka:}
 rectangle(cil^,(vybrana and 15)*10+lhx+1,(vybrana shr 4)*10+lhy+1,(vybrana and 15)*10+lhx+9,(vybrana shr 4)*10+lhy+9,0);
 rectangle(cil^,(vybrana and 15)*10+lhx,(vybrana shr 4)*10+lhy,(vybrana and 15)*10+lhx+8,(vybrana shr 4)*10+lhy+8,14);
 _napis(lhx+okt.sirka+20,h,txtbarva,tvbarva,mystr2(vybrana,3));{vypis cisla barvy}
 mouseshow;
 cekej;
 if mouse.b<>0 then
    if mouseinarea(lhx,lhy,lhx+159,lhy+159) then
       begin{vyber barvy mysi}
       vybrana2:=(mouse.x-lhx) div 10+((mouse.y-lhy) div 10)shl 4;
       mouserel;
       end;

 if xKeypressed then
    case xReadkey of
       13:begin VyberBarvuOkno_Zruseno:=false;hotovo:=true;end;{Enter}
       27:begin vybrana2:=default;VyberBarvuOkno_Zruseno:=true;hotovo:=true; end;{Escape}
       xlsipka:if vybrana2>0 then dec(vybrana2) else vybrana2:=255;
       xpsipka:if vybrana2<255 then inc(vybrana2) else vybrana2:=0;
       xhsipka:begin
               dec(vybrana2,16);
               if vybrana2<0 then inc(vybrana2,256);
               end;
       xdsipka:begin
               inc(vybrana2,16);
               if vybrana2>255 then dec(vybrana2,256);
               end;
       xhome:dec(vybrana2,vybrana2 and 15);{konec radku}
       xendk:inc(vybrana2,integer(15)-vybrana2 and 15);{zacatek radku}
    end;

 okt.kontrola; cancelt.kontrola;

 if okt.klik=1 then
    begin
    VyberBarvuOkno_Zruseno:=false;
    hotovo:=true;
    end;
 if cancelt.klik=1 then
    begin
    vybrana2:=default;
    VyberBarvuOkno_Zruseno:=true;
    hotovo:=true;
    end;

 mousehide;
 {zruseni znacky:}
 _bar((vybrana and 15)*10+lhx,(vybrana shr 4)*10+lhy,(vybrana and 15)*10+lhx+9,(vybrana shr 4)*10+lhy+9,vga2word(vybrana));
 vybrana:=vybrana2;
 until hotovo;
vyberbarvuokno:=vga2word(vybrana2);
MouseShow;
ok.done;
End;{vyberbarvuokno}

function vyberhicolorbarvuokno(nadpis:string;default:word):word;
const SIRT = 60;
var ok:okno;
    vybrana,pv:word;
    okt,cancelt,vga,mix:tlacitko;
    hotovo:boolean;
    o:word;{na cteni klaves}
    i,j:word;
    lhx,lhy:longint;
    sirka,vyska,h,n:longint;
    s:string;
Begin
s:=_MIXBAREV;
s:=_OK;
s:=s+_CANCEL;
s:=s+_PALETA;
h:=RychlaVyskaRadky(s);
n:=128+128+RychlaVyskaRadky(nadpis)+4+4;
sirka:=260;
vyska:=n+h+30;
mouserel;
if nadpis='' then nadpis:=_VYBER_BARVU;
vybrana:=default; hotovo:=false;
ok.init(NA_STRED,NA_STRED,SIRKA,VYSKA,nadpis);{okno}
with ok do begin
           lhx:=x+2;
           lhy:=y+vyska_zahlavi+2;
           n:=ok.vyska-h-4;
           h:=ok.y+ok.vyska_zahlavi+128+128+4;
           MouseHide;
           for i:=0 to 127 do for j:=0 to 127 do PutPixel(cil^,lhx-i+127,lhy-j+127,MyRGB2word(i*2,j*2,0));
           for i:=0 to 127 do for j:=0 to 127 do PutPixel(cil^,lhx+i+128,lhy-j+127,MyRGB2word(i+j,i+j,i+j));
           for i:=0 to 127 do for j:=0 to 127 do PutPixel(cil^,lhx-i+127,lhy+j+128,MyRGB2word(i*2,0,j*2));
           for i:=0 to 127 do for j:=0 to 127 do PutPixel(cil^,lhx+i+128,lhy+j+128,MyRGB2word(0,i*2,j*2));
           MouseShow;
           okt.init(ok.x+2,y+n,_OK,'',SIRT,1);   {tlacitka}
           cancelt.init(ok.x+2+SIRT+20,y+n,_CANCEL2,'',SIRT,1);
           vga.init(ok.x+2+SIRT*2+20+20,y+n,_PALETA,_VYBER_HIC_PALETA,SIRT,1);   {tlacitka}
           i:=_sirkatextu(_MIXBAREV);
           if i<SIRT then i:=SIRT;
           mix.init(ok.x+2+SIRT+20,h,_MIXBAREV,_MIX_HIC_BAREV,i,1);
           end;

i:=ok.x+2;
MouseHide;
 repeat
 {znacka:}
 Bar(cil^,i+1,h+1,i+15,h+16,vybrana);
 Rectangle(cil^,i,h,i+16,h+17,0);
 Bar(cil^,i+25,h,i+79,h+17,tvbarva);
 _napis(i+25,h,txtbarva,tvbarva,mystr(vybrana));

 mouseshow;
 cekej;
 if mouse.b<>0 then
    if mouseinarea(lhx,lhy,lhx+255,lhy+255) then
       begin
       mouserel;
       MouseHide;
       vybrana:=GetPixel(cil^,mouse.x,mouse.y);
       MouseShow;
       end;

 if xKeyPressed then
    begin
    o:=xreadkey;
    if o=xEnter then
       begin
       VyberBarvuOkno_Zruseno:=false;
       hotovo:=true
       end else
    if o=xESC then
       begin
       vybrana:=default;
       VyberBarvuOkno_Zruseno:=true;
       hotovo:=true;
       end;
    BufferOff;  {pocka na uvolneni klavesy}
    end;

 okt.kontrola; cancelt.kontrola; vga.kontrola; mix.kontrola;
 mouserel;

 if vga.klik=1 then
    begin
    pv:=VyberBarvuOkno(_Z_PALETY,15);
    if not VyberBarvuOkno_Zruseno then vybrana:=pv;
    end;

 if mix.klik=1 then
    begin
    vybrana:=NamixujBarvu(_MIX_HIC_BAREV,vybrana);
    end;

 if okt.klik=1 then
    begin VyberBarvuOkno_Zruseno:=false;hotovo:=true;end;
 if cancelt.klik=1 then
    begin
    vybrana:=default;
    VyberBarvuOkno_Zruseno:=true;
    hotovo:=true;
    end;
 mousehide;
 until hotovo;
MouseShow;
vyberhicolorbarvuokno:=vybrana;
ok.done;
End;{vyberbarvuokno}


procedure zjistujsouradnice;
const vlevo=10;
var bylkurzor:boolean;
    ok:okno;
    px:integer;{pomocna x-ova souradnice}
    mx,my:integer;
    l:longint;
    p1,p2:virtualwindow;
    barva:byte;{barva zamerovaciho krize}
    vpravo:word;{pomocna souradnice}
{}procedure vypis;{vypise do okenka souradnice kurzoru}
{}Begin
{}with ok do _box(x,y,x+sirka,y+vyska,iolhbarva,iopdbarva,iovbarva);{smazani starych cisel}
{}_print(ok.x+3,ok.y+1,0,mystr2(mouse.x,3)+':'+mystr2(mouse.y,3));{vypsani novych cisel do okenka}
{}End;{vypis}
Begin{zjistujsouradnice}
vpravo:=_maxx-89;
barva:=15;
bylkurzor:=mouse.visible;{ulozeni kurzoru}
mousehide;
mouserel;
if mouse.x>320 then px:=vlevo else px:=vpravo;{urceni polohy okenka}
l:=vyska_fn(font);
ok.init(px,_maxy-l-10,60,l,'');
init_vw(p1,_maxx+1,1,false);
init_vw(p2,1,_maxy+1,false);
mx:=mouse.x; my:=mouse.y;
vypis;
 repeat
 {zamerovaci kriz:}
 getsprite(cil^,p1,0,my);    {vodorovna}
 getsprite(cil^,p2,mx,0);    {svisla}
 _hline(0,_maxx,my,barva);
 _vline(mx,0,_maxy,barva);
  repeat
  WhatAboutMouse;
  if mouse_r then begin{zmena barvy zamerovaciho krize}
               barva:=barva xor 15;
               _hline(0,_maxx,my,barva);
               _vline(mx,0,_maxy,barva);
               mouserel;
               end;
  until (mouse.x<>mx)or(mouse.y<>my)or mouse_l or xKeyPressed;
 putsprite(cil^,p1,0,my);
 putsprite(cil^,p2,mx,0);
 mx:=mouse.x; my:=mouse.y;
 if (abs(mouse.x-(px+30))<40)and(mouse.y>_maxy-59) then begin{pokud se kurzorem blizime k okenku...}
                                                  ok.done;{...presune se na druhy konec obrazovky, aby neprekazelo:}
                                                  if px=vlevo then px:=vpravo
                                                              else px:=vlevo;
                                                  ok.init(px,_maxy-l-10,60,l,'');
                                                  end;
 vypis;
 until mouse_l or xKeyPressed;
kill_vw(p1);
kill_vw(p2);
ok.done;
if bylkurzor then mouseshow;
End;{zjistujsouradnice}


{=================-Satelitni rutiny funkce Fileselector-==================}
Function VyberSokno_2_soubor(p:pointer):string;
var v:UKnaTsoubor;
    k,s:string;
    i:longint;
    c:char;
begin
v:=p;
s:=v^.jmeno^+'.'+v^.koncovka^;
k:=Convert_UP('.'+v^.koncovka^+'|');
i:=Search(vybersoubor_priv_koncovky,k,1);
if i<>0 then
   begin
   c:=vybersoubor_priv_koncovky[i+Length(v^.koncovka^)+2];
   if c='|'
      then s:='<BARVA='+mystr(ttxtextra2barva)+'>'+s+'<SB>'
      else s:='<BARVA='+mystr(ttxtextra1barva)+'>'+s+'<SB>';
   end;
VyberSokno_2_soubor:=s;
end;

Function VyberSokno_2_adresar(p:pointer):string;
var v:UKnaTsoubor;
    s:string;
begin
v:=p;
s:=v^.jmeno^;
VyberSokno_2_adresar:=s;
end;

Function VyberSokno_disk(p:pointer):string;
var v:pstring;
begin
v:=p;
VyberSokno_disk:=v^;
end;

Procedure VyberSOkno_ZrusPS(var p:pointer);
var v:Pstring;
begin
v:=p;
ZrusPString(v);
p:=nil;
end;

Function PredkousejKoncovky(s:string):string;
var a,i:byte;
begin
a:=1;
i:=Length(s);
while a<=i do
   begin
   if s[a]='|' then
      begin
      if (a<i) and (s[a+1]<>'|') then
         begin
         insert('.',s,a+1);
         inc(i);
         inc(a);
         end;
      end;
   inc(a);
   end;
insert('.',s,1);
s:=Convert_Up(s)+'|';
PredkousejKoncovky:=s;
end;

{...........................................................................}
function Fileselector(nadpis,maska,koncovky:string;vyska:longint;moznosti:byte):PVaznik;
var ok:okno;
    okt,cancelt,novyt,infot,diskt:tlacitko;
    su,au,
    seznam_souboru,  {hlava seznamu vsech souboru v adresari}
    vystup,seznam_adresaru:PVaznik; {hlava seznamu vsech podadresaru v adresari}
    mojedisky,ret:string;
    pocetdisku:byte;
    cesta:array[1..20] of string;
    csd:byte;           {cislo akt. disku}
    lbs,lba:TListBox;

    soubor:uknatsoubor;         {vlastni udaje o souboru}
                   {oboje navazano na seznam_souboru nebo na seznam_adresaru}

    lhxa,lhxs,lhxt,lhy:integer;{souradnice okna a jeho casti}
    sirka:longint;
    vyska_textu:longint;
    sirka_tlacitka:longint;
    multi,adresareB,noveB,zmena_udaju,hns:boolean;

{}procedure info(p:PVaznik);
{}var dt:datetime;
{}    atr:string[45];
{}Begin
{}if p=nil then begin infokno(lhxa+50,lhy+40,_FS_VYBER_NECO,true);Exit;end;
{}soubor:=p^.vazba;
{}with soubor^ do
{}  begin
{}  atr:='';            {slozeni popisu atributu:}
{}  if atributy and ReadOnly=readonly then atr:=_FS_PRO_CTENI;
{}  if atributy and Hidden=hidden then atr:=atr+_FS_SKRYTY;
{}  if atributy and SysFile=sysfile then atr:=atr+_FS_SYSTEMOVY;
{}  if atributy and Archive=archive then atr:=atr+_FS_ARCHIVOVAT;
{}  if atr='' then atr:=_FS_ZADNE
{}            else begin
{}                 dec(byte(atr[0]));{odmazani mezery na konci}
{}                 atr[byte(atr[0])]:='.';{misto carky na konec tecku}
{}                 end;
{}  unpacktime(soubor^.zmeneno,dt);
{}  okokno(_FS_ZPRAVA,_FS_SOUBOR+jmeno^+'.'+koncovka^+#13#10+
{}         _FS_VELIKOST+mystr(velikost)+_FS_B^+mystr(velikost shr 10)+_FS_KB+#13#10+
{}         _FS_POSL_ZMENA+mystr(dt.day)+'.'+mystr(dt.month)+'.'+mystr(dt.year)
{}            +', '+mystr(dt.hour)+':'+mystr3(dt.min,2)+':'+mystr3(dt.sec,2)+#13#10+
{}         _FS_ATRIBUTY+atr);
{}  end;
{}End;{info}
{}
{}Procedure PridejTlacitko(tlacidlo:tlacitko;poloha_y:longint;text,napoveda:string);
{}begin
{}tlacidlo.init(lhxt,poloha_y,text,napoveda,sirka_tlacitka,1);
{}end;
{}
{}procedure VypisCestu;{vypise aktualni cestu}
{}var h:longint;
{}Begin
{}h:=lhy+vyska-vyska_textu-5;
{}mousehide;
{}_box(lhxa,h,lhxa+sirka-5,lhy+vyska-2,opdbarva,olhbarva,ovbarva);
{}_print(lhxa+2,h+1,txtbarva,zkratcestu(cesta[csd]+maska,30));
{}mouseshow;
{}End;{cvypis}
{}
{}
{}
{}Procedure Vyres_Disky_a_cesty;
{}var c:char;
{}    s:string;
{}    a:byte;
{}begin
{}mojedisky:=LogDisk;
{}pocetdisku:=Length(mojedisky);
{}for a:=1 to pocetdisku do cesta[a]:=mojedisky[a]+':\';
{}s:=FExpand(maska);
{}c:=UpCase(s[1]);
{}csd:=Pos(c,mojedisky);
{}maska:=StripName(s)+StripExt(s);
{}cesta[csd]:=StripPath(s);
{}end;
{}
{}Procedure ZmenCestu(p:PVaznik);
{}var v:UKnaTadresar;
{}    b:byte;
{}    s:string;
{}begin
{}v:=p^.vazba;
{}s:=v^.jmeno^;
{}if v^.jmeno^<>'..' then cesta[csd]:=cesta[csd]+s+'\'
{}   else begin
{}   b:=BackSearch(cesta[csd],'\',2);
{}   cesta[csd]:=Copy(cesta[csd],1,Length(cesta[csd])-b+1);
{}   end;
{}end;
{}
{}Procedure ZmenaDisku;
{}var lb:TListBox;
{}     p,q:PVaznik;
{}     n:longint;
{}     v:virtualwindow;
{}     a:byte;
{}begin
{}p:=New(PVaznik,Init(nil,nil));
{}for a:=1 to pocetdisku do
{}    p^.InitNext(NaPstring(mojedisky[a]));
{}n:=pocetdisku*vyska_textu+5;
{}Init_VW(v,65,n,false);
{}MouseHide;
{}GetSprite(cil^,v,lhxt,lhy+40);
{}MouseShow;
{}lb.init(lhxt,lhy+40,40,n,p,@VyberSokno_disk,false,true);
{}for a:=1 to csd-1 do
{}    lb.hodnota:=lb.hodnota^.dalsi;
{}lb.Zobraz;
{}repeat
{}if xkeypressed then xReadkey;
{}lb.kontrola;
{}until lb.vybrano;
{}if lb.hodnota<>nil then
{}   begin
{}   q:=lb.VratHodnotu;
{}   a:=q^.Kolikaty_ve_vazniku(p);
{}   csd:=a;
{}   end;
{}MouseHide;
{}PutSprite(cil^,v,lhxt,lhy+40);
{}MouseShow;
{}Kill_VW(v);
{}Vaznik_Done_All(p,@VyberSOkno_ZrusPS);
{}lb.Done;
{}end;
{}
{}Procedure UklidPoSobe;
{}begin
{}lbs.Done;
{}zrusseznamsouboru(seznam_souboru);
{}if adresareb then
{}   begin
{}   lba.Done;
{}zrusseznamadresaru(seznam_adresaru);
{}   end;
{}end;

Begin{fileselector}
if nadpis='' then nadpis:=_FS_VYBER_SOUBOR;
sirka:=_sirkatextu(nadpis)+10;
if sirka<400 then sirka:=400;

lhxa:=_maxx shr 1-sirka shr 1; { kam vypisovat soubory }
lhxs:=lhxa+sirka div 3;        { a kam adresare }
lhy:=_maxy shr 1-vyska shr 1;
mouserel;

ok.init(lhxa,lhy,sirka,vyska,nadpis);
inc(lhy,ok.vyska_zahlavi+4);
dec(vyska,ok.vyska_zahlavi+4);
inc(lhxa,3);
hns:=true;
vystup:=nil;
multi:=moznosti<128;
sirka_tlacitka:=_sirkatextu(_CANCEL)+10;
vyska_textu:=Vyska_FN_default;
lhxt:=lhxa+sirka-sirka_tlacitka-6;
adresareB:=not odd(moznosti);
noveB:=(moznosti and 2) = 2;
lba.vybrano:=false;  {alespon zcela minimalni inicializace pro pripad}
                     {kdy "adresareB"=false}

if noveB then novyt.init(lhxt,lhy,_NOVY,_FS_NOVY_SOUBOR,sirka_tlacitka,1);
infot.init(lhxt,lhy+20,_FS_INFO,_FS_INFO_O_SOUBORU,sirka_tlacitka,1);
if adresareb then diskt.init(lhxt,lhy+40,_FS_DISK,_FS_PREPNOUT_DISK,sirka_tlacitka,1);
okt.init(lhxt,lhy+64,_OK,_FS_POTVRD_SOUBOR,sirka_tlacitka,1);
cancelt.init(lhxt,lhy+84,_CANCEL,_FS_ZRUS_VYBER,sirka_tlacitka,1);

vybersoubor_priv_koncovky:=PredkousejKoncovky(koncovky);
Vyres_Disky_a_cesty;

repeat
zmena_udaju:=false;
seznamsouboru(seznam_souboru,cesta[csd]+maska);  {seznam}
if seznam_souboru^.dalsi=nil then hns:=false;
lbs.init(lhxs,lhy,lhxt-lhxs-20,vyska-vyska_textu-5,seznam_souboru,@VyberSokno_2_soubor,multi,hns);
lbs.Zobraz;
if adresareb then
   begin
   seznamadresaru(seznam_adresaru,cesta[csd]+'*.*');
   VypisCestu;
   lba.init(lhxa,lhy,lhxs-lhxa-20,vyska-vyska_textu-5,seznam_adresaru,@VyberSokno_2_adresar,false,not hns);
   if hns=false then lba.aktivuj;
   lba.Zobraz;
   end;
hns:=false;

   repeat
   if xKeyPressed then xReadKey;   {cteni z klavesnice}

   lbs.kontrola;                   {postarej se o pole souboru}
   if adresareb then lba.kontrola; {postarej se o pole adresaru}
   if lba.vybrano then
      begin                        {uzivatel vybral nejaky adresar?}
      if lba.stav=_escapem then
         begin zmena_udaju:=true;lbs.vybrano:=true;lbs.hodnota:=nil;end
         else begin
         au:=lba.VratHodnotu;
         if au<>nil then                    {vzdy, pokud neni adresarove pole prazdne}
            begin
            ZmenCestu(au);                  {zmenim retezec CESTA[csd]}
            lbs.Done;                       {tak obe pole zrusim}
            lba.Done;
            zmena_udaju:=true;
            end else lba.vybrano:=false;
         end;
      end;

   if lbs.vybrano then zmena_udaju:=true; {*** VYBRALI JSME POLOZKU***}

   if adresareB then
      begin
      diskt.kontrola;
      if diskt.klik=1 then
         begin{tlacitko pro prepnuti disku}
         ZmenaDisku;
         lbs.Done;                       {tak obe pole zrusim}
         lba.Done;
         hns:=true;
         zmena_udaju:=true;
         end;
      end;

   okt.kontrola;cancelt.kontrola;infot.kontrola;
   if noveB then novyt.kontrola;
   if okt.klik=1 then
      begin zmena_udaju:=true;lbs.vybrano:=true;end;
   if cancelt.klik=1 then
      begin zmena_udaju:=true;lbs.vybrano:=true;lbs.hodnota:=nil;end;
   if noveB and (novyt.klik=1) then
      begin
      ret:=vloztextokno(_FS_BEZ_KONCOVKY,40,'',true);
      if ret<>'' then
         begin{kdyz nebylo nic zadano, bere se to jako storno}
         if adresareb then ret:=cesta[csd]+ret;
         vystup:=New(PVaznik,Init(nil,nil));
         vystup^.InitNext(NaPString(ret));
         UklidPoSobe;
         ok.done;
         Exit(vystup);
         end;
      end;
   if infot.klik=1 then info(lbs.VratHodnotu);

   case xLastKey of
   xESC:begin zmena_udaju:=true;lbs.vybrano:=true;lbs.hodnota:=nil;end;
   xEnter:begin zmena_udaju:=true;lbs.vybrano:=true;end;
   xTab:begin {zmacknuti tabulatoru}
        if lba.stav=_aktivni then
           begin
           lba.stav:=_odkliknutim;  {odchazim od adresaru}
           lbs.aktivuj;             {...a prechazim k souborum}
           lbs.zobraz;
           lba.zobraz;
           zmena_udaju:=false;
           end else

        if lbs.stav=_aktivni then
           begin
           lbs.stav:=_odkliknutim;  {odchazim od souboru}
           lba.aktivuj;             {...a prechazim k adresarum}
           lba.zobraz;
           lbs.zobraz;
           zmena_udaju:=false;
           end;
        end;
   end; {case}
   xLastKey:=0;
   until zmena_udaju;

{if not lbs.vybrano then zrusseznamsouboru(seznam_souboru);
if adresareb then zrusseznamadresaru(seznam_adresaru);}

if not lbs.vybrano then
   begin
   zrusseznamsouboru(seznam_souboru);
   if adresareb then zrusseznamadresaru(seznam_adresaru);
   end;

until lbs.vybrano;

if lbs.hodnota<>nil then
   begin
   vystup:=lbs.VratMultiHodnotu;
   su:=vystup^.dalsi;
   while su<>nil do
      begin
      soubor:=su^.vazba;
      ret:=soubor^.jmeno^+'.'+soubor^.koncovka^;
      if adresareb then ret:=cesta[csd]+ret;
      su^.vazba:=NaPString(ret);
      su:=su^.dalsi;
      end;
   end;
UklidPoSobe;
ok.done;{vymazani okna}
Fileselector:=vystup;
End;{fileselector}

function VyberSouborOkno(nadpis,maska,koncovky:string;vyska:longint;moznosti:byte):string;
var p:PVaznik;
    s:string;
begin
p:=Fileselector(nadpis,maska,koncovky,vyska,moznosti+VS_BEZMULTI);
if p=nil then Exit('');
s:=pstring(p^.dalsi^.vazba)^;
fileselector_smaz(p);
VyberSouborOkno:=s;
end;

{--------------------------------------------------------------------------}
{-------- satelitni procedury procefury DvojListBox -----------------}
Procedure DLB_DodejCoChybi(pv,qv:PVaznik);
var p,pp,q:PVaznik;
    pritomno:boolean;
begin
q:=qv^.dalsi;
while q<>nil do
   begin
   pritomno:=false;
   pp:=pv;
   p:=pv^.dalsi;
   while p<>nil do
      begin
      if q^.vazba=p^.vazba then begin pritomno:=true;Break;end;
      pp:=p;
      p:=p^.dalsi;
      end;
   if not pritomno then pp^.InitNext(q^.vazba);
   q:=q^.dalsi;
   end;
end;

Procedure DLB_VyjmiPrvky(pv,qv:PVaznik);
var p,pp,q:PVaznik;
begin
q:=qv^.dalsi;
while q<>nil do
   begin
   p:=pv^.dalsi;
   while p<>nil do
      begin
      pp:=p^.dalsi;
      if p^.vazba=q^.vazba then Dispose(p,Done);
      p:=pp;
      end;
   q:=q^.dalsi;
   end;
end;


function Dvojlistbox(nadpis:string;sirka,vyska:longint;proc:Point2StrFunc;p,_q:PVaznik):PVaznik;
var ok:okno;
    okt,zrust,pridej,uber,pomoc:tlacitko;
    mujstav:byte;
    vsel,vybl,q:PVaznik;

    csd:byte;           {cislo akt. disku}
    vyb,vse:TListBox;

    soubor:uknatsoubor;         {vlastni udaje o souboru}
                   {oboje navazano na seznam_souboru nebo na seznam_adresaru}

    i,j,k,l,lhxa,lhxs,lhxt,lhy:integer;{souradnice okna a jeho casti}
    vyska_textu:longint;
    sirka_tlacitka:longint;
    multi,adresareB,noveB,zmena_udaju,hns:boolean;

Begin
if _q=nil then q:=New(PVaznik,Init(nil,nil)) else q:=_q;
if sirka<400 then sirka:=400;

lhxa:=_maxx shr 1-sirka shr 1; { kam vypisovat soubory }
lhxs:=lhxa+sirka div 3;        { a kam adresare }
lhy:=_maxy shr 1-vyska shr 1;
lhxt:=NejsirsiText(Svazej(Uzel(_PRIDEJPOL,
                          Uzel(_UBERPOL,
                          Uzel(_OK,
                          Uzel(_CANCEL,
                          Uzel(_POMOC,nil)))))));
if lhxt<40 then lhxt:=40;

mouserel;
ok.init(lhxa,lhy,sirka,vyska,nadpis);
inc(lhy,ok.vyska_zahlavi+2);
i:=lhy;
lhxs:=ok.x+ok.sirka div 2-lhxt div 2-1;

pridej.init(lhxs,i,_PRIDEJPOL,'',lhxt,1);
inc(i,pridej.vyska+5);
uber.init(lhxs,i,_UBERPOL,'',lhxt,1);
inc(i,uber.vyska+5);
okt.init(lhxs,i,_OK,'',lhxt,1);
inc(i,okt.vyska+5);
zrust.init(lhxs,i,_CANCEL,'',lhxt,1);
inc(i,zrust.vyska+5);
pomoc.init(lhxs,i,_POMOC,'',lhxt,1);
inc(i,pomoc.vyska+5);
i:=lhxs-lhxa-10-_sirpos;
j:=ok.vyska-ok.vyska_zahlavi-2;
lhxs:=lhxs+lhxt+10;
k:=RychlaVyskaRadky(_VSEPOL);
l:=RychlaVyskaRadky(_VYBPOL);
if l>k then k:=l;
inc(k,2);
_print(lhxs+i div 2-Sirka_FN(dvojlistbox_vsepol,font) div 2,lhy,ttxtextra1barva,dvojlistbox_vsepol);
_print(lhxa+i div 2-Sirka_FN(dvojlistbox_vybpol,font) div 2,lhy,ttxtextra1barva,dvojlistbox_vybpol);
inc(lhy,k);
dec(j,k);

vse.init(lhxs,lhy,i,j,p,proc,true,true);
repeat
mujstav:=0;
zmena_udaju:=false;
vyb.init(lhxa,lhy,i,j,q,proc,true,false);
vyb.zobraz;
vse.zobraz;
repeat
if xKeyPressed then xReadKey;   {cteni z klavesnice}
okt.kontrola;if okt.klik=1 then mujstav:=1;
zrust.kontrola;if zrust.klik=1 then mujstav:=2;
pomoc.kontrola;if pomoc.klik=1 then
   begin
   OKokno(_POMOC,_VYBINFO);
   if vse.stav=_aktivni then vse.aktivuj else
   if vyb.stav=_aktivni then vyb.aktivuj;
   end;

pridej.kontrola;if pridej.klik=1 then
   begin
   vse.vybrano:=true;
   if vse.stav=_aktivni then vse.aktivuj else
   if vyb.stav=_aktivni then vyb.aktivuj;
   end;

uber.kontrola;if uber.klik=1 then
   begin
   if q^.dalsi<>nil then
      begin
      vyb.vybrano:=true;
      if vse.stav=_aktivni then vse.aktivuj else
      if vyb.stav=_aktivni then vyb.aktivuj;
      end;
   end;
vse.kontrola;
vyb.kontrola;
if vse.vybrano then
   begin
   zmena_udaju:=true;
   vse.vybrano:=false;
   if vse.hodnota=nil then mujstav:=2 else
      begin
      vsel:=vse.VratMultiHodnotu;
      vyb.Done;
      DLB_DodejCoChybi(q,vsel);
      vse.OdznacVse;
      Vaznik_Done_all(vsel);
      end;
   end;

if vyb.vybrano then
   begin
   zmena_udaju:=true;
   vyb.vybrano:=false;
   if vyb.hodnota=nil then mujstav:=2 else
      begin
      vybl:=vyb.VratMultiHodnotu;
      vyb.Done;
      DLB_VyjmiPrvky(q,vybl);
      Vaznik_Done_all(vybl);
      if q^.dalsi=nil then
         begin
         vyb.stav:=_odkliknutim;
         vse.aktivuj;
         end;
      end;
   end;

case xLastKey of
   {case}
   xESC:begin zmena_udaju:=true;mujstav:=2;end;
   32:begin zmena_udaju:=true;mujstav:=1;end;
   xTab,xLSipka,xPSipka:begin {prepnuti panelu}
        if vse.stav=_aktivni then
        if q^.dalsi<>nil then
           begin
           vse.stav:=_odkliknutim;
           vyb.aktivuj;
           vse.zobraz;
           vyb.zobraz;
           zmena_udaju:=false;
           end else else

        if vyb.stav=_aktivni then
           begin
           vyb.stav:=_odkliknutim;
           vse.aktivuj;
           vse.zobraz;
           vyb.zobraz;
           zmena_udaju:=false;
           end;
        end;
   end;
if mujstav<>0 then zmena_udaju:=true;
until zmena_udaju;
until mujstav<>0;
vybl:=q^.Duplicate;
vse.Done;
vyb.Done;
ok.done;
Dvojlistbox:=vybl;
End;{dvojlistbox}


Function Listbox_retezcovy(x,y,sirka,vyska:longint;s:string;Pmysitko:VaznikProc;multi:boolean;p:PVaznik):PVaznik;
var lb:TListbox;
    ok:okno;
     q:PVaznik;
     okt,zrt:tlacitko;
begin
if ChceNaStred(x) then x:=ZeStreduX(x,sirka);
if ChceNaStred(y) then y:=ZeStreduY(y,vyska);
ok.Init(x,y,sirka,vyska,s);
okt.Init(x+sirka div 2-100,y+vyska-RychlaVyskaRadky(_OK)-6,_OK,'',60,2);
zrt.Init(x+sirka div 2+40,y+vyska-RychlaVyskaRadky(_CANCEL)-6,_CANCEL,'',60,2);
if not hned_vykresluj then
   begin okt.Zobraz;zrt.Zobraz;end;
inc(y,ok.vyska_zahlavi+2);
lb.init(x,y,sirka-15,vyska-ok.vyska_zahlavi-okt.vyska-8,p,@VyberSOkno_Disk,multi,true);
lb.LB_Mouse_R:=PMysitko;
{VyberSOknoDisk je puvodne urcen pro VyberSouborOkno, ale poslouzi dobre i tady}
lb.Zobraz;
repeat
if xKeyPressed then xReadkey;
lb.Kontrola;
okt.kontrola;if okt.klik=1 then lb.vybrano:=true;
zrt.kontrola;if zrt.klik=1 then begin lb.vybrano:=true;lb.hodnota:=nil;end;
until lb.vybrano;

if multi=true
   then q:=lb.VratMultiHodnotu
   else q:=lb.VratHodnotu;
lb.Done;
ok.done;
Listbox_retezcovy:=q;
end;

Function VB_Mouse_R(s:PStrom):longint;
var v:PPolozka;
begin
if Mouse_R then
   begin
   if (s=nil) or (s^.vazba=nil{nemelo by nikdy nastat}) then Exit(0);
   v:=s^.vazba;
   if v^.help^<>'' then infokno(v^.x2,v^.y2,v^.help^,true);
   end;
if Mouse_L then Exit(1);
VB_Mouse_R:=0;
end;

Function KeyDummy(s:PStrom;o:word;var i:longint):word;begin KeyDummy:=o;end;

Constructor TVybernicek.Init(_x,_y:longint;_moznosti:byte;_data:PStrom);
begin
x1:=_x;
y1:=_y;
x2:=x1;
y2:=y1;
data:=_data;
pozice:=data;
moznosti:=_moznosti;
pozadi:=nil;
trasa:=nil;
VB_Mouse_R_proc:=@VB_Mouse_R;
VB_Key_proc:=@KeyDummy;
_omx:=-1;
_omy:=-1;
if odd(moznosti) then Zobraz;
end;

Procedure NakresliRadky(pozice:Pstrom;a:longint);
var p:Pstrom;
    v:PPolozka;
    b,barva:longint;
begin
b:=1;
p:=pozice^.Vem;
while p<>nil do
   begin
   v:=p^.vazba;
   if b=a then barva:=miavbarva else barva:=mvbarva;
   _bar(v^.x1,v^.y1,v^.x2,v^.y2,barva);
   if v^.povoleno then barva:=miatxtbarva else barva:=mintxtbarva;
   _print(v^.x1,v^.y1,barva,v^.text^);
   if p^.potomek<>nil then
      _trojuhelnicekP(v^.x2-8,v^.y1+2,v^.y2-2,barva);
   inc(b);
   p:=p^.DejDalsi;
   end;
end;

Procedure TVybernicek.ZobrazHoriz;
const PLUS_OKRAJ = 3;
      PLUS_PRO_PODVYBER = 15;
var v:PPolozka;
    p,q,qq:PStrom;
    i,j,k,m:longint;
    max_vyska:longint;
    roztec:longint;

begin
m:=0;
max_vyska:=0;
roztec:=Roztec_horiz_pol_vybernicku;
p:=Pozice^.Vem;
q:=p;
j:=x1+PLUS_OKRAJ;
while p<>nil do
   begin
   v:=p^.vazba;
   k:=RychlaVyskaRadky(v^.text^);
   i:=Sirka_FN(v^.text^,font);
   v^.x1:=j;
   v^.x2:=j+i-1;
   v^.y1:=y1+PLUS_OKRAJ;
   if p^.potomek<>nil then
      begin
      inc(v^.x2,PLUS_PRO_PODVYBER);
      inc(m);
      end;
   if k>max_vyska then max_vyska:=k;
   inc(j,i+ROZTEC);
   p:=p^.DejDalsi;
   end;

qq:=nil;
while q<>nil do
   begin
   v:=q^.vazba;
   v^.y2:=v^.y1+max_vyska-1;
   qq:=q;
   q:=q^.DejDalsi;
   end;

if qq<>nil then
   if qq^.potomek<>nil then inc(j,PLUS_PRO_PODVYBER);

if (moznosti and vbROZTAHNI)<>0
   then x2:=cil^.breiteminus1
   else x2:=j-ROZTEC+{m*PLUS_PRO_PODVYBER+}PLUS_OKRAJ-1;

y2:=y1+max_vyska+PLUS_OKRAJ+PLUS_OKRAJ-1;
New(pozadi);
Init_VW(pozadi^,x2-x1+1,y2-y1+1,false);
MouseHide;
GetClippedSprite(cil^,pozadi^,x1,y1);
_box(x1,y1,x2,y2,mlhbarva,mpdbarva,mvbarva);
NakresliRadky(pozice,0);
dosah_kontroly:=x2;
MouseShow;
end;

Procedure TVybernicek.Zobraz;
const PLUS_OKRAJ = 3;
      ROZTEC = 3;
var p:Pstrom;
    v:PPolozka;
    i,j,k:longint;
    max_sirka:longint;
begin
if (moznosti and 2)=2 then begin ZobrazHoriz;Exit;end;
max_sirka:=0;
p:=pozice^.Vem;
j:=y1+ROZTEC;
while p<>nil do
   begin
   v:=p^.vazba;
   k:=RychlaVyskaRadky(v^.text^);
   i:=Sirka_FN(v^.text^,font);
   v^.y1:=j;
   v^.y2:=j+k-1;
   if p^.potomek<>nil then inc(i,30);
   v^.x1:=x1+PLUS_OKRAJ;
   {v^.x2 poresim az v dalsim pruchodu}
   inc(j,k+ROZTEC);
   if i>max_sirka then max_sirka:=i;
   p:=p^.DejDalsi;
   end;
i:=v^.x1+max_sirka-1;
p:=pozice^.Vem;
while p<>nil do
   begin
   v:=p^.vazba;
   v^.x2:=i;   {reseni v^.x2}
   p:=p^.DejDalsi;
   end;
x2:=x1+max_sirka+PLUS_OKRAJ+PLUS_OKRAJ;

if x2>cil^.breiteminus1 then  {necouham zprava z obrazovky?}
   begin
   i:=x2-cil^.breiteminus1;
   dec(x1,i);
   dec(x2,i);
   p:=pozice^.Vem;
   while p<>nil do
      begin
      v:=p^.vazba;
      dec(v^.x2,i);
      dec(v^.x1,i);
      p:=p^.DejDalsi;
      end;
   end;

if (moznosti and vbROZTAHNI)<>0 then y2:=cil^.hoeheminus1 else y2:=j;
New(pozadi);
Init_VW(pozadi^,x2-x1+1,y2-y1+1,false);
MouseHide;
GetClippedSprite(cil^,pozadi^,x1,y1);
_box(x1,y1,x2,y2,mlhbarva,mpdbarva,mvbarva);
NakresliRadky(pozice,0);
dosah_kontroly:=x2;
MouseShow;
end;

Function IdentifikujPolozku(pozice:PStrom;moznosti:longint):longint;
var p:Pstrom;
    v:PPolozka;
    a:longint;
    b:boolean;
begin
p:=pozice^.Vem;
a:=1;
b:=(moznosti and 4)=4;
while p<>nil do
   begin
   v:=p^.vazba;
   if (v^.povoleno or B) and MouseInArea(v^.x1,v^.y1,v^.x2,v^.y2) then Exit(a);
   inc(a);
   p:=p^.DejDalsi;
   end;
IdentifikujPolozku:=0;
end;


Function NajdiNovouPolozku(pozice:PStrom;c,pocpol,moznosti:longint;smer:boolean):longint;
var p,q,r,s:PStrom;
    v:PPolozka;
    a:longint;
begin
p:=pozice^.potomek;
r:=PStrom(p^.SearchLast);
if pocpol=0 then Exit(0);
for a:=1 to c do p:=p^.DejDalsi;
if (moznosti and 4) = 4 then  {jestlize mam dovolit i zakazane polozky, tak se vse hodne ulehci...}
   if smer then
      if c<pocpol then Exit(c+1) else Exit(1)
      else if c>1 then Exit(c-1) else Exit(pocpol);

s:=p;
if s^.dejpredchozi=nil then s:=r;
repeat
{mozna by bylo elegantnejsi prevest seznam na kruhovy, ale kdyz ja nevim...}
if smer then
   begin
   q:=p^.dejdalsi;
   if q=nil then begin p:=pozice^.Vem;c:=1;end else begin p:=q;inc(c);end;
   end else
   begin
   q:=p^.dejpredchozi;
   if q^.predchozi=nil then begin p:=r;c:=pocpol;end else begin p:=q;dec(c);end;
   end;
v:=p^.vazba;
if v^.povoleno then Exit(c);
until p=s;
NajdiNovouPolozku:=0;
end;

Function TVybernicek.AktivujMenu(i:longint):PStrom;
var p,q:PStrom;
    j:longint;
begin
q:=pozice^.potomek;
if i=0 then
   begin
   p:=Vyber;
   end
   else begin
   for j:=1 to i do q:=q^.dejdalsi;
   if q^.potomek<>nil then
      begin
      q:=q^.vem;
      UrovenZobrazeni(q);
      p:=Vyber;
      end
      else p:=q;
   end;
AktivujMenu:=p;
UrovenZobrazeni(nil);
rychly_konec:=0;
end;

Procedure __Urovenzobrazeni(var p:pointer);begin end;
Procedure TVybernicek.UrovenZobrazeni(p:PStrom); {defaultne je to koren}
begin
if trasa<>nil then Vaznik_Done_All(trasa,@__Urovenzobrazeni);
if (p=nil) then Exit;
Trasa:=p^.Vaznik_z_predku;
end;

Function TVybernicek.Vyber:PStrom;
   Function HM:boolean;
   begin HM:=(moznosti and 2 = 2);end;

var a,b,c,m,omx,omy:longint;
    pocpol:longint;
    z,reaktivace:boolean;
    p,q:PStrom;
    v:PPolozka;
    w:PVaznik;
    vb:PVybernicek;
    o:word;
begin
pocpol:=pozice^.potomek^.PocetPrvku;
a:=0; {divna vec - kdyz se to da do "promenne konstanty", tak to pri rekurzi blbne}
b:=1;
c:=NajdiNovouPolozku(pozice,0,pocpol,moznosti,true);
z:=true;
if not odd(moznosti) then Zobraz;
if trasa<>nil then
   begin
   if trasa^.PocetPrvku>2 then
      begin
      if (trasa<>nil) and (trasa^.dejdalsi^.dejdalsi^.dejdalsi<>nil) then
         begin
         {Dispose(trasa^.dejdalsi,Done);}
         w:=Trasa^.DejDalsi^.dejdalsi;
         w:=w^.DejDalsi;
         p:=w^.vazba;              {0. polozka potomka}
         q:=p^.rodic;              {krok zpet}
         v:=q^.vazba;
         if (moznosti and 4)=4 then m:=4 else m:=0; {pokud mam umoznit i zakazane polozky, tak to ma zrejme platit i pro podmenu}
         vb:=New(PVybernicek,Init(v^.x2,v^.y1,m,q));
         vb^.VB_Mouse_R_proc:=VB_Mouse_R_proc;
         vb^.VB_Key_proc:=VB_Key_proc;
         vb^.trasa:=trasa^.dejdalsi; {puvodne bylo: vb^.trasa:=trasa;}
         p:=vb^.vyber;
         Dispose(vb,Done);
         if odd(moznosti) then
               begin MouseHide;NakresliRadky(pozice,0);MouseShow;end else Schovej;
         if p<>nil then Exit(p);
         if p=nil then
            begin
            if Uvnitr(mouse.last_lpx,mouse.last_lpy,x1,y1,x2,y2)
               then c:=pozice^.potomek^.Kolikaty_ve_Vazniku(q)
               else Exit(nil);
            end;
         end;
      end else
          begin        {Tady se uz rekurze delat nebude. Ufff...}
          w:=Trasa^.dejdalsi^.dejdalsi;
          p:=w^.vazba;
          c:=pozice^.potomek^.Kolikaty_ve_Vazniku(p);
          if c<0 then c:=1;
          end;
   end;
omx:=mouse.x;
omy:=mouse.y;
repeat
reaktivace:=false;
repeat
WhatAboutMouse;
if xKeyPressed then
   begin
   o:=xreadkey;
   o:=VB_Key_proc(PStrom(pozice^.potomek^.SearchRecord(c)),o,rychly_konec);
   __o:=o;
   case o of
      xEnter:begin a:=c;Break;end;
      xESC:begin a:=0;Break;end; {navrat o jednu}
      xPSipka:if a=0 then if HM then begin Z:=true;c:=NajdiNovouPolozku(pozice,c,pocpol,moznosti,true);end;
      xLSipka:if a=0 then if HM then begin Z:=true;c:=NajdiNovouPolozku(pozice,c,pocpol,moznosti,false);end;
      xHSipka:if a=0 then if not HM then
              begin
              Z:=true;
              c:=NajdiNovouPolozku(pozice,c,pocpol,moznosti,false);
              end;
      xDSipka:if a=0 then if not HM then begin Z:=true;c:=NajdiNovouPolozku(pozice,c,pocpol,moznosti,true);end;
      1000:begin a:=0;Break;end; {nahla smrt. muze nastat jedine prostrednictvim WhatAboutKey}
   end;
   end;
if mouse.b<>0 then
   rychly_konec:=VB_Mouse_R_proc(PStrom(pozice^.potomek^.SearchRecord(a)));
                 {pri stisknuti leveho mysitko je Rychly_konec=1}

if Z then begin MouseHide;NakresliRadky(pozice,c);MouseShow;z:=false;end;
if (mouse.x<>omx) or (mouse.y<>omy) or (rychly_konec<>0) then
   begin
   if MouseInArea(x1,y1,x2,y2) then
      b:=IdentifikujPolozku(pozice,moznosti) else b:=0;
   {if (b=0) and ((moznosti and vbAKTIVACEPREJETIM)<>0) then Exit(nil);}
   if a<>b then begin z:=true;a:=b;if b<>0 then c:=b;end;
   omx:=mouse.x;
   omy:=mouse.y;
   end;
until rychly_konec<>0;
MouseRel;
if rychly_konec<0 then a:=0;  { DULEZITE ! }
if a=0 then vyber:=nil else
   begin
   p:=pozice^.potomek;
   p:=PStrom(p^.SearchRecord(a));
   v:=p^.vazba;
   if p^.potomek<>nil then
      begin
      if (moznosti and 4)=4 then m:=4 else m:=0;   {pokud mam umoznit i zakazane polozky, tak to ma zrejme platit i pro podmenu}
      vb:=New(PVybernicek,Init(v^.x2,v^.y1,m,p));
      vb^.VB_Mouse_R_proc:=VB_Mouse_R_proc;
      vb^.VB_Key_proc:=VB_Key_proc;
      q:=vb^.vyber;
      Dispose(vb,Done);
      vyber:=q;
      if q=nil then
         if (__o=xESC) or (MouseInArea(x1,y1,x2,y2)) then
            begin
            __o:=0;
            z:=true;
            a:=0;    {Lehce tajuplne :-(   }
            reaktivace:=true;
            end;
      end else vyber:=p;
   end;
until reaktivace=false;
{rychly_konec:=0;}  {Prave ze nulovat se to NESMI! Necham to tu pro vystrahu}
if odd(moznosti) then
   begin MouseHide;NakresliRadky(pozice,0);MouseShow;end
   else Schovej;
end;

Procedure TVybernicek.Schovej;
begin
if pozadi<>nil then
   begin
   MouseHide;
   PutClippedSprite(cil^,pozadi^,x1,y1);
   MouseShow;
   Kill_VW(pozadi^);
   Dispose(pozadi);
   pozadi:=nil;
   end;
end;

Function TVybernicek.Kontrola:longint;
var p:PStrom;
    v:PPolozka;
    a,mx,my:longint;
begin
if (moznosti and vbZOBRAZ) = 0 then Exit(0);
if (moznosti and vbAKTIVACEPREJETIM)=0 then if  not Mouse_L then Exit(0);
mx:=mouse.x;
my:=mouse.y;
if mx>dosah_kontroly then Exit(0);
if not Uvnitr(mx,my,x1,y1,x2,y2) then Exit(0);
a:=1;
p:=pozice^.vem;
if (moznosti and vbVEDLESEBE)<>0 then
while p<>nil do
   begin
   v:=p^.vazba;
   if v^.x2>=mx then Exit(a);
   inc(a);
   p:=p^.dejdalsi;
   end else
while p<>nil do
   begin
   v:=p^.vazba;
   if v^.y2>=my then Exit(a);
   inc(a);
   p:=p^.dejdalsi;
   end;
Kontrola:=a-1;
end;

Destructor TVybernicek.Done;
begin
Schovej;
if trasa<>nil then Vaznik_Done_All(trasa,@__Urovenzobrazeni);
end;

Constructor TVWOkno.Init(ix,iy,isirka,ivyska:longint;plocha:virtualwindow;iramecek:boolean;iakt:boolean);
var j:longint;
    hv:boolean;
begin
inherited Init;
if ChceNaStred(ix) then ix:=ZeStreduX(ix,isirka);
if ChceNaStred(iy) then iy:=ZeStreduY(iy,ivyska);
x:=ix;
y:=iy;
xx:=x;
yy:=y;
kresli_ramecek:=iramecek;
sirka:=isirka;
vyska:=ivyska;

zobr_sirka:=sirka-Sirka_Pos; {odectu sirku posuvniku}
zobr_vyska:=vyska-Vyska_Pos; {odectu vysku posuvniku}

if kresli_ramecek then
   begin
   dec(zobr_sirka,1);
   dec(zobr_vyska,1);
   inc(xx);
   inc(yy);
   end;

ob_my_key_proc:=@Default_ed_key_proc;
je_videt:=false;

zdroj:=plocha;
poc_ZobrX:=0;
poc_ZobrY:=0;
hv:=hned_vykresluj;
hned_vykresluj:=false;

if zdroj.hoehe<zobr_vyska then j:=zobr_vyska else j:=zdroj.hoehe+Vyska_Pos;
py.Init(x+sirka-Sirka_pos,y,vyska,j,0,10,poVERT);

if zdroj.breite<zobr_sirka then j:=zobr_sirka else j:=zdroj.breite;
px.Init(x,y+vyska-Vyska_pos,sirka-Sirka_pos,j,0,10,poHORZ);

if iakt then stav:=_aktivni else stav:=_neaktivni;
hned_vykresluj:=hv;

if hned_vykresluj then Zobraz;
end;

Procedure TVWOkno.Zobraz;
var i1,i2,i3,xxx,yyy:longint;
  Procedure __RectAngle;
  begin
  LineHorz(cil^,x,xx+zobr_sirka-1,y,ramobrbarva);
  LineVert(cil^,x,y,yy+zobr_vyska-1,ramobrbarva);
  end;

begin
xxx:=xx;
yyy:=yy;
MouseHide;

if zdroj.breite<zobr_sirka then
   begin
   i1:=zobr_sirka-zdroj.breite;
   i2:=i1 div 2;
   i3:=i1-i2;
   inc(xxx,i2);
   Bar(cil^,xx+zobr_sirka-i3,yy,xx+zobr_sirka-1,yy+zobr_vyska-1,vedleobrbarva+100);
   if i2>0 then
      Bar(cil^,xx,yy,xx+i2-1,yy+zobr_vyska-1,vedleobrbarva+100);
   end;

if zdroj.hoehe<zobr_vyska then
   begin
   i1:=zobr_vyska-zdroj.hoehe;
   i2:=i1 div 2;
   i3:=i1-i2;
   inc(yyy,i2);
   Bar(cil^,xx,yy+zobr_vyska-i3,xx+zobr_sirka-1,yy+zobr_vyska-1,vedleobrbarva+100);
   if i2>0 then
      Bar(cil^,xx,yy,xx+zobr_sirka,yy+i2-1,vedleobrbarva+100);
   end;

if kresli_ramecek then __RectAngle;
PutSpriteRegion(cil^,zdroj,poc_ZobrX,poc_ZobrY,poc_ZobrX+zobr_sirka-1,poc_ZobrY+zobr_vyska-1,xxx,yyy);
MouseShow;
{if (zdroj.breite<sirka) then} py.Zobraz;
{if (zdroj.hoehe<vyska) then} px.Zobraz;
end;

procedure TVWOkno.kontrola;
var i:longint;

begin
inherited Kontrola;
if py.kontrola then poc_zobrY:=py.hodnota;
if px.kontrola then poc_zobrX:=px.hodnota;
akce_posuvniku:=0;
if py.probehni then akce_posuvniku:=1;
if px.probehni then akce_posuvniku:=2;
if akce_posuvniku<>0 then
   begin
   Zobraz;
   stav:=_aktivni;
   Exit;
   end;

if not ((stav=_aktivni)or(stav=_escapem)) then
  if Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska) then
     begin {aktivace v pripade kliknuti mysi do pole}
     stav:=_aktivni;
     zobraz;
     mouserel;
     {xm:=-mouse.last_px;
     ym:=-mouse.last_py;}
     end else
  else
  begin
  if Uvnitr(Mouse.last_lpx,Mouse.last_lpy,x,y,x+sirka,y+vyska) or
     (mouse.last_lpx=-xm) and (mouse.last_lpy=-ym) then
     begin
     if (mouse.b<>0) and
        (py.tahaci_stav=false) and (px.tahaci_stav=false) then
        begin
        stav:=_aktivni;
        {else KliknutiDovnitr;}
        {xm:=-mouse.last_px;
        ym:=-mouse.last_py;}

        zobraz;
        mouserel;
        end;
     end {ne uvnitr}
     else begin
     if stav in [_aktivni,_escapem] then
        begin
        stav:=_odkliknutim;
        zobraz;
        end;
     {xm:=mouse.last_lpx;
     ym:=mouse.last_lpy;}
     Exit;
     end;   {else begin :: uvnitr}
  if mouse._wdif<>0 then
      begin
      i:={mouse.w-puv_kolecko}mouse._wdif;
      inc(poc_zobrY,i*10);
      if poc_zobrY<0 then poc_zobrY:=0;
      if poc_zobrY>py.virtvyska-py.vyska then poc_zobrY:=py.virtvyska-py.vyska;
      py.hodnota:=poc_zobrY;
      mouse._wdif:=0;        {ne zcela ciste, ale prijatelne}
      zobraz;
      end;
  OsetriVstup;
  end;   {else begin :: not ((stav=_akt...}
{OsetriVstup;}
end;

Procedure TVWOkno.OsetriVstup;
   Procedure SipkaDolu;
   begin
   if zdroj.hoehe<=vyska then exit;
   inc(poc_zobrY,10);
   if poc_zobrY>zdroj.hoeheminus1-vyska then
      poc_zobrY:=zdroj.hoeheminus1-vyska;
   py.hodnota:=poc_zobrY;
   py.Zobraz;
   end;

   Procedure SipkaNahoru;
   begin
   if zdroj.hoehe<=vyska then exit;
   dec(poc_zobrY,10);
   if poc_zobrY<0 then poc_zobrY:=0;
   py.hodnota:=poc_zobrY;
   py.Zobraz;
   end;

   Procedure SipkaDoprava;
   begin
   if zdroj.breite<=sirka then exit;
   inc(poc_zobrX,10);
   if poc_zobrX>zdroj.breiteminus1-sirka then
      poc_zobrX:=zdroj.breiteminus1-sirka;
   px.hodnota:=poc_zobrX;
   px.Zobraz;
   end;

   Procedure SipkaDoleva;
   begin
   if zdroj.breite<=sirka then exit;
   dec(poc_zobrX,10);
   if poc_zobrX<0 then poc_zobrX:=0;
   px.hodnota:=poc_zobrX;
   px.Zobraz;
   end;

var o:word;
    z:boolean;
begin
if not xKeyPressed then Exit;
o:=ob_my_key_proc(xreadkey);
z:=false;
case o of
   xDSipka:begin z:=true;SipkaDolu;end;
   xHSipka:begin z:=true;SipkaNahoru;end;
   xLSipka:begin z:=true;SipkaDoleva;end;
   xPSipka:begin z:=true;SipkaDoprava;end;
   xEnter:stav:=_enterem;
   xESC:stav:=_escapem;
   end;
if Z then Zobraz;
end;

Destructor TVWOkno.Done;
begin
{Kill_VW(v);}
end;

Constructor TLista.Init(ix,iy,isirka,ivyska,isir_tlac,iprid_tlac:longint;proc:Point2StrFunc;iprvky:PVaznik);
begin
inherited Init;
x:=ix;y:=iy;
sirka:=isirka;vyska:=ivyska;
if proc=nil then Lis_dej_retezec:=@Point2Pstring else Lis_dej_retezec:=proc;
Lis_dej_retezec2:=nil;
Lis_akce_pri_zadani:=nil;
zadane:=0;
prvni:=1;
posledni_ve_hre:=true;
sir_tlac:=isir_tlac;
kliknuto:=false;
objektiky:=New(PVaznik,Init(nil,nil));
barva_stiskleho:=vga2word(8);
nahorut.init(x,y,'',@LSipka_obrazek,@LSipka_obrazek,$FFFF);
dolut.init(x+sirka-PSipka_obrazek.breite-1,y,'',@PSipka_obrazek,@Psipka_Obrazek,$FFFF);
nahorut.barva_pruhlednosti:=23275;
dolut.barva_pruhlednosti:=23275;
NatahniPrvky(iprvky);
end;

Procedure TLista.PridejPosouvatka;
var mx:longint;
    p:PVaznik;
    v:PTlacitko;
    nvstav:boolean;
begin
p:=objektiky^.SearchRecord(prvni); {preskocim ty, ktere jsou moc vlevo}
nahorut.neviditelny:=false;
dolut.neviditelny:=false;
posledni_ve_hre:=true;
mx:=x+nahorut.sirka+3;
nvstav:=false;
while p<>nil do
   begin
   v:=p^.vazba;
   v^.neviditelny:=nvstav;
   v^.x:=mx;
   inc(mx,v^.sirka+5);
   if mx>x+sirka-dolut.sirka then
      begin
      nvstav:=true;
      posledni_ve_hre:=false;
      end;
   p:=p^.dalsi;
   end;
end;

Procedure TLista.NatahniPrvky(iprvky:PVaznik);
var hv:boolean;
    t:PTlacitko;
    mx,my,maxy:longint;
    p:PVaznik;
    s,s2:string;
begin
ofn:=FN_default;
NastavFont(hlavni_font);
Vse_zlikviduj(objektiky);                 {zlikviduju stare}
objektiky:=New(PVaznik,Init(nil,nil));    {a zalozim nove}
nahorut.neviditelny:=true;
dolut.neviditelny:=true;
posledni_ve_hre:=true;
maxy:=nahorut.vyska-3;
mx:=x+3;
my:=y+1;

hv:=hned_vykresluj;
hned_vykresluj:=false;

if iprvky<>nil then
   begin
   p:=iprvky^.dalsi;
   while p<>nil do
      begin
      s:=Lis_dej_retezec(p^.vazba);
      if Lis_dej_retezec2=nil then s2:='' else s2:=Lis_dej_retezec2(p^.vazba);
      t:=New(PTlacitko,Init(mx,my,s,s2,sir_tlac,prid_tlac));
      if t^.vyska>maxy then maxy:=t^.vyska;
      objektiky^.Initnext(t);
      inc(mx,t^.sirka+5);
      p:=p^.dalsi;
      end;
   end;
vyska:=maxy+3;
nahorut.y:=y+(vyska-nahorut.vyska) div 2;
dolut.y:=y+(vyska-dolut.vyska) div 2;
if mx>x+sirka-1 then PridejPosouvatka;
NastavFont(ofn);
Zobraz;
hned_vykresluj:=hv;
end;

Procedure TLista.Zobraz;
var p,q:PVaznik;
    v:PTlacitko;
    ob:word;
    i,b,c:longint;
begin
ufon;
_box(x,y,x+sirka-1,y+vyska-1,tlhbarva,tpdbarva,tvbarva);
i:=prvni-1;
nahorut.Zobraz;
dolut.Zobraz;
c:=x+sirka-dolut.sirka-1;

p:=objektiky^.SearchRecord(prvni); {preskocim ty, ktere jsou moc vlevo}
q:=objektiky^.dalsi;
while q<>p do
   begin
   v:=q^.vazba;
   v^.neviditelny:=true;
   q:=q^.dalsi;
   end;
while p<>nil do
   begin
   v:=p^.vazba;
   inc(i);
   ob:=tvbarva;
   if Lis_akce_pri_zadani<>nil then Lis_akce_pri_zadani(i,@self);
   if i=zadane then tvbarva:=barva_stiskleho;

   b:=cil^.breiteminus1;
   if dolut.neviditelny=false then cil^.breiteminus1:=c;
   v^.zobraz;
   cil^.breiteminus1:=b;

   tvbarva:=ob;
   p:=p^.dalsi;
   end;
ofon;
end;

Procedure TLista.SrovnejListu;
var mx:longint;
    p,q:PVaznik;
    v:PTlacitko;
    j,o:longint;
begin
if dolut.neviditelny=true then
   begin
   prvni:=1;
   Exit;
   end;
o:=x+sirka-dolut.sirka;
p:=objektiky^.SearchRecord(zadane);
j:=zadane+1;
mx:=x+nahorut.sirka+3;
while (p^.predchozi<>nil) and (mx<=o) do
   begin
   dec(j);
   v:=p^.vazba;
   inc(mx,v^.sirka+5);
   p:=p^.predchozi;
   end;
p:=p^.dalsi;
q:=objektiky^.dalsi;
   while q<>p do begin v:=q^.vazba;v^.neviditelny:=true;q:=q^.dalsi;end;
mx:=x+nahorut.sirka+3;
while p<>nil do
   begin
   v:=p^.vazba;
   v^.x:=mx;inc(mx,v^.sirka+5);
   if v^.x<o then v^.neviditelny:=false;
   p:=p^.dalsi;
   end;
prvni:=j;
end;

Procedure TLista.Kontrola;
var p:PVaznik;
    q:PTlacitko;
    b:longint;
    iops:boolean;
begin
inherited Kontrola;
kliknuto:=false;
if objektiky^.dalsi=nil then Exit;
nahorut.kontrola;
dolut.kontrola;
if nahorut.klik<>0 then
   if prvni>1 then
      begin
      dec(prvni);
      PridejPosouvatka;
      Zobraz;
      Exit;
      end;
if dolut.klik<>0 then
   if posledni_ve_hre=false then
      begin
      inc(prvni);
      PridejPosouvatka;
      Zobraz;
      Exit;
      end;
if nahorut.myszde or dolut.myszde then Exit;

b:=cil^.breiteminus1;
if dolut.neviditelny=false then
   begin
   cil^.breiteminus1:=x+sirka-dolut.sirka-1;
   end;
iops:=info_okno_presna_sirka;
{info_okno_presna_sirka:=true;}
p:=vse_kontrola(objektiky);
info_okno_presna_sirka:=iops;
cil^.breiteminus1:=b;
if p<>nil then
   begin
   q:=p^.vazba;
   if q^.hodnota=_Stiskle then
      zadane:=p^.kolikaty_ve_vazniku(objektiky);
   kliknuto:=true;
   Zobraz;
   end;
end;

Destructor TLista.Done;
begin
Vse_zlikviduj(objektiky);
inherited Done;
end;

Constructor TCiselnik.Init(ix,iy,ihodnota,imin,imax:longint;ipopis:string);
var d,d1,d2:longint;
    hv:boolean;
begin
x:=ix;y:=iy;
max:=imax;
min:=imin;
hodnota:=ihodnota;
popis:=ipopis;
d1:=Sirka_FN(MyStr(min),font);
d2:=Sirka_FN(MyStr(max),font);
if d1>d2 then d:=d1 else d:=d2;
inc(d,10);
hv:=hned_vykresluj;
hned_vykresluj:=false;
tpole.init(x,y,d,mystr(hodnota),false,false);

nahorut.init(x+tpole.sirka,y,'',@HSipka_obrazek,@HSipka_obrazek,$FFFF);
dolut.init(nahorut.x+nahorut.sirka,y,'',@DSipka_obrazek,@DSipka_obrazek,$FFFF);

if HSipka_obrazek.hoehe>tpole.vyska
   then d:=HSipka_obrazek.hoehe else d:=tpole.vyska;
vyska:=d;
sirka:=dolut.x+dolut.sirka-x;
hned_vykresluj:=hv;
inherited Init;
if hned_vykresluj then Zobraz;
end;

Procedure TCiselnik.Zobraz;
var i:longint;
begin
Ufon;
dolut.zobraz;
nahorut.zobraz;
tpole.zobraz;
i:=dolut.x+dolut.sirka+3;
_print(i,y+2,ttxtbarva,popis);
Ofon;
end;

Procedure TCiselnik.VlozHodnotu(i:longint);
begin
hodnota:=i;
tpole.hodnota:=MyStr(i);
end;

Procedure TCiselnik.Kontrola;
var i,j,oh:longint;
    s:string;
begin
oh:=hodnota;
tpole.kontrola;
if tpole.stav in [_escapem, _odkliknutim, _enterem] then
   begin
   j:=tpole.stav;
   if tpole.stav<>_escapem then
      begin
      s:=tpole.VratHodnotu(false);
      Val(s,i,j);
      if j=0 then begin
         if i>max then i:=max;
         if i<min then i:=min;
         hodnota:=i;
         end;
      end;
   tpole.stav:=_neaktivni;
   mouse.last_lpx:=-1;
   tpole.hodnota:=MyStr(hodnota);
   tpole.Zobraz;
   end;
nahorut.kontrola;
dolut.kontrola;
if nahorut.klik=1 then i:=1 else
if dolut.klik=1 then i:=-1 else i:=0;
if i<>0 then
   begin
   hodnota:=hodnota+i;
   if hodnota>max then hodnota:=max;
   if hodnota<min then hodnota:=min;
   tpole.hodnota:=MyStr(hodnota);
   tpole.Zobraz;
   end;
kliknuto:=hodnota<>oh;
end;

Destructor TCiselnik.Done;
begin
inherited Done;
end;

Procedure VWOkno(x,y,sirka,vyska:longint;s:string;zdroj:Virtualwindow);
var ok:okno;
    okt:tlacitko;
    vw:TVWOkno;
    j,i:longint;
begin
if ChceNaStred(x) then x:=ZeStreduX(x,sirka);
if ChceNaStred(y) then y:=ZeStreduY(y,vyska);
ok.Init(x,y,sirka,vyska,s);
j:=RychlaVyskaRadky(_OK2)+6;
vw.Init(x+1,y+ok.vyska_zahlavi,sirka-2,vyska-ok.vyska_zahlavi-j,zdroj,true,true);
Bar(cil^,vw.py.x,vw.px.y,vw.py.x+vw.py.sirka,vw.px.y+vw.px.vyska,posbarva);
i:=Sirka_FN(_OK2,font)+10;
j:=y+vyska-j+2;
okt.Init(x+sirka div 2-i div 2,j,_OK2,'',i,1);
okt.Zobraz;
repeat
vw.kontrola;
okt.kontrola;
until (okt.klik=1) or (vw.stav=_escapem) or (vw.stav=_enterem);
vw.done;
ok.done;
end;

Function ListboxOkno(x,y,sirka,vyska:longint;hlaska:string;p:PVaznik;proc:Point2StrFunc):PVaznik;
var lb:TListBox;
    ok:okno;
begin
ok.init(x,y,sirka,vyska,hlaska);
if proc=nil then proc:=@Point2pstring;
lb.init(ok.x+2,ok.y+ok.vyska_zahlavi+1,ok.sirka-Dsipka_obrazek.breite-4,ok.vyska-ok.vyska_zahlavi-2,p,proc,false,true);
lb.Zobraz;
repeat
if xKeyPressed then xReadKey;
lb.Kontrola;
until lb.Vybrano;
ListBoxOkno:=lb.VratHodnotu;
lb.done;
ok.done;
end;

Procedure ObvyklyStart;
begin
Init_Graph(find_mode(obv_sta_x,obv_sta_y),LFB_ACCESS,BEST_FQ or 70);
FontAdr(EXEdir+'fonty\');              {Adresar s fonty}
FN_PCX_adresar:=EXEdir;
SetLastLine(vga.hoeheminus1);
FN_ignore:=true;
Init_Mouse(vga);
MouseShow;
end;

Procedure ObvyklyKonec;
begin
MouseHide;
Kill_Mouse;
Kill_Graph;
end;

Procedure PripravSipecky;
begin
Init_VW(Lsipka_obrazek,15,15,false);
Move(_Lsipka_obrazek,pointer(Lsipka_obrazek.vwoffset)^,sizeof(_Lsipka_obrazek));
Init_VW(Psipka_obrazek,15,15,false);
Move(_Psipka_obrazek,pointer(Psipka_obrazek.vwoffset)^,sizeof(_Psipka_obrazek));
Init_VW(Hsipka_obrazek,15,15,false);
Move(_Hsipka_obrazek,pointer(Hsipka_obrazek.vwoffset)^,sizeof(_Hsipka_obrazek));
Init_VW(Dsipka_obrazek,15,15,false);
Move(_Dsipka_obrazek,pointer(Dsipka_obrazek.vwoffset)^,sizeof(_Dsipka_obrazek));
end;

Procedure InitWoknows;
begin
FN_ignore:=true;              {Zapne funkci zmenu fontu "za letu" }
InicializaceBarev;            {Zapne emulaci palety VGA}
NastavFont(FN_FONT_VGA16);    {Defaultne budu pouzivat praporcionalni uzivatelsky VGA font}
hned_vykresluj:=true;         {<objekt>.Init rovnou zavola <objekt>.Zobraz}
cil:=@venomgfx.vga;           {Defaultne budu kreslit primo do videopameti}
utf8_tbl:=@cp852tbl;          {defaultni preklad klavesnice do unicode}
NastavVystup(cil^);           {Psat budu tamtez}
NastavHlasky;                 {Nahraje veskere hlasky a texty}
WhatAboutMouse:=@Dummy;       {zadna pridavna obsluha mysi}
UKmys:=MOUSEDEF;              {kurzor mysi - sipka}
UKmysCekej:=MOUSECLK;         {kurzor mysi - presypaci hodiny}
PripravSipecky;
FN_color:=0;
SetLastLine(cil^.hoeheminus1);
end;

Procedure ZrusWoknows;
Begin

End;{zruswoknows}

BEGIN
InitWoknows;
END.
