Text byl optimalizován v rozlišení 800x600 a 16bitů/bod /// Text optimized for screen resolution 800x600 and 16bits per pixel Obsah - Abstract

This program is my first school work. I study in Czech Technical University. Program can convert any plain text to Morse code and back from Morse code to plain text. I write it in Borland Delphi 3 accoordingly can be executed in Windows 95 and compatibles operating systems. File Morseovka.zip, which you can copy from this page, contains program with source code and detailed documentation, but all texts are only in Czech language.


Tento program, který lze na této stránce stáhnout jsem napsal jako svou první semestrální práci. Celý balík, jehož součástí je i tato dokumentace obsahuje navíc i zdrojový kód programu včetně komentářů a obrázků, které jsem umístil na tlačítka i na další objekty. Dále pak nějaké samply s různými druhy pípaní. Stačí je pouze zkopírovat do adresáře s programem a přejmenovat na (TECKA.WAV a CARKA.WAV). Ostatní se dočtete v dalších částech dokumentace napsané jazykem HTML 3.2 přímo v textovém editoru (Notepad). Mimochodem, některé části se zobrazují v Netscape Communicatoru trochu jinak než bych si přál, ale je to vada naštěstí jen kosmetická.





Uživatelská příručka - User guide
Tento program, který můžete na této stránce stáhnout včetně zdrojového kódu jsem napsal jako svojí první semestrální práci a to v Borland Delphi 3. Program je tudíž použitelný ve Windows 95 (98 ??) a Windows NT 4.0. Pravděpodobně ovšem nebude pracovat na 386 s W95, ačkoliv by měl. Je to pravděpodobně dáno tím, že Delphi optimalizují kód pro Pentia s tím, že využívají instrukce 486 a vyšší.

Mimochodem, tato část dokumentace je skutečně velmi stručná, takže nezajímá-li Vás jak se mačkají tlačítka ani ji nečtěte. Raději přeskočte až k referenční části.
Program umí konvertovat mezi textem v ASCII a morseovou abecedou. Pracuje s rozšířenou sadou znaků. Tj. umí převádět tam i zpátky mimo písmen i číslice tečku, čárku a otazník. Nejsem si sice zcela jistý jestli je to úplně standartní, nicméně v literatuře, ze které jsem čerpal se vyskytují tabulky takové, že některé mají jen písmena, některé navíc i číslice a pod., ale s tabulkou obsahující úplně všechno jsem se nesetkal. Takže jsem soustředil dohromady maximum znaků ze všech tabulek a doufám, že je to tak lepší.
Tak takhle vypadá hlavní okno konvertoru. V levé části jsou soustředěny funkce pro práci s ASCII textem a v pravé zase pro práci s morseovkou. Oba editory jsou jinak téměř stejné a každý kdo umí pracovat třeba s Notepadem (součást Windows) musí bez problémů zvládnout i jejich ovládání, protože jsou stejně jako Notepad (v českých W. Poznámkový blok) založené na stejném objektu. Tím je objekt MEMO umožňující editaci tzv. plain textu. Nad editačními okny jsou tlačítka nabízející vytvoření nového souboru, načtení souboru a rychlé uložení. Úplně dole je pak StatusBar ukazující jména právě otevřených souborů a stav byl-li či nebyl-li ten který soubor změněn.
Některá tlačítka se ovšem přece jen liší. Především tlačítko se šipkou, které provede konverzi z toho okna nad nímž je umístěno do toho druhého. Tlačítko nad ASCII textem vyrobí z textu morseovku a tou přepíše obsah pravého okna a naopak tlačítko nad morseovkou vyrobí z morseovky ASCII text a tím pak přepíše obsah levého okna. Je-li obsah v cílovém okně změněn a neuložen pak se program nejdříve zeptá zda-li má být cíl opravdu přepsán a případně nabídně uložení. Pak teprve provede konverzi. Pozor na nastavení oddělovacího znaku ! Pokud bude výsledkem konverze z morseovky do ASCII prázdný text je možná chyba právě v tomto nastavení, zkuste ho změnit.
Změna oddělovacího znaku se provádí tlačítkem, které je nad morseovkou oproti textu navíc. Zatím je možné zvolit mezeru nebo lomítko. V případě potřeby by bylo možné povolit změnu na zadaný znak, ale myslím, že by to spíš způsobilo chaos.

