Haladó billentyűzet- és képernyőkezelés

 

 

25.) Vizsgáljuk meg ReadKey segítségével a billentyűzet pufferből kiolvasható kódokat.

 

Azt szeretnénk, hogy bármely billentyűre a program tovább fusson, ezért a szokásos leállításokat nem használhatjuk. Egyszerű, de ritkán használatos és kerülendő megoldást használtunk az állandó olvasás megvalósítására, a GoTo-t. A lista bármely utasítása címkével látható el (összetett esetén csak az első), és a program bármely helyéről a vezérlést feltétel nélkül ide lehet küldeni. A címke deklarációja: Label és egy jelsorozat, programunkban: 1. A címke lehelyezése: az utasítás előtt kettősponttal. Így a programunkban a WriteLn állandóan végrehajtódik. A program megszakítását Ctrl+Break-el kell kezdeményezni.

 

Program BillTest;

Uses NewDelay, Crt;

Label 1;

Begin

  TextMode(CO80);

  ClrScr;

  1: WriteLn(Ord(ReadKey));

  GoTo 1;

End.

 

Futtatva a programot, a következőket tapasztaljuk: az Esc, Tab, BackSpace, a normál betűk, számok és írásjelek egy kódot adnak vissza, Shift-el a kód változik. A következő billentyűk önmagukban nem adnak kódot: CapsLock, NumLock, ScrollLock, Pause, PrintScreen, Ctrl, Alt, Shift, F11 és F12. A további funkcióbillentyűk, a kurzorvezérlő, a Home, End, PageUp, PageDown, Insert és Delete billentyűk kettős kódot, amelyből az első nulla. Ha betűt Ctrl-el nyomunk más kódot kapunk, ha Alt-al, akkor kettős kódot.

 

26.) Írjunk programot, amely egy csillagot jelenít meg a képernyőn, és amelyet a kurzorvezérlő billentyűkkel mozgathatunk, Esc-re pedig befejeződik a program.

 

Program Vezerlo;

Uses NewDelay, Crt, CrtPlus;

Var Ch: Char;

    X, Y: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  X:= 40;

  Y:= 12;  {a képernyő közepe}

  WriteXY(X,Y,'*');

  Tunj;

  Repeat

    Ch:= ReadKey;

    If Ch=#0 Then

    Begin

      Ch:= ReadKey;

      WriteXY(X,Y,' ');

      Case Ch Of

        #72: If Y>1 Then Dec(Y);

        #75: If X>1 Then Dec(X);

        #77: If X<80 Then Inc(X);

        #80: If Y<25 Then Inc(Y);

      End;

      WriteXY(X,Y,'*');

      Tunj;

    End;

  Until Ch=#27;

End.

 

A programban a ch változóban a billentyűzetről beolvasott karakter található, X a csillag x, Y a csillag y koordinátája. A vezérlést egy Repeat ciklus végzi. A leállítás #27-re történik, ami az Esc billentyű kódja. A ciklus első függvényhívása a ch:= Readkey; ami a futást megfogja, mindaddig nem lép tovább a program, amit a billentyűzethez hozzá nem nyulunk. Ha kettőskódú billentyűt nyomtunk meg, akkor annak első kódja #0, a második minden kettőskódú billentyűnél más. Így beazonosítható, hogy melyik volt megnyomva, ha újra olvassuk a billentyűzet puffert. A feltételes elágazás után ez a szerepe az újabb ReadKey-nek. Az ismétlő eljárásban az első WriteXY kikapcsolja, a második bekapcsolja a csillagot. Közben egy Case szerkezet dönt arról, hogy mozog-e és merre a csillag, azaz hogyan változzék az X és Y. Vezérlő kódok:

 

#72:  Fel,

#75:  Balra,

#77:  Jobbra és

#80:  Lefelé.

 

A változtatást csak akkor hajtja végre, ha a koordináták nem lépik túl a képernyőnek megfelelő értékeket. A WriteXY-ok utáni Tunj; eljárásnak az a szerepe, hogy a kurzor ne villogjon a csillag mellett.

 

 

Ha futtatjuk a programot és a képernyő jobb alsó sarkába vezéreljük a csillagot azt tapasztaljuk, hogy a képernyő jobb szélén további csillagok jelennek meg, mind ahányszor az utolsó képernyőhelyre szeretnénk lépni. Ez természetes, hiszen Write-al szeretnénk írni erre a helyre, ez pedig automatikus soremeléssel jár, ezért jelennek meg a további csillagok. Az ilyen természetű problémák megoldására ad lehetőséget a következő program.

 

27.) Írjunk programot, amely a video puffert feltölti azonos értékekkel, majd megjelenít rajta egy ablakot, majd újra visszaállítja az eredeti képernyőt.

 

Ennek a feladatnak a megoldásához több új dolog is szükséges. Az első mindjárt az, hogy a Pascal lehetőséget ad saját változó típusok deklarálására. Ezt a Type kulcsszó vezeti be. Ezt követi az új típusnév, esetünkben Scr (screen=képernyő). Aztán egy egyenlőség után az új típus leírása már ismert típusokkal. Példánkban az Scr típus egy, a video puffer szerkezéhez alkalmazkodó háromdimenziós tömb, melynek elemei byte-ok. Az első index jelenti a képernyő Y(!) koordinátáját, a második az X-et. (Tehát az eddigiekhez képest fordított sorrendben!). A harmadik a képernyőhely tartalmát írja le úgy, hogy az első érték a karakter képernyő kódja, a második a színe. Így a vezérlő karaktereknek is lesz képernyő kódja, azaz megjeleníthetők. A második érték a szín byte, melynek 8 bitje a következőket jelenti: az első bit a villogást, ha értéke 1 és 0, ha nem villog a karakter; a 2-3-4 bitek a háttérszint tartalmazzák (0-7 kódot); az 5-6-7-8 bitek a karakter színét (0-15 kódot). A képernyő tehát összesen 4000 Byte-al leírható, a memóriában egymás után található a karakter kódja, majd a színkódja.

 

Program VideoPuf;

Uses NewDelay, Crt, CrtPlus;

Type Scr=Array[1..25,1..80,1..2] Of Byte;

Var KKep: Scr;

    BKep: Scr Absolute $B800:0;

    I, J: Byte;

Begin

  TextMode(CO80);

  ClrScr;

  Tunj;

  For I:= 1 To 25 Do For J:= 1 To 80 Do

  BKep[I,J,1]:= 65;

  KKep:= BKep;

  Varj;

  Ablak(4,15, 20,5,60,15, True, 'Ez egy ablak');

  Tunj;

  Varj;

  BKep:= KKep;

  Varj;

End.

 

A Var deklarációban a KKep és BKep is egy-egy képernyőt definiálnak. Csakhogy, amíg a KKep helyét a fordító az adatszegmens üres helyére teszi, addig a BKep helyét mi mondjuk meg a memóriában. A deklarációjában lévő Absolute lefoglalt szó arra utal, hogy a memória rögzített helyén kell tárolni a változót. A helyet a kulcsszó után kell leírni. A leíráshoz hexadecimális számrendszert célszerű használni. A programban egyébként bárhol használhatunk 16-os számrendszerbeli számokat, csak egy dolgot kell tenni, a szám elé $ (dollár) jelet kell tenni. Az operatív tár (RAM) objekt helyét két szakaszban kell megadni, (mivel értéke $FFFF-nél nagyobb is lehet, és legfeljebb 64kB-ot lehet folytonos memóriaterületként kezelni) először a szegmens értéket, majd pedig az ofszet-et. Mindkét érték Word típusú. Szokás a szegmens-t nagyra választani, az ofszet így 0-15 értéket vehet fel. Programunkban a szegmens $b800, az ofszet pedig $0. Ez a színes képernyő objektív helye a memóriában. A video-vezérlő áramkörök innen olvassák ki a megjelenítendő karaktereket. A BKep változónk ezek után olyan, hogy értékadással a képernyőn való megjelenítést valósíthatunk meg. Ezek szerint a BKep[1,1,1]:= 65 értékadás a képernyő első helyére egy A betűt helyez. A programban a képernyő törlése (azaz 32-es karakterekkel való feltöltése a BKep tömbnek) után a kursorra nincs szükség, hiszen nincs írás a programban (de az ablak után újra el kell tüntetni). A kettős For ciklus A betűkkel teleírja a képernyőt, a ciklus lejátszódását a gép gyorsasága miatt nem látjuk, de ha lassítást írnánk a végrehajtásba, akkor láthatnánk. A KKep:= BKep értékadással azért élhetünk, mert a két változó típusa azonos. Ha mindkettő külön-külön tömbként lenne deklarálva, akkor csak For ciklussal lehetne átvinni az adatokat egyikből a másikba, ami sokkal lassúbb lenne. A KKep a BKep tartalmát a fordító által meghatározott helyen, a képernyő memóriától függetlenül tárolja. Várakozás után egy ablak kerül a képernyőre, újabb billentyű megnyomásra az ablak eltűnik és a BKep:= KKep értékadás visszahozza az A betűket. Ezzel a program teljesen megoldja a kitűzött feladatot miközben egy régi vágyunk is teljesült: tudtunk írni a képernyő utolsó helyére.

 

 

Lássunk még két kis rövid programot, amely a gép lelki világába enged egy kis betekintést. Az első folyamatosan másolja a nullás lapot a képernyőre, megfigyelhetjük, hogy mennyire változik a tartalma.

 

Program NullasPg;

Uses NewDelay, Crt, CrtPlus;

Type Scr=Array[1..25,1..80,1..2] Of Byte;

Var NLap: scr Absolute $0:0;

    BKep: scr Absolute $b800:0;

Begin

  TextMode(CO80);

  ClrScr;

  Repeat

    BKep:= NLap;

  Until KeyPressed;

End.

 

 

Mivel a Scr típust és a színes képernyőre vonatkozó BKep-et több programban is használhatjuk, deklaráljuk ezeket is a CrtPlus-ban, az Implementation kulcsszó előtt.

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt;

. . .

Type Scr= Array[1..25,1..80,1..2] Of byte;

Var BKep: Scr Absolute $B800:0;

    KKep: Scr;

Implementation

. . .

End.

 

A következő kis programot futtatva a gép teljesen leáll, csak Reset-tel vagy ki-be kapcsolással indítható újra, ugyanis a nullás lapot 0-val teleírjuk. A FillChar eljárás a megadott a tömböt, a teljes SizeOf(a) méretben 0–val tölti fel (Csak Win98-on működik, XP már nem enged ilyen értékadást).

 

Program Rezet;

Uses NewDelay, Crt, CrtPlus;

Var A: Array[0..1023] Of Byte Absolute $0:0;

Begin

  TextMode(CO80);

  ClrScr;

  WriteXY(34,12,'Most száll el a gép');

  Varj;

  FillChar(A,SizeOf(A),0);

End.

 

Futtatás előtt feltétlen mentsük ki, mert aztán már nem lehet!

 

Eddigi programjainkban gyakran kellett a billentyűzetről adatot bevinni. Ha nem voltunk eléggé elővigyázatosak, bizony előfordult, hogy a program leállt, vagy egyszerűen megváltozott az input helye a képernyőn, mert fölöslegesen nyomtunk Enter-t. Ezek bizony egy komolyabb programnál végzetes következményekkel járna, pl. nagy mennyiségű adatvesztéshez, ami csak hosszú fáradságos munkával lenne pótolható. A programjainkat a téves billentyűzéstől a lehető legjobban meg kell védeni. Mostanra tanultunk meg annyit a Pascal nyelvből, hogy egy komoly Input rutint írhatunk. Ennek helye természetesen a CrtPlus-ban van, hiszen bármikor használni szeretnénk.

 

28.) Bővítsük a CrtPlus Unit-ot egy olyan Bevitel függvénnyel, amellyel a billentyűzetről való beolvasás a lehető legbiztonságosabb lesz.

 

A végleges megoldásban szükség lesz arra, hogy a képernyő egy – az inputnak megfelelő – területén a képernyő színeket utólag megadhassuk. A feladat megkönnyítése, illetve más programokban való alkalmazás lehetősége végett, célszerű egy kis eljárást készíteni a CrtPlus-ba, mely tehát a képernyő valamely sorában, annak egy összefüggő részén, be tudja állítani a háttér és a betű színeit. Legyen ennek az eljárásnak a neve szinez. Helyezzük a szinek eljárás után. Paraméterei: a háttérszín, karakterszín, képernyőhely X és Y koordinátája, és a sor hossza.

 

Unit CrtPlus;

Interface

Uses NewDelay, Crt;

  . . .

  Procedure Szinek(HSz,KSz: Byte);

  Procedure Szinez(HSz,KSz,X,Y,Sh: Byte);

Implementation

Procedure Szinez(HSz,KSz,X,Y,Sh: Byte);

Var I: Byte;

Begin

  For I:= X To X+Sh-1 Do BKep[Y,I,2]:= 16*HSz+KSz;

End;

  . . .

End.

 

Eek után nézzük a Bevitel függvényt. Illesszük a függvényt utolsóként a CrtPlus-ba. A függvény öt paraméterrel hívható: az inputhely háttér és karakterszíne, az inputhely első karakterének két koordinátája, valamint az input hossza (HSz,KSz,X,Y,Sh). A hely megtervezéséről nekünk kell gondoskodni, pl. kifér-e a sorban, az Bevitel ugyanis hossza maximum egy sornyi lehet. A visszaadott érték String típusú. Ha számot szeretnénk beolvasni, akkor a szöveges változóból Val eljárással nekünk számmá kell konvertálni. A változók szerepe:

 

Ax: aktuális x koordináta,

Ch: a billentyűzetről olvasott karakter;

Ovw: ha True akkor felülírásos, ha False beszúrásos az írásmód;

I: ciklusváltozó;

BSzov: munka string.

 

Az egyes részek magyarázatát a lista tartalmazza. Aki nem kíván elmélyülni a megvalósításban, megteheti, hogy csak azt tanulja meg, hogyan kell használni, úgy is hasznos lehet a számára.

 

Unit CrtPlus;

Interface

Uses NewDelay, Crt;

  ...

  Function Bevitel(HSz,KSz,X,Y,Sh: Byte): String;

Implementation

...

Function Bevitel(HSz,KSz,X,Y,Sh:Byte): String;

Var Ch: Char;

    I, Ax: Byte;

    Ovw: Boolean;

    BSzov: String;

