freebsd-dev/games/morse/morse.c

368 lines
7.7 KiB
C
Raw Normal View History

/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
* <lyndon@orthanc.com>
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1988, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93";
#endif /* not lint */
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#ifdef SPEAKER
#include <machine/speaker.h>
#include <fcntl.h>
#endif
struct morsetab {
char inchar;
char *morse;
};
static struct morsetab mtab[] = {
/* letters */
'a', ".-",
'b', "-...",
'c', "-.-.",
'd', "-..",
'e', ".",
'f', "..-.",
'g', "--.",
'h', "....",
'i', "..",
'j', ".---",
'k', "-.-",
'l', ".-..",
'm', "--",
'n', "-.",
'o', "---",
'p', ".--.",
'q', "--.-",
'r', ".-.",
's', "...",
't', "-",
'u', "..-",
'v', "...-",
'w', ".--",
'x', "-..-",
'y', "-.--",
'z', "--..",
/* digits */
'0', "-----",
'1', ".----",
'2', "..---",
'3', "...--",
'4', "....-",
'5', ".....",
'6', "-....",
'7', "--...",
'8', "---..",
'9', "----.",
/* punctuation */
',', "--..--",
'.', ".-.-.-",
'?', "..--..",
'/', "-..-.",
'-', "-....-",
'=', "-...-", /* BT */
':', "---...",
';', "-.-.-.",
'(', "-.--.", /* KN */
')', "-.--.-",
'$', "...-..-",
'+', ".-.-.", /* AR */
/* prosigns without already assigned values */
'#', ".-...", /* AS */
'@', "...-.-", /* SK */
'*', "...-.", /* VE */
'%', "-...-.-", /* BK */
'\0', ""
};
static struct morsetab iso8859tab[] = {
'<EFBFBD>', ".--.-",
'<EFBFBD>', ".--.-",
'<EFBFBD>', ".--.-",
'<EFBFBD>', ".-.-",
'<EFBFBD>', "-.-..",
'<EFBFBD>', "..-..",
'<EFBFBD>', "..-..",
'<EFBFBD>', "-..-.",
'<EFBFBD>', "---.",
'<EFBFBD>', "..--",
'\0', ""
};
static struct morsetab koi8rtab[] = {
/*
* the cyrillic alphabet; you'll need a KOI8R font in order
* to see the actual characters
*/
'<EFBFBD>', ".-", /* a */
'<EFBFBD>', "-...", /* be */
'<EFBFBD>', ".--", /* ve */
'<EFBFBD>', "--.", /* ge */
'<EFBFBD>', "-..", /* de */
'<EFBFBD>', ".", /* ye */
'<EFBFBD>', ".", /* yo, the same as ye */
'<EFBFBD>', "...-", /* she */
'<EFBFBD>', "--..", /* ze */
'<EFBFBD>', "..", /* i */
'<EFBFBD>', ".---", /* i kratkoye */
'<EFBFBD>', "-.-", /* ka */
'<EFBFBD>', ".-..", /* el */
'<EFBFBD>', "--", /* em */
'<EFBFBD>', "-.", /* en */
'<EFBFBD>', "---", /* o */
'<EFBFBD>', ".--.", /* pe */
'<EFBFBD>', ".-.", /* er */
'<EFBFBD>', "...", /* es */
'<EFBFBD>', "-", /* te */
'<EFBFBD>', "..-", /* u */
'<EFBFBD>', "..-.", /* ef */
'<EFBFBD>', "....", /* kha */
'<EFBFBD>', "-.-.", /* ce */
'<EFBFBD>', "---.", /* che */
'<EFBFBD>', "----", /* sha */
'<EFBFBD>', "--.-", /* shcha */
'<EFBFBD>', "-.--", /* yi */
'<EFBFBD>', "-..-", /* myakhkij znak */
'<EFBFBD>', "..-..", /* ae */
'<EFBFBD>', "..--", /* yu */
'<EFBFBD>', ".-.-", /* ya */
'\0', ""
};
void show(const char *), play(const char *), morse(char);
static int pflag, sflag;
static int wpm = 20; /* words per minute */
#define FREQUENCY 600
static int freq = FREQUENCY;
#ifdef SPEAKER
#define DASH_LEN 3
#define CHAR_SPACE 3
#define WORD_SPACE (7 - CHAR_SPACE - 1)
static float dot_clock;
int spkr;
tone_t sound;
#endif
static struct morsetab *hightab = iso8859tab;
int
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
register int ch;
register char *p;
while ((ch = getopt(argc, argv, "spw:f:")) != -1)
switch ((char) ch) {
case 'f':
freq = atoi(optarg);
break;
case 'p':
pflag = 1;
break;
case 's':
sflag = 1;
break;
case 'w':
wpm = atoi(optarg);
break;
case '?':
default:
fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr);
exit(1);
}
if (pflag && sflag) {
fputs("morse: only one of -p and -s allowed\n", stderr);
exit(1);
}
if (pflag && ((wpm < 1) || (wpm > 60))) {
fputs("morse: insane speed\n", stderr);
exit(1);
}
if (pflag && (freq == 0))
freq = FREQUENCY;
#ifdef SPEAKER
if (pflag) {
if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
perror(SPEAKER);
exit(1);
}
dot_clock = wpm / 2.4; /* dots/sec */
dot_clock = 1 / dot_clock; /* duration of a dot */
dot_clock = dot_clock / 2; /* dot_clock runs at twice */
/* the dot rate */
dot_clock = dot_clock * 100; /* scale for ioctl */
}
#endif
argc -= optind;
argv += optind;
if((p = getenv("LC_CTYPE")) ||
(p = getenv("LC_ALL")) ||
(p = getenv("LANG"))) {
if(strlen(p) >= sizeof(".KOI8-R") &&
strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0)
hightab = koi8rtab;
}
(void) setlocale(LC_CTYPE, "");
if (*argv) {
do {
for (p = *argv; *p; ++p) {
morse(*p);
}
morse(' ');
} while (*++argv);
} else {
while ((ch = getchar()) != EOF)
morse(ch);
}
exit(0);
}
void
morse(char c)
{
struct morsetab *m;
if (isalpha((unsigned char)c))
c = tolower((unsigned char)c);
if ((c == '\r') || (c == '\n'))
c = ' ';
if (c == ' ') {
if (pflag) {
play(" ");
return;
} else {
show("");
return;
}
}
for (m = ((unsigned char)c < 0x80? mtab: hightab);
m->inchar != '\0';
m++) {
if (m->inchar == c) {
if (pflag) {
play(m->morse);
} else
show(m->morse);
}
}
}
void
show(const char *s)
{
if (sflag)
printf(" %s", s);
else
for (; *s; ++s)
printf(" %s", *s == '.' ? "dit" : "dah");
printf("\n");
}
void
play(const char *s)
{
#ifdef SPEAKER
const char *c;
for (c = s; *c != '\0'; c++) {
switch (*c) {
case '.':
sound.frequency = freq;
sound.duration = dot_clock;
break;
case '-':
sound.frequency = freq;
sound.duration = dot_clock * DASH_LEN;
break;
case ' ':
sound.frequency = 0;
sound.duration = dot_clock * WORD_SPACE;
break;
default:
sound.duration = 0;
}
if (sound.duration) {
if (ioctl(spkr, SPKRTONE, &sound) == -1) {
perror("ioctl play");
exit(1);
}
}
sound.frequency = 0;
sound.duration = dot_clock;
if (ioctl(spkr, SPKRTONE, &sound) == -1) {
perror("ioctl rest");
exit(1);
}
}
sound.frequency = 0;
sound.duration = dot_clock * CHAR_SPACE;
ioctl(spkr, SPKRTONE, &sound);
#endif
}