Další odlišností je tlačítko s reproduktorem. Toto tlačítko nabízí přepípat celou morseovku. Po stisknutí (kliknutí) se ukáže takový malý přehrávač. Se standartními tlačítky pro posun na konec, na začátek, přehrávání, pozastavení, zastavení a ukončení. Pomocí ukazatele (TrackBar) se lze posunout do libovolné pozice morseovky. Přehrávač pracuje s multimedia systemem Windows, a jelikož Windows nepodporují speaker, vyžaduje i toto jednoduché přehrávání zvukovou kartu. Má-li někdo simulátor zvukovky na speaker mělo by to pracovat bez problémů, ale není to vyzkoušeno.

Poslední tlačítko vyvolá okno "O Programu", které jsem nakreslil na ZX Spectru v programu ART-Studio 48k. Tohle asi ocení jen rodilí Spectristé, ale pro ně to tu ostatně je. Okno můžete zavřít kliknutím na obdélníček OK nebo na levý horní roh.

Zde je tabulka znaků a jejich protějšků v morseově abecedě

Na velikosti písmen nezáleží, v morseově abecedě je stejně nerozlišitelné. Pro lepší čitelnost v programu při převodu do ASCII používám velká písmena. V další verzi by měla být velikost znaků volitelná.
A       .-              K       -.-             U       ..-             1       -----
B       -...            L       .-..            V       ...-            2       .----
C       -.-.            M       --              W       .--             3       ..---
D       -..             N       -.              X       -..-            4       ...--
E       .               O       ---             Y       -.--            5       ....-
F       ..-.            P       .--.            Z       --..            6       .....
G       --.             Q       --.-                                    7       -....
H       ....            R       .-.             .       .-.-.-          8       --...
I       ..              S       ...             ,       --..--          9       ---..
J       .---            T       -               ?       ..--..          0       ----.

AHOJ, JAK SE MAS ?      =       .-/..../---/.---/--..--//.---/.-/-.-//..././/--/.-/...//..--..//
                        =       .- .... --- .--- --..--  .--- .- -.-  ... .  -- .- ...  ..--..    

Dnes je pondeli.        =       -../-././...//.---/.//.--./---/-./-.././.-../../.-.-.-//
                        =       -.. -. . ...  .--- .  .--. --- -. -.. . .-.. .. .-.-.-  

V morseovce lze používat jedině tyto znaky, nic jiného !
Ještě jedna drobnost. Po vypípání znaku je nutné udělat pro srozumitelnost mezeru. Mezera je reprezentována oddělovačem (mezera,lomítko), takže chci-li udělat mezeru navíc, vložím do textu v morseovce jeden, nebo více oddělovačů.





Technické detaily - Technical details
Program byl navržen jako školní práce, takže v něm nejsou žádné převratné myšlenky, ale jedině užití toho co jsem se za první semestr naučil (a vlastně spíš před ním - učili jsme se Turbo Pascal).

Při popisu programu předpokládám alespoň minimální znalost prostředí Delphi. Nebudu proto popisovat k čemu je morse.DPR (Delphi Project), morse.RES (Resources), xxx.DCU (Delphi Compiled Unit), nebo třeba xxx.DFM (Delphi ForM). Soustředím se na to co je nutné vytvořit při psaní programu a ne na to co vytvářejí Delphi.

Základní část programu tedy tvoří formulář MORSEOVKA, na něj navazují další tři formuláře a to MORSEOVKA_PIPANI, MORSEOVKA_O_PROGRAMU a MORSEOVKA_NASTAVENI.
MORSEOVKA
Tento formulář se ukáže při spuštění programu jako první. Jsou na něm soustředěny všechny ovládací prvky - objekty, jako tlačítka, menu a další. Funkce některých objektů je podobná.

