XIX. |
JEDNOTKA CRT |
Jednotka Crt implementuje převážně prostředky pro řízení vstupu z klávesnice a výstupu na obrazovku. Standardní podpora těchto zařízení je implementována jednotkou System, která je zpracovává jako textové soubory, spojené s proměnnými Input a Output. Jednotka Crt nepoužívá pro ovládání souborů Input a Output univerzální přístup k obecným textovým souborům, nýbrž instaluje vlastní ovladače konkrétních fyzických zařízení klávesnice a obrazovka. Tento přístup umožňuje implementaci řady specializovaných mechanismů, využívajících zvláštní vlastnosti těchto zařízení, které jiná textová zařízení obecně nemají (například výstup textu na obrazovku není orientovaný pouze sekvenčně, pozici prvního znaku vypisovaného textu lze volit).
XIX.1. |
Vstup textu z klávesnice |
povel | účinek | |||||||
---|---|---|---|---|---|---|---|---|
BACKSPACE | vymaže naposled zadaný znak | |||||||
ESC | vymaže celý obsah vstupní řádky | |||||||
CTRL+D | obnoví jeden znak z poslední vstupní řádky | |||||||
CTRL+F | obnoví celý obsah poslední vstupní řádky | |||||||
ENTER | ukončí vstupní řádku dvojicí znaků CR, LF | |||||||
CTRL+Z | ukončí vstupní řádku znakem konce souboru |
XIX.2. |
Proměnné CheckEof a CheckBreak |
const CheckEof : Boolean = False;
CheckBreak : Boolean = True;
Hodnota True resp. False proměnné CheckEof povoluje resp. zakazuje generování znaku konce souboru (CTRL+Z) a hodnota True resp. False proměnné CheckBreak povoluje resp. zakazuje generování požadavku na ukončení programu (CTRL+BREAK). Implicitní hodnoty proměnných jsou False resp. True. Při zákazu nemá stisk příslušné kombinace kláves žádný efekt.
XIX.3. |
Funkce KeyPressed a ReadKey |
Pro testování aktuálního stavu klávesnice a čtení znaku poskytuje jednotka Crt funkce KeyPressed a ReadKey.
Vrací True, pokud se ve vyrovnávací paměti klávesnice nachází alespoň jeden generovaný znak, jinak False.
Vrací znak, přečtený z vyrovnávací paměti klávesnice. Pokud je vyrovnávací paměť v okamžiku volání prázdná, funkce vyčká na vstup znaku z klávesnice, který okamžitě převezme (bez odezvy na obrazovce a bez možnosti editace).
{======================================================================} program Kody; {======================================================================} uses Crt; var Key: Char; { generovaný znak } begin { program } Writeln; repeat { opakuj } Write('klávesa (ESC = konec): '); { výzva } Key := ReadKey; { načtení znaku } if Key = #0 then { funkční klávesa } Writeln('#0, #', Ord(ReadKey)) else { obyčejná klávesa } Writeln('#', Ord(Key), ' (''', Key, ''')') until Key = #27; { do stisku ESC } Writeln end. { program }
XIX.4. |
Výstup textu na obrazovku |
V zásadě mohou videoadaptér a procesor spolupracovat ve dvou kvalitativně odlišných třídách módů — textových a grafických. Jednotka Crt implementuje podporu textových módů, ve kterých mohou být na obrazovce monitoru zobrazovány pouze znaky. Do videopaměti adaptéru zapisuje procesor na příslušnou pozici (definovanou pozicí kurzoru na obrazovce) hodnoty znaku a jeho atributu (barvy), převod do rastru elementárních zobrazovacích bodů realizuje adaptér podle definiční tabulky znakové sady.
Při zápisu znaku na obrazovku procedurou Write nebo Writeln mají následující znaky řídící význam. Ostatní znaky jsou zapsány normálně (objeví se na obrazovce).
znak | řídící funkce | |||||||
---|---|---|---|---|---|---|---|---|
BELL (#7) | akustický signál (pípnutí) | |||||||
BACKSPACE (#8) | posun kurzoru o pozici vlevo (není-li na začátku řádky) | |||||||
LF (#10) | posun kurzoru o pozici dolů | |||||||
CR (#13) | posun kurzoru na začátek řádky |
XIX.5. |
Textové módy |
const BW40 = 0; { 25 řádek × 40 sloupců, černobíle }
CO40 = 1; { 25 řádek × 40 sloupců, barevně }
BW80 = 2; { 25 řádek × 80 sloupců, černobíle }
CO80 = 3; { 25 řádek × 80 sloupců, barevně }
Mono = 7; { 25 řádek × 80 sloupců, černobíle }
Font8x8 = 256; { 43/50 řádek × 40 sloupců }
Hodnotami uvedených konstant jsou čísla jednotlivých textových módů, používaná jako parametry procedury TextMode (níže). Hodnoty 0 až 3 odpovídají čtyřem textovým módům adaptéru CGA, hodnota 7 jedinému módu adaptéru MDA. Adaptér VGA podporuje všechny uvedené módy, barevná složka videosignálu však není v módech 0 a 2 potlačena (módy 0 a 1 resp. 2 a 3 jsou tedy na VGA stejné). Na VGA/EGA je mód obecně reprezentován dvoubytovým číslem, jehož vyšší byte definuje počet řádek — 25 resp. 50 (na EGA pouze 43) pokud je nulový resp. nenulový — a nižší byte by měl obsahovat některou z povolených hodnot 0, 1, 2, 3 nebo 7. Například číslo 259 (Font8x8 + CO80) definuje textový mód o rozlišení 50/43 řádek krát 80 sloupců.
procedure TextMode (Mode: Word);
Nastaví požadovaný textový mód, specifikovaný parametrem Mode, a jeho číslo uschová do proměnné LastMode. Vedlejším efektem změny módu je reinicializace parametrů zobrazení (vesměs jsou popsány dále v této kapitole) — výmaz obrazovky, vložení počáteční hodnoty do proměnné TextAttr, nastavení implicitního výstupního okna a přesun kurzoru do jeho levého horního rohu.
Obsahuje automaticky udržované číslo aktuálního textového módu. Počáteční hodnota proměnné je inicializována na začátku běhu programu (je vhodné ji uschovat a původní mód před ukončením běhu programu obnovit), k automatické aktualizaci dochází při změně módu procedurou TextMode.
XIX.6. |
Výstupní okna |
Jednotka Crt implementuje zobrazovací souřadnice tak, že řádky jsou číslovány od 1 shora (souřadnice y) a sloupce od 1 zleva (souřadnice x). Pouze při definici nového okna se používají absolutní souřadnice, vztažené k počátku (levému hornímu rohu) celé zobrazovací plochy. Ve všech ostatních případech jsou veškeré uváděné souřadnice vztaženy relativně k počátku aktuálního okna.
Mimo aktuální okno je obrazovka nepřístupná, uvnitř mají všechna okna stejné vlastnosti (až na rozměry) jako celá zobrazovací plocha (přechod kurzoru na novou řádku při dosažení pravého okraje, rolování při dosažení spodního okraje). Implicitním oknem (automaticky nastaveným při startu programu a při každé změně textového módu) je celá zobrazovací plocha.
Proměnná WindMin resp. WindMax obsahuje absolutní obrazovkové souřadnice levého horního resp. pravého dolního rohu aktuálního výstupního okna. V nižších bytech proměnných jsou uloženy souřadnice horizontální (sloupce), ve vyšších souřadnice vertikální (řádky). Řádky i sloupce jsou však v těchto proměnných číslovány od 0!
procedure Window (XL, YH, XP, YD: Byte);
Vytvoří nové výstupní okno, definované absolutními souřadnicemi XL, YH (levý horní roh) a XP, YD (pravý dolní roh). Rozměry vytvořeného okna jsou tedy hodnotami výrazů XP – XL + 1 (šířka) a YD – YH + 1 (výška). Pokud jsou však zadané souřadnice neplatné (některá ze souřadnic je mimo zobrazovací plochu nebo je XL > XP či YH > YD), nemá volání procedury žádný efekt (původní výstupní okno zůstane zachováno).
Po vytvoření okna je kurzor umístěn do jeho levého horního rohu (souřadnice 1, 1) a absolutní souřadnice levého horního a pravého dolního rohu okna jsou uloženy (zmenšené o jedničku) do proměnných WindMin a WindMax. Již zobrazený text není vytvořením nového okna ovlivněn (výmaz obsahu okna se neprovádí).
XIX.7. |
Barvy |
pořadí bitu |
|
||||||||||
hodnota bitu |
|
Nejnižší čtveřice bitů atributu obsahuje číslo zzzz barvy popředí, použité pro zobrazení tahů znaku. Jeho rozsah je 0000 až 1111 binárně, čili 0 až 15 decimálně.
Další trojice bitů atributu obsahuje číslo ppp barvy pozadí, použité pro zobrazení podkladu znaku. Jeho rozsah je 000 až 111 binárně, čili 0 až 7 decimálně.
Hodnota b nejvyššího bitu atributu je tzv. příznak blikání. Hodnota 0 resp. 1 příznaku zakazuje resp. povoluje blikání znaku. Při povoleném blikání je barva popředí znaku nahrazována v pravidelných intervalech barvou pozadí znaku a opět obnovována.
Zobrazitelných barev je tedy celkem šestnáct a jsou reprezentovány čísly 0 až15. Všechny jsou použitelné pro definici barvy popředí znaku, ale jen prvých osm (s čísly 0 až 7) může být použito pro definici barvy pozadí znaku. Číselným hodnotám implicitně odpovídají následující vizuální barvy:
const Black = 0; { černá }
Blue = 1; { modrá }
Green = 2; { zelená }
Cyan = 3; { azurová }
Red = 4; { červená }
Magenta = 5; { fialová }
Brown = 6; { hnědá }
LightGray = 7; { světle šedá }
DarkGray = 8; { tmavošedá }
LightBlue = 9; { jasně modrá }
LightGreen = 10; { jasně zelená }
LightCyan = 11; { jasně azurová }
LightRed = 12; { jasně červená }
LightMagenta = 13; { jasně fialová }
Yellow = 14; { žlutá }
White = 15; { bílá }
Blink = 128; { příznak blikání }
Uvedené konstanty jsou veřejnými konstantami jednotky Crt. Jejich identifikátory tedy mohou být ve zdrojových textech používány místo příslušných číselných literálů.
Aktuální atribut, používaný procedurami Write a Writeln. Na pozici atributu každého vypisovaného znaku ve videopaměti je procedurou Write resp. Writeln zapsána aktuální hodnota proměnné TextAttr. Počáteční hodnota proměnné je při startu programu inicializována hodnotou atributu znaku na aktuální pozici kurzoru. Protože se jedná o veřejnou proměnnou jednotky Crt, může být její hodnota změněna přímo, přiřazovacím příkazem. Například:
Od okamžiku provedení tohoto příkazu až do další změny hodnoty proměnné TextAttr budou všechny vypisované znaky barveny atributem 226, takže budou červené (0100b = 4), na hnědém pozadí (110b = 6) a blikající. Stejný přiřazovací příkaz lze zapsat i názorněji:TextAttr := 226 { = 1 110 0100 binárně }
Barvu pozadí je nutno v hodnotě atributu posunout o čtyři bity výše (vlevo), což zajistí operátor shl (nebo vynásobení barvy pozadí šestnácti): 4 + 96 + 128 = 226.TextAttr := Red + Brown shl 4 + Blink
Kromě přímé definice hodnoty proměnné TextAttr přiřazovacím příkazem lze aktuální barevný atribut měnit i pomocí veřejných procedur TextColor, TextBackGround, LowVideo, HighVideo a NormVideo jednotky Crt.
procedure TextColor (Popredi: Byte);
Přepíše nejnižší čtyři bity proměnné TextAttr (aktuální barvu popředí) nejnižšími čtyřmi bity parametru Popredi a do nejvyššího bitu proměnné TextAttr (příznak blikání) vloží hodnotu 0 resp. 1, pokud parametr Popredi není resp. je větší než 15 (tedy pokud je každý ze čtyř vyšších bitů parametru roven nule resp. některý z nich není). Hodnoty ostatních bitů proměnné TextAttr (aktuální barva pozadí) zůstanou zachovány.
Příkaz TextColor (Red + Blink) například nastaví barvu popředí v proměnné TextAttr na hodnotu Red (červená) a příznak blikání na hodnotu 1 (blikání povoleno).
procedure TextBackGround (Pozadi: Byte);
Přepíše bity 4 až 6 proměnné TextAttr (aktuální barvu pozadí) nejnižšími třemi bity parametru Pozadi. Hodnoty ostatních bitů proměnné TextAttr (aktuální barva popředí a příznak blikání) zůstanou zachovány.
Příkaz TextBackGround (Brown) například nastaví barvu pozadí v proměnné TextAttr na hodnotu Brown (hnědá).
Nastaví nižší intenzitu barvy popředí nulováním bitu 3 proměnné TextAttr. Ostatní bity ponechá beze změny. Pokud má například aktuální barva popředí hodnotu LightRed (= 12 = 1100b), bude mít po volání procedury LowVideo hodnotu Red (= 4 = 0100b).
Nastaví vyšší intenzitu barvy popředí vložením hodnoty 1 do bitu 3 proměnné TextAttr. Ostatní bity ponechá beze změny. Pokud má například aktuální barva popředí hodnotu Red (= 4 = 0100b), bude mít po volání procedury HighVideo hodnotu LightRed (= 12 = 1100b).
Reinicializuje hodnotu proměnné TextAttr její hodnotou počáteční, tedy atributem znaku na aktuální pozici kurzoru při startu programu.
XIX.8. |
Ovládání pozice kurzoru |
function WhereX: Byte;
function WhereY: Byte;
Hodnotou funkce WhereX resp. WhereY je horizontální resp. vertikální souřadnice aktuální pozice kurzoru v okně (pořadí sloupce od levého okraje okna resp. pořadí řádky od horního okraje okna).
Absolutní souřadnice pozice kurzoru na obrazovce lze získat jako součty relativní souřadnice a příslušného bytu proměnné WindMin. Vertikální absolutní souřadnice kurzoru je tedy hodnotou výrazu WhereY + Hi (WindMin) a horizontální absolutní souřadnice kurzoru hodnotou výrazu WhereX + Lo (WindMin).
procedure GotoXY (X, Y: Byte);
Přesune kurzor na pozici o relativních souřadnicích X, Y (sloupec, řádka). Pokud jsou zadané souřadnice neplatné (definují pozici mimo výstupní okno), nemá volání procedury GotoXY žádný efekt (původní pozice kurzoru zůstane zachována).
XIX.9. |
Editování textu v okně |
Smaže obsah aktuálního okna. Všechny pozice v okně jsou vyplněny znakem mezera a aktuálním atributem. Kurzor je přesunut do levého horního rohu okna.
Smaže obsah aktuální řádky od pozice kurzoru včetně až po pravý okraj okna. Všechny uvedené pozice jsou vyplněny znakem mezera a aktuálním atributem. Pozice kurzoru je zachována.
Smaže v okně řádku na pozici kurzoru. Obsah všech níže položených řádek roluje v okně o jednu pozici nahoru (původní obsah kurzorem označené řádky tedy zanikne) a všechny pozice poslední řádky okna jsou vyplněny znakem mezera a aktuálním atributem. Pozice kurzoru zůstane zachována.
Vloží do okna prázdnou řádku na pozici kurzoru. Obsah kurzorem označené řádky a všech řádek níže položených (vyjma poslední) roluje v okně o jednu pozici dolů (původní obsah poslední řádky okna zanikne) a všechny pozice kurzorem označené řádky jsou vyplněny znakem mezera a aktuálním atributem. Pozice kurzoru zůstane zachována.
{======================================================================} program CrtDemo; {======================================================================} uses Crt; const AltC = #46; AltW = #17; { použité Alt-kombinace } AltD = #32; Vlevo = #75; { a funkční klávesy } AltE = #18; Vpravo = #77; AltI = #23; Nahoru = #72; AltQ = #16; Dolu = #80; AltR = #19; var Key : Char; { čtený znak } Konec : Boolean; { indikace požadavku na } { ukončení programu } procedure Init; { počáteční inicializace } {-------------} const Normal = 6; Jas = 4; Podklad = 7; { barvy menu } begin { Init } TextMode(CO80); { 25 řádek x 80 sloupců } Window(1, 25, 80, 25); { nastavení okna menu } TextBackGround(Podklad); { výpis menu } ClrScr; GotoXY(3, 1); TextColor(Jas); Write('W'); TextColor(Normal); Write('indow'); TextColor(Jas); Write(' R'); TextColor(Normal); Write('andomText'); TextColor(Jas); Write(' C'); TextColor(Normal); Write('lrScr Clr'); TextColor(Jas); Write('E'); TextColor(Normal); Write('OL'); TextColor(Jas); Write(' D'); TextColor(Normal); Write('elLine'); TextColor(Jas); Write(' I'); TextColor(Normal); Write('nsLine'); TextColor(Jas); Write(' Q'); TextColor(Normal); Write('uit'); Window(1, 1, 80, 24); { počáteční nastavení } NormVideo; { demonstračního okna } ClrScr { a atributu } end; { Init } procedure Okno; { nové demonstrační okno } {-------------} var Xl, Yh, Xp, Yd : Byte; { souřadnice okna } Pozadi, Popredi, Blikani : Byte; { aktuální barvy } begin { Okno } Xl := Random(80) + 1; { náhodné souřadnice } Xp := Random(81 - Xl) + Xl; Yh := Random(24) + 1; Yd := Random(25 - Yh) + Yh; Pozadi := Random(8); { náhodná barva pozadí } repeat { náhodná barva popředí } Popredi := Random(16) until Pozadi <> Popredi; Blikani := Random(2); { náhodný příznak blikání} TextAttr := Popredi + Pozadi shl 4 + Blink; { definice atributu } Window(Xl, Yh, Xp, Yd); { založení okna a výmaz } ClrScr { jeho obsahu } end; { Okno } procedure RandomText; { výpis náhodných znaků } {-------------------} { do stisku lib. klávesy } begin { RandomText } repeat Write(Chr(Random(256))) until KeyPressed { stiskem klávesy vygenerovaný znak zůstává nezpracován - bude po } { návratu do příkazové části programu vyzvednut do Key a použit } end; { RandomText } begin { program } Init; { inicializace } Konec := False; repeat { hlavní cyklus } Key := ReadKey; { (čekání na) vstup znaku} { z klávesnice } if Key = #0 then { funkční klávesa nebo } begin { ALT-kombinace } Key := ReadKey; { rozlišovací znak } case Key of { volba akce: } Vlevo : GotoXY(WhereX - 1, WhereY); { - kurzor vlevo } Vpravo : GotoXY(WhereX + 1, WhereY); { - kurzor vpravo } Nahoru : GotoXY(WhereX, WhereY - 1); { - kurzor nahoru } Dolu : GotoXY(WhereX, WhereY + 1); { - kurzor dolů } AltW : Okno; { - nové okno } AltR : RandomText; { - náhodný text } AltC : ClrScr; { - výmaz okna } AltE : ClrEOL; { - výmaz zbytku řádky } AltD : DelLine; { - zrušení řádky } AltI : InsLine; { - vložení řádky } AltQ : Konec := True { - požadavek ukončení } end { programu } end else { obyčejná klávesa } begin { výstup generovaného } Write(Key); { znaku do demonst. okna } if Key = #13 then Write(#10) { když CR tak i LF } end until Konec { konec po stisku ALT+Q } end. { program }
XIX.10. |
Tónový generátor |
Zahájí generování tónu. Hodnotou parametru Hz je požadovaná frekvence (výška) tónu v hertzích. Zadaný tón je trvale generován až do dalšího volání Sound (nový tón) nebo NoSound (konec tónu).
Ukončí generování tónu — vypne generátor (pokud je již vypnut, nemá volání NoSound žádný efekt).
Každý program, který používá tónový generátor, by měl příkaz NoSound obsahovat ve své úklidové proceduře. Pokud by program skončil se zapnutým generátorem, bude zvuk generován dále (až do vypnutí počítače, restartu systému nebo spuštění programu, který generátor vypne).
Pro řízení délky tónu (doby mezi zapnutím a vypnutím generátoru) lze použít různých typů čekacích smyček — například čekání na stisk klávesy nebo cyklus s pevně zvoleným počtem průchodů. Zvláště vhodným prostředkem je procedura Delay, která umožňuje přesné nastavení délky tónu.
Zastaví výpočet programu na dobu, specifikovanou parametrem MS v milisekundách.
{======================================================================} program Sirena; {======================================================================} uses Crt; const Min = 600; { parametry frekvenčního rozsahu } Max = 900; Rozsah = Max - Min; var Y : Word; { aktuální frekvenční přírustek } DalsiKonec : Pointer; { původní hodnota ExitProc } procedure Konec; far; { úklidová procedura programu } {-------------------} begin { Konec } ExitProc := DalsiKonec; NoSound { vypnutí tónového generátoru } end; { Konec } begin { program } DalsiKonec := ExitProc; { instalace úklidové procedury } ExitProc := @Konec; Y := 0; { inicializace frekvenčního přírustku } repeat { frekvenční cyklus } if Y <= Rozsah then { lineární růst frekv. od Min do Max } Sound(Min+Y) else { lineární pokles frekv. od Max do Min } Sound(Max + Rozsah - Y); Delay(50); { délka tónu } Y := (Y + 10) mod (2 * Rozsah){ aktualizace frekvenčního přírustku } until KeyPressed { do stisku klávesy } end. { program }