Begin

  Szinez(HSz,KSz,X,Y,Sh);

  Ax:= X;

  GoToXY(Ax,Y);

  Ovw:= False;

  Repeat

    Ch:= ReadKey;

    Case Ch Of

      #0:Begin {ha kettős kódú billentyűt nyomtak}

           Ch:= ReadKey;

           Case Ch Of

             #71: Ax:= X; {Home}

             #75: If Ax>X Then Dec(Ax);    {Balra}

             #77: If Ax<X+Sh Then Inc(Ax); {Jobbra}

             #79: Begin   {End}

                    I:= X+Sh;

                    Repeat

                      Dec(I);

                    Until (BKep[Y,I,1]<>32) Or (I<X);

                    Ax:= I+1;

                  End;

             #82: Ovw:= Not Ovw; {Ins: felülírás-beszúrás váltása}

             #83: If Ax<X+Sh Then {Delete}

                  Begin

                    For I:= Ax To X+Sh-1 Do

                    BKep[Y,I,1]:= BKep[Y,I+1,1];

                    BKep[Y,X+Sh-1,1]:= 32;

                  End;

           End;

         End;

      #8: If Ax<>X Then {BackSpace}

          Begin

            For I:= Ax-1 To X+Sh-1 Do

            BKep[Y,I,1]:= BKep[Y,I+1,1];

            BKep[Y,X+Sh-1,1]:= 32;

            Dec(Ax);

          End;

      #9: ;  {Tab}

      #13: ; {Enter}

      #27: ; {Esc}

      Else   {megjeleníthető karakter esetén}

      If Ax<X+Sh Then

      Begin

        If Not Ovw Then {beszúrás esetén helyet csinál}

        For I:= X+Sh-1 DownTo Ax+1 Do

        BKep[Y,I,1]:= BKep[Y,I-1,1];

        BKep[Y,Ax,1]:= Ord(Ch);

        Inc(Ax);

      End;

    End;

    GotoXY(Ax,Y);

  Until Ch In [#9,#13,#27]; {a bevitel Enter, Tab vagy Esc-re áll le}

  If Ch=#27 Then bevitel:= '' Else {ha Esc-re állt le, az bevitel üres String}

  Begin

    BSzov:= '';

    I:= X+Sh;

    Repeat {megkeresi az utolsó nem üres helyet}

      Dec(I);

    Until (BKep[Y,I,1]<>32) Or (I=X);

    Ax:= I;

    {a karakterek összerakása szöveggé a munka stringben}

    For I:= X To Ax Do BSzov:= BSzov+Chr(BKep[Y,I,1]);

    Bevitel:= BSzov;

  End;

End;

 

End.

 

29. Készítsünk egy kis program, amely a most készített bevitelt teszteli.

 

Program InputPro;

Uses NewDelay, Crt, CrtPlus;

Var Sz: String;

Begin

  TextMode(CO80);

  Szinek(1,3);

  ClrScr;

  Sz:= Bevitel(7,0, 20,10,15);

  WriteXY(20,20,Sz);

  Tunj;

  Varj;

End.

 

 

 

 

 

30. Bővítsük a CrtPlus Unitot egy menu függvénnyel. A függvénynek meg kell oldani a felhasználó által elkészített, ablakban megjelenő menüpontokból való választást a kurzorvezérlő billentyűk segítségével. A függvény visszaadott értéke a kiválasztott menüpont sorszáma, ESC-re kilép és a visszaadott érték nulla.

 

Eddigi programjaink olyanok voltak, hogy egy-egy részét legfeljebb csak egyszer hajtotta végre futása közben. Az ilyen felépítést lineárisnak is nevezhetnénk. Ha más feltételekkel (paraméterekkel) akartuk lefuttatni, akkor újra el kellett indítani a programot és a bevitelt kellett megváltoztatni. Ha a program újra futtatása nélkül, tetszőleges sorrendben és számban szeretnénk egy-egy programrészletet használni anélkül, hogy a teljes programot leállítanánk, ezt legkönnyebben menü segítségével tudjuk elérni. A többször is végrehajtandó részfeladatokra általában eljárásokat szoktunk szervezni. A Unit-ba építhető végleges megoldás előtt, nézzünk néhány megoldási lehetőséget. Az elsőben még a menü sorszáma alapján választhatunk. A főprogram Repeat ismétlő eljárásának érdekessége, hogy a leállító feltétele False, azaz állandóan hamis. A program végét jelentő menüpontban ugyanis az egyszerű megállítás mellett, (pontosabban előtte) még egyéb tevékenységek is szükségesek lehetnek, pl. adatok kimentése háttértárolóra vagy a környezeti paraméterek visszaállítása a program futtatása előtti állapotnak megfelelően.

 

Program Menu1;

Uses NewDelay, Crt, CrtPlus;

Procedure Elso;

Begin

  ClrScr;

  Write('Első');

  Tunj;

  Varj;

End;

Procedure Masodik;

Begin

  ClrScr;

  Write('Második');

  Tunj;

  Varj;

End;

Procedure Vege;

Begin

  ClrScr;

  Write('Vége');

  Tunj;

  Varj;

  Halt;

End;

Function Menu: Byte;

Var Ch: Char;

Begin

  ClrScr;

  WriteXY(38,3,'Menü');

  VVonal(37,42,4);

  WriteXY(36,7,'1. Első');

  WriteXY(36,9,'2. Második');

  WriteXY(36,11,'3. Vége');

  WriteXY(20,14,'A megfelelő szám segítségével választhat!');

  Tunj;

  Repeat

    Ch:= ReadKey;

  Until Ch In ['1'..'3',#27];

  Menu:= Ord(Ch)-48;

End;

Begin

  TextMode(CO80);

  Repeat

    Case Menu Of

      1: Elso;

      2: Masodik;

      3: Vege;

    End;

  Until False;

End.

 

 

A második megoldásban egy jobbra mutató nyíl mozgatható a menüpontok előtt, amikor a kívánt menüpont előtt áll, megnyomhatjuk az ENTER-t, ezáltal a választás megtörténik. (Az előző programból, Mentés másként (Save as…) funkcióval készüljön a következő lista, és így csak javítani kell a megfelelő részeket.)

 

Program Menu2;

Uses NewDelay, Crt, CrtPlus;

Procedure Elso;

Begin

  ClrScr;

  Write('Első');

  Tunj;

  Varj;

End;

Procedure Masodik;

Begin

  ClrScr;

  Write('Második');

  Tunj;

  Varj;

End;

Procedure Vege;

Begin

  ClrScr;

  Write('Vége');

  Tunj;

  Varj;

  Halt;

End;

Function Menu: Byte;

Var Ch: Char;

    X, Y: Byte;

    Mp: Byte;

Begin

  Szinek(1,4);

  ClrScr;

  Ablak(7,0,31,6,50,12,True,'Menü');

  WriteXY(36,7,'1. Első');

  WriteXY(36,9,'2. Második');

  WriteXY(36,11,'3. Vége');

  WriteXY(13,18,'A le-fel billentyű segítségével választhat + ENTER!');

  X:= 34;

  Y:= 7;

  Mp:= 1;

  WriteXY(x,y,Chr(26));

  Tunj;

  Repeat

    Ch:= ReadKey;

    If Ch=#13 Then

    Begin

      Menu:= Mp;

      Exit;

    End;

    If ch=#0 Then

    Begin

      Ch:= ReadKey;

      WriteXY(X,Y,' ');

      Case Ch Of

        #72: If Y>7 Then

             Begin

               Dec(Y,2);

               Dec(Mp);

             End

             Else

             Begin

               Y:= 11;

               Mp:= 3;

             End;

        #80: If Y<11 Then

             Begin

               Inc(Y,2);

               Inc(Mp);

             End

             Else

             Begin

               Y:= 7;

               Mp:= 1;

             End;

      End;

      WriteXY(x,y,Chr(26));

      Tunj;

    End;

  Until False;

End;

Begin

  TextMode(CO80);

  Repeat

    Case Menu of

      1: elso;

      2: masodik;

      3: vege;

    End;

  Until False;

End.

 

 

A harmadik megoldás már megjelenésében a véglegest tükrözi. A menüpontok között a kurzorvezérlőkkel választhatunk, az aktuális menüpont inverz kiírással jelenik meg. Új nyelvi elem a konstans tömb megadásának módja, mely tömb itt a menüpontok neveit tartalmazza.

 

Program Menu3;

Uses NewDelay, Crt, CrtPlus;

Const Msor: Array[1..3] Of String[9]=

      (' Első    ',

       ' Második ',

       ' Vége    ');

Procedure Elso;

Begin

  ClrScr;

  Write('Első');

  Tunj;

  Varj;

End;

Procedure Masodik;

Begin

  ClrScr;

  Write('Második');

  Tunj;

  Varj;

End;

Procedure Vege;

Begin

  ClrScr;

  Write('Vége');

  Tunj;

  Varj;

  Halt;

End;

Function Menu:Byte;

Var Ch: Char;

    I,X,Y: Byte;

    Mp:Byte;

Begin

  Szinek(1,4);

  ClrScr;

  Ablak(7,0, 33,6,48,12, True,'Menü');

  Szinek(7,0);

  For I:= 1 To 3 Do

  WriteXY(36,5+2*i,msor[i]);

  WriteXY(13,18,'A le-fel billentyű segítségével választhat + ENTER!');

  X:= 34;

  Y:= 7;

  Mp:= 1;

  Szinek(0,15);

  WriteXY(36,5+2*mp,msor[mp]);

  Tunj;

  Repeat

    Ch:= ReadKey;

    If Ch=#13 Then

    Begin

      Menu:= Mp;

      Exit;

    End;

    If Ch=#0 Then

    Begin

      Ch:= ReadKey;

      Szinek(7,0);

      WriteXY(36,5+2*mp,msor[mp]);

      Case Ch Of

        #72: If Y>7 Then

             Begin

               Dec(Y,2);

               Dec(Mp);

             End

             Else

             Begin

               Y:= 11;

               Mp:= 3;

             End;

        #80: If Y<11 Then

             Begin

               Inc(Y,2);

               Inc(Mp);

             End

             Else

             Begin

               Y:= 7;

               Mp:= 1;

             End;

      End;

      Szinek(0,15);

      WriteXY(36,5+2*mp,msor[mp]);

      Tunj;

    End;

  Until False;

End;

Begin

  TextMode(CO80);

  Repeat

    Case Menu Of

      1: Elso;

      2: Masodik;

      3: Vege;

    End;

  Until False;

End.

 

 

Nézzük ezek után a végleges megoldást a CrtPlus Unit-ban. Illesszük be utolsó függvényként. Paraméterei: háttérszín, karakterszín, kiválasztó háttérszín, bal felső csúcs X és Y koordinátája, menüsorok hossza, menüsorok száma, aktuális menüpont sorszáma.

 

Unit CrtPlus;

Interface

Uses NewDelay, Crt;

  . . .

  Function menu(HSz,KSz,SZz,Bfx,Bfy,Sh,Ss,As:Byte): Byte;

Implementation

. . .

Function menu(HSz,KSz,VSz,Bfx,Bfy,Sh,Ss,As:Byte): Byte;

Var Ch: Char;

Begin

  Szinez(Vsz,KSz,Bfx,Bfy+As-1,Sh);

  repeat

    Ch:= ReadKey;

    If Ch=#0 Then

    Begin

      Ch:= ReadKey;

      If Ch In [#71,#72,#75,#77,#79,#80] Then

      Szinez(HSz,Ksz,Bfx,Bfy+As-1,Sh);

      Case Ch Of

            #71: As:=1;

        #72,#75: If As>1 Then Dec(As) Else As:= Ss;

        #77,#80: If As<Ss Then Inc(As) Else As:= 1;

            #79: As:= Ss;

      end;

      If Ch In [#71,#72,#75,#77,#79,#80] Then

      Szinez(VSz,KSz,Bfx,Bfy+As-1,Sh);

    End;

  Until Ch In [#13,#27];

  If Ch=#13 Then Menu:= As Else Menu:= 0;

End;

 

End.

 

A következő kis program a most megírt menu függvényt teszteli. Fontos elemezni, az ablak és a menu paramétereinek illesztését.

 

Program MenuPro;

Uses NewDelay, Crt, CrtPlus;

Const Msor: Array[1..3] Of String[9]=

      (' Első    ',

       ' Második ',

       ' Vége    ');

Var Mp: Byte;

    I: Byte;

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  Ablak(7,0,33,4,45,8,True,'Menü');

  For I:= 1 To 3 Do WriteXY(35,4+I,Msor[I]);

  Tunj;

  Mp:= Menu(7,0,green,35,5,9,3,1);

  WriteXY(1,24,Msor[Mp]);

  Varj;

End.

 

 

 

 

 

Rekordok és file-kezelés

 

 

31. Írjunk programot, mely bekér néhány gépkocsi adatát egy végjelig (pl.: - ), majd gyártási éve szerint csökkenő sorrendben kiírja az összes adatot a képernyőre. A gépkocsik adatai: gyártó, típus, rendszám, szín, gyártási év és érvényes-e a műszakija.

 

Gyakran előfordul, hogy az adatok nem függetlenek, hanem egy-egy tárgy vagy személy különböző jellemzői. Ebben az esetben az a célszerű, ha ezt adatszerkezetileg is együtt vannak. Több adat együttes tárolására eddig csak a tömb volt használható. Ennek a mostani felvetésben az a problémája, hogy csak azonos típusú adatokat lehet benne tárolni. Új típusra lenne szükség, amelyben szöveget, számok különböző típusait, logikai változókat tárolhatunk. Ennek a típusnak a neve: rekord (Record), deklarációját a Type vezeti be és a mezők leírása az ezt követő End;-ig tart. A mezők típusa bármilyen előzőleg ismert, vagy deklarált típus lehet, lehet akár Record is. A rekord egy mezőjére Recordnev.Mezonev formában hivatkozhatunk. Megengedett az azonos típusú rekordok között a közvetlen értékadás is, valamint képezhetünk rekordokból akár tömböt is. Ha egy rekord több mezejét akarjuk kezelni egymás után, akkor a rekordazonosító többszöri kiírása helyett a With . . . Do minősítő utasítást (szerkezetet) is használhatjuk. Mivel több mezőt szeretnénk kezelni a Do után, ezért kötelező összetett utasítást írni, azaz szinte biztosan Begin . . . End;-el folytatódik a program.

 

Program Kocsik;

Uses NewDelay, Crt, CrtPlus;

Const Max=100;

Type Kocsi=Record

             Gyarto  :String[10];

             Tipus   :String[15];

             Rendszam:String[8];

             Szin    :String[12];

             GyEv    :Integer;

             Muszak  :String[5];

           End;

Var KocsiTomb: Array[1..Max] Of Kocsi;

    UKocsi: Kocsi;

Procedure Init;

Var I: Byte;

Begin

  UKocsi.Gyarto  := ’’;

  UKocsi.Tipus   := ’’;

  UKocsi.Rendszam:= ’’;

  UKocsi.Szin    := ’’;

  UKocsi.GyEv    := 0;

  UKocsi.Muszak  := ’’;

  For I:= 1 To Max Do KocsiTomb[I]:= UKocsi;

End;

Procedure Adatbe;

Var I: Byte;

Begin

  ClrScr;

  I:= 0;

  Repeat

    Inc(I);

    With KocsiTomb[I] Do

    Begin

      Write(’Kérem a ’,i:3,’. kocsi gyártóját        : ’);

      ReadLn(Gyarto);

      If Gyarto<>’-’ Then

      Begin

        Write(’Kérem a ’,i:3,’. kocsi típusát          : ’);

        ReadLn(Tipus);

        Write(’Kérem a ’,i:3,’. kocsi rendszámát       : ’);

        ReadLn(Rendszam);

        Write(’Kérem a ’,i:3,’. kocsi színét           : ’);

        ReadLn(Szin);

        Write(’Kérem a ’,i:3,’. kocsi gyártási évét    : ’);

        ReadLn(GyEv);

        Write(’Van-e a ’,i:3,’. kocsinak műszakija     : ’);

        ReadLn(Muszak);

      End;

    End;

  Until KocsiTomb[I].Gyarto=’-’;

End;

Procedure Kepre;

Var I: Byte;

Begin

  Szinek(0,15);

  CrlScr;

  WriteLn(’Gyártó’:10,’ ’,’Típus’:15,’ ’,’Rendszám’:8,’ ’,’Szín’:12,’ ’,’Gyév’:12,’ ’,’Műszak’:5);

  Szinek(0,7);

  I:= 0;

  While KocsiTomb[I].Gyarto<>’-’ Do

  With KocsiTomb[I] Do

  Begin

    WriteLn(Gyarto:10,’ ’,Tipus:15,’ ’,Rendszam:8,’ ’,Szin:12,’ ’,GyEv:12,’ ’,Muszak:5);

    Inc(I);

  End;

  Tunj;

  Varj;

End;

Begin

  TextMode(CO80);

  Init;

  Adatbe;

  Kepre;

End.

 

 

 

 

32. Írjunk programot, amely lemezen tudja tárolni a felhasználó nevét és lakhelyét. Indítás után kiírja a tárolt adatokat, megkérdezi, hogy helyesek-e, ha nem, bekéri és kimenti a helyes adatokat.

 

A legtöbb program több-kevesebb olyan adattal dolgozik, amely minden futtatáshoz szükséges, esetleg a futtatások alkalmával megváltozik, de a legközelebbi használatkor a legutóbbi állapotoknak megfelelően kell rendelkezésre állni. A programnak gondoskodni kell tehát az adatoknak lemezre való mentéséről. Ennek alapjaival ismerkedünk meg ennek a programnak a kapcsán. A pascal programok lemezes állományba menthetik az adatokat (és természetesen onnan be is olvashatják). A lemezes állományok vagy file-ok három csoportját tudja kezelni a pascal: szöveges állományok, tipizált állományok és típus nélküli állományok. A szöveges állományok ASCII karaktereket tartalmaznak, sorokra tagolódnak, melyeket soremelés, kocsi-vissza karakterek választanak el egymástól, írni és olvasni soronként lehet. A tipizált állományokban általában rekordok találhatók, bennük minden rekordnak ugyanannyi byte a hossza, a rekordokon mozoghatunk, rekordokat írhatunk és olvashatunk. A típus nélküli állományok, vagy bináris file-ok, változó hosszúságú írás és olvasást engedélyez, de a kiolvasott adatok helyes értelmezése a program(ozó) felelőssége. Feladatunk legegyszerűbben tipizált file segítségével oldható meg. Az FNev logikai file-név, egy személyekből álló file-t jelent. A DNev a file OS-beli neve, melyet teljesen konkrétan értékadással le kell írni. A főprogramnak ez az első sora. A név tetszőleges lehet, csak az OS által támasztott követelményeknek kell megfelelnie. A program első futtatáskor még biztosan nem tudja teljesíteni a specifikáció feltételeit, hiszen a nevet tartalmazó file-nak valamikor létre kell jönni. Ezért a program első változata csak a kimentést tartalmazza. A file-kezelés lépéseit a Lemezre eljárásban figyelhetjük meg. Első lépésként a logikai és a fizikai file-neveket egymáshoz kell rendelni. Ezt hajtja végre az Assign eljárás. Ettől kezdve minden utasítást a logikai file-névre adunk ki, de az a fizikai állományon fog végrehajtódni. A file-t kétféleképpen lehet megnyitni: írásra és olvasásra. Írásra a ReWrite-tal kell megnyitni, ami egyúttal a file teljes újra építését is jelenti, azaz, ha létezett az eljárás meghívása előtt, akkor teljesen elvész a régi tartalom. Lényegében így hozzuk létre az új file-t. A másik megnyitás a Reset, amely után a file-t olvashatjuk és írhatjuk is. Ekkor a régi tartalom megmarad, mármint azok a rekordok, amelyeket nem írunk fölül. Ez a második programlistában láthatjuk, a Lemezrol függvényben. Annak érdekében, hogy a file tartalma el ne vesszen, az adatkezelés után, de legkésőbben a program leállása előtt zárni kell. Ezt végzi a Close eljárás. A Write eljárás alkalmazása jelent még itt újdonságot. Eddig csak a képernyőre írásra használtuk. Ha a Write-ot úgy hívjuk meg, hogy első paramétere egy logikai file-név, akkor nem a képernyőre, hanem a megfelelő file-ba ír. Szöveges állománynál a Write helyett WritLln-t kell használni, itt a tipizált állománynál viszont csak a Write használható.

 

Program Nevem;

Uses NewDelay, Crt, CrtPlus;

Type Szemely= Record

                Neve: String[30];

                Lakhelye: String[40];

              End;

Var En: Szemely;

    FNev: File Of Szemely;

    DNev: String;

Procedure Adatbe;

Begin

  Szinek(0,7);

  ClrScr;

  Write('Kérem a személy nevét    : '); ReadLn(En.Neve);

  Write('Kérem a személy lakhelyét: '); ReadLn(En.Lakhelye);

End;

Procedure Lemezre;

Begin

  Assign(FNev,DNev); ReWrite(FNev);

    Write(FNev,En);

  Close(FNev);

End;

Begin

  TextMode(CO80);

  DNev:= 'ne.vem';

  Adatbe;

  Lemezre;

End.

 

A második, teljes listában természetesen a Lemezrol tartogat meglepetéseket. Az első mindjárt az, hogy nem eljárás, hanem függvény logikai visszaadott értékkel. Ez most kétszeresen is indokolt. Egyrészt nem biztos, hogy file amit olvasni kell az egyáltalán létezik-e, másrészt nem biztos, hogy a benne lévő adat megfelelő-e. Mindkettőre logikai értékkel válaszolhatunk. Így a két vizsgálatot egyetlen függvény visszaadott értékében kifejezhetjük. Az első az igazán érdekes, vajon mi van akkor, ha az adatot tartalmazó állomány nem is létezik, mert pl. valaki letörölte. Hát bizony kellemetlen lenne, ha emiatt a program nem lenne futtatható, mert Run-time error-ral megállna. A futás idejű hibák egy részének kezelésére alkalmas az IOResult hibakezelő függvény. Pontosan az input-output eljárások meghíváskor fellépő hibák kezelhetők vele. Ha értéke nem nulla meghíváskor, akkor az érték a hiba jellegére utal. Ahhoz, hogy a hiba létrejöttekor a program le ne álljon, még egy dolgot tenni kell. A lehetséges hibaforrást (ez esetben a Reset eljárást) körbe kell venni fordítási direktívákkal, olyanokkal, amely az input-output hibafigyelő gépi rutinokat kikapcsolja, majd visszakapcsolja. A {$I-} kikapcsol, a {I$+} bekapcsol. Viszont a következő utasításban a hibakezelő függvényt kell lekezelni, különben értéke elvész. Ha tehát a nem létező file-t olvasásra szeretnénk megnyitni, akkor az IOResult értéke nem lesz nulla. Ekkor nyilván a tartalma sem egyezhet meg a felhasználó nevével. Ezért a Lemezrol függvény False értéket kapja és Exit-el befejeződik.

 

Program Nevem;

Uses NewDelay, Crt, CrtPlus;

Type Szemely= Record

                Neve:String[30];

                Lakhelye:String[40];

              End;

Var En: szemely;

    FNev: File Of Szemely;

    DNev: String;

Function Lemezrol: Boolean;

Var Ch: Char;

Begin

  Szinek(0,15);

  ClrScr;

  Assign(FNev,DNev);{$I-}Reset(FNev);{$I+}

    If IOResult<>0 Then

    Begin

      Lemezrol:= False;

      Exit;

    End;

    Read(FNev,En);

  Close(FNev);

  WriteLn('A felhasználó adatai:');

  WriteLn;

  Szinek(0,7);

  WriteLn('Neve    : ',En.Neve);

  WriteLn('Lakhelye: ',En.Lakhelye);

  WriteLn;

  Szinek(0,15);

  WriteLn('Helyesek az adatok (I/N)?');

  Tunj;

  Repeat

    Ch:= ReadKey;

    Ch:= UpCase(ch);

  Until Ch In ['I','N'];

  Lemezrol:= Ch='I';

End;

Procedure Adatbe;

Begin

  WriteXY(1,8,'Kérem a személy nevét    : '); ReadLn(En.Neve);

  WriteXY(1,9,'Kérem a személy lakhelyét: '); ReadLn(En.Lakhelye);

End;

Procedure Lemezre;

Begin

  Assign(FNev,DNev); ReWrite(FNev);

    Write(FNev,En);

  Close(FNev);

End;

Begin

  DNev:= 'ne.vem';

  If Not lemezrol Then

  Begin

    Adatbe;

    Lemezre;

  End;

End.

 

 

Ha a file létezik, akkor tartalmát Read-el kiolvassa. Aztán tér rá annak megkérdezésére, hogy jó-e a tárolt adat. A válasz kiértékelésekor használjuk az UpCase függvényt, amely a betűkhöz a nagybetűs alakját rendeli, ezért elegendő csak nagybetűs I és N-nel a logikai beállítást megtenni. Végül is, így a főprogramban egyetlen Lemezrol függvényhívással kezelhetjük mindkét, előzőleg említett logikai értékkel bíró esetet.

 

33. Írjunk programot, amely tanulók adatait tudja nyilvántartani. Legyen lehetőség az adatok felvételére (név, születési év, osztálya, lakása és tanulmányi átlaga), azok javitására. A program egyszerre tudjon kezelni 50 tanuló adatát, melyet lemezes állományban tárol. Legyen lehetőség a következő lekérdezésekre: névsor szerint, korok szerint, lakhely szerint, átlag szerint és tudjon osztályátlagot számítani.

 

A program megírásához gyakorlatilag mindent megtanultunk az eddigi programok kapcsán. Ez a program annyiban lesz új, hogy ilyen komplex program megírására eddig még nem vállalkoztunk. A program használata közben szükség lesz arra, hogy egy esemény bekövetkezéséről a gép informáljon minket (lemezműveletek), illetve eldöntendő kérdést tegyen fel a program (pl. adatmentéssel kapcsolatban). Ilyen rutin illetve függvény más programban is hasznos lehet, ezért ezeket a CrtPlus-ba helyezzük.

 

Unit CrtPlus;

Interface

Uses NewDelay, Crt;

  . . .

  Procedure Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay: Byte; Arny: Boolean; C: String);

  Procedure Uzenet(HSz,KSz: Byte; Sz: String);

  Function Kerdezo(HSz,KSz: Byte; Sz: String): Boolean;

  . . .

Implementation

. . .

Procedure Uzenet(HSz,KSz: Byte; Sz: String);

Var Bfx,Bfy,Jax,Jay: Byte;

    LKep: Scr;

    N: Byte;

Begin

  N:= Length(Sz);

  If N<10 then N:= 10;

  Bfx:= 40-Round(N/2)-2;

  Bfy:= 11;

  Jax:= 40+Round(N/2)+1;

  Jay:= 13;

  LKep:= BKep;

  Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay,True,’Info’);

  Writexy(40-Round(Length(Sz)/2,12,Sz);

  Tunj;

  Varj;

  BKep:= LKep;

End;

 

Function Kerdezo(HSz,KSz: Byte; Sz: String): Boolean;

Var Bfx,Bfy,Jax,Jay: Byte;

    LKep: Scr;

    N: Byte;

    Ch: Char;

Begin

  N:= Length(Sz);

  If N<20 Then N:= 20;

  Bfx:= 40-Round(N/2)-2;

  Bfy:= 11;

  Jax:= 40+round(N/2)+1;

  Jay:= 13;

  LKep:= BKep;

  Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay,True,’Válaszoljon (I/N)’);

  Writexy(40-Round(Length(Sz)/2,12,Sz);

  Tunj;

  Repeat

    Ch:= ReadKey;

    Ch:= UpCase(Ch);

  Until Ch In [’I’,’N’];

  Kerdezo:= Ch=’I’;

  BKep:= LKep;

End;

. . .

End.

 

Gyakran előfordul, hogy a programok által kezelt objektumok közül választanunk kell azért, hogy a program a továbbiakban a kiválasztott elemen végezzen bizonyos műveletek. Legtöbb esetben az elemek lineárisan rendezett tömbökben helyezkedik el. A választást megkönnyíthetjük azáltal, hogy az objektumok (legtöbbször rekordok) kulcsmezőit egy string-listába helyezzük, majd egy ablakban megmutatjuk és a listából a kurzorvezérlő billentyükkel választhatunk. A választás eredménye (visszaadott értéke) a kiválasztott elem sorszáma. A most vázolt megoldás szintén elég általános, a megvalósító függvényt a CrtPlus-ban helyezzük el. A listázandó stringeket a Tomb[1..Max] String tömbbe kell előzőleg betölteni.

 

Unit CrtPlus;

Interface

Uses NewDelay, Crt;

  . . .

  Function Menu(Bfx,Bfy,Sh,Ss,As: Byte): Byte;

  Function Listazo(HSz,KSz,VSz,Bfx,Bfy,Sh,Ss,Ls,As: Integer;

                   Arny: Boolean; C: String): Integer;

const Max=500;

Var

    . . .

    Tomb: Array[1..Max] Of String[80];

    VCh: Char;

    . . .

Implementation

. . .

Function Listazo(HSz,KSz,Vsz,Bfx,Bfy,Sh,Ss,Ls,As: Integer;

                 Arny: Boolean; C: String): Integer;

Var Ki,Ai,Vi,Aks: Integer;

    Ch: Char;

  Procedure Kiir;

  Var J, Ay: Integer;

  Begin

    Ki:= Round(As-Ls/2); Vi:= Round(As+Ls/2)-1;

    If Ki<=0 Then Inc(Ki,Ss); If Vi>Ss Then Dec(Vi,Ss);

    Window(Bfx+2,Bfy+1,Bfx+Sh-2,Bfy+Ls);

    ClrScr;

    If Vi>Ki Then For J:= Ki To Vi Do WriteXY(1,1+J-ki, Copy(Tomb[J],1,Sh-1))

    Else

    Begin

      If As<=Ss-Ls/2 Then Inc(Ki);

      For J:= Ki To Ss Do WriteXY(1,1+J-Ki,Copy(Tomb[J],1,Sh-1));

      Ay:= WhereY;

      For J:= 1 To Vi Do

      Begin Inc(Ay); WriteXY(1,Ay,Copy(Tomb[J],1,Sh-1)) End;

    End;

    Window(1,1,80,25);

    Tunj;

  End;

Begin

  If Ls>Ss Then Ls:= Ss; If Ls<3 Then Ls:= 3;

  If Not Odd(Ls) Then Dec(Ls);

  If Ls>21 Then Ls:= 21;

  If Bfy+Ls+1>24 Then Repeat Dec(Bfy) Until Bfy+Ls+1<25;

  Aks:= Bfy+Round(Ls/2);

  Ablak(HSz,KSz,Bfx,Bfy,Bfx+Sh,Bfy+Ls+1,Arny,C);

  Kiir;

  Szinez(VSz,KSz,Bfx+2,Aks,Sh-3);

  Repeat

    Ch:= ReadKey;

    If (Ch=#0) And KeyPressed Then

    Begin

      Ch:= ReadKey;

      If Ch In [#71,#72,#73,#79,#80,#81] Then Szinez(HSz,KSz,Bfx+2,Aks,Sh-3);

      Case Ch Of

        #71: As:=1;

        #72: Begin

               Dec(Ki); Dec(As); Dec(Vi);

               If Ki<1 Then Ki:= Ss;

               If As<1 then As:= Ss;

               If Vi<1 Then Vi:= Ss;

             End;

        #73: Begin

               Dec(Ki,Ls); Dec(As,Ls); Dec(Vi,Ls);

               If Ki<1 Then Begin If Ki=0 Then Ki:= Ss Else Ki:= Ki+Ss+1 End;

               If As<1 Then Begin If As=0 Then As:= Ss Else As:= As+Ss+1 End;

               If Vi<1 Then Begin If Vi=0 Then Vi:= Ss Else Vi:= Vi+Ss+1 End;

             End;

        #79: As:= Ss;

        #80: Begin

               Inc(ki); Inc(As); Inc(Vi);

               If Ki>Ss Then Ki:= 1;

               If As>Ss Then As:= 1;

               If Vi>Ss Then Vi:= 1;

             End;

        #81: Begin

               Inc(Ki,Ls); Inc(As,Ls); Inc(Vi,Ls);

               If Ki>Ss Then Ki:= Ki-Ss;

               If As>Ss Then As:= As-Ss;

               If Vi>Ss Then Vi:= Vi-Ss;

             End;

      End;

      Kiir;

      If Ch In [#71,#72,#73,#79,#80,#81] Then Szinez(VSz,KSz,Bfx+2,Aks,Sh-3);

 

    End;

  Until Ch In [#13,#27];

  VCh:= Ch;

  If Ch=#27 Then Listazo:= 0 Else Listazo:= As;

End;

 

End.

 

A Listazo függvény paraméterei:

 

HSz: ablak háttérszín;

KSz: ablak karakterszín;

VSz: választósor háttérszíne;

Bfx: az ablak bal felső sarka X koordinátája;

Bfy: az ablak bal felső sarka Y koordinátája;

Sh: sorok hossza;

Ss: sorok száma;

Ls: látható sorok száma;

As: aktuális sorszám.

 

Ezek után nézzük a Tanulok nevű program listáját. Az egyes rutinok funkciói:

 

Init: kezdő illetve üres értékek beállítása;

Lemezrol: az adatállomány lemezről való betöltése, ha nem létezik létrehozása;

Lemezre: adatállomány lemezre mentése;

Nevtolto: a tanulónevek betöltése a Tomb[1..Max] tömbbe, a listázó függvény számára;

Javitás: az adatok karbantartását végző eljárás;

Smake: a minden tanulói adatot tartalmazó string tömb előállítása a listázó függvény számára;

Nevszerint: a tanulói adatok rendezése név szerint;

Korszerint: a tanulói adatok rendezése kor szerint;

Lakszerint: a tanulói adatok rendezése lakhely szerint;

Atlszerint: a tanulói adatok rendezése átlag szerint;

Osztatlag: osztályátlag kiszámítása;

Stati: a statisztikai műveletek hívását végző rutin;

 

Program Tanulok;

Uses NewDelay, Crt,CrtPlus;

Const Amax=50;

      Msor: Array[1..4] Of String[15]=

          (' Betöltés      ',

           ' Tanuló adatai ',

           ' Lekérdezések  ',

           ' Befejezés     ');

Type Tanulo=Record

              Nev: String[25];

              Szul: Integer;

              Oszt: String[3];

              Lak: String[30];

              Atl: Real;

            End;

 

Var ATanulo,UTanulo: Tanulo;

    At: integer;

    TTanulo: Array[1..Amax] Of Tanulo;

    Mp: Byte;

    I: Integer;

    Adatbent, Adatvalt: Boolean;

    FNev: File Of Tanulo;

    DNev: String;

    Atlag: Real;

 

Procedure Init;

Begin

  Adatbent:= False;

  Mp:= 1; At:= 1;

  With UTanulo Do

  Begin

    Nev:= '-';

    Szul:= 0;

    Oszt:= '-';

    Lak:= '-';

    Atl:= 0;

  End;

  For I:= 1 To Amax Do TTanulo[I]:= UTanulo;

  DNev:= '11b.tan';

End;

 

Procedure Lemezrol;

Begin

  If Adatbent Then

  Begin

    Uzenet(5,15,'Az adatállomány már be van töltve!');

    Exit;

  End;

  Assign(FNev,DNev); {$I-}Reset(FNev);{$I+}

    If IOResult<>0 Then

    Begin

      ReWrite(fnev);

      For I:= 1 To Amax Do Write(FNev,TTanulo[I]);

    End

    Else

    For I:= 1 To Amax Do Read(FNev,TTanulo[I]);

  Close(FNev);

  Adatbent:= True;

  Uzenet(5,15,'Az adatállomány betöltve!');

End;

 

Procedure Lemezre;

Begin

  Assign(FNev,DNev); ReWrite(FNev);

    For I:= 1 To Amax Do Write(FNev,TTanulo[I]);

  close(FNev);

  Uzenet(5,15,'Az adatállomány kimentve!');

End;

 

Procedure Nevtolto;

Var S: String;

Begin

  For I:= 1 To Amax Do

  Begin

    Str(I,S);

    If I<10 Then S:= ' '+S;

    Tomb[I]:= ' '+S+'.'+TTanulo[I].Nev;

  End;

End;

 

Procedure Javitas;

Var S: String;

    Sz,Kod :integer;

    R: real;

Begin

  If Not Adatbent Then

  Begin

    Uzenet(5,15,'Nincs megnyitva adatállomány!');

    Exit;

  End;

  Szinek(1,0); ClrScr;

  At:= Listazo(7,0,2,25,5,30,Amax,11,At,True,'Tanulók névsora:');

  If VCh=#27 Then Exit;

  Szinek(7,0); ClrScr;

  ATanulo:= TTanulo[At];

  Ablak(1,14,10,6,70,18,True,'A tanuló adatai:');

  WriteXY(13, 8,'A tanuló neve.......:');

  WriteXY(13,10,'Születési éve.......:');

  WriteXY(13,12,'Osztálya............:');

  WriteXY(13,14,'Lakhelye............:');

  WriteXY(13,16,'Tanulmányi átlaga...:');

  Szinek(0,14);

  With Atanulo Do

  Begin

    WriteXY(37,8,nev);

    Str(Szul,S);

    WriteXY(37,10,S);

    WriteXY(37,12,Oszt);

    WriteXY(37,14,Lak);

    GoToXY(37,16);

    Write(Atl:4:2);

  End;

  With Atanulo Do

  Begin

    S:= Bevitel(7,0,37,8,25); If VCh<>#27 Then

    Begin Adatvalt:= True; Nev:= s End;

    Repeat

      S:= Bevitel(7,0,37,10,4); Val(S,Sz,Kod);

    Until (Kod=0) Or (VCh=#27);

    If VCh<>#27 Then Begin Adatvalt:= True; Szul:= Sz End;

    S:= Bevitel(7,0,37,12,3);

    If VCh<>#27 Then Begin Adatvalt:= True; Oszt:= S End;

    S:= Bevitel(7,0,37,14,30);

    If VCh<>#27 Then Begin Adatvalt:= True; Lak:= S End;

    Repeat

      S:= Bevitel(7,0,37,16,4); Val(S,R,Kod);

    Until (Kod=0) Or (VCh=#27);

    If VCh<>#27 Then Begin Adatvalt:= True; Atl:= R End;

  End;

  If Adatvalt Then TTanulo[At]:= ATanulo;

End;

 

Procedure SMake;

Var Ws,W: String[80];

Begin

  For I:= 1 To Amax Do

  Begin

    Ws:= '';

    Str(I,Ws);

    If Length(Ws)=1 Then Ws:= ' '+Ws;

    Ws:= Ws+'.';

    Ws:= Ws+TTanulo[I].Nev;

    Ws:= Copy(Ws+'                             ',1,29);

    Str(TTanulo[I].Szul,W);

    Ws:= Ws+W;

    Ws:= Copy(Ws+'      ',1,34);

    Ws:= Ws+TTanulo[I].Oszt;

    Ws:= Copy(Ws+'     ',1,38);

    Ws:= Ws+TTanulo[I].Lak;

    Ws:= Copy(Ws+'                               ',1,69);

    Str(TTanulo[I].Atl:4:2,W);

    Ws:= Ws+W;

    Tomb[I]:= Ws;

  End;

End;

 

Procedure Nevszerint;

Var I, J: Integer;

    PTanulo: Tanulo;

Begin

  For I:= 1 To Amax-1 Do For J:= I+1 To Amax Do

  If TTanulo[I].Nev>TTanulo[J].Nev Then

  Begin

    PTanulo:= TTanulo[I];

    TTanulo[I]:= TTanulo[J];

    TTanulo[J]:= PTanulo;

    Adatvalt:= True;

  End;

  While TTanulo[1].Nev[1]='-' Do

  Begin

    For J:= 1 To Amax-1 Do TTanulo[J]:= TTanulo[J+1];

    TTanulo[Amax]:= UTanulo;

  End;

  SMake;

  Listazo(7,0,2,1,3,77,Amax,19,1,True,'A tanulók névsor szerint:');

End;

 

Procedure Korszerint;

Var I, J: Integer;

    PTanulo: Tanulo;

Begin

  For I:= 1 To Amax-1 Do For J:= I+1 To Amax Do

  If TTanulo[I].Szul>TTanulo[J].Szul Then

  Begin

    PTanulo:= TTanulo[I];

    TTanulo[I]:= TTanulo[J];

    TTanulo[J]:= PTanulo;

    Adatvalt:= True;

  End;

  While TTanulo[1].Nev[1]='-' Do

  Begin

    For J:= 1 To Amax-1 Do TTanulo[J]:= TTanulo[J+1];

    TTanulo[Amax]:= UTanulo;

  End;

  SMake;

  Listazo(7,0,2,1,3,77,Amax,19,1,True,'A tanulók névsora koruk szerint:');

End;

 

Procedure Lakszerint;

Var I, J: Integer;

    PTanulo: Tanulo;

Begin

  For I:= 1 To Amax-1 Do For J:= I+1 To Amax Do

  If TTanulo[I].Lak>TTanulo[J].Lak Then

  Begin

    PTanulo:= TTanulo[I];

    TTanulo[I]:= TTanulo[J];

    TTanulo[J]:= PTanulo;

    Adatvalt:= True;

  End;

  While TTanulo[1].Nev[1]='-' Do

  Begin

    For J:= 1 To Amax-1 Do TTanulo[J]:= TTanulo[J+1];

    TTanulo[Amax]:= UTanulo;

  End;

  SMake;

  Listazo(7,0,2,1,3,77,amax,19,1,True,'A tanulók névsora lakhely szerint:');

End;

 

Procedure Atlszerint;

Var I, J: Integer;

    PTanulo: Tanulo;

Begin

  For I:= 1 To Amax-1 Do For J:= I+1 To Amax Do

  If TTanulo[I].Atl>TTanulo[J].Atl Then

  Begin

    PTanulo:= TTanulo[I];

    TTanulo[I]:= TTanulo[J];

    TTanulo[J]:= PTanulo;

    Adatvalt:= True;

  End;

  While TTanulo[1].Nev[1]='-' Do

  Begin

    For J:= 1 To Amax-1 Do TTanulo[J]:= TTanulo[J+1];

    TTanulo[Amax]:= UTanulo;

  End;

  SMake;

  Listazo(7,0,1,3,77,Amax,19,1,True,'A tanulók névsora tanulmányi átlaguk szerint:');

End;

 

Procedure Osztatlag;

Var Jsz: integer;

    Ossz: real;

    S: String;

Begin

  Szinek(1,0); ClrScr;

  Jsz:=0; Ossz:= 0; S:= '';

  For I:= 1 To Amax Do

  With TTanulo[I] Do If Atl<>0 Then

  Begin

    Inc(Jsz);

    Ossz:= Ossz+Atl;

  End;

  If Jsz<>0 Then Atlag:= Ossz/Jsz;

  Str(Atlag:4:2,S);

  Uzenet(5,15,'Az osztály átlaga: '+S);

End;

 

Procedure Stati;

Var Amp:byte;

Const Amsor: Array[1..6] Of String[17]=

            (' Névsor szerint  ',

             ' Korok szerint   ',

             ' Lakhely szerint ',

             ' Átlag szerint   ',

             ' Osztály átlaga  ',

             ' Főmenű          ');

 

Begin

  If Not Adatbent Then

  Begin

    Uzenet(5,15,'Nincs megnyitva adatállomány!');

    Exit;

  End;

  Repeat

    Szinek(1,0);

    ClrScr;

    Ablak(7,0,29,8,49,15,True,'Lekérdezések:');

    For I:= 1 To 6 Do WriteXY(31,8+i,Amsor[i]);

    Tunj;

    Amp:= Menu(7,0,2,31,9,17,6,1);

    Case Amp Of

      1: Nevszerint;

      2: Korszerint;

      3: Lakszerint;

      4: Atlszerint;

      5: Osztatlag;

      6: Exit;

    End;

  Until False;

End;

 

Begin

  TextMode(CO80);

  Init;

  Repeat

    Szinek(1,0);

    ClrScr;

    Ablak(7,0,30,8,48,13,True,'Főmenű:');

    For I:= 1 To 4 Do WriteXY(32,8+i,Msor[i]);

    Tunj;

    Mp:= Menu(7,0,2,32,9,15,4,1);

    Case Mp Of

      1: Begin Lemezrol; Nevtolto End;

      2: Begin Javitas; Nevtolto End;

      3: Begin Stati; Nevtolto End;

      4: Begin

           If Adatvalt Then

           If Kerdezo(5,15,'Lemezre menti-e a megváltozott adatokat?') Then Lemezre;

           Szinek(0,7); ClrScr; Halt

         End;

    End;

  Until False;

End.

 

 

 

 

A Tanulok nevű program kódolási sorrendje:

 

Keretprogram;

Deklarációk;

Init;

Lemezre;

Lemezrol;

Nevtolto;

Javitas;

Stati;

Nevszerint;

Korszerint;

Lakszerint;

Atlszerint;

Osztatlag.

 

Gyakran gondot jelent, hogy a DOS-ban megirt programjaink adatállományait nem tudjuk programból szép formátumban papírra vetni. Ezen segít a következő kis eljárás, amely olyan szöveges állományt hoz létre, amely könnyen betölthető az Excel táblázatkezelőbe. Ezután már könnyedén formázhatjuk, szépíthetjük irományunkat. A most következő rutint a Tanulok listájába kell beszúrni, valamint a főmenüt bővíteni kell egy 'TXT-file' menüponttal.

 

Procedure TxtFile;

Var I: Integer;

    TxtFNev: Text;

    TxtDNev: String;

Begin

  TxtDNev:= 'diakok.txt';

  Assign(TxtFNev,TxtDNev); ReWrite(TxtFNev);

    For I:= 1 To Amax Do With TTanulo[I] Do

    Write(TxtFNev,Nev,#9,Szul,#9,Oszt,#9,Lak,#9,Atl,#13);

  Close(TxtFNev);

End;

 

Adatainkat az Excel-ből még tovább vándoroltathatjuk, ha Word-ben formaleveleket szeretnénk írni. Megtehetjük, hogy körlevél készítésnél a törzsadatoknak az Excel-ből kimentett állományunkat választjuk, így a DOS-os felületen bevitt adataink végül egy Word dokumentumban jelennek meg.

 

Egy String input esetén a bevitt szöveg tartalmazhat fölösleges SPACE-eket, akár az elején vagy a végén, de a string belsejében is. Írjunk a CrtPlus-ba egy olyan függvényt, mely a fölösleges üres helyeket kitörli a szövegből. Legyen ennek a függvénynek a neve: ValidSt.

 

Function ValidSt(s: String): String;

Var I, N: Byte;

    Ws: String;

    Van: Boolean;

Begin

  N:= Length(S);

  ValidSt:= '';

  If N=0 Then Exit;

  Ws:= S;

  While Ws[N]=' ' Do

  Begin

    Ws:= copy(Ws,1,N-1);

    Dec(N);

  End;

  If N>0 Then

  While Ws[1]=' ' Do

  Begin

    Ws:= Copy(s,2,N-1);

    Dec(N);

  End;

  Van:= True;

  If N>3 then While Van Do

  Begin

    Van:= False;

    N:= Length(Ws);

    For I:= 2 To N-1 Do If (Ws[I]=' ') And (Ws[I+1]=' ') Then

    Begin

      Van:= True;

      Ws:= Copy(Ws,1,I) + Copy(Ws,I+2,N-I-1);

    End;

  End;

  ValidSt:= Ws;

End;

 

Gyakran lehet szükség arra, hogy string-listákat kezeljünk, rendezéseket, kereséseket hajtsunk végre. A következő függvény gyakorlatilag egy olyan lista, mely stringeket tud tárolni, a listában csak egyszer szerepelhet egy string, és a tárolás rendezetten történik. Új lista létrehozásakor először a Tomb[1..Max] string tömböt üres stringekkel kell feltölteni. Mindannyiszor, amikor egy stringet ráhelyezünk a listára, a Listara függvényt kell meghívni a ráhelyezendő stringgel, mint paraméterrel. Az átvett stringet a függvény először a ValidSt függvény segítségével megszabadítja a fölösleges SPACE-ektől. A lista függvény visszaadott értéke a lista új hossza. A lista üres stringet nem tartalmazhat, és a tárolás növekedő nagyságrendben történik. Ha a listát üres stringgel hívjuk meg, akkor megkapjuk az aktuális hosszát. Ha a meghívással a lista hossza nem változik, akkor a paraméterként átadott string már szerepel a listában. (pl: ha Listara(’’)=Listara(’alma’) akkor az ’alma’ string már szerepel a listán.) A leírtakból az is kitűnik, hogy ez a lista ezzel a függvénnyel csak növelhető, szabályos törlésre nincs lehetőség. A Listara függvény helye a CrtPlus unit-ban van. Mivel a függvény a listára helyezés előtt egyszerű string összehasonlítást végez, a Listara a kis- és nagybetűket megkülönbözteti.

 

Function Listara(S: String): Integer;

Var I, J, N: Integer;

Begin

  S:= ValidSt(S);

  N:=0; While Tomb[N+1]<>'' Do Inc(N);

  If S='' Then Begin Listara:= n; Exit End;

  If N=0 Then Begin Tomb[1]:= S; Listara:= 1; Exit end;

  For I:= 1 to N Do If Tomb[I]=S Then Begin Listara:= n; Exit End;

  I:= 1; While (S>Tomb[I]) And (Tomb[I]<>'') Do Inc(I);

  For J:= N DownTo I Do Tomb[J+1]:= Tomb[J];

  Tomb[I]:= S;

  Listara:= N+1;

End;

 

Most írjunk egy olyan függvényt, amely a listáról elemeket tud levenni. Legyen ennek a neve: Listarol és természetesen ez is a CrtPlus-ban lesz elhelyezve.

 

Function Listarol(S: String): Integer;

Var I, J, N: Integer;

Begin

  S:= ValidSt(S);

  N:= 0; While Tomb[N+1]<>'' Do Inc(N);

  If (S='') Or (N=0) Then Begin Listarol:= N; Exit End;

  For I:= 1 To N Do If Tomb[I]=S Then

  Begin

    For J:= I To N-1 Do Tomb[J]:= Tomb[J+1];

    Tomb[N]:= '';

    Listarol:= N-1;

    Exit;

  end;

  Listarol:= 0;

End;

 

A Listarol függvény tehát leveszi a listáról az átvett stringet, visszaadott értéke a lista új hossza, ha pedig nem volt a listán, a visszaadott érték 0. Ha üres stringgel hívjuk meg, akkor a visszaadott érték a lista aktuális hossza. Mivel a levétel előtt validálást hajt végre, nem érzékeny a fölösleges SPACE-ekre.

 

34. Írjunk programot, amely hozzáfűzésre megnyit egy szöveges állományt, majd üres string beírásáig a billentyűzetről strigeket olvas, amelyeket a megnyitott lemezes állomány végéhez hozzáfűz. Az input végeztével betölti a lemezről a stringeket, és sorrendbe rakva visszaírja ugyanabba az állományba. Használjuk a Listara függvényünket.

 

Program TextFile;

Uses NewDelay, Crt, CrtPlus;

Var NevSor: Text;

    NevSorOS: String;

Procedure AdatBe;

Var S: String;

Begin

  S:= ' ';

  Assign(NevSor, NevSorOS); {$I-}Append(NevSor);{$I-}

    If IOResult=0 Then ReWrite(NevSor);

    While S<>'' Do

    Begin

      ReadLn(S);

      If S<>'' Then WriteLn(NevSor, S);

    End;

  Close(NevSor);

End;

Procedure Rendez;

Var S: String;

    I, Sh: Integer;

Begin

  ClrScr;

  For I:= 1 To Max Do Tomb[I]:= '';

  Assign(Nevsor, NevSorOS); Reset(NevSor);

    While Not EOF(NevSor) Do

    Begin

      ReadLn(NevSor, S);

      Listara(S);

    End;

  Close(NevSor);

  I:= 1;

  Sh:= 0;

  Assign(NevSor, NevSorOS); Rewrite(NevSOr);

    While Tomb[I]<>'' Do

    Begin

      WriteLn(NevSor, Tomb[I]);

      If Length(Tomb[I])>Sh Then Sh:= Length(Tomb[I]);

      Inc(I);

    End;

  Close(Nevsor);

  ClrScr;

  Dec(I);

  Listazo(7,0,2,20,2,Sh+6,I,5,1,True,'Lista');

End;

Begin

  TextMode(CO80);

  Szinek(1,14);

  ClrScr;

  NevSorOS:= 'NevSor.Txt';

  AdatBe;

  Rendez;

  Varj;

End.

 

Az AdatBe eljárás először hozzáfűzésre próbálja megnyitni az állományt, ha ez nem sikerül, akkor ReWrite-tal. Majd billentyűzetről olvas üres string végjelig. A Rendez eljárás a file végéig (EOF) olvassa a lemezes állományt, közben a stringeket listára teszi. Majd lezárja és írásra megnyitja az állományt, és a teljes listát kiírja az állományba. Végül a listát a listázóban megtekinthetjük.

 

 

 

 

 

Hangok

 

Előfordulhat, hogy egy adott tevékenységre hanggal is fel szeretnénk hívni a géphasználó figyelmét, főleg akkor, ha a felhasználónak be kellene avatkozni a program további menetébe. Ilyen lehet egy menüből való választás, vagy egy input lekezelése. Erre az esetre írjunk egy Duda nevű eljárást és tegyük azt a CrtPlus unitba:

 

Procedure Duda;

Begin

  Sound(1000);

  Delay(200);

  Nosound;

End;

 

Ha valaki dallamosabb hangot szeretne hallani, akkor azt egyéni ízlés szerint kialakíthatja. Ehhez a CrtPlus unitba elhelyezhetjük a zenei hangok frekvenciáit:

 

Const

  Hq=   1.059463;

  Ha=   440;

  Hc=   Round(Ha/Hq/Hq/Hq/Hq/Hq/Hq/Hq/Hq/Hq);

  Hcisz=Round(Hc*Hq);

  Hd=   Round(Hcisz*Hq);

  Hdisz=Round(Hd*Hq);

  He=   Round(Hdisz*Hq);

  Hf=   Round(He*Hq);

  Hfisz=Round(Hf*Hq);

  Hg=   Round(Hfisz*Hq); 

  Hgisz=Round(Ha/Hq);

  Hbe=  Round(Ha*Hq);

  Hh=   Round(Ha*Hq*Hq);

 

Ezek a frekvenciák kiszámolva:

 

Hc=   261;

Hcisz=232;

Hd=   294;

Hdisz=311;

He=   329;

Hf=   349;

Hfisz=370;

Hg=   392;

Hgisz=415;

Ha=   440;

Hbe=  466;

Hh=   494;

 

Szöveges képernyőmódok

 

 

35. Írjunk programot, amely bemutatja, hogy milyen szöveges képernyőmódokat tud kezelni a Turbo Pascal.

 

Program SzovKep;

Uses NewDelay, Crt, CrtPlus;

Var Eredeti: Byte;

Begin

  Eredeti:= LastMode;

  TextAttr:= 15;

  ClrScr;

  TextMode(0);

  Write(’BW40=0: fekete-fehér 40*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(1);

  Write(’CO40=1: színes 40*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(2);

  Write(’BW80=2: fekete-fehér 80*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(3);

  Write(’CO80=3: színes 80*25, színes adapteren’);

  Tunj;

  Varj;

  TextMode(7);

  Write(’MONO=7: fekete-fehér 80*25, monokróm adapteren’);

  Tunj;

  Varj;

  TextMode(3+256);

  Write(’3+Font8x8=259: színes 80*43 ill. 80*50, EGA/VGA adapteren’);

  Tunj;

  Varj;

  TextMode(eredeti);

End.

 

A megjelenítési módokat a TextMode paraméteres eljárással állíthatjuk be. A LastMode változó a legutoljára beállított üzemmódot tartalmazza.

 

 

36. Írjunk bemutató programot a képernyő megjelenítés különböző eljárásaira, írassuk ki és értelmezzük a WindMin és WindMax változók értékét. Mutassuk be az InsLine és DelLine eljárások működését.

 

 

A képernyőn való szövegmegjelenést a LowVideo, HighVideo, NormVideo eljárásokkal szabályozhatjuk. Hatásukat jól szemlélteti a következő rövid program. A LowVideo alacsony intenzitásúra, a HighVideo magas intenzitásúra állítja a karakter színeit. NormVideo a program indításakor detektált attributumokat tartalmazza.

 

Program Kepernyo;

Uses NewDelay, Crt, Crtplus;

Var I: Byte;

Begin

  TextMode(CO80);

  Szinek(1,5);

  Clrscr;

  Write(’Funkció....’);

  HighVideo;

  Write(’F1’);

  Tunj;

  Varj;

  WriteXY(1,5,’N’);

  LowVideo;

  Write(’em’);

  Tunj;

  Varj;

  Normvideo;

  WriteXY(1,10,’Vége is lehetne, de nincs ...’);

  Tunj;

  Varj;

  GoToXY(1,15);

  Writeln(WindMin,’  ’,WindMax);

  Writeln(Lo(WindMin)+1,’  ’,Hi(WindMin)+1);

  WriteLn(Lo(WindMax)+1,’  ’,Hi(WindMax)+1);

  WriteXY(30,20,'*');

  Write(WhereX,’  ’,WhereY,’ Helyen volt a kurzor’);

  Tunj;

  Varj;

  GotoXY(1,1);

  For I:= 1 To 5 Do

  Begin

    Varj;

    DelLine;

  End;

  Varj;

  GoToXY(1,10);

  For i:= 1 to 5 do

  Begin

    Varj;

    InsLine;

  End;

  Tunj;

  Varj;

End.

 

A programot futtatva a WindMin és WindMax értékét és a belőlük származó ablakkoordinátákat kaphatjuk meg. A WhereX és WhereY segítségével a kurzor pozícióját kérdezhetjük le. Az InsLine és DelLine működését a két For ciklus szemlélteti.

 

 

A DOS unit

 

 

37.  Írjunk programot, amely kilistázza az aktuális könyvtár tartalmát, majd kiírja a a lemez szabad kapacitását.

 

A lemezkezelő eljárások többségét a DOS unit tartalmazza, ezért ezt használatba kell venni. A Katalogus az aktuális könyvtárnak a neve. A ChDir könyvtárcserét végez, a DOS parancsoknak megfelelően. A FindFirst az  első, a FindNext a további bejegyzéseket keresi az aktuális könyvtárban. A bejegyzések Record típusúak, és a Bejegyzes-ben  tároljuk őket. A DosError a lemezműveleteknél fellépő futás idejű hibákat tartalmazza. 0 esetén nincs hiba. A Bejegyzes Record Name mezőjében a név, az Attr mezőjében az attributum található. A DiskFree függvény visszaadott értéke a lemez szabad kapacitása. A típusa miatt csak 2Gb-ig mutat helyes értéket.

 

Program Director;

Uses NewDelay, Crt, CrtPlus, Dos;

Var Bejegyzes: SearchRec;

    Katalogus: String;

    Meret, Szabad: longint;

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  ChDir('..');

  GetDir(0,Katalogus);

  If Katalogus[Length(Katalogus)]<>'\' then Katalogus:= Katalogus+'\';

  Katalogus:= Katalogus+'*.*';

  WriteLn(Katalogus,' könyvtár tartalma:');

  FindFirst(Katalogus, AnyFile, Bejegyzes);

  If DosError<>0 Then WriteLn('Hiba') Else

  While DosError=0 Do

  Begin

    Write(Bejegyzes.Name);

    If Bejegyzes.Attr And Directory=Directory Then

    WriteXY(14,WhereY,'<DIR>');

    WriteLn;

    FindNext(Bejegyzes);

  End;

  WriteLn;

  Szabad:= DiskFree(Ord(Katalogus[1])-Ord('A')+1);

  Szabad:= DiskSize(Ord(Katalogus[1])-Ord('A')+1);

  WriteLn(Meret,' Byte-ból ');

  WriteLn(Szabad,' Byte szabad');

  Tunj;

  Varj;

End.

 

 

Gyakran igény van arra, hogy egy program futása közben, valamely lemez illetve könyvtár tartalmát megnézzük. Például azért, hogy az ott lévő file-okból válogassunk. Egy könyvtár tartalmának elolvasásához a DOS standard Unit használata szükséges. A következő feladatunk e témában az lesz, hogy egy általános file-keresőt írjunk, amelyet a CrtPlus-ban szeretnénk elhelyezni. Ehhez először a lista elején lévő Uses sor bővítendő:

 

Unit CrtPlus;

InterFace

Uses NewDelay, Crt, Dos;

. . .

 

38. Írjunk olyan függvényt, amely egy általunk megadott meghajtó aktuális könyvtárának a tartalmát úgy listázza ki, hogy csak a megadott kiterjesztéssel rendelkező file-okat jeleníti meg.

 

A feladat értelmében a függvény paraméterei a következők:

HSz: Háttérszin;

KSz: Karakterszin;

VSz: Választószin;

Dr: a lemezes egység száma (0: aktuális, 1: A:\; 2:B:\; 3: C:\; 4: D:\; …);

Ext: a keresési maszkhoz a file kiterjesztése.

A függvényt a CrtPlus-ban helyezzük el.

 

Function FileKereso(HSz,KSz,DSz,Dr: Byte; Ext: String): String;

Var I, V, Sh: Integer;

    Bejegyzes: SearchRec;

    Katalogus: String;

Begin

  For I:= 0 To max do Tomb[I]:= '';

  GetDir(Dr,Katalogus);

  If Katalogus[Length(Katalogus)]<>'\' Then Katalogus:= Katalogus+'\';

  Katalogus:= Katalogus+'*.'+Ext;

  FindFirst(Katalogus,AnyFile,Bejegyzes);

  If DosError<>0 Then Begin FileKereso:=''; Exit End;

  I:= 1;

  While DosError=0 Do

  Begin

    Tomb[I]:= ' '+Bejegyzes.Name;

    FindNext(Bejegyzes);

    Inc(I);

  End;

  Dec(I);

  Sh:= Length(Katalogus)+5;

  If Sh<17 Then Sh:=17;

  V:= Listazo(HSz,KSz,VSz,Round(40-Sh/2),6,Sh,I,11,1,True, Katalogus);

  FileKereso:= ValidSt(Tomb[V]);

End;

 

A GetDir (System Unit) eljárás a Katalogus stringbe tölti a Dr által meghatározott lemezes egység aktuális könyvtárának a nevét. Ha nem a gyökérkönyvtárban vagyunk, akkor a '\' jel hiányozni fog a bejárási út végéről, ezért a vizsgálat és a hozzáfűzés. A '*.'+ext -el adjuk meg a kiterjesztést. A FindFirst (Dos Unit) eljárás, a Katalogus-ban megadott könyvtárban keresi, az AnyFile attributumu első file-t, és ha megtalálja a Bejegyzes-ben helyezi el. Az első DosError vizsgálat eredményes volta akkor következik be, ha a kapott elérési út érvénytelen, vagy hiányzik a megfelelő lemezes egység, vagy üzemképtelen. A FindNext (Dos Unit) eljárás az előző eljárásban már megkezdett katalógus bejegyzéseit tovább olvassa. Hiba esetén az olvasás befejeződik (mert nincs több bejegyzés). A Bejegyzéseket a Tomb-ben helyezzük el. A Listazo függvénnyel a katalógust megnézhetjük, sőt még választhatunk is belőle. A SearchRec tipus és az AnyFile konstans a Dos Unitban vannak deklarálva. További, az állományok állapotát leíró konstansok: ReadOnly, Hidden, SysFile, VolumeID, Directory és Archive. A megírt függvényt a következő kis program teszteli:

 

Program DirProba;

Uses NewDelay, Crt, CrtPlus;

Var FileNev: String;

Begin

  TextMode(CO80);

  Szinek(1,14);

  ClrScr;

  FileNev:= FileKereso(7,0,Green,0,'*');

  WriteXY(1,24,filenev);

  Tunj;

  Varj;

End.

 

 

39. Irjunk programot, amely a főkönyvtárban könyvtárakat (mappákat) hoz létre, és mindegyikben egy file-bejegyzést. A file most lehet üres is.

 

A program olyan egyszerű, hogy magyarázat nélkül is könnyen érthető. A könyvtárkészítő parancs teljesen megegyezik a DOS-beli megfelelőjével.

 

Program DirsMake;

Uses NewDelay, Crt, CrtPlus, Dos;

Var Ch: Char;

Procedure DirMake(D: String);

Var FNev: Text;

    DNev: String;

Begin

  ChDir('\');

  DNev:= 'user.dat';

  MkDir(D);

  ChDir(D);

  Assign(FNev,DNev);

    ReWrite(FNev);

  Close(FNev);

End;

Begin

  For Ch:='a' To 'f' Do DirMake(Ch);

End.

 

40. Írjunk programot, amely egy megadott könyvtár alatti összes könyvtár tartalmát kilistáz, és közben egy adott nevű file-t minden könyvtárból töröl (természetesen csak onnan, ahol volt).

 

 

Program DirList;

Uses NewDelay, Crt, Dos;

Var Katalogus: DirStr;

    Bejegyzes: SearchRec;

    F: File;

    D, HD: String;

Procedure KatalogusLista(Katalogus: DirStr);

Var Bejegyzes: SearchRec;

Begin

  WriteLn(Katalogus);

  If WhereY>23 Then Begin ReadLn; ClrScr End;

  If Katalogus[Length(Katalogus)]='\'

  Then Delete(Katalogus,Length(Katalogus),1);

  FindFirst(Katalogus+'\*.*',AnyFile,Bejegyzes);

  While (DosError=0) And (Bejegyzes.Name[1]='.') Do FindNext(Bejegyzes);

  While DosError=0 Do

  Begin

    If (Bejegyzes.Attr And Directory)=Directory Then

    KatalogusLista(Katalogus+'\'+Bejegyzes.Name)

    Else WriteLn(Katalogus,'\',Bejegyzes.Name);

    If WhereY>23 Then Begin Readln; ClrScr End;

    FindNext(Bejegyzes);

    If Bejegyzes.Name=D Then

    Begin

      HD:= Katalogus+'\'+Bejegyzes.Name;

      Assign(F,HD);

      Erase(F);

    End;

  End;

End;

Begin

  TextMode(CO80);

  D:= 'USER.DAT';

  ClrScr;

  Write('Katalógusnév: ');

  ReadLn(Katalogus);

  FindFirst(Katalogus + '\*.*',AnyFile,Bejegyzes);

  If DosError=3 Then WriteLn('Nincs ilyen katalógus')

  Else KatalogusLista(Katalogus);

  ReadLn;

End.

 

A program az eddigiek alapján könnyen érthető, ezért elemzésétől eltekintünk. A KatalogusLista rekurzív hívással jut el a mélyebb könyvtárakba.

 

41. Írjunk programot, amely a lemez kapacitásával, DOS verzióval, a dátummal és az idővel kapcsolatos eljárásokat és függvények használatát mutatja be.

 

Program DosDemo;

Uses NewDelay, Crt, CrtPlus, Dos;

Const Honap: Array[1..12] Of String=

      ('Jan','Febr','Márc','Ápr','Máj','Jún',

       'Júl','Aug','Szept','Okt','Nov','Dec');

      Het: Array[0..6] Of String=

('Vasárnap','Hétfő','Kedd','Szerda','Csütörtök','Péntek','Szombat');

Var Ev, Ho, Nap, HetNap: Word;

    Ora, Perc, Mp, Mp100: Word;

    Ch: Char;

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  WriteXY(1,7,'d: új dátum, t: új idő');

  GoToXY(1,1);

  WriteLn('Az aktuális lemez kapacitása ',DiskSize(0)/1024/1024:8:2,' Mbyte.');

  WriteLn('Az aktuális lemezen ',DiskFree(0),' byte szabad.');

  WriteLn('Dos Vezió: ',Lo(DosVersion),'.',Hi(DosVersion));

  GetDate(Ev, Ho, Nap, HetNap);

  WriteLn('A mai nap: ',Ev,'. ',Honap[Ho],'. ',Nap,', ',Het[HetNap],'.');

  Repeat

    GetTime(Ora, Perc, Mp, Mp100);

    Write('A pontos idő: ',Ora,' óra ',Perc,' perc ',Mp,' másodperc.');

    Delay(1000);

    GoToXY(1,WhereY);

  Until KeyPressed;

  Ch:= ReadKey;

  Case Ch Of

    'd': Begin

           WriteXY(1, 9,'Új év : '); ReadLn(Ev);

           WriteXY(1,10,'Új hó : '); ReadLn(Ho);

           WriteXY(1,11,'Új nap: '); ReadLn(Nap);

           SetDate(Ev, Ho, Nap);

         End;

    't': Begin

           WriteXY(1, 9,'Új óra  : '); ReadLn(Ora);

           WriteXY(1,10,'Új perc : '); ReadLn(Perc);

           WriteXY(1,11,'Új mperc: '); ReadLn(Mp);

           SetTime(Ora, Perc, Mp, 0);

         End;

  End;

End.

 

 

42. Írjunk programot, amely a felhasználó által meghatározható, de az operációs rendszer által elfogadható évre vonatkozóan kártyanaptárt készít. Végül el lehessen dönteni, hogy a képernyőt kimenjük-e lemezre, vagy kinyomtatjuk nyomtatón, esetleg egyiket sem, csak egyszerűen kilépünk a programból.

 

Első lépésként a képernyőtervet kell elkészíteni. Egy hónapra vonatkozóan csak egyszer kellene kiirni a napok nevét, pontosabban a napok nevének az első kezdőbetűjét. Mivel a 12 hónapnevet egymás mellé, a hónapok napjait pedig egymás alá írva nem férnek el a képernyőn, ezért célszerű egy-egy téglalap alakú területet egy hónapra fenntartani. A hónapokat hetekre bontva a függőleges méret minimum 7 +1 a hónap nevének. A kérdéses téglalap tehát 8 karakter magas, amiből 3 fér egy oszlopba. A 12 hónapból tehát 4-et kell egy sorban elhelyezni. Mivel a képernyő 80 karakteres, egy hónapra 20 karakter széles terület jut. Elfér-e ezen egy hónap? Szerencsére pontosan elfér. Ha ugyanis alaposan megnézünk egy naptárat, akkor láthatjuk, hogy egy hónap maximum 6 hétre nyúlhat szét. Mert ha mondjuk, szombatra esik elseje egy 31 napos hónapban, akkor abban 5 szombat van, de még az ötödik mindig csak a hónap 29 napja, tehát 30-a vasárnap és 31-e hétfő, azaz valóban 6 hétre nyúlik szét. Mivel a napok sorszáma a hónapokon belül maximum két számjegyű, kihagyásokat is figyelembe véve 6*3, azaz 18 karakter széles hely kell neki, plusz a hét napnevének az első betűje plusz egy kihagyás, az összesen 6*3+2=20. Tehát éppen elfér a naptár a képernyőn. A többi magyarázatot a programlista tartalmazza.

 

Program OrokNap;

Uses NewDelay, Crt, Crtplus, Dos, Printer;

     {Mivel nyomtatni is szeretnénk, használnunk kell a Printer Unit-ot}

Const Honap: Array[1..12] Of String=

      ('Január','Február','Március','Április',

       'Május','Június','Július','Augusztus',

       'Szeptember','Október','November','December');

      Het: Array[0..6] Of String= ('V','H','K','S','C','P','S');

Var Ev,Ho,Nap,NapNev,Oldev,Oldho,Oldnap: Word;

    I,J,Hoszam,Napszam,Elsonap,Anap,Vv: Integer;

    Szoko: Boolean;

    Hh: Array[1..12] Of Byte;

    Ch: Char;

    ws: String;

    FNev: Text;

    DosNev: String;

Begin

  Hh[1]:=31;Hh[2]:=28;Hh[3]:=31;Hh[4]:=30;Hh[5]:=31;Hh[6]:=30;

  Hh[7]:=31;Hh[8]:=31;Hh[9]:=30;Hh[10]:=31;Hh[11]:=30;Hh[12]:=31;

  ClrScr;

  GetDate(Ev,Ho,Nap,NapNev);

  Oldev:= ev; Oldho:= ho; Oldnap:= nap;

  GoToXY(38,1); Write(Ev);

  WriteXY(24,2,'Akarsz-e évet változtatni (i/n)?');

  Repeat

    Ch:= ReadKey;

    Ch:= UpCase(ch);

  Until Ch In ['I','N'];

  If Ch='I' Then

  Begin

    WriteXY(31,3,'Kérem az évszámot: ');

    ReadLn(Ev);

    SetDate(Ev,Ho,Nap);

    GetDate(Ev,Ho,Nap,NapNev);

    SetDate(Oldev,Oldho,Oldnap);

    {Hogy minél kevesebb ideig éljen a program miatti új időpont}

  End;

  Szoko:= False;

  If (Ev Mod 4)=0 Then Szoko:= True;

  If (Ev Mod 100)=0 Then Szoko:= False;

  If (Ev Mod 400)=0 Then Szoko:= True;

  If Szoko Then Hh[2]:= 29;

  {Ez volt a szökőév megállapítás}

  Hoszam:=1; Napszam:= 0;

  While Hoszam<ho Do

  Begin

    Inc(Napszam,Hh[Hoszam]);

    Inc(Hoszam);

  End;

  Inc(Napszam,Nap);

  {Napszam= a kérdéses évben a mai nap sorszáma}

  Napszam:= Napszam Mod 7;

  {A maradékképzéssel hét lehetséges esetre vezetjük vissza az első nap napnevének a megállapítását:}

  Case Napszam Of

       0: Elsonap:= (NapNev+1) Mod 7;

       1: Elsonap:= NapNev;

    2..6: While Napszam>1 Do

          Begin

            Dec(Napszam);

            Dec(NapNev);

            If NapNev>6 Then NapNev:=6; {Mivel a NapNev Word típusú}

            Elsonap:= NapNev;

          end;

  End;

  {Elsonap= az év első napja erre a napra esett, 0=V, 1=H, 2=K ... 6=S}

  Anap:= Elsonap;

  {Az Anap-ban tároljuk azt, hogy az aktuális kiíráskor nap a hét melyik napja}

  Szinek(1,15);

  ClrScr;

  GoToXY(38,1);

  Write(ev);

  For I:= 1 To 12 Do WriteXY(((I-1) Mod 4)*20+7,((I-1) Div 4)*8+2,Honap[I]);

  For I:= 1 To 12 Do For J:= 0 To 6 Do

  WriteXY(((I-1) Mod 4)*20+1,((I-1) Div 4)*8+3+J,Het[J]);

  For I:= 1 To 12 Do

  Begin

    Vv:= 0;

    For J:= 1 To Hh[I] Do

    Begin

      GoToXY(((I-1) Mod 4)*20+3+Vv,((I-1) Div 4)*8+3+Anap);

      Inc(Anap);

      Anap:= Anap Mod 7;

      If Anap=0 Then Inc(Vv,3);

      Write(J:2);

    End;

  End;

  {A Vv változó szerepe az íráshelyek vízszintes széthúzása}

  GoToXY(1,1);

  Write('(F: File  P: Printer)');

  Tunj;

  Ch:= ReadKey;

  GoToXY(1,1);

  Write('                     ');

  {Ha file-ba mentjük a képernyőt az op-rendszerbeli neve legyen az évszám + .txt kiterjesztés:}

  If Ch='F' Then

  Begin

    Str(Ev,DosNev);

    DosNev:= DosNev+'.txt';

    Assign(FNev,DosNev);

      ReWrite(FNev);

      For I:= 1 To 25 Do

      Begin

        Ws:= '';

        For J:= 1 To 79 Do Ws:= Ws+Chr(BKep[I,J,1]);

        WriteLn(FNev,Ws);

      End;

    Close(FNev);

  End;

  {Ha kinyomtatjuk a képernyőt:}

  If Ch='P' Then

  Begin

    For I:= 1 To 25 Do

    Begin

      Ws:= '';

      For J:= 1 To 80 Do Ws:= Ws+Chr(BKep[I,J,1]);

      WriteLn(Lst,Ws);

      {Nyomtatóra tehát ugyanúgy írunk, mint szöveges file-ba}

    End;

  End;

End.

 

 

 

Dinamikus tárkezelés, adatstruktúrák

 

 

A téma bevezetéseként ismételjük át, hogy eddig milyen változókkal ismerkedtünk meg. Elsőként a globális változókkal, amelyet a program deklarációs részében irtunk le, s amelyeket a teljes programba, bárhol használhattunk. Aztán megismerkedtünk az eljárásokkal és függvényekkel. Ezeknek a belsejében is deklarálhattunk változókat, ezek voltak a lokális változók. A lokális változókat csak a deklarálás helyén, vagy az alatta lévő szinteken lehetett használni. Az ugyanazon szinten lévő rutinok nem látták egymás változóit, sőt a főprogram sem. Definiáltunk továbbá konstansokat és tipizált konstansokat. A Max értékek konstansok, a menüpontok nevei tipizált konstansok voltak. Az eddig megismert változókat és konstansokat statikusoknak nevezzük azért, mert fordításkor a helyük létrejön és a program futásának a végéig változatlanul meg is marad.

 

Nézzük ezután, hogyan helyezkednek el a pascal program esetén a memóriában a kódok és az adatok. Kezdetben, a 4.0 verzióig a turbo pascal *.com tárgyprogramokat készített, melynek rögzített betöltési helye volt a memóriában és mérete maximálisan egy lap, azaz 64 Kb lehetett. Ehhez kapcsolódott az adatszegmens maximum 64 Kb-tal és az Ovelay terület (azaz átlapolási terület az Overlay-be fordított Unit-ok részére, - mindig az aktuálisan szükséges kódot töltötte a rendszer a lemezről a RAM-ba). A kimarad memóriaterületen volt a Stack (a verem). Ezeket a korlátokat manapság jelentősen átléphetjük az új típusú memória kiosztás és kezelés révén. Első fontos dolog, hogy a Turbo Pascal 7.0 már nem *.com hanem *.exe állományokat készít, melyet a hagyományos memória bármely üres helyére betölthet, nincs rögzített helye. Méretére nincs korlátozás, hacsak az nem, hogy a szövegszerkesztő maximálisan 64 Kb-os szöveget tud kezelni. Ezen viszont az tud segíteni, hogy saját Unit-okat írhatunk, melynek darabszáma nincs korlátozva. Így az összeszerkesztett exe állomány akár több-száz Kb is lehet. Itt említenénk meg, hogy a pascal rendszer két IDE-t tartalmaz a DOS-os környezetre. Ezek: a Turbo és a Tpx. A Turbo úgy dolgozik, hogy a fordítást alapértelmezésben a RAM-ba készíti és a segédállományokat is itt hozza létre. Nagyméretű programok esetén ez akadály lehet, hiszen DOS-ban csak maximum 10 lap (640 Kb) áll rendelkezésre, s ha mindent a memóriában oldunk meg, hamar elfogyhat a standard memória. A Tpx viszont a fordítást mindig lemezre végzi és az ideiglenes állományait is itt hozza létre. Ezzel tehát nagyobb programokat lehet irni. Ezért használtuk eleve ezt a fejlesztéseink alkalmával. A mai rendszerben a memória kiosztása a következő (az alacsony címtől kezdve a magasak felé haladva):

-         *.exe állomány,

-         Unit-ok,

-         tipizált konstansok (nem tartoznak az adatszegmenshez),

-         globális (statikus) változók - maximum 64 Kb -,

-         Stack - maximum 64 Kb -,

-         Overlay - ha van,

-         Heap - a memória tetejéig.

 

Vizsgáljuk meg egy kicsit jobban a Stack-et, miért szükséges és hogyan működik. A program futása közben gyakran előfordul, hogy a programnak alprogramhoz kell fordulnia, amely gyakorlatilag egy objekt helyre való ugrást jelent. Az alprogram végrehajtása után - alapértelmezésben - a programot a hívás helye utáni memóriacímen kell folytatni. A gép úgy tud visszatalálni, hogy minden alprogramhíváskor lementi a hívás helyét a memóriába. Természetesen alprogramból újra alprogramba ugorhatunk, így az eredeti helytől már két ugrásra vagyunk. A visszajutás először a legutóbbi, aztán az eggyel korábbi cím ismerete alapján lehetséges. Az adatokat tehát úgy kell feljegyezni, hogy amit később irtunk le, arra hamarabb van szükség, amit legkorábban, arra pedig legutoljára. Ennek az adattárolásnak az angol neve: LIFO (Last Input, First Output), magyarul: amit utoljára behelyezünk, azt vesszük ki elsőnek. Ez úgy működik, mint egy verem (Stack), ami a verem alján van, azt csak akkor tudjuk kivenni a veremből, ha már mindent, amit utána tettünk bele, már kivettünk. Azt, hogy a verem véges méretű, könnyen leellenőrizhetjük a következő kis programmal.

 

Program Verem;

Procedure Ide;

  Ide;

End;

Begin

  Ide;

End.

 

Ez a program gyakorlatilag semmit nem tesz, csak azt, hogy egy rekurzív eljárást hív meg, (amely természetesen most nincs megfelelően kidolgozva, majd a későbbiekben látunk rekurzív hívásra értelmes és hasznos megoldásokat is). Mivel állandóan önmagát kell meghívnia, mindig menti a visszalépési címet, amely olyan gyorsan történik, hogy a program azonnal leáll Stack Overflow - verem túlcsordulás hibaüzenettel. Ha már itt tartunk, említsünk meg a másik nevezetes adattárolást és a hozzá kapcsolódó hardware megoldást. Ez pedig a FIFO (First Input, First Output), magyarul: amit először behelyezünk, azt vehetjük ki elsőnek. Ez egy csőhöz hasonlítható, amelybe torlódnak az adatok (mint például a hurkatöltőben a töltelék). Pl. (szemléletesen) a baloldalon kerülnek be a csőbe az adatok, és jobb oldalon kerülnek ki a csőből. A számítógépeink mindegyike rendelkezik ilyen elven működő tárral: ez CACHE memória. Ezt a memóriát a processzor és az operatív tár közé helyezik. Működési alapelve azon alapszik, hogy ha a processzornak adatra van szüksége a memóriából, akkor nagyon valószínű, hogy nem csak egy-két Byte-ra, hanem a memória közeli területéről többre is. Így nem csak a kívánt adatok indulnak el a gyorsító tárba, hanem több is, akár 512 kb -is, a CACHE méretétől függően. A CACHE -t ugyanis a processzor sokkal gyorsabban el tudja érni, mint a RAM-ot. Ezáltal a gép működése felgyorsul.

 

43. Írjunk programot, amely bemutatja, hogy maximálishoz közeli statikus tömb deklarációja után még több, szintén maximális méretű dinamikus tömb deklarálható és kezelhető a pascal programban.

 

Program Din1;

Uses NewDelay, Crt;

Var A: Integer;

    AMut: ^Integer;

 

    STomb: Array[1..800] Of String[80];

 

Type PTomb=^TTomb;

     TTomb=Array[1..800] Of String[80];

 

Var T1,T2,T3,T4:PTomb;

    P: Pointer;

 

Begin

  TextMode(CO80);

  TextColor(15);

  ClrScr;

  A:= 123;

  A:= 2*A;

  WriteLn('A: ',A);

  New(AMut);

    AMut^:= 777;

    AMut^:= 2*AMut^;

    WriteLn('AMut^: ',AMut^);

    AMut:= @A;

    AMut^:= AMut^+4;

    WriteLn('A+4: ',A);

    AMut:= Nil; {Sehov  sem mutat}

  {Dispose(AMut); Ha egy statikus változóra  állitottuk,

   már nem szabaditható fel}

  New(T1); New(T2); New(T3); New(T4);

    T1^[800]:= 'Nagy Medve';

    T2^[799]:= T1^[800];

    T3^[798]:= T2^[799];

    T4^[797]:= T3^[798];

    WriteLn('T4^[797]: ',T4^[797]);

    WriteLn('Szabad Heap: ',MemAvail,' , maxim lis blokk: ',MaxAvail);

  Dispose(T1);

  WriteLn('Szabad Heap: ',MemAvail,' , maxim lis blokk: ',MaxAvail);

  Dispose(T2);

  WriteLn('Szabad Heap: ',MemAvail,' , maxim lis blokk: ',MaxAvail);

  Dispose(T3);

  WriteLn('Szabad Heap: ',MemAvail,' , maxim lis blokk: ',MaxAvail);

  Dispose(T4);

  WriteLn('Szabad Heap: ',MemAvail,' , maxim lis blokk: ',MaxAvail);

  ReadLn;

End.

 

 

44. Írjunk programot, amely egy egyszerű láncolt listát kezel. Üres string végjelig bekér például neveket, majd a beirás sorrendjében kiirja a képernyőre és folyamatosan felszabadítja a változó területét.

 

Program Din2;

Uses NewDelay, Crt, CrtPlus;

 

type RecMut=^Rec;

     Rec=Record

           Nev: String;

           Ind: Integer;

           KMut: RecMut;

         End;

 

Var ElsoRec, UjRec, AktRec: RecMut;

    S: String;

    I: Integer;

 

Procedure Felfuz(UjRec: RecMut);

Begin

  If UjRec= Nil Then Exit;

  If ElsoRec= Nil Then Begin ElsoRec:= UjRec; AktRec:= ElsoRec End

  Else

  Begin

    AktReC^.KMut:= UjRec;

    AktRec:= UjRec;

  End;

End;

 

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  I := 0;

  ElsoRec:= Nil;

  Write('Kérem a(z) 1. nevet: ');

  ReadLn(S);

  While S<>'' Do

  Begin

    UjRec:= New(RecMut);

    With UjRec^ Do

    Begin

      Nev:= S;

      Inc(I);

      Ind:= I;

      KMut:= Nil;

    End;

    Felfuz(UjRec);

    Write('Kérem a(z) ',i+1,'. nevet: ');

    ReadLn(S);

  End;

 

  WriteLn;

  WriteLn('A lista:');

  AktRec:= ElsoRec;

  While AktRec <> Nil Do With AktRec^ Do

  Begin

    WriteLn(Ind:4,'. ',Nev);

    ElsoRec:= AktRec;

    AktRec:= KMut;

    Dispose(ElsoRec);

  End;

  Tunj;

  Varj;

End.

 

 

45. Írjunk programot, amely kétirányú láncolt listát kezel. Üres string végjelig bekér például neveket, majd először a beirás sorrendjében, másodszorra pedig ezzel fordított sorrendben kiirja a képernyőre és folyamatosan felszabadítja a változó területét.

 

Program Din3;

Uses NewDelay, Crt, CrtPlus;

 

type RecMut=^Rec;

     Rec=Record

           Nev: String;

           Ind: Integer;

           EMut,

           KMut: RecMut;

         End;

 

Var ElsoRec, UjRec, AktRec, UtolsoRec: RecMut;

    S: String;

    I: Integer;

 

Procedure Felfuz(UjRec: RecMut);

Begin

  If UjRec= Nil Then Exit;

  If ElsoRec= Nil Then

  Begin ElsoRec:= UjRec; UtolsoRec:= UjRec; AktRec:= ElsoRec; Exit End

  Else

  Begin

    AktReC^.KMut:= UjRec;

    UjRec^.EMut:= AktRec;

    UtolsoRec:= UjRec;

    AktRec:= UjRec;

  End;

End;

 

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  I:= 0;

  ElsoRec:= Nil;

  Write('Kérem a(z) 1. nevet: ');

  ReadLn(S);

  While S<>'' Do

  Begin

    UjRec:= New(RecMut);

    With UjRec^ Do

    Begin

      Nev:= S;

      Inc(I);

      Ind:= I;

      EMut:= Nil;

      KMut:= Nil;

    End;

    Felfuz(UjRec);

    Write('Kérem a(z) ',i+1,'. nevet: ');

    ReadLn(S);

  End;

 

  WriteLn;

  WriteLn('A lista előre:');

  AktRec:= ElsoRec;

  While AktRec<>Nil Do With AktRec^ Do

  Begin

    WriteLn(Ind:4,'. ',Nev);

    {ElsoRec:= AktRec;}

    AktRec:= KMut;

    {Dispose(ElsoRec);}

  End;

 

  WriteLn;

  WriteLn('A lista vissza:');

  AktRec:= UtolsoRec;

  While AktRec<>Nil Do With AktRec^ Do

  Begin

    WriteLn(Ind:4,'. ',Nev);

    UtolsoRec:= AktRec;

    AktRec:= EMut;

    Dispose(UtolsoRec);

  End;

  Tunj;

  Varj;

End.

 

 

46. Írjunk programot, amely kétirányú rendezett láncolt listát kezel. Üres string végjelig bekér például neveket, majd először a növekedő sorrendben, másodszorra pedig csökkenő sorrendben kiirja a képernyőre és folyamatosan felszabadítja a változó területét.

 

Program Din4;

Uses NewDelay, Crt, CrtPlus;

 

type RecMut=^Rec;

     Rec=Record

           Nev: String;

           Ind: Integer;

           EMut,

           KMut: RecMut;

         End;

Var ElsoRec, UjRec, AktRec, UtolsoRec: RecMut;

    S: String;

    I: Integer;

 

Procedure Felfuz(UjRec: RecMut);

Begin

  If UjRec= Nil Then Exit;

 

  If ElsoRec= Nil Then

  Begin ElsoRec:= UjRec; UtolsoRec:= UjRec;Exit End;

 

  If ElsoRec = UtolsoRec Then

  Begin

    If ElsoRec^.Nev<UjRec^.Nev Then UtolsoRec:= UjRec Else ElsoRec:= UjRec;

    ElsoRec^.KMut:= UtolsoRec;

    UtolsoRec^.EMut:= ElsoRec;

    Exit;

  End;

 

  AktRec:= ElsoRec;

  While (AKtRec^.Nev<UjRec^.Nev) And (AktRec<>Nil) Do

  AktRec:= AktRec^.KMut;

 

  If (AktRec<>ElsoRec) And (AktRec<>Nil) Then

  Begin

    AktRec^.EMut^.KMut:= UjRec;

    UjRec^.EMut:= AktRec^.EMut;

    AktRec^.EMut:= UjRec;

    UjRec^.KMut:= AktRec;

    Exit;

  End;

 

  If AktRec=ElsoRec Then

  Begin

    ElsoRec^.EMut:= UjRec;

    UjRec^.KMut:= ElsoRec;

    ElsoRec:=UjRec;

    Exit;

  End;

 

  If AktRec=Nil Then

  Begin

    UtolsoRec^.KMut:= UjRec;

    UjRec^.EMut:= UtolsoRec;

    UtolsoRec:= UjRec;

  End;

 

End;

 

Begin

  TextMode(CO80);

  Szinek(1,15);

  ClrScr;

  I:= 0;

  ElsoRec:= Nil;

  Write('Kérem a(z) 1. nevet: ');

  ReadLn(S);

  While S<>'' Do

  Begin

    UjRec:= New(RecMut);

    With UjRec^ Do

    Begin

      Nev:= S;

      Inc(I);

      Ind:= I;

      EMut:= Nil;

      KMut:= Nil;

    End;

    Felfuz(UjRec);

    Write('Kérem a(z) ',i+1,'. nevet: ');

    ReadLn(S);

  End;

 

  WriteLn;

  WriteLn('A lista előre:');

  AktRec:= ElsoRec;

  While AktRec<>Nil Do With AktRec^ Do

  Begin

    WriteLn(Ind:4,'. ',Nev);

    {ElsoRec:= AktRec;}

    AktRec:= KMut;

    {Dispose(ElsoRec);}

  End;

 

  WriteLn;

  WriteLn('A lista vissza:');

  AktRec:= UtolsoRec;

  While AktRec<>Nil Do With AktRec^ Do

  Begin

    WriteLn(Ind:4,'. ',Nev);

    UtolsoRec:= AktRec;

    AktRec:= EMut;

    Dispose(UtolsoRec);

  End;

  Tunj;

  Varj;

 

End.

 

 

 

 

Az egér használata

 

         Az egér egy olyan mutató eszköz, mellyel a számítógép használója beavatkozhat a program futásának menetébe. A képernyőn megjelenő, az egér jeleit felfogni képes objektumok reagálnak az egér mozgására, kattintásra, kettős kattintásra vagy vonszolásra. Így aztán egérrel parancsot adhatunk, menüpontot aktivizálhatunk vagy átrendezhetjük a felhasználói képernyőt. Ebben a fejezetben a karakteres képernyőn megjelenő egér lehetőségeivel ismerkedünk meg. Az egérkurzor egy téglalap, melynek egy karakternyi a mérete. Minden karakterhely fölé odavihető, bekapcsolt állapotban és jól működő program esetén mindig látható. Az egér használatához szükség van: természetesen egy egérre, egy meghajtó programra, amelyet az operációs rendszernek kell installálni. Szükség van továbbá egy olyan programcsomagra, amely esetünkben a Pascal nyelven belül megfogalmazza az egér megjelenésével és lekérdezésével kapcsolatos eljárásokat és függvényeket. Megtehetnénk, hogy ez utóbbi Unit-ot saját magunk megírjuk, de a Pascal nyelvben már van egy egység, amely ezeket tartalmazza, ezért mi ezt fogjuk használni. Ennek az egységnek a neve Drivers. Programjainkban ezt az egységet is használatba kell venni, ha egeret szeretnénk használni.

 

         Nézzük a Drivers Unit egérkezelő függvényeit és eljárásait. Mivel a Drivers a Pascal nyelv Turbo Vision részéhez tartozik, néhány szót erről is kell ejtenünk. A Turbo Vision segítségével olyan felépítésű programokat írhatunk, mint amilyen az IDE. Teljesen objektum orientált, eseményvezérelt, ablaktechnikára épülő, menüvezérelt programokat. A későbbiekben, csak néhány program erejéig, megismerkedünk a Turbo Vision lehetőségeivel is. A Drivers egység tartalmazza a Turbo Vision eseménykezelő eljárásait és függvényeit, amelyet szintén használni fogunk. Nézzük akkor első egérkezelő programunkat.

 

 

47. Írjunk programot, amely bemutatja az egér működését programban. Kérdezzük le az egér koordinátáit, vezessük egérrel az írókurzort, kattintással rakjunk csillagokat a képernyőre, majd pedig írjuk minden pillanatban a képernyőre az  egér összes állapotát. Végül a Menu függvényünket (CrtPlus) tanítsuk meg az egér használatára.

 

         Első lépésként tehát a Drivers egységet használatba kell venni. Egeret használó programunk első eljáráshívása az InitEvents, amely inicializálja az eseménykezelőt. Második a ShowMouse, amely az egeret jeleníti meg. Ha csak ennyi lenne a programunkban (és egy végtelen ciklus), akkor az egér már látható lenne a képernyőn. Az egér képernyő koordinátáit a MouseWhere rekord tartalmazza. Ennek a rekordnak két mezője van, az x és az y, és az egér helyének két koordinátáját tartalmazza. Ez állandóan frissül, csak az a feladatunk, hogy programjainkban lekérdezzük. Ez látható a programunk első szakaszában. Ha megfigyeljük a futtatás eredményét, megállapíthatjuk, hogy a GoToXY eljárással a koordináták nincsenek szinkronban. A képernyő első helyének két egér koordinátája (0,0), az utolsóé (79,24). Ha a MouseWhere két koordinátája alapján szeretnénk a kurzort vezérelni, akkor mindkettőhöz egyet hozzá kell adni. Ez látható a második szakaszban. A harmadik szakasz az egérkattintásra figyel. A MouseButtons függvény értéke 1, ha kattintottak az egérrel, 0 ha nem. A MouseButtons érték is folyamatosan frissül, tehát lenyomott gombbal és mozgatással a program folyamatosan rajzol a képernyőre. A negyedik szakaszban már a teljes megfigyelést valósítottuk meg. Ehhez szükség van egy Esemeny változóra, melynek típusa TEvent, mely egy eseményrekordot jelent. Az eseményrekord létrehozását a Drivers elvégzi helyettünk. Ha billentyűzet eseményt szeretnénk bekérni, akkor GetKeyEvent(Esemeny), ha egér eseményt, akkor a GetMouseEvent(Esemeny) eljárást kell meghívnunk. Az esemény rekord What mezőjében található az, hogy mi történt. Az esemény Buttons mezője azt tartalmazza, hogy a történés melyik egérgombbal következett be (bal vagy jobb, mbLeftButton vagy mbRightButton). Az esemény Double mezője igaz, ha dupla kattintás volt, és hamis ha szimpla. A lehetséges egéresemények:

evMouseDown = Gomb lenyomva.

evMouseUp     = Gomb felengedve.

evMouseMove = Az egér elmozdult.

eMouseAuto    = Az egér lenyomott gombbal mozog.

evNothing       = Nincs esemény.

 

Program EgerDemo;

Uses NewDelay, Crt, CrtPlus, Drivers;

Var Esemeny: TEvent;

    Mp: Byte;

Begin

  TextMode(CO80);

  InitEvents; ShowMouse; Szinek(1,15);

  ClrScr; WriteXY(1,1,'Első szakasz');

  Repeat

    With MouseWhere do Begin GotoXY(37,1); Write(x:3,y:3) End;

  Until Keypressed;

  ClrScr; WriteXY(1,1,'Második szakasz'); KeyEmpty;

  Repeat

    GotoXY(MouseWhere.x+1,MouseWhere.y+1)

  Until KeyPressed;

  ClrScr; WriteXY(1,1,'Harmadik szakasz');

  Gotoxy(1,1); KeyEmpty;

  Repeat

    If MouseButtons=1 then

    Begin

      WriteXY(MouseWhere.x+1,MouseWhere.y+1,'*');

      GotoXY(WhereX-1,WhereY);

    End;

  Until KeyPressed;

  ClrScr; WriteXY(1,1,'Negyedik szakasz'); KeyEmpty;

  Repeat

    GetMouseEvent(Esemeny);

    Case Esemeny.What Of

      evMouseDown: Begin

                     WriteXY(1,9,'Gomb lenyomva          ');

                     If Esemeny.Double Then

                        WriteXY(1,13,'Dupla kattintás  ');

                     If Not Esemeny.Double Then

                        WriteXY(1,13,'Szimpla kattintás');

                   End;

      evMouseUp  : WriteXY(1,9,'Gomb felengedve        ');

      evMouseMove: Begin

                     WriteXY(1,10,'Egér elmozdult         ');

                     gotoxy(20,1);

                     Write(MouseWhere.X:4,MouseWhere.Y:4);

                   End;

      evMouseAuto: begin

                     WriteXY(1,10,'Lenyomott gombbal mozog');

                     gotoxy(20,1);

                     Write(MouseWhere.X:4,MouseWhere.Y:4);

                   end;

      evNothing  : WriteXY(1,11,'Nincs esemény          ');

    End;

    Case Esemeny.Buttons of

      mbLeftButton: WriteXY(1,12,'Bal gomb lenyomva ');

      mbRightButton:WriteXY(1,12,'Jobb gomb lenyomva');

    End;

  Until KeyPressed;

  ClrScr; WriteXY(1,1,'Ötödik szakasz'); KeyEmpty;

  Tomb[1]:=' Első     ';

  Tomb[2]:=' Második  ';

  Tomb[3]:=' Harmadik ';

  Tomb[4]:=' Vége     ';

  For Mp:=1 to 4 do SzTomb[Mp]:=Mp;

  Ablak(7,0,34,8,47,13,True,'Menű');

  For Mp:=1 to 4 Do WriteXY(36,8+Mp,Tomb[Mp]);

  Mp:=Menu(7,0,Green,36,9,10,4,1); Writexy(1,24,Tomb[Mp]);

  Tunj; Varj;

End.

 

 

Ahhoz hogy programunk ötödik szakasza működjön, azaz a Menu függvényünk megértse az egér üzeneteket, egy kicsit ki kell bővítenünk. Ehhez töltsük be a CrtPlus-t, és javítsuk ki a következőképpen. A CrtPlus-ban is használatba kell venni a Drivers Unit-ot. Fel kell venni egy Esemeny nevű Tevent típusú lokális változót a Menu függvényben.

 

function menu(hsz,ksz,vsz,bfx,bfy,sh,ss,as:byte):byte;

var i:integer;

    ch:char;

    Esemeny: TEvent;

begin

  szinez(vsz,ksz,bfx,bfy+as-1,sh);

  repeat

    GetMouseEvent(Esemeny);

    If Esemeny.What=evMouseDown then With MouseWhere do

    If (X>bfx-2) And (X<Bfx+sh-1) And

       (Y>Bfy-2) And (Y<Bfy+ss-1) then

    Begin

      szinez(hsz,ksz,bfx,bfy+as-1,sh); as:=Y-bfy+2;

      szinez(vsz,ksz,bfx,bfy+as-1,sh); Menu:=as;

      While MouseButtons=1 do;

      Exit;

    End;

    If Keypressed then ch:=readkey;

    if ch=#0 then

    begin

      ch:=readkey;

      if ch in [#71,#72,#79,#80] then

      szinez(hsz,ksz,bfx,bfy+as-1,sh);

      case ch of

            #71:as:=1;

            #72:if as>1 then dec(as) else as:=ss;

            #80:if as<ss then inc(as) else as:=1;

            #79:as:=ss;

      end;

      if ch in [#71,#72,#79,#80] then

      szinez(vsz,ksz,bfx,bfy+as-1,sh);

    end;

  until ch in [#13,#27,#75,#77];

  if ch in [#13,#75,#77] then menu:=as else menu:=0;

  vch:=ch;

end;

 

Lényegében csak az elején, a ch:= readkey karakterbeolvasás helyett kellett az egéresemény kezelésével kapcsolatos sorokat megírnunk. A függvény végtelen ciklusába bekerült az egéresemény-bekérő eljárás, valamint a programot megállító ch:= readkey helyett, az If Keypressed Then ch:= Readkey sor került, mely billentyűesemény hiányában szintén nem áll meg. Ez a megoldás biztosítja azt, hogy a függvény mindkét eseményt kezelni tudja. Egeret használó programokban megfigyelhetjük azt, hogy a parancs végrehajtása nem a kattintás pillanatában, hanem az egérgomb elengedésekor hajtódik végre. Ezt szolgálja az Exit sor előtti While MouseButtons=1 Do; üres ciklus. A Menu a visszaadott értékét az egér helykoordinátáiból állapítja meg.

 

Programokban gyakran találkozunk nyomógombbal, amelynek segítségével, egérrel is tudunk parancsot adni, funkciót aktivizálni. Készítsünk olyan általánosan használható nyomógombot, mely megjelenésében és működésében a legjobban hasonlít az IDE nyomógombjaihoz. Tegyük alkalmassá arra, hogy a nyomógomb funkcióját billentyűzetről és egérrel is aktivizálhassuk. A nyomógombot a CrtPlus-ban fogjuk deklarálni. Ehhez szükség van egy gombrekordra, amely a gomb típusát (arra gondolva, hogy nemcsak nyomógomb lehet), helyét, méretét és forró billentyű karakterét fogja tartalmazni.

 

Type GombRec= Record

                tip:byte;

                gx,gy,gsh:byte;

              End;

 

A képernyőre egy időben több nyomógomb, illetve olyan látvány is kikerülhet, amelynek ugyanilyen paraméterei lehetnek, illetve képesek az egérre és a billentyűzetre egyaránt reagálni. Ezek maximális száma legyen gtmax=64. A gombrekordokat egy tömbben fogjuk tárolni. Ezért a deklarációk a következők:

 

Const gtmax=64;

Var GombT:array[1..gtmax] of GombRec;

    GombIndex:byte;

 

A gombindex a képernyő felépülése közben inkrementálódik, azaz tartalmazza a képernyőn látható nyomógombok számát. Lesz egy gombkereső eljárásunk, amely maximálisan eddig az indexig fogja keresni azt a gombot (vagy egyéb egérkezelésre alkalmas látványt), amelyen a kattintás történt. A gomb paraméterei: háttérszín, karakterszín, választószín (a forró billentyű karakterszíne), kezdőhely x koordináta és y koordináta, a gomb hossza és a gomb felirata. A felirat tartalmazhat egy tilde jelet, mely nem kerül megjelenítésre, és a tilde jel utáni karakter lesz a forró billentyű jele. A nyomógomb kattintás hatására benyomódik, a fekete árnyéka eltűnik, a címke jobbra tolódik, elengedéskor az eredeti látvány áll vissza. A gomb eljárás a megjelenésért és a regisztrálásért felelős.

 

Procedure gomb(hsz,ksz,vsz,x,y,sh:byte;s:string);

Begin

  Kh:=Pos(chr(126),s);

  if Kh<>0 Then

  Begin

    Gotoxy(x+1,y);

    for i:=1 to length(s) do

    if s[i]<>chr(126) then Write(s[i]);

  End

  Else

  Writexy(x+1,y,s);Szinez(hsz,ksz,x,y,sh);

  If kh<>0 Then Szinez(hsz,vsz,x+kh,y,1);

  hsz:=bkep[y,x+sh,2] div 16;

  Szinek(hsz,0);Writexy(x+sh,y,chr(220));

  For I:=x+1 to x+sh do Writexy(i,y+1,chr(223));

  Inc(GombIndex);

  With GombT[GombIndex] do

  begin

    tip:=1;

    gx:=x;gy:=y;gsh:=sh;Key:=#0;

    if Kh<>0 then Key:=AltKod[UpCase(s[Pos(chr(126),s)+1])];

  End;

End;

 

A fenti listában található egy AltKod tömbre való hivatkozás. Ez a táblázat kapcsolja össze az egér kezelésére alkalmassá tett elem címkéjében megjelenő karaktert a billentyűzetről alt kód segítségével beírt karakterrel, mint paranccsal. Azaz, ettől kezdve teljesen mindegy, hogy a Case szerkezet számára a szelektor érték honnan származik, és így csak egy szakaszt kell a végrehajtó szakaszban egy parancshoz megírni. Íme a kérdéses tömb.

 

Const AltKod:Array[#42..'Z'] Of Char=

      (#42,#43,#0,#45,#46,#47,

       #129,#120,#121,#122,#123,#124,#125,#126,#127,#128,

       #0,#0,#0,#61,#0,#0,#0,

       #30,#48,#46,#32,#18,#33,#34,#35,#23,#36,#37,#38,#50,

       #49,#24,#25,#16,#19,#31,#20,#22,#47,#17,#45,#21,#44);

 

A gomb forró billentyűjének megkeresését a gombkereső végzi el. Szüksége van arra a helyre, amelyen az egérrel kattintottak. Visszaadott értéke a kulcs karakter. Végignézi a regisztrált gombokat, megnézi, hogy a kattintás melyiken történt, és visszaadja a Key mező tartalmát. A repeat until ciklus addig állítja meg a programot, ameddig lenyomva tartjuk az egér gombját. Az egyszerű nyomógomb típusa 1, tehát ha ennél nagyobb a típus-érték, akkor a függvényből kilépünk, ha viszont nyomógombon történt a kattintás, akkor a nyomógombnak be kell nyomódnia, ahogy azt fentebb már leírtuk. Ennek a látványnak a megírását tartalmazza a függvény további része.

 

Function GombKereso(x,y:byte):Char;

Var i,j,hsz:byte;

Begin

  GombKereso:=#0;

  For i:=1 to gtmax do with GombT[i] do

  if (gy=y) and (gx<=x) and (x<gx+gsh) then

  Begin

    GombKereso:=Key;

    if tip>1 then

    Begin

      Repeat Until MouseButtons<>1;

      exit;

    End;

    For J:=gx+1 to gx+gsh do bkep[gy+1,j,1]:=32;

    For j:=gx+gsh downto gx do

    Begin

      bkep[y,j,1]:=bkep[y,j-1,1];

      bkep[y,j,2]:=bkep[y,j-1,2];

    End;

    bkep[y,gx,1]:=32;

    Repeat Until MouseButtons<>1;

    hsz:=bkep[y,gx,2] div 16;

    For j:=gx to gx+gsh do

    Begin

      bkep[y,j,1]:=bkep[y,j+1,1];

      bkep[y,j,2]:=bkep[y,j+1,2];

    End;

    Szinek(hsz,0);Writexy(gx+gsh,y,chr(220));

    For J:=gx+1 to gx+gsh do Writexy(J,gy+1,chr(223));

    tunj;

    Exit;

  End;

End;

 

48. Írjunk programot, amely a fentebb megírt nyomógombot teszteli. A fehér képernyőn jelenjen meg két nyomógomb. Az egyik felirata legyen Irjál, a másiké Vége. Ha az Irjál feliratú gombot megnyomjuk, akkor a program a képernyő véletlen helyére véletlen színnel, két véletlen karaktert jelenít meg, egy nagybetűt és egy számjegyet. A másik gomb megnyomására fejeződjön be a program. A két forró billentyű az I és a V.

 

A program a véletlen karaktermegjelenítést az Irogat eljárás végzi. A főprogram először a látvány létrehozását végzi el. Kialakítja a hátteret, kirakja a két nyomógombot, eltünteti a kurzort, inicializálja az eseménykezelőt és a véletlen-szám generátort, majd megjeleníti az egérkurzort. Majd a program egy végtelen repeat ciklusba kezd. Ha nincs sem billentyű- sem egéresemény, akkor megáll. Ha megnyomtuk a billentyűzetet, akkor beolvassa a ch változóba a karaktert. A program végrehajtó része a ch által vezérelt többszörös elágazás. A ch a billentyüzet Alt-kódját várja, azaz az írást Alt+I-vel, a végét Alt+V-vel lehet aktiválni. Gyakran a programból való kilépésre, úgy mint az IDE esetén, Alt+X-et használják. Programjainkban mi is így fogunk eljárni, ezért a kilépés Alt+X-szel is elérhető.

 

Program GombPro;

Uses  NewDelay, Crt, CrtPlus, Drivers;

Var Ch: char;

Procedure Irogato;

Begin

  Szinek(7,Random(16));Writexy(random(79)+1,Random(25)+1,

  chr(Random(26)+65)+chr(Random(10)+48));tunj;

Begin

  TextMode(CO80);

  Szinek(7,0); ClrScr;

  Gomb(2,0,14,10,5,7,'~Irj l'); Gomb(2,0,14,20,10,6,'~Vége');

  Tunj; InitEvents; Randomize; ShowMouse;

  Repeat

    while (not keypressed) and (MouseButtons<>1) do;

    If Keypressed Then Ch:=Readkey;

    If MouseButtons=1 then

    Ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);

    Case Ch Of

          #23: Irogato;

      #45,#47: Halt;

    End;

  Until False;

End.

 

 

Mivel a továbbiakban hasonló felépítésű programokat fogunk írni, készítsünk el egy olyan alap-képernyőt, amely az üres IDE-hez nagyon hasonlít, lehessen a programból kilépni, azaz legyen a nyomógombhoz hasonló felülete és forró billentyűje. Az üres IDE-t DeskTop-nak nevezi a Pascal rendszer, nevezzük mi is így. A látványt a CrtPlus-ban kódoljuk le.

 

De mielőtt ebbe belekezdenénk, néhány egyszerű, a képernyőn való műveletekkel kapcsolatos eljárást és függvényt kell megírnunk, természetesen szintén a CrtPlus-ban, ezek a Töröl, a Tölt az Olvas és az ÍrXY modulok. A töröl egy egysoros téglalapot töröl a képernyőn. A tölt egy egysoros téglalapot tölt fel megadható karakterrel. Az olvas a képernyő egy egysoros téglalapján lévő karakterekből egy stringet készít, és ezt adja vissza. Az ÍrXY a képernyő egy adott helyére megadható szöveget kiír úgy, hogy közben az ottani színek nem változnak meg, azaz nem használja a Write aktuális színeit.

 

Procedure torol(x,y,sh:byte);

Var i:byte;

Begin

  For i:=x to x+sh-1 do bkep[y,i,1]:=32;

End;

 

Procedure tolt(x,y,sh:byte;c:char);

var i:byte;

begin

  for i:=x to x+sh-1 do bkep[y,i,1]:=ord(c);

end;

 

Function olvas(x,y,sh:byte):string;

Var i:byte;

    ws:string;

Begin

  ws:='';for i:=x to x+sh-1 do

  ws:=ws+chr(bkep[y,i,1]);olvas:=ws;

End;

 

Procedure irxy(x,y:byte;sz:string);

Var i:byte;

Begin

  For I:=1 to length(sz) do bkep[y,x+i-1,1]:=ord(sz[i]);

End;

 

Íme a DeskTop modul:

 

Procedure DeskTop;

Var i:integer;

Begin

  Szinek(7,1);ClrScr;

  For i:=2 to 24 do tolt(1,i,80,chr(176));

  Szinek(7,0); WriteXY(1,25,'Alt-X Exit'); Tunj;

  Szinez(7,4,2,25,5); Inc(GombIndex);

  With GombT[GombIndex] do

  Begin

    tip:=6;gx:=2;gy:=25;gsh:=5;Key:=AltKod['X'];

  End;

  InitEvents; ShowMouse;

End;

 

Ezek után az Alap program listája a következő:

 

Program Alap;

Uses NewDelay, Crt, CrtPlus, Drivers;

Var Ch: Char;

Begin

  TextMode(CO80);

  DeskTop;

  Repeat

    While (Not Keypressed) And (MouseButtons<> 1) Do;

    If KeyPressed Then Ch := ReadKey;

    If MouseButtons= 1 Then

    Ch:= GombKereso(MouseWhere.X+1, MouseWhere.Y+1);

    Case Ch Of

      #45: Halt;

    End;

  Until False;

End.

 

 

Minden új programot úgy kezdhetünk írni, hogy ezt betöltjük, az új program nevével kimentjük lemezre és már javíthatjuk, bővíthetjük új programunkat. Ehhez legtöbb esetben a Case szakaszt kell bővíteni, illetve a DeskTop után a látványokat a képernyőre kell helyezni.

 

49. Írjunk programot, amely a képernyőn megjeleníti a DeskTop-ot egy elég nagy címkés ablakkal, rajta két beviteli mezőt, egyikben egy számértéket, a másikban egy növekmény lehessen beírni. Legyen a képernyőn továbbá négy nyomógomb a következő funkciókkal. Az első növeli az értéket a léptékkel, a második csökkenti, a harmadik törli mindkét beviteli mezőt, a negyedikkel kiléphetünk a programból.

 

            Mielőtt e programot megírnánk, meg kell írni még két dolgot. Az egyik a CrtPlus Bevitel függvényének az egérkezelését, valamint egy InputLine látványt. Kezdjük az elsővel.

 

function bevitel(hsz,ksz,x,y,sh:byte):string;

var ch:char; i,ax:byte; ovw:boolean; bszov:string;

begin

  szinez(hsz,ksz,x,y,sh); ax:=x; gotoxy(ax,y); ovw:=false;

  repeat

    while (not keypressed) and (MouseButtons<>1) do;

    If MouseButtons<>1 Then ch:=readkey;

    case ch of

      #0:begin

           ch:=readkey;

           case ch of

             #71:ax:=x;

             #75:if ax>x then dec(ax);

             #77:if ax<x+sh then inc(ax);

             #79:begin

                   i:=x+sh;

                   repeat dec(i) until bkep[y,i,1]<>32;

                   ax:=i+1;

                 end;

             #82:ovw:=ovw=false;

             #83:if ax<x+sh then

                 begin

                   for i:=ax to x+sh-1 do

                   bkep[y,i,1]:=bkep[y,i+1,1];

                   bkep[y,x+sh-1,1]:=32;

                 end;

           end;

         end;

      #8:if ax<>x then

         begin

           for i:=ax-1 to x+sh-1 do

           bkep[y,i,1]:=bkep[y,i+1,1];

           bkep[y,x+sh-1,1]:=32; dec(ax);

         end;

      #9:;    #13:;     #27:;

      else if MouseButtons<>1 then if ax<x+sh then

      begin

        if not ovw then for i:=x+sh-1 downto ax+1 do

        bkep[y,i,1]:=bkep[y,i-1,1]; bkep[y,ax,1]:=ord(ch);

        inc(ax);

      end;

    end;

    gotoxy(ax,y);

  until (ch in [#13,#27,#9]) or (MouseButtons=1);

  vch:=ch;

  if ch=#27 then bevitel:='' else

  begin

    bszov:=''; i:=x+sh;

    repeat dec(i); until (bkep[y,i,1]<>32) or (i=x); ax:=i;

    for i:=x to ax do bszov:=bszov+chr(bkep[y,i,1]);

    bevitel:=bszov;

  end; tunj;

end;

 

A függvényben az aláhúzott részek oldják meg azt, hogy kattintásra a Bevitel függvény elhagyható. A második egy InpuLine megírása. Az InputLine egy beviteli mezőből és egy címkéből áll. A címke a beviteli sor felett van, a befogadó dobozban érvényes színeket nem feszi figyelembe. Ezeket a színeket tehát körültekintően adjuk meg. A címke a doboz területén van, és rendelkezik forró billentyűvel. Az InputLine 2-es típusú egeres látvány.

 

Function InputLine(dhsz,dksz,dvsz,hsz,ksz,x,y,sh:byte;

                   s:string):String;

Var i,kh:byte;

Begin

  Szinek(dhsz,dksz); Kh:=Pos(chr(126),s);

  if Kh<>0 Then

  Begin

    Gotoxy(x,y-1);

    for i:=1 to length(s) do if s[i]<>chr(126) then

    Write(s[i]);

  End Else Writexy(x,y-1,s);

  If kh<>0 Then Szinez(dhsz,dvsz,x+kh-1,y-1,1);

  Szinez(hsz,ksz,x,y,sh); Inc(GombIndex);

  With GombT[GombIndex] do

  begin

    tip:=2;gx:=x;gy:=y;gsh:=sh;Key:=#0;

    if Kh<>0 then Key:=AltKod[UpCase(s[Pos(chr(126),s)+1])];

  End;

End;

 

Az InputLine paraméterei: a befogadó doboz háttérszíne, a befogadó doboz karakterszíne, a címke választószíne, a beviteli sor háttérszíne, a beviteli sor karakterszíne, a beviteli sor kezdőhelye (x,y) és hossza, a címke szövege, visszaadott érték String, amelyet most még nem használunk ki.

 

         Ezek után a léptető program kódja:

 

Program Lepteto;

Uses NewDelay, Crt, CrtPlus, Drivers;

Var Ch: Char;

    ErtekSt, LeptekSt: String;

    Ertek, Leptek: Longint;

    Kod: Integer;

Begin

  TextMode(CO80);

  DeskTop;

  Ablak(7,15,15,5,65,20,True,'Léptető');

  InputLine(7,0,14,1,15,25,7,8,'Érté~k:');

  InputLine(7,0,14,1,15,50,7,8,'~Lépték:');

  Gomb(2,0,14,36,7,10,'~Növel');

  Gomb(2,0,14,36,9,10,'~Csökkent');

  Gomb(2,0,14,36,11,10,'~Töröl');

  Gomb(2,0,14,36,15,10,'~Vége');

  Ertek:= 0; Leptek:= 0; Tunj;

  Repeat

    While (Not Keypressed) And (MouseButtons<> 1) Do;

    If KeyPressed Then Ch := ReadKey;

    If MouseButtons= 1 Then

    Ch:= GombKereso(MouseWhere.X+1, MouseWhere.Y+1);

    Case Ch Of

      #37: Val(Bevitel(1,15,25,7,8), Ertek, Kod);

      #38: Val(Bevitel(1,15,50,7,8), Leptek, Kod);

      #49: If Leptek<>0 Then

           Begin

             Inc(Ertek, Leptek); Str(Ertek, ErtekSt);

             Torol(25,7,8); IrXY(25,7,ErtekSt);

           End;

      #46: If Leptek<>0 Then

           Begin

             Dec(Ertek, Leptek); Str(Ertek, ErtekSt);

             Torol(25,7,8); IrXY(25,7,ErtekSt);

           End;

      #20: Begin

             Ertek:= 0; Leptek:=0;

             Torol(25,7,8); Torol(50,7,8);

           End;

      #45,

      #47: Halt;

    End;

  Until False;

End.

 

 

50. Írjunk programot, amely két beviteli és egy kimeneti InpuLine-al rendelkezik. Az két beviteli mezőbe beírhatunk két számot. A kimeneti mező értékét a következő funkciójú gombok állíthatják: a két szám összege, a két szám különbsége, a két szám szorzata, a két szám hányados, a két szám számtani közepe és a két szám mértani közepe. Legyen nyomógomb a program elhagyására is.

 

         Új dolgokra már nincs szükség a CrtPlus-ban. A program listája a következő:

 

Program Muvelet;

Uses NewDelay, Crt, CrtPlus, Drivers;

Var Ch: Char;

    a,b,c:real;

    kod:integer;

    ws:string;

Begin

  TextMode(CO80);

  DeskTop;

  Ablak(7,15,4,3,76,22,true,'Műveletek:');

  InputLine(7,15,14,1,15,18,6,10,'''~A'' szám:');

  InputLine(7,15,14,1,15,18,9,10,'''~B'' szám:');

  InputLine(7,15,14,1,15,18,15,10,' ~Eredmény:');

  Gomb(2,0,14,40,5,23,'A két szám öss~zege');

  Gomb(2,0,14,40,8,23,'A két szám ~különbsége');

  Gomb(2,0,14,40,11,23,'A két szám szorza~ta');

  Gomb(2,0,14,40,14,23,'A két szám ~hányadosa');

  Gomb(2,0,14,40,17,23,'~Számtani közepük');

  Gomb(2,0,14,40,20,23,'~Mértani közepük');

  Gomb(2,0,14,18,20,6,'~Vége');

  tunj;

  Repeat

    while (not keypressed) and (MouseButtons<>1) do;

    If Keypressed Then Ch:=Readkey;If MouseButtons=1 Then

    ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);

    val(validst(olvas(18,6,10)),a,kod);

    val(validst(olvas(18,9,10)),b,kod);

    Case Ch Of

      #30: Bevitel(1,15,18,6,10);

      #48: Bevitel(1,15,18,9,10);

      #44: c:=a+b;

      #37: c:=a-b;

      #20: c:=a*b;

      #35: if b<>0 then c:=a/b else ws:='     Error';

      #31: c:=(a+b)/2;

      #50: if a*b>=0 then c:=sqrt(a*b) else ws:='     Error';

      #47,

      #45: halt;

    End;

    if ws<>'     Error'then str(c:10:4,ws);

    While ws[length(ws)]='0' do ws:=copy(ws,1,length(ws)-1);

    If ws[length(ws)]='.' then ws:=copy(ws,1,length(ws)-1);

    torol(18,15,10);irxy(28-length(ws),15,ws);

    Ws:='';

  Until False;

  Tunj;

  Varj;

End.

 

 

51. Írjunk programot, amely zsebszámológépet jelenít meg. Legyen nyomógomb a kikapcsolásra, minden adat törlésére, a kijelző törlésére, tudja a négy alapműveletet és előjelváltást.

 

A gombok elhelyezését és címkézését, ahol lehetett for ciklussal oldottuk meg. Az eddigieknél egy kicsit összetettebb listát kaptunk, de a feladat sem egyszerű.

 

Program ZsebSzam;

Uses NewDelay, Crt, CrtPlus, Drivers;

Var I     : Byte;                      Ch, MCh : Char;

    os,as : Real;                           ws : String;

    Kod   : Integer;    Volt, Elso, Vege, Hiba : Boolean;

Begin

  TextMode(CO80);

  Szinek(3,0);ClrScr;

  Ablak(7,15,25,4,53,18,True,'Zsebszámológép');

  InputLine(7,0,14,1,15,27,6,24,'E~redmény:');

  Gomb(2,0,14,27,8,5,'~OFF');Gomb(2,0,14,34,8,5,'C~LR');

  Gomb(2,0,14,41,8,5,'C~E'); Gomb(2,0,14,48,8,3,'~+');

  For I:=1 To 9 Do

  Gomb(2,0,14,((I-1) Mod 3)*7+27,

              ((I-1) Div 3)*2+10,3,'~'+chr(48+I));

  Gomb(2,0,14,48,10,3,'~-');Gomb(2,0,14,48,12,3,'~*');

  Gomb(2,0,14,48,14,3,'~/');Gomb(2,0,14,27,16,3,'~0');

  Gomb(2,0,14,34,16,3,'~.');Gomb(2,0,14,41,16,3,'~S');

  Gomb(2,0,14,48,16,3,'~=');

  InitEvents;ShowMouse;Tunj;

  Elso:=True;Vege:=False;Hiba:=false;

 

  Repeat

    while (not keypressed) and (MouseButtons<>1) do;

    If Keypressed Then Ch:=Readkey; If MouseButtons=1 then

    Ch:=GombKereso(MouseWhere.x+1,MouseWhere.y+1);

    Case Ch Of

             #18: Torol(27,6,24);

             #19: Bevitel(1,15,27,6,24);

      #120..#129: Begin

                    If Vege Then

                    Begin Vege:=False; Torol(27,6,24) End;

                    I:=27;

                    While (BKep[6,I,1]<>32)and(I<50)do Inc(I);

                    If ch=#129 Then BKep[6,I,1]:=Ord(Ch)-81

                    Else BKep[6,I,1]:=Ord(Ch)-71;

                  End;

    #46,#48..#57: Begin

                    If Vege Then

                    Begin Vege:=False; Torol(27,6,24) End;

                    I:=27;Volt:=false;

                    While (BKep[6,I,1]<>32) and (I<50) do

                    Begin

                      If BKep[6,I,1]=46 then volt:=true;Inc(I)

                    End;

                    If (Ch<>#46) or (Not Volt) Then

                    BKep[6,I,1]:=Ord(Ch);

                  End;

             #38: Begin Torol(27,6,24);os:=0 End;

             #31: Begin

                    If Bkep[6,27,1] in [48..57,46] Then

                    Begin

                      For I:=50 downto 28 do

                      Bkep[6,i,1]:=Bkep[6,i-1,1];

                      Bkep[6,27,1]:=32;

                    end;

                    If Bkep[6,27,1]=32 then Bkep[6,27,1]:=45

                    else

                    If Bkep[6,27,1]=45 Then Bkep[6,27,1]:=43

                    else

                    If Bkep[6,27,1]=43 Then Bkep[6,27,1]:=45;

                  End;

         #13,#61,

         #42,#43,

         #45,#47: Begin

                    ws:=ValidSt(Olvas(27,6,24));

                    Val(Ws,As,Kod); Torol(27,6,24);                   

                    If Elso Then

                    Begin os:=as;elso:=false;MCh:=ch End Else

                    Begin

                      Case Mch of

                        #42:os:=os*as;

                        #43:os:=os+as;

                        #45:os:=os-as;

                        #47:If as=0 then

                            Begin

                              IrXY(46,6,'Error'); Hiba:=true;

                            End else os:=os/as;

                      End;

                      MCh:=ch;

                    End;

                    If MCh in [#13,#61] Then

                    Begin

                      If not hiba then

                      Begin

                        Str(Os:24:6,ws);

                        While ws[length(ws)]='0' do

                        ws:=copy(ws,1,length(ws)-1);

                        If ws[length(ws)]='.' then

                        ws:=copy(ws,1,length(ws)-1);

                        IrXY(50-Length(ws),6,ws);

                      End;

                      Os:=0;Vege:=true;

                      Elso:=True;Hiba:=false;MCh:=#0;

                    End;

                  End;

         #27,#24: Halt;

    End;

    Ch:=#0;

  Until False;

End.

 

 

52. Írjunk egy kis egyszerű játékprogramot. A játék lényege: a gép véletlen számértékeket mutat 1-től 6-ig (kockadobás). A játékos minden dobás után tippelhet, vajon a következő véletlen szám a mutatotthoz képest milyen lesz: kisebb, nagyobb vagy egyenlő. Ha eltalálta, akkor pontjai eggyel nőnek, ha nem, akkor a gép pontjai nőnek eggyel. Ha sikerül a játékosnak előbb elérni a 10-et akkor nyer, ha a gépnek akkor veszít. Az állást folyamatjelző jelezze a képernyőn.

 

         A program kódja semmi újat nem tartalmaz.

 

Program Talalo;

Uses NewDelay, Crt, CrtPlus, Drivers;

Var Ch: Char;

    a, b, t, n: byte;

    Ws: String;

    St, Vege: Boolean;

Procedure Start;

Begin

  t:= 0; n:= 0; St:= True; Vege:= False; Szinek(7,15);

  WriteXY(37,13,'Talált:'); Szinez(7,1,37,14,10);

  Tolt(37,14,10,chr(176)); WriteXY(37,16,'Nem talált:');

  Szinez(7,1,37,17,10); Tolt(37,17,10,chr(176));

  Torol(55,15,13); Torol(10,8,12);Torol(55,8,12);

  Tunj;

End;

Begin

  TextMode(CO80);DeskTop; Ablak(7,15,4,3,75,22,True,'Találó');

  InputLine(7,15,13,1,15,10,8,12,'Az ''A'' szám:');

  InputLine(7,15,13,1,15,55,8,12,'A  ''B'' szám:');

  Gomb(2,0,14,34,6,14,'~Kisebb mint');

  Gomb(2,0,14,34,8,14,'~Egyenlő');

  Gomb(2,0,14,34,10,14,'~Nagyobb mint');

  Gomb(2,0,14,22,20,7,'~Start');

  Gomb(2,0,14,55,20,7,'~Vége'); Start; St:= False; Randomize;

  Repeat

    while (not keypressed) and (MouseButtons<>1) do;

    If Keypressed Then Ch:= Readkey; If MouseButtons=1 Then

    ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);

    Case Ch Of

      #31: Begin

             Start; A:=Random(6)+1; Str(A,Ws); IrXY(11, 8, Ws)

           End;

      #37: If Not Vege Then

           Begin

             St:=False;B:=Random(6)+1;Str(B,Ws);IrXY(56,8,Ws);

             If A<B Then

             Begin inc(t);IrXY(36+t,14,Chr(219))End Else

             Begin inc(n); IrXY(36+n,17,Chr(219)) End;

           End;

      #18: If Not Vege Then

           Begin

             St:=False;B:=Random(6)+1;Str(B,Ws);IrXY(56,8,Ws);

             If A = B Then

             Begin inc(t); IrXY(36+t,14,Chr(219)) End Else

             Begin inc(n); IrXY(36+n,17,Chr(219)) End;

           End;

      #49: If Not Vege Then

           Begin

             St:=False;B:=Random(6)+1;Str(B,Ws);IrXY(56,8,Ws);

             If A > B Then

             Begin inc(t); IrXY(36+t,14,Chr(219)) End Else

             Begin inc(n); IrXY(36+n,17,Chr(219)) End;

           End;

      #45,

      #47: halt;

    End;

    If Ch<>#0 Then

    Begin

      If (T=10) Or (N=10) Then Vege:=True;

      If (Not St) And (Not Vege) Then

      Begin

        Delay(1000);A:=Random(6)+1; Str(A,Ws);IrXY(11, 8, Ws);

        Torol(55,8,10); Duda;

      End;

      If Vege Then

      Begin

        Szinek(7,Blink);

        If T=10 Then WriteXY(55,15,'Nyertél!!!')

        Else WriteXY(55,15,'Vesztettél!!!'); Tunj;

      End;

    End;

  Until False;

End.

 

 

53. Írjunk labdatartást folyamatosan számoló és kijelző programot.

 

         Ebben a kódlistában egyetlen új dolog található. Mégpedig az, hogy ha nincs sem egér, sem billentyűzet esemény, akkor is számolnia kell az eltelt időt, ezért az eddigi while (not keypressed) and (MouseButtons<>1) do szakasz most nem lesz üres. Itt történik a számolás és a kijelzés.

 

Program Labda;

Uses NewDelay, Crt, CrtPlus, Drivers;

Var Ch: Char;

    Anal: Boolean;

    a, as, b, bs, n: Longint;

    wsa, wsb: String;

Begin

  TextMode(CO80); DeskTop;

  Ablak(7,0,15,4,65,21,True,'Labdatartást figyelő program');

  InputLine(7,0,14,1,15,26,7,8,'A Csapat');

  InputLine(7,0,14,1,15,46,7,8,'B Csapat');

  Gomb(2,0,14,25,12,10,'~A Csapat');

  Gomb(2,0,14,45,12,10,'~B Csapat');

  Gomb(2,0,14,38,18,6,'~Vége');

  Tunj;

  Anal:= True;

  Repeat

    while (not keypressed) and (MouseButtons<>1) do

    Begin

      Inc(n);

      If Anal Then

      Begin IrXY(32,10,'A-nál van a labda'); Inc(a) End

      Else Begin IrXY(32,10,'B-nél van a labda'); Inc(b) End;

      Str(Round(100*a/n):4,Wsa); IrXY(26,7,Wsa+'%');

      Str(Round(100*b/n):4,Wsb); IrXY(46,7,Wsb+'%');

    End;

    If Keypressed Then Ch:= Readkey;

    If MouseButtons=1 Then

    ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);

    Case Ch Of

      #30: Anal:= True;

      #48: Anal:= False;

      #45,

      #47: halt;

    End;

  Until False;

End.

 

 

54. Írjunk egy tipizált lemezes állományt kezelő programot, például a Pascal nyelv nyelvi elemeinek tárolására. Tároljunk kulcsszavakat, típusukkal együtt, jelezzük milyen egységben találhatók, írjunk rá mintapéldát és magyarázatot. Az állományon lehessen mozogni, lehessen beszúrni, törölni és javítani. Az aktuális rekord mindig jelenjen meg a képernyőn.

 

Program Help;

Uses NewDelay, Crt, CrtPlus, Drivers;

Type HelpRec= Record

                Kulcsszo: String[20];

                Tipus:    String[10];

                Egyseg:   String[10];

                Minta:    String[64];

                Megjegy:  String[64];

              End;

Var Ch         : Char;

    ARec, PRec : HelpRec;

    FNev       : File Of HelpRec;

    DNev       : String;

    I, RS, AS  : Integer;

    Ws,WW      : String;

Procedure KezdoKep;

Begin

  Ablak(7,15,4,3,74,22,True,

        'Turbo Pascal Help-file kezelő program');

  InputLine(7,15,14,1,15,7,6,20,'~A keresett kulcsszó:');

  InputLine(7,15,14,1,15,7,9,10,'~Típusa:');

  InputLine(7,15,14,1,15,7,12,10,'~Unit:');

  InputLine(7,15,14,1,15,7,15,64,'~Példa:');

  InputLine(7,15,14,1,15,7,18,64,'~Megjegyzés:');

  InputLine(7,15,14,1,15,61,6,10,'Index:');

  Gomb(2,0,14,7,20,11,'~Következő');

  Gomb(2,0,14,21,20,7,'~Előző');

  Gomb(2,0,14,31,20,8,'~Beszúr');

  Gomb(2,0,14,42,20,7,'~Javít');

  Gomb(2,0,14,52,20,7,'Tö~röl');

  Gomb(2,0,14,64,20,6,'~Vége');

End;

Procedure AdatTorles;

Begin

  Torol(7,6,20);Torol(7,9,10);Torol(7,12,10);

  Torol(7,15,64);Torol(7,18,64);

End;

Procedure AdatKepre;

Begin

  AdatTorles;

  With ARec Do

  Begin

    IrXY(7,6,Kulcsszo);IrXY(7,9,Tipus);IrXY(7,12,Egyseg);

    IrXY(7,15,Minta);IrXY(7,18,Megjegy);

  End;

End;

Procedure AdatKeprol;

Begin

  With ARec Do

  Begin

    Kulcsszo := ValidSt(Olvas(7,6,20));

    Tipus := ValidSt(Olvas(7,9,10));

    Egyseg   := ValidSt(Olvas(7,12,10));

    Minta := ValidSt(Olvas(7,15,64));

    Megjegy  := ValidSt(Olvas(7,18,64));

  End;

End;

Procedure Lemezrol;

Begin

  DNev:='Turbo.shl';Assign(FNev,DNev);{$I-}Reset(FNev);{$I+}

  If IOResult<>0 Then RewRite(Fnev);RS:=FileSize(FNev);

  AS:=0; If RS>0 Then Begin Seek(FNev,AS);Read(Fnev,ARec) End;

End;

Begin

  TextMode(CO80);DeskTop; KezdoKep; Lemezrol; AdatKepre; Tunj;

  Repeat

    Str(RS,WS);Str(AS,WW);

    IrXY(61,6,Copy(WW+'/'+WS+'         ',1,10));

    while (not keypressed) and (MouseButtons<>1) do;

    If Keypressed Then

    Begin Ch:=Readkey;If ch=#0 Then Ch:=ReadKey End;

    If MouseButtons=1 Then

    ch:= GombKereso(MouseWhere.x+1,MouseWhere.y+1);

    With ARec Do

    Case Ch Of

      #30:Kulcsszo:= Bevitel(1,15,7,6,20);   {Kulcsszó}

      #20:Tipus   := Bevitel(1,15,7,9,10);   {Típus}

      #22:Egyseg  := Bevitel(1,15,7,12,10);  {Unit}

      #25:Minta   := Bevitel(1,15,7,15,64);  {Példa}

      #50:Megjegy := Bevitel(1,15,7,18,64);  {Megjegyzés}

      #73,

      #37:If AS<RS-1 Then                    {Következő}

          Begin

            Inc(AS);Seek(FNev,AS);Read(Fnev,ARec);AdatKepre

          End

          Else Begin AdatTorles;If AS<RS Then Inc(AS) End;

      #81,

      #18:If AS>0 Then                       {Előző}

          Begin

            Dec(AS);Seek(FNev,AS);Read(Fnev,ARec);Adatkepre

          End;

      #13,

      #48:If ValidSt(Olvas(7,6,20))<>'' Then {Beszúr}

          Begin

            AdatKeprol;

            If (RS=0) Or (AS=RS) Then Write(FNev,ARec)

            Else

            If AS=RS-1 Then

            Begin

              Read(FNev,PRec);Write(FNev,PRec);Seek(FNev,AS);

              Write(FNev,ARec);Inc(RS);

            End

            Else

            If AS<RS-1 Then

            Begin

              For I:=RS DownTo AS+1 Do

              Begin

                Seek(FNev,I-1);

                Read(FNev,PRec);

                Write(FNev,PRec)

              End;

              Seek(FNev,AS);Write(FNev,ARec);Seek(FNev,AS);

            End;

            Inc(RS);

          End;

      #36:If ValidSt(Olvas(7,6,20))<>'' Then {Javˇt}

          Begin

            AdatKeprol;Seek(FNev,AS);Write(Fnev,ARec)

          End;

 

      #19:If Kerdezo(5,15,' Valóban törölni

                            akarja az aktuális rekordot? ')

          Then If RS>0 Then                  {Töröl}

          Begin

            If RS=1 Then ReWrite(FNev)

            Else

            If AS=RS Then Inc(RS)

            Else

            If AS=RS-1 Then Truncate(FNev)

            Else

            If AS<RS-1 Then

            Begin

              For I:=AS+1 To RS-1 Do

              Begin

                Seek(FNev,I);Read(FNev,PRec);

                Seek(FNev,I-1);Write(FNev,PRec);

              End;

              Seek(FNev,RS-1);Truncate(FNev);

              If AS=RS then Dec(AS);

              Seek(FNev,AS);Read(FNev,ARec);

              AdatKepre;Seek(FNev,AS);

            End;

            Dec(RS);If RS=0 Then AdatTorles;

          End;

      #47,

      #45: Begin Close(FNev);Szinek(0,7);ClrScr;halt End;

    End;

    Tunj;

  Until False;

End.

 

 

55. Készítsünk Turbo Vision segítségével szótár programot.

 

Program Szotar5;

Uses App, Drivers, Objects, Menus, Views, Dialogs;

 

Const cmSzotarDialogus= 100;

      cmSzoItemFocused= 101;

      cmASzoBeiro     = 102;

      cmMSzoBeiro     = 103;

 

      SzoVolt:Boolean= False;

Type SzoDataRec= Record

                   ASzo:       String[60];

                   MSzo:       String[60];

                   Szavak:     PSortedCollection;

                   SzoFocused: Integer;

                 End;

 

Const cSzoDataRec: SzoDataRec= (ASzo:        '';

                                Mszo:        '';

                                Szavak:     Nil;

                                SzoFocused:  0);

 

Type PSzoCollection= ^TSzoCollection;

     TSzoCollection= Object(TSortedCollection)

                       Function KeyOf(Item:Pointer):Pointer;Virtual;

                       Function Compare(Key1,Key2:Pointer):Integer;Virtual;

                     End;

 

     PSzotarListBox= ^TSzotarListBox;

     TSzotarListBox= Object(TListBox)

                       Function GetText(Item:Integer;MaxLen:Integer):String;Virtual;

                       Procedure FocusItem(Item:Integer);Virtual;

                     End;

 

     PASzoInputLine= ^TASzoInputLine;

     TASzoInputLine= Object(TInputLine)

                       Constructor Init(Var Bounds:TRect;AMaxLen:Integer);

                       Procedure HandleEvent(Var Event:TEvent);Virtual;

                     End;

 

     PMSzoInputLine= ^TMSzoInputLine;

     TMSzoInputLine= Object(TInputLine)

                       Constructor Init(Var Bounds:TRect;AMaxLen:Integer);

                       Procedure HandleEvent(Var Event:TEvent);Virtual;

                     End;

 

     PSzotar= ^TSzotar;

     TSzotar= Object(TObject)

                FSzo: SzoDataRec;

                Constructor Init(ISzo:SzoDataRec);

                Constructor Load(Var S:TStream);

                Procedure   Store(Var S:TStream);

              End;

 

     TTVApp= Object(TApplication)

               SzotarDialogData:SzoDataRec;

               Constructor Init;

               Procedure HandleEvent(Var Event:TEvent);Virtual;

               Procedure InitMenuBar;Virtual;

               Destructor Done;Virtual;

             End;

 

Const RSzo:           TStreamRec= (

      ObjType:        150;

      VMTLink:        Ofs(TypeOf(TSzotar)^);

      Load:           @TSzotar.Load;

      Store:          @TSzotar.Store);

 

      RSzoCollection: TStreamRec= (

      ObjType:        154;

      VMTLink:        Ofs(TypeOf(TSzoCollection)^);

      Load:           @TSzoCollection.Load;

      Store:          @TSzoCollection.Store);

 

Var Szotar:       PSzoCollection;

    SzotarStream: TBufStream;

 

Function TSzoCollection.KeyOf(Item:Pointer):Pointer;

Var S: String;

Begin

  S:= PSzotar(Item)^.FSzo.ASzo;

  KeyOf:=@S;

End;

Function TSzoCollection.Compare(Key1,Key2:Pointer):Integer;

Begin

  If PString(Key1)^= PString(Key2)^ Then Compare:=  0 Else

  If PString(Key1)^< PString(Key2)^ Then Compare:= -1 Else

                                         Compare:=  1;

End;

 

Function TSzotarListBox.GetText(Item:Integer;MaxLen:Integer):String;

Begin

  GetText:=PSzotar(List^.AT(Item))^.Fszo.ASzo;

End;

Procedure TSzotarListBox.FocusItem(Item:Integer);

Var S: String;

Begin

  Inherited FocusItem(Item);

  If Szotar^.Count<>0 Then

  Begin

    S:= PSzotar(List^.AT(Item))^.FSzo.ASzo;

    Message(Owner,evBroadcast,cmSzoItemFocused+cmASzoBeiro,@S);

    S:= PSzotar(List^.AT(Item))^.FSzo.MSzo;

    Message(Owner,evBroadcast,cmSzoItemFocused+cmMSzoBeiro,@S);

  End;

End;

 

Constructor TASzoInputLine.Init(Var Bounds:TRect;AMaxLen:Integer);

Begin

  Inherited Init(Bounds,AMaxLen);

  EventMask:=EventMask Or evBroadcast;

End;

Procedure TASzoInputLine.HandleEvent(Var Event:TEvent);

Begin

  Inherited HandleEvent(Event);

  If (Event.What=evBroadcast) And

     (Event.Command=cmSzoItemFocused+cmASzoBeiro) And

     (State And sfSelected=0) Then

  Begin

    Data^:=PString(Event.InfoPtr)^;

    DrawView;

  End;

End;

 

Constructor TMSzoInputLine.Init(Var Bounds:TRect;AMaxLen:Integer);

Begin

  Inherited Init(Bounds,AMaxLen);

  EventMask:=EventMask Or evBroadcast;

End;

Procedure TMSzoInputLine.HandleEvent(Var Event:TEvent);

Begin

  Inherited HandleEvent(Event);

  If (Event.What=evBroadcast) And

     (Event.Command=cmSzoItemFocused+cmMSzoBeiro) And

     (State And sfSelected=0) Then

  Begin

    Data^:=PString(Event.InfoPtr)^;

    DrawView;

  End;

End;

 

Constructor TSzotar.Init(ISzo:SzoDataRec);

Begin

  Inherited Init;

  FSzo:= ISzo;

End;

Constructor TSzotar.Load(Var S:TStream);

Begin

  S.Read(FSzo,SizeOf(FSzo));

End;

Procedure TSzotar.Store(Var S:TStream);

Begin

  S.Write(FSzo,SizeOf(FSzo));

End;

 

Constructor TTVApp.Init;

Begin

  Inherited Init;

  RegisterApp;

  RegisterDialogs;

  RegisterMenus;

  RegisterObjects;

  RegisterViews;

  RegisterType(RSzo);

  RegisterType(RSzoCollection);

 

  With SzotarStream Do

  Begin

    Init('szotar.str',STOpen,1024);

    Szotar:=PSzoCollection(Get);

    Done;

  End;

  If SzotarStream.Status<>0 Then

  Szotar:=New(PSzoCollection,Init(10,5));

End;

 

Procedure TTVApp.HandleEvent(Var Event:TEvent);

Var SzotarDialog: PDialog;

    R           : TRect;

    Control     : PView;

    V           : Integer;

  Procedure SzotarDialogus;

  Begin

    R.Assign(1,1,77,22);

    New(SzotarDialog,Init(R,'Angol-Magyar szótár'));

    With SzotarDialog^ Do

    Begin

      R.Assign(11,2,71,3);

      Control:=New(PASzoInputLine,Init(R,60));Insert(Control);

      R.Assign(2,2,10,3);

      Insert(New(PLabel,Init(R,'~A~ngol: ',Control)));

 

      R.Assign(11,4,71,5);

      Control:=New(PMSzoInputLine,Init(R,60));Insert(Control);

      R.Assign(2,4,10,5);

      Insert(New(PLabel,Init(R,'Ma~g~yar: ',Control)));

 

      R.Assign(73,8,74,20);

      Control:=New(PScrollBar,Init(R));

      Insert(Control);

      R.Assign(2,8,73,20);

      Control:=New(PSzotarListBox,Init(R,6,PScrollBar(Control)));

      Insert(Control);

 

      R.Assign(2,6,12,8);

      Insert(New(PButton,Init(R,'~B~eszúr',cmOk,bfDefault)));

      R.Assign(22,6,32,8);

      Insert(New(PButton,Init(R,'~J~avít',cmYes,bfNormal)));

      R.Assign(42,6,52,8);

      Insert(New(PButton,Init(R,'~T~öröl',cmNo,bfNormal)));

      R.Assign(62,6,72,8);

      Insert(New(PButton,Init(R,'~M~égsem',cmCancel,bfNormal)));

 

      SelectNext(False);

      SzotarDialogData:=cSzoDataRec;

      If Szotar^.Count<>0 Then SzotarDialogData.Szavak:=Szotar;

      SetData(SzotarDialogData);

      V:= DeskTop^.ExecView(SzotarDialog);

      GetData(SzotarDialogData);

      If (SzotarDialogData.ASzo<>'') And (V<>cmCancel) Then

      Begin

        SzoVolt:=True;

        Case V Of

           cmOK: Szotar^.Insert(New(PSzotar,Init(SzotarDialogData)));

          cmYes: Szotar^.AtPut(SzotarDialogData.SzoFocused,

                               New(PSzotar,Init(SzotarDialogData)));

           cmNo: Szotar^.AtDelete(SzotardialogData.SzoFocused);

        End;

      End;

    End;

    Szotar^.Pack;

    Dispose(SzotarDialog,Done);

  End;

Begin

  Inherited HandleEvent(Event);

  If Event.What=evCommand Then

  Case Event.Command Of

    cmSzotarDialogus: SzotarDialogus;

  End;

  ClearEvent(Event);

End;

 

Procedure TTVApp.InitMenuBar;

Var R: TRect;

Begin

  GetExtent(R);

  R.B.Y:= R.A.Y+1;

  MenuBar:= New(PMenuBar,Init(R,NewMenu(

    NewSubMenu('~S~zótár',hcNoContext,NewMenu(

      NewItem('~A~ngol-magyar szótár','F2',kbF2,cmSzotarDialogus,hcNoContext,

      NewLine(

      NewItem('E~x~it','Alt-x',kbAltX,cmQuit,hcNoContext,

    Nil)))),

  Nil))));

End;

 

Destructor TTVApp.Done;

Begin

  If SzoVolt Then With SzotarStream Do

  Begin

    Init('szotar.str',STCreate,1024);

    Put(Szotar);

    Done;

  End;

  Inherited Done;

  Dispose(Szotar,Done);

End;

 

Var TVApp:TTVApp;

 

Begin

  If Not

  TVApp.Init Then Halt(1);

  TVApp.Run;

  TVApp.Done;

End.

 

 

 

 

A teljes CrtPlus Lista, melyből néhány modult nem is használtunk a bemutatott programozási feladatainkban:

 

Unit CrtPlus;

Interface

Uses NewDelay, Crt, Dos, Drivers;

  Procedure KeyEmpty;

  Procedure Varj;

  Procedure Felre;

  Procedure Tunj;

  Procedure Szinek(HSz,KSz: Byte);

  Procedure Szinez(HSz,KSz,X,Y,Sh: Byte);

  Procedure Torol(X,Y,Sh: Byte);

  Procedure Tolt(X,Y,Sh: Byte; C: Char);

  Function Olvas(X,Y,Sh: Byte): String;

  Procedure WriteXY(X,Y: Byte; Sz: String);

  Procedure IrXY(X,Y: Byte; Sz: String);

  Procedure Vvonal(Xk,Xv,Y: Byte);

  Procedure Fvonal(X,Yk,Yv: Byte);

  Procedure Keret(Bfx,Bfy,Jax,Jay: Byte);

  Procedure Racs(Bfx,Bfy,BX,By,NX,Ny: Byte);

  Procedure Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay: Byte; Arny: Boolean; C: String);

  Procedure Uzenet(HSz,KSz: Byte; Sz: String);

  Procedure Duda;

  Function Kerdezo(HSz,KSz: Byte; Sz: String): Boolean;

  Function Bevitel(HSz,KSz,X,Y,Sh: Byte): String;

  Function PassWord(HSz,KSz,X,Y,Sh: Byte; Pw: String): Boolean;

  Function Menu(HSz,KSz,Vsz,Bfx,Bfy,Sh,Ss,AS: Byte): Byte;

  Function Kmenu(Fmp: Byte): Integer;

  Function Listazo(HSz,KSz,Vsz,Bfx,Bfy,Sh,Ss,Ls,AS: Integer;

                   Arny: Boolean; C: String): Integer;

  Function Combo(X,Y,Sh,KS: Byte; Ss,AS: Integer; C: String): Integer;

  Function ValidSt(S: String): String;

  Function Listara(S: String): Integer;

  Function Listarol(S: String): Integer;

  Function FileKereso(HSz,KSz,Vsz,Dr: Byte; Ext: String): String;

  Procedure Gomb(HSz,KSz,Vsz,X,Y,Sh: Byte; S: String);

  Function GombKereso(X,Y: Byte): Char;

  Function InputLine(Dhsz,Dksz,DVsz,HSz,KSz,X,Y,Sh: Byte; S: String): String;

  Procedure RadioGomb(Dhsz,Dksz,HSz,KSz,Vsz,Bfx,Bfy,Sh,Ss,AS: Byte; S: String);

  Function RadioGombKapcs(HSz,KSz,Bfx,Bfy,Sh,Ss,AS: Byte): Byte;

  Procedure DeskTop;

  Function Binaris(S: Word): String;

  Function Tizes(S: String): Word;

  Function SetBit(W: Word; N,B: Byte): Word;

  Function ValtBit(W: Word; N: Byte): Word;

Const Max=250;

      GtMax=64;

Type Scr=Array[1..25,1..80,1..2] Of Byte;

     GombRec=Record

               Tip: Byte;

               GX,Gy,Gsh: Byte;

               Key: Char;

             End;

     Hang=Record

            Hq: Real;

            Hc,Hcisz,Hd,Hdisz,He,Hf,Hfisz,Hg,Hgisz,Ha,Hbe,Hh: Integer;

          End;

Const AltKod: Array[#42..'Z'] Of Char=

      (#42,#43,#0,#45,#46,#47,

       #129,#120,#121,#122,#123,#124,#125,#126,#127,#128,

       #0,#0,#0,#61,#0,#0,#0,

       #30,#48,#46,#32,#18,#33,#34,#35,#23,#36,#37,#38,#50,

       #49,#24,#25,#16,#19,#31,#20,#22,#47,#17,#45,#21,#44);

Var BKep: Scr Absolute $B800:0;

    KKep: Scr;

    VCh: Char;

    Tomb: Array[1..Max] Of String[80];

    Sztomb: Array[0..25] Of Word;

    Funkcio: Byte;

    BeviteliSor: String[80];

    GombT: Array[1..GtMax] Of GombRec;

    GombIndex: Byte;

    H: Hang;

Type PMRec=^MRec;

     MRec=Record

            Nev: String[32];

            Cmp: Word;

            Key: Word;

            Eng: Boolean;

            Kiv: Boolean;

            HEMut, VEMut, HKMut, VKMut: PMRec;

          End;

 

Var ElsoMRec, AktMRec, UJMRec: PMRec;

    Esemeny: TEvent;

 

Implementation

 

Procedure KeyEmpty;

Begin

  While KeyPressed Do ReadKey;

End;

 

Procedure Varj;

Begin

  Repeat Until KeyPressed; KeyEmpty

End;

 

Procedure Felre;

Begin

  GoToXY(1,Hi(WindMax)-Hi(WindMin)+1);

End;

 

Procedure Tunj;

Var HSz: Byte;

Begin

  HSz:= BKep[Hi(WindMax)+1,Lo(WindMin)+1,2] Div 16;

  Szinez(HSz,HSz,Lo(WindMin)+1,Hi(WindMax)+1,1);

  GoToXY(1,Hi(WindMax)-Hi(WindMin)+1);

End;

 

Procedure Szinek(HSz,KSz: Byte);

Begin

  TextBackGround(HSz);

  TextColor(KSz);

End;

 

Procedure Szinez(HSz,KSz,X,Y,Sh: Byte);

Var I: Byte;

Begin

  For I:= X To X+Sh-1 Do BKep[Y,I,2]:= 16*HSz+KSz;

End;

 

Procedure Torol(X,Y,Sh: Byte);

Var I: Byte;

Begin

  For I:= X To X+Sh-1 Do BKep[Y,I,1]:= 32;

End;

 

Procedure Tolt(X,Y,Sh: Byte; C: Char);

Var I: Byte;

Begin

  For I:= X To X+Sh-1 Do BKep[Y,I,1]:= Ord(C);

End;

 

Function Olvas(X,Y,Sh: Byte): String;

Var I: Byte;

    WS: String;

Begin

  WS:= ''; For I:= X To X+Sh-1 Do WS:= Ws+Chr(BKep[Y,I,1]);

  OlvaS:= Ws;

End;

 

Procedure WriteXY(X,Y: Byte;Sz: String);

Begin

  GoToXY(X,Y);

  Write(Sz);

End;

 

Procedure IrXY(X,Y: Byte;Sz: String);

Var I: Byte;

Begin

  For I:= 1 To Length(Sz) Do BKep[Y,X+I-1,1]:= Ord(Sz[I]);

End;

 

Procedure Vvonal(Xk,Xv,Y: Byte);

Var I: Byte;

Begin

  For I:= Xk To Xv Do WriteXY(I,Y,Chr(196));

End;

 

Procedure Fvonal(X,Yk,Yv: Byte);

Var I: Byte;

Begin

  For I:= Yk To Yv Do WriteXY(X,I,Chr(179));

End;

 

Procedure Keret(Bfx,Bfy,Jax,Jay: Byte);

Begin

  Vvonal(Bfx+1,Jax-1,Bfy);

  Vvonal(Bfx+1,Jax-1,Jay);

  Fvonal(Bfx,Bfy+1,Jay-1);

  Fvonal(Jax,Bfy+1,Jay-1);

  WriteXY(Bfx,Bfy,Chr(218));

  WriteXY(Jax,Bfy,Chr(191));

  WriteXY(Bfx,Jay,Chr(192));

  WriteXY(Jax,Jay,Chr(217));

End;

 

Procedure Racs(Bfx,Bfy,BX,By,Nx,Ny: Byte);

Var I,J,SX,Sy: Byte;

Begin

  If Nx*Ny=0 Then Exit;

  Sx:= Bfx+Nx*(BX+1);

  Sy:= Bfy+Ny*(By+1);

  Keret(Bfx,Bfy,Sx,Sy);

  I:= Bfx+Bx+1;

  While I<Sx Do

  Begin

    WriteXY(I,Bfy,Chr(194));

    WriteXY(I,Sy,Chr(193));

    Fvonal(I,Bfy+1,Sy-1);

    Inc(I,Bx+1);

  End;

  J:= Bfy+By+1;

  While J<Sy Do

  Begin

    WriteXY(Bfx,J,Chr(195));

    WriteXY(SX,J,Chr(180));

    Vvonal(Bfx+1,Sx-1,J);

    Inc(J,By+1);

  End;

  For I:= 1 To Nx-1 Do For J:= 1 To Ny-1 Do

  WriteXY(Bfx+I*(BX+1),Bfy+J*(By+1),Chr(197));

End;

 

Procedure Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay: Byte; Arny: Boolean; c: String);

Var I,Px,Py: Byte;

Begin

  If Arny Then

  Begin

    Px:= Jax+2;

    Py:= Jay+1;

    If Px>80 Then Px:= 80;

    If Py>25 Then Py:= 25;

    For I:= Bfy+1 To Jay+1 Do Szinez(0,8,Bfx+2,I,Jax-Bfx+1);

  End;

  Window(Bfx,Bfy,Jax,Jay);

  Szinek(HSz,KSz);

  ClrScr;

  Window(1,1,80,25);

  Keret(Bfx+1,Bfy,Jax-1,Jay);

  If C<>''Then

  WriteXY(Round(Bfx+(Jax-Bfx-Length(c))/2-1),Bfy,' '+C+' ');

End;

 

Procedure Uzenet(HSz,KSz: Byte;Sz: String);

Var Bfx,Bfy,Jax,Jay,N: Byte;

Begin

  N:= Length(Sz);

  If n<10 Then N:= 10;

  Bfx:= 40-Round(n/2)-2;

  Bfy:= 11;

  Jax:= 40+Round(n/2)+1;

  Jay:= 13;

  KKep:= BKep;

  Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay,True,'Info');

  WriteXY(40-Round(Length(Sz)/2),12,Sz);

  Tunj;

  Varj;

  BKep:= KKep;

End;

 

Procedure Duda;

Begin

  Sound(2*h.a);

  Delay(80);

  NoSound;

End;

 

Function Kerdezo(HSz,KSz: Byte;Sz: String): Boolean;

Var Bfx,Bfy,Jax,Jay,N: Byte;

    Ch: Char;

Begin

  N:= Length(Sz);If n<20 Then N:= 20;

  Bfx:= 40-Round(n/2)-2;Bfy:= 11;Jax:= 40+Round(n/2)+1;Jay:= 13;

  KKep:= BKep;

  Ablak(HSz,KSz,Bfx,Bfy,Jax,Jay,True,'Válaszoljon! (i/n)');

  WriteXY(40-Round(Length(Sz)/2),12,sz);

  Tunj;

  Repeat

    Ch:= ReadKey;

    Ch:= UpCase(Ch);

  Until Ch In ['I','N'];

  Kerdezo:= Ch='I';

  BKep:= KKep;

End;

 

Function Bevitel(HSz,KSz,X,Y,Sh: Byte): String;

Var Ch: Char;

    I,Ax: Byte;

    Ovw: Boolean;

    Bszov: String;

Begin

  Szinez(HSz,KSz,X,Y,Sh);

  Ax:= X;

  GoToXY(AX,Y);

  Ovw:= False;

  Repeat

    While (Not KeyPressed) And (MouseButtons<>1) Do;

    If MouseButtons<>1 Then Ch:= ReadKey;

    Case Ch Of

      #0:Begin

           Ch:= ReadKey;

           Case Ch Of

             #71: Ax:= X;

             #75: If Ax>x Then Dec(Ax);

             #77: If Ax<X+Sh Then Inc(Ax);

             #79: Begin

                    I:= X+Sh;

                    Repeat

                      Dec(I);

                    Until BKep[Y,I,1]<>32;

                    Ax:= I+1;

                  End;

             #82: Ovw:= Ovw=False;

             #83: If Ax<X+Sh Then

                  Begin

                    For I:= Ax To X+Sh-1 Do

                    BKep[Y,I,1]:= BKep[Y,I+1,1];

                    BKep[Y,X+Sh-1,1]:= 32;

                  End;

           End;   

         End;

      #8: If Ax<>x Then

          Begin

            For I:= Ax-1 To X+Sh-1 Do

            BKep[Y,I,1]:= BKep[Y,I+1,1];

            BKep[Y,X+Sh-1,1]:= 32;

            Dec(Ax);

          End;

      #9: ;

      #13: ;

      #27: ;

      Else If MouseButtons<>1 Then

      If Ax<X+Sh Then

      Begin

        If Not Ovw Then

        For I:= X+Sh-1 DownTo AX+1 Do

        BKep[Y,I,1]:= BKep[Y,I-1,1];

        BKep[Y,AX,1]:= Ord(Ch);

        Inc(Ax);

      End;

    End;

    GoToXY(AX,Y);

  Until (Ch In [#13,#27,#9]) Or (MouseButtons=1);

  VCh:= Ch;

  If Ch=#27 Then Bevitel:= '' Else

  Begin

    Bszov:= '';

    I:= X+Sh;

    Repeat

      Dec(I);

    Until (BKep[Y,I,1]<>32) Or (I=X);

    Ax:= I;

    For I:= X To Ax Do Bszov:= Bszov+Chr(BKep[Y,I,1]);

    Bevitel:= Bszov;

  End;

  Tunj;

End;

 

Function PassWord(HSz,KSz,X,Y,Sh: Byte;Pw: String): Boolean;

Var Ch: Char;

    I,Ax: Byte;

    WS: String;

Begin

  Szinez(HSz,KSz,X,Y,Sh);

  Ax:= X;

  GoToXY(Ax,Y);

  WS:= '';

  Repeat

    While (Not KeyPressed) And (MouseButtons<>1) Do;

    If MouseButtons<>1 Then Ch:= ReadKey;

    Case Ch Of

      #0: Ch:= ReadKey;

      #8: If Ax<>x Then

          Begin

            WS:= Copy(Ws,1,Length(Ws)-1);

            Dec(Ax);

            BKep[Y,AX,1]:= 32;

          End;

      #9: ;

      #13: ;

      #27: ;

      Else If MouseButtons<>1 Then

      If Ax<X+Sh Then

      Begin

        WS:= Ws+Ch;

        BKep[Y,Ax,1]:= Ord('*');

        Inc(Ax);

      End;

    End;

    GoToXY(Ax,Y);

  Until (Ch In [#13,#27,#9]) Or (MouseButtons=1);

  PassWord:= WS=pw;

End;

 

Function menu(HSz,KSz,Vsz,Bfx,Bfy,Sh,Ss,AS: Byte): Byte;

Var I: Integer;

    Ch: Char;

Begin

  Szinez(Vsz,KSz,Bfx,Bfy+As-1,Sh);

  Repeat

    GetMouseEvent(Esemeny);

    If Esemeny.What=evMouseDown Then With MouseWhere Do

    If (X>Bfx-2) And (X<Bfx+Sh-1) And (Y>Bfy-2) And (Y<Bfy+Ss-1) Then

    Begin

      Szinez(HSz,KSz,Bfx,Bfy+As-1,Sh);

      AS:= Y-Bfy+2;

      Szinez(Vsz,KSz,Bfx,Bfy+As-1,Sh);

      Menu:= As;

      While MouseButtons=1 Do;

      Exit;

    End;

    If KeyPressed Then Ch:= ReadKey;

    If Ch=#0 Then

    Begin

      Ch:= ReadKey;

      If Ch In [#71,#72,#79,#80] Then

      Szinez(HSz,KSz,Bfx,Bfy+As-1,Sh);

      Case Ch Of

            #71: As:= 1;

            #72: If As>1 Then Dec(As) Else As:= Ss;

            #80: If As<Ss Then Inc(As) Else As:= 1;

            #79: As:= Ss;

      End;

      If Ch In [#71,#72,#79,#80] Then

      Szinez(Vsz,KSz,Bfx,Bfy+As-1,Sh);

    End;

  Until Ch In [#13,#27,#75,#77];

  If Ch In [#13,#75,#77] Then Menu:= As Else Menu:= 0;

  VCh:= Ch;

End;

 

Function Kmenu(Fmp: Byte): Integer;

label 1;

Var I,J,Lhs,ABfx,AJax: Byte;

    Fmh: Array[1..20] Of Byte;

    FmSz: Byte;

    Ch: Char;

    Nyitva: Boolean;

    Amp: Word;

    Oldmp: Byte;

Begin

  For I:= 1 To 20 Do Fmh[I]:= 0;

  Szinez(7,0,1,1,80);

  Szinez(7,0,1,25,80);

  Szinek(7,0);

  GoToXY(2,1);

  Fmh[1]:= 2;

  Nyitva:= False;

  I:= 1;

  AktMRec:= ElsoMRec;

  While AktMRec<>nil Do with AktMRec^ Do

  Begin

    Write(' ',Nev,' ');

    Fmh[I+1]:= WhereX;

    AktMRec:= AktMRec^.HKMut;

    Inc(I);

  End;

  Tunj;

  KKep:= BKep;

  FmSz:= I-1;

  Fmh[I+1]:= Fmh[I]+Length(AktMRec^.Nev);

  Szinez(green,0,fmh[fmp],1,fmh[fmp+1]-fmh[fmp]);

  Amp:= 0;

  Repeat

    Ch:= ReadKey;

    If (Not Nyitva) And (Ch=#13) Then

    Begin Nyitva:= True; KeyEmpty End;

    If Ch=#0 Then

    Begin

      Ch:= ReadKey;

      If Ch=#80 Then Nyitva:= True;If Ch In [#75,#77,#80] Then

      Szinez(7,0,Fmh[Fmp],1,Fmh[Fmp+1]-Fmh[Fmp]);

      1:

      Case Ch Of

        #75: If fmp>1 Then Dec(fmp) Else fmp:= fmsz;

        #77: If fmp<fmsz Then Inc(fmp) Else fmp:= 1;

      End;

      If Nyitva And (Ch In [#75,#77,#80]) Then

      Begin

        BKep:= KKep;

        AktMRec:= ElsoMRec;

        For I:= 1 To 25 Do Tomb[I]:= '';

        LhS:= 0;

        Oldmp:= 1;

        For I:= 1 To fmp-1 Do

        AktMRec:= AktMRec^.HKMut;AktMRec:= AktMRec^.VKMut;

        I:= 0;

        While AktMRec<>nil Do with AktMRec^ Do

        Begin

          Inc(I);

          Tomb[I]:= ' '+Nev+' ';

          If AktMRec^.HKMut<>nil Then Tomb[I]:= Tomb[I]+Chr(16)+' ';

          If Length(Tomb[I])>Lhs Then LhS:= Length(Tomb[I]);

          Sztomb[I]:= cmp;

          If Kiv Then Oldmp:= I;

          UjMRec:= AktMRec;

          AktMRec:= AktMRec^.VKMut

        End;

        If I>0 Then

        Begin

          Szinez(Green,0,Fmh[Fmp],1,Fmh[Fmp+1]-Fmh[Fmp]);

          ABfx:= Fmh[Fmp]-1;

          AJax:= Fmh[Fmp]+Lhs+2;

          While AJax>80 Do Begin Dec(ABfx);Dec(AJax) End;

          Ablak(7,0,ABfx,2,AJax,3+I,True,'');

          For J:= 1 To I Do WriteXY(ABfx+2,J+2,Tomb[J]);

          Felre;

          Amp:= Menu(7,0,Green,ABfx+2,3,Lhs,I,Oldmp);

          Ch:= VCh;

          If (Pos(Chr(16),Tomb[Amp])<>0) And (Ch=#13) Then

          Begin

            AktMRec:= UjMRec;

            While I>Amp Do

            Begin

              Dec(I);

              AktMRec:= AktMRec^.VEMut;

            End;

            For I:= 1 To 25 Do Tomb[I]:= '';lhS:= 0;I:= 0;

            oldmp:= 1;

            AktMRec:= AktMRec^.HKMut;

            While AktMRec<>Nil Do with AktMRec^ Do

            Begin

              Inc(I);

              Tomb[I]:= ' '+Nev+' ';

              If Length(Tomb[I])>Lhs Then LhS:= Length(Tomb[I]);

              Sztomb[I]:= Cmp;

              If Kiv Then Oldmp:= I;

              UjMRec:= AktMRec;

              AktMRec:= AktMRec^.VKMut

            End;

            ABfx:= Fmh[Fmp]+1;

            AJax:= Fmh[Fmp]+Lhs+4;

            While AJax>80 Do Begin Dec(ABfx); Dec(AJax) End;

            Ablak(7,0,ABfx,Amp+3,AJax,Amp+4+I,True,'');

            For J:= 1 To I Do WriteXY(ABfx+2,Amp+J+3,Tomb[J]);

            Felre;

            Amp:= Menu(7,0,Green,ABfx+2,Amp+4,Lhs,I,Oldmp);

            Ch:= VCh;

          End;

 

          If Ch In [#13,#75,#77] Then

          Begin

            AktMRec:= UjMRec;

            While i>amp Do

            Begin

              Dec(I);

              AktMRec^.Kiv:= False;

              AktMRec:= AktMRec^.VEMut;

            End;

            AktMRec^.Kiv:= True;

            While I>1 Do

            Begin

              Dec(I);

              AktMRec:= AktMRec^.VEMut;

              AktMRec^.Kiv:= False;

            End;

          End;

          If Ch In [#75,#77] Then GoTo 1;

        End;

      End;

      If Ch In [#75,#77] Then

      Szinez(Green,0,Fmh[Fmp],1,Fmh[Fmp+1]-Fmh[Fmp]);

    End;

  Until Ch In [#13,#27];

  If Ch=#13 Then Kmenu:= Sztomb[Amp] Else Kmenu:= 0;

End;

 

Function Listazo(HSz,KSz,Vsz,Bfx,Bfy,Sh,Ss,Ls,AS: Integer;

                 Arny: Boolean;c: String): Integer;

Var I,Ki,Ai,Vi,AkS: Integer;

    Ch: Char;

  Procedure Kiir;

  Var J,Ay: Integer;

  Begin

    Ki:= Round(As-Ls/2);

    Vi:= Round(As+Ls/2)-1;

    If Ki<=0 Then Inc(Ki,Ss);

    If Vi>Ss Then Dec(Vi,Ss);

    Window(Bfx+2,Bfy+1,Bfx+Sh-2,Bfy+Ls);

    ClrScr;

    If Vi>Ki Then

    For J:= Ki To Vi Do WriteXY(1,1+j-Ki,Copy(Tomb[J],1,Sh-1))

    Else

    Begin

      If As<=Ss-Ls/2 Then Inc(Ki);

      For J:= Ki To Ss Do WriteXY(1,1+j-Ki,Copy(Tomb[J],1,Sh-1));

      Ay:= WhereY;

      For J:= 1 To Vi Do

      Begin Inc(Ay);WriteXY(1,Ay,Copy(Tomb[J],1,Sh-1)) End;

    End;

    Window(1,1,80,25);

    Tunj

  End;

Begin

  If LS>Ss Then LS:= Ss;If Ls<3 Then LS:= 3;

  If Not Odd(Ls) Then Dec(Ls);

  If LS>21 Then LS:= 21;

  If Bfy+Ls+1>24 Then Repeat Dec(Bfy) Until Bfy+Ls+1<25;

  AkS:= Bfy+Round(Ls/2);

  Ablak(HSz,KSz,Bfx,Bfy,Bfx+Sh,Bfy+Ls+1,Arny,c);

  Kiir;

  Szinez(Vsz,KSz,Bfx+2,Aks,Sh-3);

  Repeat

    Ch:= ReadKey;

    If (Ch=#0) And KeyPressed Then

    Begin

      Ch:= ReadKey;

      If Ch In [#71,#72,#73,#79,#80,#81] Then Szinez(HSz,KSz,Bfx+2,Aks,Sh-3);

      Case Ch Of

        #71: AS:= 1;

        #72: Begin

               Dec(Ki);Dec(As);Dec(Vi);

               If Ki<1 Then Ki:= Ss;

               If As<1 Then AS:= Ss;

               If Vi<1 Then Vi:= Ss;

             End;

        #73: Begin

               Dec(Ki,Ls);Dec(As,Ls);Dec(Vi,Ls);

               If Ki<1 Then Begin If Ki=0 Then Ki:= Ss Else Ki:= KI+Ss+1 End;

               If As<1 Then Begin If AS=0 Then AS:= Ss Else AS:= As+Ss+1 End;

               If Vi<1 Then Begin If Vi=0 Then Vi:= Ss Else Vi:= VI+Ss+1 End;

             End;

        #79: As:= Ss;

        #80: Begin

               Inc(Ki);Inc(As);Inc(Vi);

               If Ki>Ss Then Ki:= 1;

               If AS>Ss Then AS:= 1;

               If Vi>Ss Then Vi:= 1;

             End;

        #81: Begin

               Inc(Ki,Ls);Inc(As,Ls);Inc(Vi,Ls);

               If Ki>Ss Then Ki:= KI-Ss;

               If AS>Ss Then AS:= As-Ss;

               If Vi>Ss Then Vi:= VI-Ss;

             End;

      End;

      If Ch In [#71,#72,#73,#79,#80,#81] Then

      Begin

        Kiir;

        Szinez(Vsz,KSz,Bfx+2,Aks,Sh-3);

      End;

    End;

  Until Ch In [#13,#27];

  If Ch=#27 Then Listazo:= 0 Else Listazo:= As;

  VCh:= Ch;

End;

 

Function Combo(X,Y,Sh,kS: Byte;Ss,As: Integer;c: String): Integer;

label 1,2,3,4;

Var I,Ik,Iv,Pik,Piv: Byte;

    Ch,Ch1: Char;

    Elso: Boolean;

    Kks,Apos: Byte;

    Ws: String;

  Procedure Kiir;

  Var I: Byte;

  Begin

    Window(1,1,80,25);

    If Elso Then Szinek(2,15) Else Szinek(1,15);

    WriteXY(X,Y,' '+Tomb[As]);

    Window(X+1,Y+2,X+Sh+1,Y+ks+2);

    If Elso Then

    Begin

      Ik:= As;

      Iv:= Ss;

      While Iv>As+ks-1 Do Dec(iv);

      Pik:= Ik;

      Piv:= Iv;

      For I:= As To Iv Do

      Begin

        If I=As Then Begin KkS:= WhereY; Szinek(2,15) End Else Szinek(3,0);

        WriteLn(Tomb[I]);

      End;

      GoToXY(X+1,Y+2);

    End

    Else

    Begin

      If As<Pik Then Begin Dec(Pik); If Piv-Pik=Ks Then Dec(Piv) End Else

      If As>Piv Then Begin Inc(Pik); Inc(Piv) End;

      For I:= Pik To Piv Do

      Begin

        If I=As Then Begin KkS:= WhereY; Szinek(2,15) End Else Szinek(3,0);

        WriteLn(Tomb[I]);

      End;

    End;

    Szinek(3,0);

    Window(1,1,80,25);

    Case Apos Of

      1: GoToXY(X+1,Y);

      2: GoToXY(X+1,Kks+6);

    End;

  End;

Begin

  Ablak(7,15,x-5,Y-2,X+Sh+14,Y+ks+3,True,C);

  Szinek(2,0);

  WriteXY(54, 7,' Beszúr ');

  WriteXY(54, 9,' Javít  ');

  WriteXY(54,11,' Töröl  ');

  WriteXY(54,13,' Mégsem ');

  Window(X,Y+2,X+Sh+1,Y+ks+1);

  Szinek(3,0);

  ClrScr;

  Elso:= True; ApoS:= 1;

  Kiir;

  Elso:= False;

  Repeat

    If Ch<>#9 Then Repeat Until KeyPressed; Ch:= ReadKey;

    If Ch=#27 Then GoTo 3;

    1:If Ch=#9 Then Begin Inc(Apos); If ApoS>6 Then ApoS:= 1 End;

      If Ch=#0 Then

      Begin

        Ch:= ReadKey; If Ch=#15 Then

        Begin Dec(Apos); If Apos<1 Then ApoS:= 6 End;

      End;

    Case Apos Of

      1: Begin

           GoToXY(X+1,Y);

           Szinez(2,15,X+1,Y,Sh-2);

           Repeat Until KeyPressed;

           Ch:= ReadKey;

           If Ch In [#13,#0,'0'..'9',' ',

                     'A'..'Z','Á','É','Í','Ó','Ö','Ő','Ú','Ü','Ű',

                     'a'..'z','á','é','í','ó','ö','ő','ú','ü','ű'] Then

           Begin

             If KeyPressed Then

             Begin

               Ch1:= ReadKey;

               If Ch1<>#77 Then GoTo 4;

             End;

             WS:= Bevitel(1,15,X+1,Y,Sh);

             Szinez(1,15,X,Y,Sh+2);

             GoToXY(X+1,Y);

           End;

          4: Szinez(1,15,X,Y,Sh-1);

        End;

      2: Begin

           GoToXY(X+1,kks+6);

           2: Repeat Until KeyPressed;

           Ch:= ReadKey;

           Case Ch Of

             #9:GoTo 1;

             #27:GoTo 3;

           End;

           If (Ch=#0) And KeyPressed Then

           Begin

             Ch:= ReadKey;

             Case Ch Of

               #15: Begin ApoS:= 1; GoTo 1; End;

               #72: If AS>1 Then Dec(As);

               #80: If SS>As Then Inc(As);

             End;

             Kiir;

           End;

           GoTo 2;

         End;

      3: Begin

           Szinez(2,15,54,7,8);

           Tunj;

           Repeat Until KeyPressed;

           Szinez(2,0,54,7,8);

           Ch:= ReadKey;

           If Ch In [#13,#27] Then GoTo 3 Else GoTo 1;

         End;

      4: Begin

           Szinez(2,15,54,9,8);

           Tunj;

           Repeat Until KeyPressed;

           Szinez(2,0,54,9,8);

           Ch:= ReadKey;

           If Ch In [#13,#27] Then GoTo 3 Else GoTo 1;

         End;

      5: Begin

           Szinez(2,15,54,11,8);

           Tunj;

           Repeat Until KeyPressed;

           Szinez(2,0,54,11,8);

           Ch:= ReadKey;

           If Ch In [#13,#27] Then GoTo 3 Else GoTo 1;

         End;

      6: Begin

           Szinez(2,15,54,13,8);

           Tunj;

           Repeat Until KeyPressed;

           Szinez(2,0,54,13,8);

           Ch:= ReadKey;

           If Ch In [#13,#27] Then GoTo 3 Else GoTo 1;

         End;

    End;

  Until (Apos In [3..6]) And (Ch=#13);

  3:If Ch=#27 Then Combo:= 0 Else Combo:= As;

  VCh:= Ch;

  Funkcio:= Apos;

  BeviteliSor:= '';

  For I:= X+1 To X+Sh Do BeviteliSor:= BeviteliSor+Chr(BKep[Y,I,1]);

End;

 

Function ValidSt(S: String): String;

Var I,N: Byte;

    Ws: String;

    Van: Boolean;

Begin

  N:= Length(s);

  ValidSt:= '';

  If N=0 Then Exit;

  WS:= s;

  While WS[N]=' ' Do

  Begin

    WS:= Copy(Ws,1,N-1);

    Dec(N);

  End;

  If N>0 Then

  While WS[1]=' ' Do

  Begin

    Ws:= Copy(Ws,2,N-1);

    Dec(N);

  End;

  Van:= True;

  If N>3 Then While Van Do

  Begin

    Van:= False;

    N:= Length(Ws);

    For I:= 2 To N-1 Do If (Ws[I]=' ') And (Ws[I+1]=' ') Then

    Begin

      Van:= True;

      Ws:= Copy(Ws,1,i)+Copy(Ws,I+2,N-I-1);

    End;

  End;

  ValidSt:= Ws;

End;

 

Function Listara(S: String): Integer;

Var I,J,N: Integer;

Begin

  S:= ValidSt(s);

  N:= 0;

  While Tomb[N+1]<>''Do Inc(N);

  If S='' Then Begin Listara:= N; Exit End;

  If n=0 Then Begin Tomb[1]:= S; Listara:= 1; Exit End;

  For I:= 1 To N Do If Tomb[I]=S Then Begin Listara:= n; Exit End;

  I:= 1; While (S>Tomb[I]) And (Tomb[I]<>'') Do Inc(I);

  For J:= N DownTo I Do Tomb[J+1]:= Tomb[J];

  Tomb[I]:= s;

  Listara:= N+1;

End;

 

Function Listarol(S: String): Integer;

Var I,J,N: Integer;

Begin

  S:= ValidSt(s);

  N:= 0;

  While Tomb[N+1]<>''Do Inc(N);

  If (S='') or (N=0) Then Begin Listarol:= N; Exit End;

  For I:= 1 To N Do If Tomb[I]=S Then

  Begin

    For J:= I To N-1 Do Tomb[J]:= Tomb[J+1];

    Tomb[N]:= '';

    Listarol:= N-1;

    Exit;

  End;

  Listarol:= 0;

End;

 

Function FileKereso(HSz,KSz,Vsz,dr: Byte;ext: String): String;

Var I,v,Sh: Integer;

    Bejegyzes: SearchRec;

    Katalogus: String;

Begin

  For I:= 0 To Max Do Tomb[I]:= '';GetDir(dr,Katalogus);

  If Katalogus[Length(Katalogus)]<>'\' Then Katalogus:= Katalogus+'\';

  Katalogus:= Katalogus+'*.'+ext;FindFirst(Katalogus,AnyFile,Bejegyzes);

  If Doserror<>0 Then Begin FileKereso:= ''; Exit End;

  I:= 1;

  While Doserror=0 Do

  Begin Tomb[I]:= ' '+Bejegyzes.Name;FindNext(Bejegyzes);Inc(I) End;

  Dec(I);Sh:= Length(Katalogus)+5;If Sh<17 Then Sh:= 17;

  v:= Listazo(HSz,KSz,Vsz,Round(40-Sh/2),6,Sh,I,11,1,True,Katalogus);

  FileKereso:= ValidSt(Tomb[V]);

End;

 

Procedure Gomb(HSz,KSz,Vsz,X,Y,Sh: Byte;S: String);

Var I,kh: Byte;

Begin

  HideMouse; Kh:= Pos(Chr(126),s);

  If Kh<>0 Then

  Begin

    GoToXY(X+1,Y);

    For I:= 1 To Length(s) Do If S[I]<>Chr(126) Then Write(S[I]);

  End Else WriteXY(X+1,Y,s);

  Szinez(HSz,KSz,X,Y,Sh);

  If kh<>0 Then Szinez(HSz,Vsz,X+kh,Y,1);

  HSz:= BKep[Y,X+Sh,2] Div 16;

  Szinek(HSz,0);

  WriteXY(X+Sh,Y,Chr(220));

  For I:= X+1 To X+Sh Do WriteXY(I,Y+1,Chr(223));

  Inc(GombIndex);

  With GombT[GombIndex] Do

  Begin

    Tip:= 1;

    Gx:= X; Gy:= y; Gsh:= Sh; Key:= #0;

    If Kh<>0 Then Key:= AltKod[UpCase(S[Pos(Chr(126),s)+1])];

  End;

  ShowMouse;

End;

 

Function GombKereso(X,Y: Byte): Char;

Var I,J,HSz: Byte;

Begin

  GombKereso:= #0;

  For I:= 1 To gtMax Do with GombT[I] Do

  If (gy=y) And (gx<=x) And (x<gX+Gsh) Then

  Begin

    GombKereso:= Key;

    If Tip>1 Then

    Begin

      Repeat Until MouseButtons<>1;

      Exit;

    End;

    HideMouse;

    For J:= Gx+1 To Gx+Gsh Do BKep[Gy+1,J,1]:= 32;

    For J:= Gx+Gsh DownTo Gx Do

    Begin

      BKep[Y,J,1]:= BKep[Y,J-1,1];

      BKep[Y,J,2]:= BKep[Y,J-1,2];

    End;

    BKep[Y,Gx,1]:= 32;

    ShowMouse; Repeat Until MouseButtons<>1; HideMouse;

    HSz:= BKep[Y,Gx,2] Div 16;

    For J:= Gx To Gx+Gsh Do

    Begin

      BKep[Y,J,1]:= BKep[Y,J+1,1];

      BKep[Y,J,2]:= BKep[Y,J+1,2];

    End;

    Szinek(HSz,0);WriteXY(gX+Gsh,Y,Chr(220));

    For J:= Gx+1 To Gx+Gsh Do WriteXY(J,Gy+1,Chr(223));

    Tunj;

    ShowMouse; Exit;

  End;

End;

 

Function InputLine(Dhsz,Dksz,dVsz,HSz,KSz,X,Y,Sh: Byte; S: String): String;

Var I,kh: Byte;

Begin

  HideMouse; Szinek(Dhsz,Dksz);

  Kh:= Pos(Chr(126),s);

  If Kh<>0 Then

  Begin

    GoToXY(X,Y-1);

    For I:= 1 To Length(s) Do If S[I]<>Chr(126) Then Write(S[I]);

  End Else WriteXY(X,Y-1,s);

  If kh<>0 Then Szinez(Dhsz,dVsz,X+kh-1,Y-1,1);

  Szinez(HSz,KSz,X,Y,Sh);

  Inc(GombIndex);

  With GombT[GombIndex] Do

  Begin

    Tip:= 2; Gx:= X; Gy:= y; Gsh:= Sh; Key:= #0;

    If Kh<>0 Then Key:= AltKod[UpCase(S[Pos(Chr(126),S)+1])];

  End; ShowMouse;

End;

 

Procedure RadioGomb(Dhsz,Dksz,HSz,KSz,Vsz,Bfx,Bfy,Sh,Ss,AS: Byte; S: String);

Var I,J,kh,dy: Integer;

    Ch: Char;

Begin

  HideMouse; Szinek(Dhsz,Dksz);WriteXY(Bfx,Bfy-1,s);

  For I:= 1 To Ss Do Szinez(HSz,KSz,Bfx,Bfy-1+I,Sh);

  Szinek(HSz,KSz);

  For I:= 1 To Ss Do WriteXY(Bfx,Bfy-1+I,' ( )');

  dy:= 0;

  For I:= 1 To Ss Do

  Begin

    Kh:= Pos(Chr(126),Tomb[I]);

    If Kh<>0 Then

    Begin

      GoToXY(Bfx+5,Bfy-1+i);

      For J:= 1 To Length(Tomb[I]) Do

      If Tomb[I][J]<>Chr(126) Then Write(Tomb[I][J]);

    End Else WriteXY(Bfx+6,Bfy-1+I,Tomb[I][J]);

    If kh<>0 Then Szinez(HSz,Vsz,Bfx+5+kh-1,Bfy-1+I,1);

    Inc(GombIndex);

    With GombT[GombIndex] Do

    Begin

      tip:= 3;

      gx:= Bfx;gy:= Bfy+dy;Inc(dy);Gsh:= Sh;Key:= #0;

      If Kh<>0 Then Key:= AltKod[UpCase(Tomb[I][Pos(Chr(126),Tomb[I])+1])];

    End;

  End;

  WriteXY(Bfx+2,Bfy-1+As,Chr(4)); ShowMouse;

End;

 

Function RadioGombKapcs(HSz,KSz,Bfx,Bfy,Sh,Ss,AS: Byte): Byte;

Var I,Ax,Ay: Integer;

    Ch: Char;

Begin

  Repeat

    Szinek(HSz,KSz);GoToXY(Bfx+2,Bfy-1+As);

    While (Not KeyPressed) And (MouseButtons<>1) Do;

    If KeyPressed Then Ch:= ReadKey;

    If MouseButtons=1 Then With MouseWhere Do

    If (X>Bfx-1) And (X<Bfx+Sh-1) And (Y>Bfy-2) And (Y<Bfy+Ss-1) Then

    Begin

      For I:= Bfy To Bfy+Ss-1 Do WriteXY(Bfx+2,I,' ');

      As:= Y-Bfy+2;

      WriteXY(Bfx+2,Bfy-1+As,Chr(4));

      GoToXY(WhereX-1,WhereY);

      RadioGombKapcS:= As;

      Exit;

    End;

    If Ch=#0 Then

    Begin

      Ch:= ReadKey;

      If Ch In [#72,#80] Then WriteXY(Bfx+2,Bfy-1+As,' ');

      Case Ch Of

        #72: If AS>1 Then Dec(As) Else AS:= Ss;

        #80: If As<Ss Then Inc(As) Else AS:= 1;

      End;

      If Ch In [#72,#80] Then WriteXY(Bfx+2,Bfy-1+As,Chr(4));

    End

    Else

    Begin

      Ax:= 0; Ay:= 0;

      Ch:= AltKod[UpCase(Ch)];

      For I:= 1 To 16 Do with GombT[I] Do If Key=Ch Then

      Begin

        Ax:= gx; Ay:= gy;

        If Not ((Ax>Bfx-1) And (Ax<Bfx+Sh-1) And

                (Ay>Bfy-1) And (Ay<Bfy+Ss)) Then Ax:= 0;

      End;

      If Ax*Ay<>0 Then

      Begin

        WriteXY(Bfx+2,Bfy-1+As,' ');

        GoToXY(WhereX-1,WhereY);

        AS:= Ay-Bfy+1;

        WriteXY(Bfx+2,Bfy-1+As,Chr(4));

        GoToXY(WhereX-1,WhereY);

      End;

    End;

  Until Ch In [#9,#13,#27];

  RadioGombkapcS:= As;

  Tunj;

End;

 

Procedure DeskTop;

Var I: Integer;

Begin

  Szinek(7,1);

  ClrScr;

  For I:= 2 To 24 Do Tolt(1,I,80,Chr(176));

  Szinek(7,0);

  WriteXY(1,25,' Alt-X Exit');

  Tunj;

  Szinez(7,4,2,25,5);

  Inc(GombIndex);

  With GombT[GombIndex] Do

  Begin

    Tip:= 6; Gx:= 2; Gy:= 25; Gsh:= 5; Key:= AltKod['X'];

  End;

  InitEvents; ShowMouse;

End;

 

Function Binaris(S: Word): String;

Var WS: String;

    B: Word;

Begin

  WS:= '';

  B:= $8000;

  While B<>0 Do

  Begin

    If B And S=0 Then Ws:= Ws+'0' Else Ws:= Ws+'1';

    B:= B Shr 1;

  End;

  Binaris:= Ws;

End;

 

Function Tizes(S: String): Word;

Var Wn: Word;

    B,I: Byte;

    Kod: Integer;

Begin

  Wn:= 0;

  While Length(S)<16 Do S:= '0'+S;

  For I:= 16 DownTo 1 Do

  Begin

    Val(S[I],B,Kod);

    If B>1 Then

    Begin

      Tizes:= 0;

      Exit;

    End;

    Wn:= Wn+B*Round(Exp((16-i)*Ln(2)));

  End;

  Tizes:= Wn;

End;

 

Function SetBit(W: Word; N,B: Byte): Word;

Var S,WS: String;

Begin

  If (N=0) Or (N>16) Or (B>1) Then

  Begin

    SetBit:= W;

    Exit;

  End;

  S:= Binaris(W);

  Str(B,Ws);

  S[16-N+1]:= Ws[1];

  SetBit:= Tizes(s);

End;

 

Function ValtBit(W: Word; N: Byte): Word;

Var S: String;

Begin

  If (N=0) or (N>16) Then

  Begin

    ValtBit:= W;

    Exit;

  End;

  S:= Binaris(W);

  If S[16-N+1]='0' Then S[16-N+1]:= '1' Else S[16-N+1]:= '0';

  ValtBit:= Tizes(s);

End;

 

Begin

  With H Do

  Begin

    Hq:=   1.059463;

    Ha:=   440;

    Hc:=   Round(a/q/q/q/q/q/q/q/q/q);

    HciSz:= Round(c*q);

    Hd:=   Round(cisz*q);

    HdiSz:= Round(d*q);

    He:=   Round(disz*q);

    Hf:=   Round(e*q);

    HfiSz:= Round(f*q);

    Hg:=   Round(fisz*q);

    HgiSz:= Round(a/q);

    Hbe:=  Round(a*q);

    Hh:=   Round(be*q);

  End;

End.