MEMO_ASCII a MEMO_MORSE Nejdůležitější 2 objekty na tomto formuláři jsou ravděpodobně MEMO_ASCII a MEMO_MORSE. Vnich je totiž uložen text jak v ASCII tak i v morseově kódu. Tyto dva objekty mimo jiné udávají chování programu během editace textu a díky nim je práce s textem prakticky totožná jako v jiných textových editorech (viz. Notepad - součást Windows). U těchto objektů zpracovávám jen dvě události a to OnChange a OnExit. První využívám k zobrazení nastalé změny na informačním panelu, mimo to nastaví vlastnost modified=True, to testuju při ukládacích operacích, a při druhé (OnExit) nastavím True nebo False vlastnost pomocného objektu, která pak slouží k rozlišení u funkcí společných pro oba objekty typu memo. Není to nejideálnější metoda, ale nepodařilo se mi přijít na lepší. Možná jedině přes nějakou globální proměnnou.

TLAČÍTKA a MENU tvoří prakticky celé uživatelské rozhranní tohoto programu. Všechny funkce nabízené tlačítky jsou obsaženy v menu. Naproti tomu jsou v menu některé funkce navíc a to ukončení programu, kopírování, vkládání, přesouvání a mazání textu. Tyto funkce jsou stejně obvykle volány horkou klávesou, takže vytvoření tlačítka postrádá smysl. Ostatně v menu jsou jen proto, že jsou na to někteří uživatelé zvyklí a nepamatují si příslušné kombinace kláves.
- Nejdůležitější jsou pohopitelně funkce pro konverzi, ale těm se budu věnovat dál v samostané části. Skoro stejně důležité jsou funkce pro práci se soubory. Jsou rozděleny z bezpečnostních důvodů do dvou částí pro text a morseovku. Chtěl jsem je původně ponechat sloučené, ale ukázalo se, že s tím jsou problémy při používání (nikoliv programování).
- První z těchto funkcí je vytvoření nového souboru. Při zavolání dojde jednak k vymazání textu (morseovky), ale i k přejmenování souboru na "NONAME.TXT" (NONAME.MOR) a k nastavení příznaku změny objektu MEMO_xxxxx.MODIFIED na FALSE.
- Další je otevření souboru z disku. Tato funkce je již složitější. Nejdříve je provedeno testování příznaku změny a došlo-li ke změně je uživateli nabídnuto uložení. Při tom může uživatel soubor uložit, neuložit případně celou akci přerušit. Při volbě uložení je zavolána procedure "rychlé uložení", s tím také souvisí další chování programu. Viz dále. Tato funkce používá objekt typu OPENDIALOG.
- Rychlé uložení jako první provede test, jestli už byl soubor pojmenován.To pozná podle toho jestli je jméno jenom "NONAME.xxx" nebo jestli je u něho i cesta do adresáře a tudíž se sice může jmenovat (NONAME.xxx), ale je už zapsán na disku (nebo z něj načten) a není tedy třeba ho znovu pojmenovat. Uložení může být provedeno. Případně pojmenován nebyl a bude zavolána procedura "uložit jako".
- Uložit jako se liší od rychlého uložení, tím, že vždy nabídne pojmenování souboru. Respektive zavolá funkci EXECUTE objektu SAVEDIALOG1, která vrací FALSE při stornování, nebo TRUE pokud uživatel zadal nějaké jméno souboru (stejně jako u OPENDIALOG). Pod tímto jménem souboru pak bude soubor uložen a to procedurou MEMO_xxxxx.SAVETOFILE (filename). kde filename je string obsahující jméno souboru. Ale to je vše celkem pochopitelné ze zdrojového textu.

- Ještě tu zbývají uživ. funkce pro nastavení oddělovače (viz. MORSEOVKA_NASTAVENI), přehrání morseovky na zvukový výstup (viz. MORSEOVKA_PIPANI) a zobrazení informací o programu (viz. MORSEOVKA_O_PROGRAMU). Při zvolení této funkce dojde pouze k zabrazení příslušného formuláře a při tom je mu až do jeho uzavření plně předáno řízení (čtení a zpracování všech událostí, které souvisejí s programem morseovka).
LABEL, STATUSBAR, PROGRESSBAR a CHECKBOX jsou poslední objekty podřízené a umístěné na objektu Morseovka. Objekty nereagují na žádnou událost. Pouze jsou různými procedurami nastavovány jejich vlastnosti.
- Objekty typu Label složí jen jako nadpis nad příslušným editačním oknem objektů MEMO.
- Status bar zobrazuje informace o názvech editovaných souborů a ještě k tomu informaci jestli byl či nebyl soubor změněn (#=nastala změna).
- ProgressBar je používán jako ukazatel během konverze. Mimo ní má vlastnost Visible nastavenou jako FALSE.
- Check box je ten objekt, jehož vlastnost checked je True nebo False podle toho jestli se právě edituje morseovka nebo text. Vím, že by to šlo nahradit globální proměnnou, ale to je zakázané (v zadání této práce) a proto jsem tedy zvolil těžkopádnější řešení a použil jsem k tomuto účelu předdefinovaný objekt.


KONVERZE Z ASCII DO MORSEOVKY
Touto začnu, neboť je jednodušší. Zavoláním procedury dojde k vytvoření rozsáhlého pole, které v každé položce odpovídající jednomu ASCII znaku ukrývá jeho vyjádření v morseovce. Tento způsob je výhodný při konverzi delších textů, protože při každém cyklu je přidán do výsledného řetězce řetězec z tohoto pole bez jakéhokoliv testování. Mimo to je při konverzi zajištěno zachování odstaců a to jednoduchou podmínkou, stejně tak vypuštění nesmyslných znaků. Výsledek je pak uložen do cílového objektu MEMO_MORSE.
- Mimochodem než je tato konverze vůbec spuštěna proběhne testování jestli není náhodou cílový soubor změněn-neuložen. Je li příznam MEMO_MORSE.MODIFIED=TRUE pak se program uživatele zeptá jestli opravdu chce konverzi provést.


KONVERZE Z MORSEOVKY DO ASCII
Tato část je pravděpodobně nejsložitější z celého programu. Navíc je víceméně jeho hlavní částí. Celá je zapouzdřena do procedury MORSE_TO_ASCII, která obsahuje ještě čtyři podprocedury a to funkci vytvářející jednotlivé uzly binárního stromu UZEL, funkci vytvářející pomocí té předešlé celý binární strom VYTVOR_STROM, dále proceduru ODSTRAN_STROM, která pomocí rekurze umí uvolnit paměť obsazenou jednotlivými prvky stromu, a nakonec proceduru DEKODUJ, která z retězce text_m vyrobí retězec text_a. Vše je voláno z hlavního bloku procedury MORSE_TO_ASCII.

Možná bych měl nejdříve vysvětlit, jak takový binární strom funguje. Binární strom je praktickým využitím dynamických proměnných. Obsahuje prvky, obvykle typu záznam, složené z datové části a dvou (u nebinárních stromů více) ukazatelů na prvek stejného typu. Tímto vzniká struktura stromu. Pokud prvek neukazuje na žádný další, je hodnota ukazatele NIL. Pokud je v levém podstromu výrazně odlišný počet prvků než v pravém, pak říkámě, že je strom nevyvážený. V tomto případě je prvkem stromu takovýto záznam :

type	TPUzel=^TUzel;		// Typ ukazatele na prvek stromu
	TUzel=record		// Typ prvku tvořícího strom
	  znak:char;		  // datová část
	  tecka:TPUzel;		  // Ukazatel na LEVÝ PODSTROM
	  carka:TPUzel;		  // Ukazatel na PRAVÝ PODSTROM
	end;
První prvek, který ukazuje na další prvky, ale na něj přitom ukazováno není se nazývá kořen. Tedy takhle, ukazováno na něj být musí, ale ne prvkem stromu, nýbrž zvláštním ukazatelem, jenž lze pak předávat jako parametr do volaných procedur. Tento ukazatel vrací funkce VYTVOR_STROM, a naopak ho potřebují všechny funkce a procedury se stromem pracující.

Struktura binárního stromu v tomto případě (částečně nevyvážená, kvůli nestandartním znakům):
Pomocí tohoto stromu provádím dekódování morseovky procedurou dekóduj. Tato procedura používá jeden ukazatel na prvek a tento nejdříve nastaví na kořen stromu. Načte znak a porovnává, je-li znak tečka pak vezme z kořene ukazatel na levý podstrom, je-li tečka pak na pravý podstrom. Tak pokračuje dokud nenarazí na oddělovací znak (pak uloží do výsledného řetězce obsah prvku), nebo dokud nenastane situace, taková, že prvek ukazuje na NIL a tudíž už není další prvek pro případ, který nastal. V této situaci, když už není k dispozici příslušný uzel, je načítaný znak nesmyslný a proto místo něho zapíšu do výsledného řetězce # a pokračuji v dekódování dalších znaků. POZOR ! Pokud je špatně zadaný oddělovač znaků, je výsledkem řetězec #.
Znak EOL bude přenesen beze změny, stejně tak jako při konverzi opačné.

Doporučuji přečíst si zdrojový text, který je přiložen v adresáři SOURCE a je podrobně komentován.
MORSEOVKA_PIPANI
Tento formulář slouží jako takový přehrávač, přehrávající morseovku na zvukový výstup. Bohužel Windows a potažmo Delphi neumí pracovat s interním speakerem, takže i tohle vyžaduje zvukovou kartu. Nicméně na druhou stranu takový výstup umožňuje použití různých zvuků. V adresáři source\sounds je zazipovaný soubor obsahující několik takových zvuků, které stačí zkopírovat do adresáře s programem Morse.exe a přejmenovat na "tecka.wav", "carka.wav" a "ticho.wav". Sampl ticho je důležitý kvůli přesnému definování časové prodlevy mezi zvuky pro tecku a carku.
- Ovládání přehrávače jsem zajistil několika tlačítky a jedním objektem TrackBar. Tlačítka se chovají stejně jako v jiných přehrávačích, naproti třeba MEDIA PLAYERu jsem vynechal tlačítka pro rychlý posuv. Podle mne je jednak zbytečné a jednak je jejich funkce lehce nahraditelná práve posuvníkem typu TRACKBAR - viz dále.
UDÁLOST FORM_ACTIVATE
Tato Událost nastává vždy,když je formulář Morseovka_pipani zavolán/zobrazen procedurou ShowModal z jakékoliv jiné procedury v jiném formuláři. Stejně jako další dva formuláře o programu a nastavení. Při této události se pro jistotu zakáže Timer, přenese text do místního objektu Memo, nastaví vlastnosti objektu TrackBar a tlačítek (typu SpeedButton). Dále se ještě zobrazí na panelu StatusBar základní informace jako je celkový počet znaků, pozice (číslo znaku) a Ascii kód nastaveného oddělovače, který lze během přehrávání měnit.

Vše je celkem pochopitelné až na to, proč přenáším text z jednoho objektu Memo do druhého. Ono to totiž funguje i když to neprovedu, ale někdy program padá. Nevím proč. No a protože tímto jsem nespolehlivost odstranil tak jsem to tak už musel nechat. Budu vděčný za každou radu proč tomu tak může být.
OVLÁDACÍ TLAČÍTKA
Vezmu je tak jak jsou umístěny na formuláři. Každé tlačítko mění vlastnost enabled ostatních tlačítek, nebo i sebe sama tak aby nemohlo dojít k zavolání některé funkce v okamžiku, kdy by byla nesmyslná. Toto nastavování je dobře komentováno ve zdrojovém textu a nebudu ho tu podrobně uvádět. Vlastnost position objektu TrackBar je v tomto případě využita jako index určující pozici přehrávání. Jeho změna je proto důležitá. Následuje tedy stručný seznam akcí prováděných při událostech OnClick na příslušných tlačítkách.
- Posun na začátek, nastaví pozici TrackBaru na začátek a NEmění nastavení povolení objektu Timer.
- Přehrávání, nejdříve se zkontroluje není-li pozice TrackBaru rovna poslednímu znaku, tedy vše již bylo přehráno, pak se nastaví pozice na začátek. Jinak zůstane nezměněna. V obou případech se povolí timer.
- Pause, zakáže timer, ale nemění pozici TrackBaru.
- Stop, zakáže timer a současně nastaví pozici TracBaru na začátek.
- Eject, zakáže timer a zavolá proceduru Close čímž zavře přehrávací okno.
- Posun nakonec, nastaví opět pozici TrackBaru, tentokrát na poslední znak a zakáže Timer. Stejně už není co přehrávat.
TIMER - událost OnTimer
Tato procedura je víceméně srdcem celého přehrávače. Jako první nastane-li adálost OnClick je provedeno zakázání Timeru (i když interně se možná provádí automaticky). Poté se vezme index (pozice trackbaru), zjistí se jaký je zvolen oddělovač a jaká je délka textu. Přečte se znak z řetězce v objektu memo. Pokud by náhodou přece jen došlo k tomu, že by se měl číst znak mimo rozsah tohoto řetězce bude místo něho podstrčen jiný. Tato podmínka zbyla z doby ladění, přesto ji tam raději ponechám.
Následuje jednoduchá kombinace podmínek rozhodující jaký ze tří možných zvuků bude přehrán. Není li znak tečka, čárka ani oddělovač pak nebude přehráno nic. Poté se ještě otestuje jestli právě přehraný (přeskočený) znak nebyl poslední z celého řeťezce. V tom případě bude index nastaven na začátek, povolena/zakázána příslušná tlačítka a hlavně před ukončením procedury nebude povolen timer. V opačném případě povolen bude a index bude zvýšen o 1. V obou případech bude na panelu StatusBaru zobrazena aktuální informace o stavu přehrávání.
TRACKBAR - OnChange
Jak jsem se zmínil, vlastnost tohoto objektu position je použitá jako index na právě přehrávaného znaku. Mimo to může být ukazatelem tohoto objektu posunuto a tím se změní i index-position. A to právě zpracovává procedura volaná při události OnChange. V ní je pak zajištěno nastavení tlačítek (enable) podle toho je-li posunuto ukazatelem na konec, začátek nebo někam mezi tyto dva body. Stejně tak je nová pozice zobrazena na panelu objektu StatusBar.
TLAČÍTKA - O programu a Nastavení
Posledními objekty na formuláři morseovka_pipani jsou tyto dvě tlačítka. Ve skutečnosti se jmenují SpeedButton7 a SpeedButton8. "Sedmička" pouze zobrazí formulář morseovka_o_programu procedurou ShowModal a "osmička" navíc po zobrazení formuláře morseovka_nastavení zobrazí Ascii kód oddělovače na panelu objektu StatusBar. A to je vše.

MORSEOVKA_O_PROGRAMU
Toto okno neumí prakticky nic. Je na něm umístěn jediný objekt a to IMAGE, který reaguje na událost MOUSEDOWN. Při této události se podle souřadnic buď nestane nic, nebo se okno zavře a předá se řízení tomu oknu, které ho zavolalo pomocí procedury SHOWMODAL. Vlastnosti jsem nastavil tak aby nebylo vidět nic jiného, než bitmapa v objektu IMAGE, kterou jsem vyrobil v ART STUDIU na ZX Spectru a ta bitmapa vypadá jako okenní aplikace na něm vytvářené (Tedy já je takové vytvářel, protože jsem byl nevímproč fanda okenních aplikací. Dnes už vím, že máme i dveře. :-) ).

MORSEOVKA_NASTAVENI
Tato procedura je ze všech úplně nejjednodušší. Jediná událost na níž reaguje je kliknutí na tlačítko a to neprovede nic jiného než zavření formuláře procedurou Close. Mimo tlačítko je na formuláři GroupBox a v něm dva RadioButtony, znichž jen jeden je vždy Checked a ten druhý ne. Toto se pak zjišťuje v různých procedurách v jiných formulářích a podle toho je nastaven oddělovací znak mezi znaky morseovky.






Licence
Tento program je naprostý freeware, a lze s ním dělat cokoliv se Vám zlíbí. Můžete ho třeba vydávat za svůj, protože Vás bude hryzat Vaše svědomí, když budete ostatním lhát. Mě je to úplně jedno.

Pochopitelně se v takovém případě distancuji od jakýchkoliv škod programem způsobených. Stejně tak ani v jiných případech nezaručuji, že je program zcela dokonalý a 100% bez chyb. Napsal jsem ho jako školní práci a ne jako aplikaci pro Pentagon. Tudíž prošel testováním jen na mém a školním počítači, nikoliv za účasti davu betatesterů. Z toho plyne, že ho můžete libovolně používat a zneužívat jedině a pouze na vlastní riziko.





Poděkování - Acknowledgment
Děkuji autorům literatury, kterou jsem použil a všem kteří se podíleli na tvorbě vývojového prostředí Delphi. Stejně tak děkuji všem kteří mi byli jakýmkoliv způsobem nápomocni.

Použitá literatura :
[1] ???
Mistrovství v Delphi 2, ???

[2] J. Jinoch, K. Muller, J. Vogel,
Programování v jazyku Pascal, SNTL Praha 1988