home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 164.lha / ARexx / SpeechToy / SPTOY.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-28  |  54.6 KB  |  2,148 lines

  1. /* SpeechToy.c  Original by Dave Lucas, Enhancements by Rob Peck.
  2.  *
  3.  * o  Can now read and write its own icon to get the defaults you set.
  4.  * o  New menu item added to save current speech settings.
  5.  * o  Can be started from WBENCH or CLI; if from CLI, can still
  6.  *    read the icon file to get the default values.
  7.  *
  8.  * In the toolstrings, the data takes the form:
  9.  *
  10.  * SEX=1
  11.  * SEX=0
  12.  * for female (1) or male (0) voice.
  13.  *
  14.  * MODE=0
  15.  * MODE=1
  16.  * for expressive (0) or robotic (1) voice.
  17.  *
  18.  * FREQUENCY=20000
  19.  * numeric range from sampling frequency MIN to 
  20.  * frequency MAX (see the audio.h file)
  21.  * 
  22.  * RATE=150
  23.  * words per minute rate, see audio.h for range.
  24.  *
  25.  * VOLUME=64
  26.  * volume range from 0 to 64 (max).
  27.  *
  28.  * PITCH=224
  29.  * pitch value for speech, range see audio.h
  30.  *
  31.  * These values can be saved in the icon by using the save menu item
  32.  * --------------------------------------------------------------------
  33.  *
  34.  * WORDS=This is Amiga Speaking
  35.  * anything you want it to insert in the English Phrase area.
  36.  *
  37.  * TRANS=1
  38.  * means: Translate whatever words there are in the english.
  39.  *
  40.  * SPEAK=1
  41.  * means: Say it.  When this is in the icon, it opens up talking.
  42.  *
  43.  * PHON=DHIHS IHZ AHMIY3GAH SPIY4KIHNX.
  44.  * This is the way you insert your own custom pronunciation.
  45.  * Note that it MUST be legal phonetics per the Speech docs.
  46.  */
  47.  
  48. /* AREXX support:
  49.  *
  50.  * AREXX port is named SPEECHTOY, so that AREXX, which capitalizes
  51.  * things automatically, doesn't need quotes on the name to
  52.  * prevent it from capitalizing and not finding the port.
  53.  *
  54.  * To change any parameter, do EXACTLY as the toolstrings description
  55.  * shows... I use the SAME routines to parse the command that AREXX
  56.  * sends as are used to decode the icon's toolstrings.
  57.  *
  58.  * To send a command directly from a CLI interface, using AREXX
  59.  * support function, do this:
  60.  *
  61.  * rx "address speechtoy 'WORDS=Say this you turkey'"
  62.  * rx "address speechtoy 'TRANS=1'"
  63.  * rx "address speechtoy 'SPEAK=1'"
  64.  */
  65.  
  66. /* CLI startup:
  67.  *
  68.  * To allow speechtoy to read its own icon, either CD to the
  69.  * directory where speechtoy is located, then:  run speechtoy
  70.  * OR CD anywhere, then:
  71.  *
  72.  *     run speechtoy <dir-where-icon-is-located>
  73.  *
  74.  * example:
  75.  *
  76.  * CD DF0:
  77.  * RUN df1:speechtoy df1:
  78.  */
  79.  
  80. /* COMPILING:  Lattice - compiles cleanly under Lattice 3.03 and 4.0
  81.  *             if stack is set to 20000
  82.  *
  83.  *             Manx 3.4b compiles cleanly, used for this object file.
  84.  *
  85.  * Original LUCAS comments (for most part) removed, see the FISH
  86.  * disk with original speechtoy to see what was there before.
  87.  * File got up over 65k source when I was through with it.
  88.  *
  89.  * Enhancements needed:  Add capability to input PHONETIC strings.
  90.  *                       Strip it down into just a speech server
  91.  *                       with no windowing interface, but still read
  92.  *                       the icon file for the defaults.
  93.  */
  94.  
  95. /* Written by David M Lucas. */
  96. /* Enhanced by Rob Peck */
  97.  
  98. /* If you find somthing you don't like, fix it! Have fun! */
  99. /* Send complaints to /dev/null. really. */
  100. /* Thanks Amiga. */
  101.  
  102. #include "exec/types.h"
  103. #include "exec/exec.h"
  104. #include "intuition/intuition.h"
  105. #include "intuition/intuitionbase.h"
  106. #include "devices/narrator.h"
  107. #include "libraries/translator.h"
  108. #include "exec/memory.h"
  109. #include "libraries/dosextens.h"
  110. #include "workbench/workbench.h"
  111. #include "workbench/icon.h"
  112. #include "workbench/startup.h"
  113.  
  114. #undef LIBRARY_VERSION
  115. #undef LIBRARY_VERSION
  116. #define LIBRARY_VERSION 0
  117.  
  118. /* forward declarations and external functions */
  119.  
  120. extern struct Library *OpenLibrary();
  121. extern APTR AllocMem();
  122. extern struct FileLock *CurrentDir();
  123. extern struct DiskObject *GetDiskObject();
  124. extern struct Task *FindTask();
  125. extern struct Message *GetMsg();
  126. extern long   WriteIcon();
  127. extern struct Window *OpenWindow();
  128. extern void Delay();
  129.  
  130. char **toolsave;    /* place to save the old pointer */
  131. char *toolstrings[7];   /* a new set of toolstrings to use for writing */
  132.  
  133. struct MyDefaults {
  134.     int freq; int rate; int pitch;
  135.     int vol;  int sex;  int mode;
  136. };
  137.  
  138. long speakdone;        /* if TRUE, (nonzero), voice_io is back */
  139.  
  140. struct MyDefaults Defaults;
  141.  
  142. struct Library *IconBase;
  143. extern struct DiskObject *ReadInfoFile();
  144. void menumessage();
  145. void gadgetmessage();
  146. void DrawFace();
  147. void freeimages();
  148.  
  149. /* #define DEBUG */
  150.  
  151. #define CONTWINDW 321
  152. #define CONTWINDH 123
  153. #define FACEWINDW 32
  154. #define FACEWINDH 44
  155.  
  156. /* Pen numbers to draw gadget borders/images/text with */
  157. #define REDP   3
  158. #define BLKP   2
  159. #define WHTP   1
  160. #define BLUP   0
  161.  
  162. /* the length of the English and phonetic buffers */
  163. #define ESTRINGSIZE 512
  164. #define PSTRINGSIZE 768 /* phonemes are longer than english */
  165.  
  166. #define NUMPROPS 4
  167.  
  168. /* Ranges of proportional data */
  169. #define RNGFREQ  (MAXFREQ  - MINFREQ)  +1
  170. #define RNGRATE  (MAXRATE  - MINRATE)  +1
  171. #define RNGPITCH (MAXPITCH - MINPITCH) +1
  172. #define RNGVOL   (MAXVOL   - MINVOL)   +1
  173.  
  174. #define DEFFREQ2    Defaults.freq
  175. #define DEFRATE2    Defaults.rate
  176. #define DEFPITCH2   Defaults.pitch
  177. #define DEFVOL2     Defaults.vol
  178. #define DEFSEX2     Defaults.sex
  179. #define DEFMODE2    Defaults.mode
  180.  
  181.  
  182. /* This section is part of the AREXX distribution disk,
  183.  * Copyright 1987, 1988 W. Hawes, reprinted by permission.
  184.  */
  185.  
  186. /* This structure is used for passing arguments to external programs.
  187.  * It is usually passed as an "argstring", a pointer to the string buffer.
  188.  */
  189. struct RexxArg {
  190.    LONG     ra_Size;    /* total allocated length        */
  191.    UWORD    ra_Length;  /* length of string              */
  192.    UBYTE    ra_Flags;   /* attribute flags               */
  193.    UBYTE    ra_Hash;    /* hash code                     */
  194.    BYTE     ra_Buff[8]; /* buffer area                   */
  195.    };                   /* size: 16 bytes (minimum)      */
  196.  
  197. /* The RexxMsg structure is used for all communications with Rexx programs.
  198.  * It is an EXEC message with a parameter block appended.
  199.  */
  200.  
  201. struct RexxMsg {
  202.    struct Message rm_Node;  /* EXEC message structure        */
  203.    APTR     rm_TaskBlock;   /* pointer to global structure   */
  204.    APTR     rm_LibBase;     /* library base                  */
  205.    LONG     rm_Action;      /* command (action) code         */
  206.    LONG     rm_Result1;     /* primary result (return code)  */
  207.    LONG     rm_Result2;     /* secondary result              */
  208.    STRPTR   rm_Args[16];    /* argument block (ARG0-ARG15)   */
  209.  
  210.    struct MsgPort *rm_PassPort; /* forwarding port               */
  211.    STRPTR   rm_CommAddr;        /* host address (port name)      */
  212.    STRPTR   rm_FileExt;         /* file extension                */
  213.    LONG     rm_Stdin;           /* input stream (filehandle)     */
  214.    LONG     rm_Stdout;          /* output stream (filehandle)    */
  215.    LONG     rm_avail;           /* future expansion              */
  216.    };                           /* size: 128 bytes               */
  217. /* end of selected portion of rexx/storage.h */
  218.  
  219. /* This is a dummy array, identical in form to the toolstrings array.
  220.  * Only one pointer (the first one) gets initialized to point to
  221.  * the argstring for the command that is transmitted by AREXX.
  222.  * The second pointer is NULL, ending what looks like a toolstrings
  223.  * array.  This way we can use a single routine to obey both icon
  224.  * toolstring commands and AREXX commands.
  225.  */
  226.  
  227. char *rexxstrings[2];
  228.  
  229. struct DiskObject *diskobj;
  230.  
  231. struct TextAttr TestFont = /* Needed for opening screen */
  232.    {
  233.    (STRPTR)"topaz.font",
  234.    TOPAZ_EIGHTY, 0, 0
  235.    };
  236.  
  237. /* Which audio channels to use */
  238. UBYTE audio_chan[] = {3, 5, 10, 12};
  239. /* Pointer to translator library vectors */
  240. struct Library *TranslatorBase = 0;
  241. struct MsgPort talk_port; /* Message port for the say's I/O  */
  242. struct MsgPort read_port; /* Message port for the say's I/O  */
  243.  
  244.  
  245. struct MsgPort *rexxport, *CreatePort();  /* added by RAP */
  246.  
  247.  
  248. struct mouth_rb mouth_io;  /* IO Request block, mouth flavor */
  249. /* IO Request block, narrator flavor */
  250. struct narrator_rb voice_io;
  251. /* indicative of the Open return */
  252. UBYTE NarratorOpenError = -1;        /* not yet opened */
  253. /* indicative of a Translations success */
  254. UBYTE TranslatorError = 0;
  255. USHORT i;
  256.  
  257. /* These are used to draw the eyes and mouth size relative */
  258. USHORT MouthWMult;
  259. USHORT EyesLeft;
  260. USHORT MouthHMult;
  261. USHORT EyesTop;
  262. USHORT EyesBottom;
  263. USHORT YMouthCenter;  /* Pixels from top edge */
  264. USHORT XMouthCenter;  /* Pixels from left edge */
  265. USHORT yaw;
  266. USHORT LipWidth, LipHeight;
  267.  
  268. /* String Gadgets */
  269.  
  270. USHORT StrVectors[] = {
  271.    0, 0,   297, 0,   297, 14,   0, 14,
  272.    0, 1,   296, 1,   296, 13,   1, 13,
  273.    1, 1
  274. };
  275. struct Border StrBorder = {
  276.    -4, -3,           
  277.    WHTP, BLUP, JAM1,
  278.    9,               
  279.    StrVectors,
  280.    NULL
  281. };
  282.  
  283. /* The same undo buffer is used for both string gadgets,
  284.  * this is sized to largest so that largest fits.
  285.  */
  286. UBYTE UndoBuffer[PSTRINGSIZE];
  287.  
  288. /* default text */
  289. UBYTE EnglBuffer[ESTRINGSIZE] = "This is amiga speaking.";
  290. struct StringInfo EnglInfo = {
  291.    EnglBuffer,
  292.    UndoBuffer,
  293.    0,         
  294.    ESTRINGSIZE,
  295.    0, 0,
  296.    24,
  297.    0, 0, 0,
  298.    NULL,
  299.    0,
  300.    NULL
  301. };
  302. struct IntuiText EnglText = {
  303.    WHTP, BLUP,
  304.    JAM1,
  305.    0, -13,
  306.    &TestFont,
  307.    "English:",
  308.    NULL
  309. };
  310. struct Gadget EnglStrGadget = {
  311.    NULL,
  312.    11, 63, 290, 10,
  313.    GADGHCOMP,
  314.    RELVERIFY,
  315.    STRGADGET,
  316.    (APTR)&StrBorder,
  317.    NULL,
  318.    &EnglText,
  319.    0,
  320.    (APTR)&EnglInfo,
  321.    0,
  322.    NULL
  323. };
  324.  
  325. /* Phonetic string gadget is where the program puts the
  326.  * translated string, necessating a call to RefreshGadgets(),
  327.  * and is where the user can type in Phonemes.
  328.  */
  329. UBYTE PhonBuffer[PSTRINGSIZE] =
  330.   "DHIHS IHZ AHMIY3GAH SPIY4KIHNX.";
  331. struct StringInfo PhonInfo = {
  332.    PhonBuffer,
  333.    UndoBuffer,
  334.    0,
  335.    PSTRINGSIZE,
  336.    0, 0,
  337.    32,
  338.    0, 0, 0,
  339.    NULL,
  340.    NULL,
  341.    NULL
  342. };
  343. struct IntuiText PhonText = {
  344.    WHTP, BLUP,
  345.    JAM1,
  346.    0, -13,
  347.    &TestFont,
  348.    "Phonetics:",
  349.    NULL
  350. };
  351. struct Gadget PhonStrGadget = {
  352.    &EnglStrGadget,
  353.    11, 94, 290, 10,
  354.    GADGHCOMP,
  355.    RELVERIFY,
  356.    STRGADGET,
  357.    (APTR)&StrBorder,
  358.    NULL,
  359.    &PhonText,
  360.    0,
  361.    (APTR)&PhonInfo,
  362.    0,
  363.    NULL
  364. };
  365. /* Female Toggle (Highlight Image)
  366.    (Quasi mutual exclude with Male Toggle) */
  367. struct Image FemaleImage = {
  368.    0, 0,
  369.    20, 10, 1,
  370.    NULL,
  371.    0x1, 0x0
  372. };
  373. struct Gadget FemaleGadget = {
  374.    &PhonStrGadget,
  375.    134, 34, 20, 10,
  376.    GADGIMAGE | GADGHCOMP,
  377.    /* Activation flags */
  378.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  379.    BOOLGADGET,
  380.    (APTR)&FemaleImage,
  381.    NULL,
  382.    NULL,
  383.    0,
  384.    NULL,
  385.    0,
  386.    NULL
  387. };
  388.  
  389. /* Male Toggle (Highlight Image)
  390.    (Quasi mutual Exclude with above) */
  391. struct Image MaleImage = {
  392.    0, 0,
  393.    20, 10, 1,
  394.    NULL,
  395.    0x1, 0x0
  396. };
  397. struct Gadget MaleGadget = {
  398.    &FemaleGadget,
  399.    154, 34, 20, 10,
  400.    GADGIMAGE | GADGHCOMP | SELECTED,
  401.    /* Activation flags */
  402.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT | ACTIVATE,
  403.    BOOLGADGET,
  404.    (APTR)&MaleImage,
  405.    NULL,
  406.    NULL,
  407.    0,
  408.    NULL,
  409.    0,
  410.    NULL
  411. };
  412.  
  413. /* This boolean toggle gadget has an
  414.  * alternate image that indicates
  415.  * selection. The image stays flipped
  416.  * until it gets another hit. (it toggles)
  417.  */
  418. /* Inflection Mode Toggle (AltImage) *************************/
  419. struct Image HumanImage = {
  420.    0, 0,
  421.    40, 20, 1,
  422.    NULL,
  423.    0x1, 0x0
  424. };
  425. struct Image RobotImage = {
  426.    0, 0,
  427.    40, 20, 1,
  428.    NULL,
  429.    0x1, 0x0
  430. };
  431. struct Gadget ModeGadget = {
  432.    &MaleGadget,
  433.    134, 2, 40, 20,
  434.    GADGIMAGE | GADGHIMAGE,
  435.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  436.    BOOLGADGET,
  437.    (APTR)&HumanImage,
  438.    (APTR)&RobotImage,
  439.    NULL,
  440.    0,
  441.    NULL,
  442.    0,
  443.    NULL
  444. };
  445.  
  446. /* Face Toggle (image and text) */
  447. struct IntuiText FaceIText = {
  448.    WHTP, BLUP,
  449.    JAM2,
  450.    4, 1,
  451.    &TestFont,
  452.    "Face",
  453.    NULL
  454. };
  455. struct Image FaceImage = {
  456.    0, 0,
  457.    40, 10, 1,
  458.    NULL,
  459.    0x1, 0x0
  460. };
  461. struct Gadget FaceGadget = {
  462.    &ModeGadget,
  463.    134, 23, 40, 10,
  464.    GADGIMAGE | GADGHCOMP,
  465.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  466.    BOOLGADGET,
  467.    (APTR) &FaceImage,
  468.    NULL,
  469.    &FaceIText,
  470.    0,
  471.    NULL,
  472.    0,
  473.    NULL
  474. };
  475.  
  476. /* Stop Hit (image and text) */
  477. struct IntuiText StopIText = {
  478.    WHTP, BLUP,
  479.    JAM2,
  480.    4, 1,
  481.    &TestFont,
  482.    "Stop",
  483.    NULL
  484. };
  485. struct Image StopImage = {
  486.    0, 0,
  487.    40, 10, 1,
  488.    NULL,
  489.    0x1, 0x0
  490. };
  491. struct Gadget StopGadget = {
  492.    &FaceGadget,
  493.    134, 45, 40, 10,
  494.    GADGIMAGE | GADGHCOMP,
  495.    RELVERIFY | GADGIMMEDIATE,
  496.    BOOLGADGET,
  497.    (APTR) &StopImage,
  498.    NULL,
  499.    &StopIText,
  500.    0,
  501.    NULL,
  502.    0,
  503.    NULL
  504. };
  505.  
  506. /* This is a hit (as opposed to toggle)
  507.    gadget that starts the translation.*/
  508. /* Translate Hit (Highlight image) */
  509. USHORT TransVectors[] = {
  510.    0, 0,    79, 0,    79, 13,   0, 13,
  511.    0, 1,    78, 1,    78, 12,   1, 12,
  512.    1, 1
  513. };
  514. struct Border TransBorder = {
  515.    -4, -3,
  516.    WHTP, BLUP, JAM1,
  517.    9,
  518.    TransVectors,
  519.    NULL
  520. };
  521. struct IntuiText TranslateIText = {
  522.    WHTP, BLUP,
  523.    JAM2,
  524.    0, 0,
  525.    &TestFont,
  526.    "Translate",
  527.    NULL
  528. };
  529. struct Gadget TranslateGadget = {
  530.    &StopGadget,
  531.    229, 48, 71, 8,
  532.    GADGHCOMP,
  533.    RELVERIFY | GADGIMMEDIATE,
  534.    BOOLGADGET,
  535.    (APTR)&TransBorder,
  536.    NULL,
  537.    &TranslateIText,
  538.    0,
  539.    NULL,
  540.    0,
  541.    NULL
  542. };
  543.  
  544. /* This is a hit (as opposed to toggle) Starts the narration */
  545. /* Speak Hit (Highlight Image) */
  546. USHORT SpeakVectors[] = {
  547.    0, 0,    47, 0,    47, 13,   0, 13,
  548.    0, 1,    46, 1,    46, 12,   1, 12,
  549.    1, 1
  550. };
  551. struct Border SpeakBorder = {
  552.    -4, -3,
  553.    WHTP, BLUP, JAM1,
  554.    9,
  555.    SpeakVectors,
  556.    NULL
  557. };
  558. struct IntuiText SpeakIText = {
  559.    WHTP, BLUP,
  560.    JAM2,
  561.    0, 0,
  562.    &TestFont,
  563.    "Speak",
  564.    NULL
  565. };
  566. struct Gadget SpeakGadget = {
  567.    &TranslateGadget,
  568.    261, 79, 40, 8,
  569.    GADGHCOMP,
  570.    RELVERIFY | GADGIMMEDIATE,
  571.    BOOLGADGET,
  572.    (APTR)&SpeakBorder,
  573.    NULL,
  574.    &SpeakIText,
  575.    0,
  576.    NULL,
  577.    0,
  578.    NULL
  579. };
  580.  
  581. /* Now the proportional gadgets. */
  582. /* Proportional Gadgets **************************************/
  583. /* The following variables are used to create proportional
  584.  * Gadgets. These variables will be filled in with copies of
  585.  * the generic Gadgetry below.
  586.  */
  587. SHORT PropCount = 0;       /* index to next available Gadget */
  588. struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */
  589. /* dummy AUTOKNOB Images are required */
  590. struct Image PImages[NUMPROPS];
  591. /* These get copies of TPropInfo */
  592. struct PropInfo PInfos[NUMPROPS];
  593. /* These get copies of TPropGadget */
  594. struct Gadget Props[NUMPROPS];
  595. struct IntuiText TPropText = {
  596.    WHTP, BLUP,
  597.    JAM1,
  598.    0, -10,
  599.    &TestFont,
  600.    NULL,
  601.    NULL
  602. };   
  603. struct PropInfo TPropInfo = {
  604.    AUTOKNOB | FREEHORIZ,
  605.    0, 0,
  606.    0x1FFF, 0x1FFF,
  607.    0, 0, 0, 0, 0, 0
  608. };
  609. /* this is the template for the Gadget of a horizontal */
  610. /* Proportional Gadget */
  611. struct Gadget TPropGadget = {
  612.    &SpeakGadget,
  613.    7, 12, 115, 10,
  614.    GADGHCOMP | GADGIMAGE,
  615.    GADGIMMEDIATE | RELVERIFY,
  616.    PROPGADGET,
  617.    NULL,
  618.    NULL,
  619.    NULL,
  620.    0,
  621.    NULL,
  622.    0,
  623.    NULL
  624. };
  625.  
  626. struct IntuitionBase *IntuitionBase = 0;
  627. struct GfxBase *GfxBase = 0;
  628.  
  629. /* Only one menu. */
  630.  
  631. ULONG MenuNumber;
  632. ULONG TheMenu;
  633. ULONG TheItem;
  634.  
  635. struct IntuiText MenuItemText = {
  636.    BLUP,
  637.    WHTP,
  638.    JAM2,
  639.    0,
  640.    0,
  641.    &TestFont,
  642.    "About SpeechToy...",
  643.    NULL
  644. };
  645. struct IntuiText MenuItemText2 = {
  646.    BLUP,
  647.    WHTP,
  648.    JAM2,
  649.    0,
  650.    0,
  651.    &TestFont,
  652.    "Save Current Speech Settings",
  653.    NULL
  654. };
  655.  
  656. struct MenuItem MyMenuItem2 = {
  657.    NULL,
  658.    0,
  659.    10,
  660.    250,
  661.    8,
  662.    ITEMTEXT | ITEMENABLED | HIGHCOMP,
  663.    0,
  664.    (APTR)&MenuItemText2,
  665.    NULL,
  666.    NULL,
  667.    NULL,
  668.    MENUNULL
  669. };
  670. struct MenuItem MyMenuItem = {
  671.    &MyMenuItem2,
  672.    0,
  673.    0,
  674.    250,
  675.    8,
  676.    ITEMTEXT | ITEMENABLED | HIGHCOMP,
  677.    0,
  678.    (APTR)&MenuItemText,
  679.    NULL,
  680.    NULL,
  681.    NULL,
  682.    MENUNULL
  683. };
  684.  
  685. struct Menu MyMenu = {
  686.    NULL,
  687.    0,0,150,0,
  688.    MENUENABLED,
  689.    "SpeechToy Menu",
  690.    &MyMenuItem
  691. };
  692.  
  693. struct IntuiText ReqText1 = {
  694.    BLUP,
  695.    WHTP,
  696.    JAM2,
  697.    5,
  698.    23,
  699.    &TestFont,
  700.    "Version 1.2  15 Apr, 1988",
  701.    NULL
  702. };
  703. struct IntuiText ReqText2 = {
  704.    BLUP,
  705.    WHTP,
  706.    JAM2,
  707.    5,
  708.    13,
  709.    &TestFont,
  710.    "Written by David M Lucas ",
  711.    &ReqText1
  712. };
  713. struct IntuiText ReqText3 = {
  714.    BLUP,
  715.    WHTP,
  716.    JAM2,
  717.    5,
  718.    3,
  719.    &TestFont,
  720.    "Enhancements by Rob Peck",
  721.    &ReqText2
  722. };
  723.  
  724. struct IntuiText OKIText = {
  725.    BLUP, WHTP,
  726.    JAM2,
  727.    6, 3,
  728.    &TestFont,
  729.    "OK",
  730.    NULL
  731. };
  732.  
  733. struct Requester *AboutRequester;
  734.  
  735. USHORT autoret;
  736. struct Window *ControlWindow = NULL;
  737. struct Window *FaceWindow = NULL;
  738. struct IntuiMessage *MyIntuiMessage;
  739. struct NewWindow NewControlWindow = {
  740.    00, 11,
  741.    CONTWINDW, CONTWINDH,
  742.    -1, -1,
  743.    GADGETUP | CLOSEWINDOW | MENUPICK,
  744.    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
  745.    | GIMMEZEROZERO | ACTIVATE,
  746.    &Props[NUMPROPS-1],
  747.    NULL,
  748.    (UBYTE *)"SpeechToy",
  749.    NULL,
  750.    NULL,
  751.    20, 20,
  752.    CONTWINDW, CONTWINDH,
  753.    WBENCHSCREEN
  754. };
  755.  
  756. struct NewWindow NewFaceWindow = {
  757.    CONTWINDW, 11,
  758.    FACEWINDW * 2, FACEWINDH,
  759.    -1, -1,
  760.    SIZEVERIFY | NEWSIZE | MENUPICK,
  761.    /* Flags (can be NULL) */
  762.    WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING
  763.     | SIZEBBOTTOM | GIMMEZEROZERO | ACTIVATE,
  764.    NULL,
  765.    NULL,
  766.    (UBYTE *)"Face",
  767.    NULL,
  768.    NULL,
  769.    FACEWINDW, FACEWINDH,
  770.    640, 200,
  771.    WBENCHSCREEN
  772. };
  773.  
  774. USHORT FemaleIData[] = {
  775. /*   ----    -  These nibbles matter to image. */
  776.    0x0000, 0x0000,
  777.    0x00F0, 0x0000,
  778.    0x0198, 0x0000,
  779.    0x030C, 0x0000,
  780.    0x0198, 0x0000,
  781.    0x00F0, 0x0000,
  782.    0x0060, 0x0000,
  783.    0x01F8, 0x0000,
  784.    0x0060, 0x0000,
  785.    0x0000, 0x0000
  786. };
  787.  
  788. USHORT MaleIData[] = {
  789. /*   ----    -   These nibbles matter to image. */
  790.    0x0000, 0x0000,
  791.    0x003E, 0x0000,
  792.    0x000E, 0x0000,
  793.    0x0036, 0x0000,
  794.    0x01E0, 0x0000,
  795.    0x0330, 0x0000,
  796.    0x0618, 0x0000,
  797.    0x0330, 0x0000,
  798.    0x01E0, 0x0000,
  799.    0x0000, 0x0000
  800. };
  801. USHORT HumanIData[] = {
  802. /*   ----   ----   --   These nibbles matter to image. */
  803.    0x0000,0x0000,0x0000,
  804.    0x0000,0x0000,0x0000,
  805.    0x0000,0x0000,0x0000,
  806.    0x0000,0x0000,0x0000,
  807.    0x0007,0x9E00,0x0000,
  808.    0x0001,0x8600,0x0000,
  809.    0x0000,0x0000,0x0000,
  810.    0x0000,0x0000,0x0000,
  811.    0x0000,0x2000,0x0000,
  812.    0x0000,0x1000,0x0000,
  813.    0x0000,0x0800,0x0000,
  814.    0x0000,0x7C00,0x0000,
  815.    0x0000,0x0000,0x0000,
  816.    0x0000,0x0000,0x0000,
  817.    0x0000,0x0000,0x0000,
  818.    0x0000,0x7800,0x0000,
  819.    0x0000,0x0000,0x0000,
  820.    0x0000,0x0000,0x0000,
  821.    0x0000,0x0000,0x0000,
  822.    0x0000,0x0000,0x0000
  823. };
  824. USHORT RobotIData[] = {
  825. /*   ----   ----   --   These nibbles matter to image. */
  826.    0x0000,0x0000,0x0000,
  827.    0x0000,0x0000,0x0000,
  828.    0x0000,0x0000,0x0000,
  829.    0x0000,0x0000,0x0000,
  830.    0x0007,0x9E00,0x0000,
  831.    0x0004,0x9200,0x0000,
  832.    0x0007,0x9E00,0x0000,
  833.    0x0000,0x0000,0x0000,
  834.    0x0000,0x0000,0x0000,
  835.    0x0000,0x0000,0x0000,
  836.    0x0000,0x0000,0x0000,
  837.    0x0000,0x0000,0x0000,
  838.    0x0000,0x0000,0x0000,
  839.    0x0001,0xF800,0x0000,
  840.    0x0001,0x0800,0x0000,
  841.    0x0001,0xF800,0x0000,
  842.    0x0000,0x0000,0x0000,
  843.    0x0000,0x0000,0x0000,
  844.    0x0000,0x0000,0x0000,
  845.    0x0000,0x0000,0x0000
  846. };
  847. USHORT FaceIData[] = {
  848. /*   ----   ----   --   These nibbles matter to image. */
  849.    0x0000,0x0000,0x0000,
  850.    0x0000,0x0000,0x0000,
  851.    0x0000,0x0000,0x0000,
  852.    0x0000,0x0000,0x0000,
  853.    0x0000,0x0000,0x0000,
  854.    0x0000,0x0000,0x0000,
  855.    0x0000,0x0000,0x0000,
  856.    0x0000,0x0000,0x0000,
  857.    0x0000,0x0000,0x0000,
  858.    0x0000,0x0000,0x0000
  859. };
  860. USHORT StopIData[] = {
  861. /*   ----   ----   --   These nibbles matter to image. */
  862.    0x0000,0x0000,0x0000,
  863.    0x0000,0x0000,0x0000,
  864.    0x0000,0x0000,0x0000,
  865.    0x0000,0x0000,0x0000,
  866.    0x0000,0x0000,0x0000,
  867.    0x0000,0x0000,0x0000,
  868.    0x0000,0x0000,0x0000,
  869.    0x0000,0x0000,0x0000,
  870.    0x0000,0x0000,0x0000,
  871.    0x0000,0x0000,0x0000
  872. };
  873. USHORT *FemaleIData_chip = 0;
  874. USHORT *MaleIData_chip = 0;
  875. USHORT *HumanIData_chip = 0;
  876. USHORT *RobotIData_chip = 0;
  877. USHORT *FaceIData_chip = 0;
  878. USHORT *StopIData_chip = 0;
  879.  
  880. LONG foundicon = FALSE;        /* status variable */
  881. LONG clistart = FALSE;        /* status variable */
  882.  
  883. extern struct WBStartup *WBenchMsg;
  884. char *iconname;
  885. BPTR  testlock, iconlock;
  886. char namebuff[256];    /* where to store icon name if start from CLI */
  887. char dirbuff[256];    /* store icon directory name if started from CLI */
  888. ULONG parseresult;    /* what happened when we parsed the strings */
  889. ULONG ParseStrings();
  890. void ParseRexxStrings();
  891. void SetValues();
  892. ULONG GetDefaults();
  893. struct RexxMsg *myrexmsg;
  894.  
  895.  
  896. /** start of code ***************************/
  897.  
  898. void
  899. ModGadget(g)
  900. struct Gadget *g;
  901. {
  902.     USHORT i;
  903.     i = RemoveGadget(ControlWindow, g);
  904.     if(g == &ModeGadget)
  905.         ModeGadget.Flags ^= SELECTED;
  906.     if(g == &MaleGadget)
  907.         MaleGadget.Flags ^= SELECTED;
  908.     if(g == &FemaleGadget)
  909.         FemaleGadget.Flags ^= SELECTED;
  910.     AddGadget(ControlWindow, g, i);
  911.     RefreshGadgets(g, ControlWindow, NULL);    
  912. }
  913.  
  914.  
  915.  
  916. #define IssueTranslate()  gadgetmessage(&TranslateGadget,ControlWindow)
  917. #define IssueSpeak()      gadgetmessage(&SpeakGadget,ControlWindow)
  918.  
  919. void
  920. InitVoiceValues()
  921. {
  922.    voice_io.sex      = DEFSEX2;
  923.    voice_io.mode     = DEFMODE2;
  924.    voice_io.rate     = DEFRATE2;
  925.    voice_io.pitch    = DEFPITCH2;
  926.    voice_io.volume   = DEFVOL2;
  927.    voice_io.sampfreq = DEFFREQ2;
  928. }
  929.  
  930. void
  931. main(argc, argv)
  932. int argc;
  933. char **argv;
  934. {
  935.    struct WBArg *wbarg;    
  936.    USHORT i;
  937.  
  938.    ULONG Signals;        /* Wait() tells me which to look at */
  939.    ULONG MIClass;        /* Save quickly, ReplyMsg() asap */
  940.    USHORT MICode;        /* These hold my needed information */
  941.    APTR MIAddress;
  942.  
  943.    iconlock = NULL;
  944.    iconname = NULL;
  945.    speakdone = TRUE;    /* no speech started yet, so it MUST be done. */
  946.  
  947.    clistart = FALSE;
  948.    if(argc != 0) clistart = TRUE;
  949.  
  950.    /* let MyCleanup know these signals not allocated yet */
  951.    talk_port.mp_SigBit = -1;
  952.    read_port.mp_SigBit = -1;
  953.  
  954.    /* Open those libraries that the program uses directly */
  955.    if ((IntuitionBase = (struct IntuitionBase *)
  956.     OpenLibrary("intuition.library", LIBRARY_VERSION)) == 0) {
  957. #ifdef DEBUG
  958.    if(clistart)
  959.       printf("Can't open the intuition library\n");
  960. #endif
  961.       MyCleanup(1);
  962.       exit(FALSE);
  963.    }
  964.  
  965.    if ((GfxBase = (struct GfxBase *)
  966.     OpenLibrary("graphics.library", LIBRARY_VERSION)) == 0) {
  967. #ifdef DEBUG
  968.    if(clistart)
  969.       printf("Can't open the graphics library\n");
  970. #endif
  971.       MyCleanup(2);
  972.       exit(FALSE);
  973.    }
  974.  
  975.    if ((TranslatorBase = (struct Library *)
  976.     OpenLibrary("translator.library", LIBRARY_VERSION)) == 0) {
  977. #ifdef DEBUG
  978.    if(clistart)
  979.       printf("Can't open the translator library\n");
  980. #endif
  981.       MyCleanup(3);
  982.       exit(FALSE);
  983.    }
  984.  
  985.    if ((IconBase = (struct Library *)
  986.     OpenLibrary("icon.library", 1)) == 0) {
  987. #ifdef DEBUG
  988.    if(clistart)
  989.       printf("Can't open the icon library\n");
  990. #endif
  991.       MyCleanup(4);
  992.       exit(FALSE);
  993.    }
  994.  
  995.    /* Open the device */
  996.    if ((NarratorOpenError = OpenDevice("narrator.device", 0,
  997.     &voice_io, 0)) != 0) {
  998. #ifdef DEBUG
  999.    if(clistart)
  1000.       printf("Can't open the narrator device\n");
  1001. #endif
  1002.       MyCleanup(5);
  1003.       exit(FALSE);
  1004.    }
  1005.  
  1006.    /* **RAP */
  1007.  
  1008.    if(argc == 0)    /* opened from Workbench!!, Good! */
  1009.    {
  1010.     wbarg    = WBenchMsg->sm_ArgList;
  1011.     iconlock = wbarg->wa_Lock;
  1012.     iconname = wbarg->wa_Name;
  1013.     clistart = FALSE;
  1014.    }
  1015.    else        /* open from CLI, see if currentdir has icon */
  1016.    {
  1017.     clistart = TRUE;
  1018.  
  1019.     namebuff[0] = '\0';
  1020.     strcat(namebuff, argv[0]);
  1021.     strcat(namebuff, ".info");
  1022.  
  1023.     /* Look in the CURRENT directory to see if file is there */
  1024.  
  1025.     testlock = Lock(namebuff, ACCESS_READ);
  1026.  
  1027.     /* To see if the icon file exists, we have to put .info
  1028.      * onto the name of the file itself.  BUT,
  1029.      * when we read the icon, we do it without '.info' on it */
  1030.  
  1031.     if(testlock == NULL)
  1032.     {
  1033.         /* the icon file is not in the CURRENT dir. */
  1034.         iconlock = NULL;
  1035.         iconname = NULL;
  1036.     
  1037.         /* Now see if the user specified a directory
  1038.          * in which the icon IS located; passed as argv[1] */
  1039.  
  1040.         if(argc == 2)
  1041.         {
  1042.         dirbuff[0] = '\0';
  1043.         strcat(dirbuff, argv[1]);
  1044.         iconlock = Lock(dirbuff, ACCESS_READ);
  1045.  
  1046.         /* If THAT directory exists, will pass it
  1047.          * as a parameter IF we can also find that
  1048.          * the icon is really there.  More than one
  1049.          * way to do this - could lock directory,
  1050.          * go in there, then search for the file.
  1051.          * Instead I chose to build directory path
  1052.          * then try to lock the file.  Same difference.
  1053.          */
  1054.         if(iconlock != NULL)   /* directory exists */
  1055.  
  1056.             /* actually, this could be a 
  1057.              * file instead of a directory
  1058.              * but who cares. */
  1059.         {
  1060.            namebuff[0] = '\0';
  1061.            strcat(namebuff, argv[1]);
  1062.            if(namebuff[strlen(argv[1])-1] != ':')
  1063.             strcat(namebuff,"/");
  1064.            strcat(namebuff, argv[0]);
  1065.  
  1066.            /* This makes a complete path name to the icon */
  1067.  
  1068.        /* WARNING - reusing variable named testlock here */
  1069.  
  1070.            testlock = Lock(namebuff, ACCESS_READ);
  1071.            if(testlock != NULL)
  1072.            {
  1073.             /* OK, the icon exists, lets hand it over 
  1074.              * (without the .info attached to it)
  1075.              */
  1076.             namebuff[0] = '\0';
  1077.             strcat(namebuff, argv[0]);
  1078.             iconname = namebuff;
  1079.             UnLock(testlock);
  1080.            } /* end of if testlock (inner) */
  1081.         }    /* end of if iconlock  */
  1082.         }         /* end of if argc == 2 */
  1083.     }         /* end of if testlock (outer) */
  1084.     else         /* else associated with if testlock (outer) */
  1085.     {
  1086.         /* testlock (first try) was non-NULL, icon IS in current dir */
  1087.  
  1088.         /* OK, the icon exists in the current dir;
  1089.          * lets hand it over 
  1090.          * (without the .info attached to it)
  1091.          */
  1092.         namebuff[0] = '\0';
  1093.         strcat(namebuff, argv[0]);
  1094.         iconname = namebuff;
  1095.         UnLock(testlock);
  1096.  
  1097.             /* pass a lock on CURRENT dir. */
  1098.  
  1099.         iconlock = Lock("",ACCESS_READ); 
  1100.     }   /* end of else */
  1101.    }        /* end of else from test argc == 0 */
  1102.  
  1103.    parseresult = GetDefaults(iconlock,iconname);
  1104.  
  1105.    if(parseresult == FALSE)   
  1106.         /* added - read the icon toolstrings */
  1107.    {
  1108.     MyCleanup(6);
  1109.     exit(FALSE);
  1110.    }
  1111. #ifdef DEBUG
  1112.    if(clistart)
  1113.       printf("Got past getting the defaults\n");
  1114. #endif
  1115.  
  1116.    /* This is where the proportional gadgets are set up, using
  1117.     * the templates that were declared staticly.
  1118.     */
  1119.    for(PropCount = 0; PropCount < NUMPROPS; PropCount++) {
  1120.       PTexts[PropCount] = TPropText;
  1121.       Props[PropCount] = TPropGadget;
  1122.       PInfos[PropCount] = TPropInfo;
  1123.       Props[PropCount].GadgetText = (struct IntuiText *)
  1124.        &PTexts[PropCount];
  1125.       Props[PropCount].GadgetRender = (APTR)
  1126.        &PImages[PropCount];
  1127.       Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount];
  1128.       switch (PropCount) {
  1129.       case 0:
  1130.          PTexts[PropCount].IText = "Sample Freq:";
  1131.          if (DEFFREQ2 == MAXFREQ)
  1132.             PInfos[PropCount].HorizPot = 65535;
  1133.          else
  1134.             PInfos[PropCount].HorizPot = ((DEFFREQ2 - MINFREQ)
  1135.              << 16) / (MAXFREQ - MINFREQ);
  1136.          break;
  1137.       case 1:
  1138.          PTexts[PropCount].IText = "Rate:";
  1139.          Props[PropCount].TopEdge += 22;
  1140.          Props[PropCount].NextGadget = &Props[PropCount-1];
  1141.          if (DEFRATE2 == MAXRATE)
  1142.             PInfos[PropCount].HorizPot = 65535;
  1143.          else
  1144.             PInfos[PropCount].HorizPot = ((DEFRATE2 - MINRATE)
  1145.              << 16) / (MAXRATE - MINRATE);
  1146.          break;
  1147.       case 2:
  1148.          PTexts[PropCount].IText = "Pitch:";
  1149.          Props[PropCount].LeftEdge += 183;
  1150.          Props[PropCount].NextGadget = &Props[PropCount-1];
  1151.          if (DEFPITCH2 == MAXPITCH)
  1152.             PInfos[PropCount].HorizPot = 65535;
  1153.          else
  1154.             PInfos[PropCount].HorizPot = ((DEFPITCH2-MINPITCH)
  1155.              << 16) / (MAXPITCH - MINPITCH);
  1156.          break;
  1157.       case 3:
  1158.          PTexts[PropCount].IText = "Volume:";
  1159.          Props[PropCount].TopEdge += 22;
  1160.          Props[PropCount].LeftEdge += 183;
  1161.          Props[PropCount].NextGadget = &Props[PropCount-1];
  1162.          if (DEFVOL2 == MAXVOL)
  1163.             PInfos[PropCount].HorizPot = 65535;
  1164.          else
  1165.             PInfos[PropCount].HorizPot = ((DEFVOL2 - MINVOL)
  1166.              << 16) / (MAXVOL - MINVOL);
  1167.          break;
  1168.       }
  1169.    }
  1170.  
  1171.    /* Now allocate memory accessable by the chips for images */
  1172.    if (InitImages() != TRUE) {
  1173. #ifdef DEBUG
  1174.    if(clistart)
  1175.       printf("Couldn't Allocate Images in chip memory.\n");
  1176. #endif
  1177.       MyCleanup(7);
  1178.       exit(FALSE);
  1179.    }
  1180.  
  1181.    /* Set up the write port, allocate the signal, */
  1182.    /* and the message */
  1183.    talk_port.mp_Node.ln_Type = NT_MSGPORT;
  1184.    talk_port.mp_Flags = 0;
  1185.    if ((talk_port.mp_SigBit = AllocSignal(-1)) == -1) {
  1186. #ifdef DEBUG
  1187.    if(clistart)
  1188.       printf("Couldn't Allocate talk Signal bit\n");
  1189. #endif
  1190.       MyCleanup(8);
  1191.       exit(FALSE);
  1192.    }
  1193.    talk_port.mp_SigTask = (struct Task *) FindTask((char *)
  1194.     NULL);
  1195.    NewList(&talk_port.mp_MsgList);
  1196.  
  1197.    /* Set up the read port, allocate the signal, */
  1198.    /*  and the message */
  1199.    read_port.mp_Node.ln_Type = NT_MSGPORT;
  1200.    read_port.mp_Flags = 0;
  1201.    if ((read_port.mp_SigBit = AllocSignal(-1)) == -1) {
  1202. #ifdef DEBUG
  1203.    if(clistart)
  1204.       printf("Couldn't Allocate read Signal bit\n");
  1205. #endif
  1206.       MyCleanup(9);
  1207.       exit(FALSE);
  1208.    }
  1209.    read_port.mp_SigTask = (struct Task *)
  1210.     FindTask((char *) NULL);
  1211.    NewList(&read_port.mp_MsgList);
  1212.  
  1213.    /* Set up the write channel information */
  1214.  
  1215.    /* **RAP */
  1216.    rexxport = CreatePort("SPEECHTOY",0);
  1217.    if(rexxport == NULL)
  1218.    {
  1219. #ifdef DEBUG
  1220.    if(clistart)
  1221.        printf("Couldn't create rexxport\n");
  1222. #endif
  1223.       MyCleanup(10);
  1224.       exit(FALSE);
  1225.    }
  1226.    InitVoiceValues();
  1227.  
  1228.    voice_io.ch_masks = (audio_chan);
  1229.    voice_io.nm_masks = sizeof(audio_chan);
  1230.    voice_io.mouths = 0;
  1231.    voice_io.message.io_Message.mn_ReplyPort = &talk_port;
  1232.    voice_io.message.io_Command = CMD_WRITE;
  1233.    voice_io.message.io_Offset = 0;
  1234.    voice_io.message.io_Data = (APTR)PhonBuffer;
  1235.    voice_io.message.io_Message.mn_Length = sizeof(voice_io);
  1236.  
  1237.   /* Set up the read channel information */
  1238.    mouth_io.voice = voice_io;
  1239.    mouth_io.width = 0;
  1240.    mouth_io.height = 0;
  1241.    mouth_io.voice.message.io_Message.mn_ReplyPort = &read_port;
  1242.    mouth_io.voice.message.io_Command = CMD_READ;
  1243.    mouth_io.voice.message.io_Error = 0;
  1244.    if (FaceWindow == NULL) {
  1245.       if ((ControlWindow = (struct Window *)OpenWindow
  1246.        (&NewControlWindow)) == NULL) {
  1247. #ifdef DEBUG
  1248.    if(clistart)
  1249.          printf("Couldn't open the control window.\n");
  1250. #endif
  1251.          MyCleanup(11);
  1252.          exit(FALSE);
  1253.       }
  1254.    }
  1255.  
  1256.    /* fill background of window */
  1257.    SetAPen(ControlWindow->RPort, BLKP);
  1258.    RectFill(ControlWindow->RPort,0,0,
  1259.     ControlWindow->GZZWidth, ControlWindow->GZZHeight);
  1260.    RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL);
  1261.  
  1262.    SetMenuStrip(ControlWindow, &MyMenu);
  1263.  
  1264.    SetValues();
  1265.  
  1266. /* !!! Ah, But what if FaceWindow's not been opened? */
  1267.    for (;;) {  /* ever wait for a signal and process it */
  1268.       /* wait lets the rest of the system run, */
  1269.       /* this program sleeps */
  1270.       Signals = Wait((1 << ControlWindow->UserPort->mp_SigBit)
  1271. | (1 << FaceWindow->UserPort->mp_SigBit)
  1272. | (1 << voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)
  1273. | (1 << mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)
  1274. | (1 << rexxport->mp_SigBit));
  1275.       /* now check to see to what we owe the intrusion */
  1276.  
  1277.       if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
  1278.          /* Process the Intuition message */
  1279.          while (MyIntuiMessage=(struct IntuiMessage *)
  1280.                       GetMsg(ControlWindow->UserPort)) {
  1281.             /* Get all the needed info and give message back */
  1282.             MIClass = MyIntuiMessage->Class;
  1283.             MICode = MyIntuiMessage->Code;
  1284.             MIAddress = MyIntuiMessage->IAddress;
  1285.             ReplyMsg(MyIntuiMessage);
  1286.             /* Now, what was it you wanted? */
  1287.             switch (MIClass) {
  1288.                case MENUPICK:
  1289.                   menumessage(MICode, ControlWindow);
  1290.                   break;
  1291.                case GADGETUP:         /* reply, then process */
  1292.                   gadgetmessage(MIAddress, ControlWindow);
  1293.                   break;
  1294.                case CLOSEWINDOW:       /* bye! */
  1295.           if(speakdone)
  1296.             /* don't accept close window 
  1297.              * if I/O in process 
  1298.              * (avoids crash) 
  1299.              */
  1300.           {
  1301.                    while (MyIntuiMessage = (struct
  1302.                    IntuiMessage *) GetMsg(
  1303.                    ControlWindow->UserPort))
  1304.                     ReplyMsg(MyIntuiMessage);
  1305.                   MyCleanup(12);
  1306.                   exit(TRUE);
  1307.                   break;
  1308.           }
  1309.           else
  1310.           {
  1311.             break; 
  1312.           }
  1313.                default:
  1314. #ifdef DEBUG
  1315.    if(clistart)
  1316.                   printf("Unhandled Message Received.\n");
  1317. #endif
  1318.                   break;
  1319.             }  /* switch */
  1320.          } /* while */
  1321.       } /* if */
  1322.  
  1323.  
  1324.       /* Woken by intuition for FaceWindow*/
  1325.       if (Signals & (1<< FaceWindow->UserPort->mp_SigBit)) {
  1326.          /* Process the Intuition message */
  1327.          while (MyIntuiMessage=(struct IntuiMessage *)
  1328.           GetMsg(FaceWindow->UserPort)) {
  1329.             switch (MyIntuiMessage->Class) {
  1330.                case SIZEVERIFY:
  1331.                   ReplyMsg(MyIntuiMessage);
  1332.                   break;
  1333.                case MENUPICK:
  1334.                   menumessage(MyIntuiMessage->Code,FaceWindow);
  1335.                   ReplyMsg(MyIntuiMessage);
  1336.                   break;
  1337.                case NEWSIZE:  /* Don't reply until processed */
  1338.                   DrawFace();
  1339.                   ReplyMsg(MyIntuiMessage);
  1340.                   break;
  1341.                default:
  1342. #ifdef DEBUG
  1343.    if(clistart)
  1344.                   printf("Unhandled Message Received.\n");
  1345. #endif
  1346.                   ReplyMsg(MyIntuiMessage);
  1347.                   break;
  1348.             }  /* switch */
  1349.          } /* while */
  1350.       } /* if */
  1351.  
  1352.       /* A voice SendIO (Write) has completed */
  1353.       if (Signals & (1 <<
  1354.        voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  1355.          /* Was it Sucessful? filter out the abort error */
  1356.          if (voice_io.message.io_Error == -2)
  1357.             voice_io.message.io_Error = 0;
  1358.          if (voice_io.message.io_Error != 0) {
  1359. #ifdef DEBUG
  1360.    if(clistart)
  1361.             printf("Narrator won't. (%ld)\n",
  1362.              voice_io.message.io_Error);
  1363. #endif
  1364.             /* flash this screen */
  1365.             DisplayBeep(ControlWindow->WScreen);
  1366.             /* let user see where phoneme string was bad. */
  1367.             i = RemoveGadget(ControlWindow, &PhonStrGadget);
  1368.             /* move the cursor to the error char */
  1369.             PhonInfo.BufferPos = voice_io.message.io_Actual -1;
  1370.             /* assure cursor (error point) is shown in gad. */
  1371.             /* within 29 (number of chars shown) of front */
  1372.             if (voice_io.message.io_Actual < 29)
  1373.                PhonInfo.DispPos = 0;
  1374.             /* within 29 of end */
  1375.             else if ((voice_io.message.io_Length -
  1376.                       voice_io.message.io_Actual) < 29)
  1377.                PhonInfo.DispPos = voice_io.message.io_Length
  1378.                                   - 29;
  1379.             else
  1380.                PhonInfo.DispPos = voice_io.message.io_Actual
  1381.                                   - 15;
  1382.             AddGadget(ControlWindow, &PhonStrGadget, i);
  1383.             RefreshGadgets(&PhonStrGadget, ControlWindow,
  1384.              NULL);
  1385.             voice_io.message.io_Error = 0;
  1386.          }
  1387. /*       SpeakGadget.Flags ^= GADGDISABLED;
  1388.          FaceGadget.Flags ^= GADGDISABLED;
  1389. */
  1390.          OnGadget(&SpeakGadget, ControlWindow, NULL);
  1391.          OnGadget(&FaceGadget,  ControlWindow, NULL);
  1392.      speakdone = TRUE;    /* signal to accept more arexx msgs */
  1393.  
  1394.       }
  1395.  
  1396.       /* A mouth DoIO (Read) has completed */
  1397.       if (Signals & (1 <<
  1398.   mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  1399.          WaitBOVP(&FaceWindow->WScreen->ViewPort);
  1400.          SetAPen(FaceWindow->RPort, WHTP);
  1401.          RectFill(FaceWindow->RPort, 0, EyesBottom,
  1402.           FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1403.          if (MouthWMult == 0)
  1404.             LipWidth = mouth_io.width >> 1;
  1405.          else
  1406.             LipWidth = mouth_io.width * MouthWMult;
  1407.          if (MouthHMult == 0)
  1408.             LipHeight = mouth_io.height >> 1;
  1409.          else
  1410.             LipHeight = mouth_io.height * (MouthHMult);
  1411.          SetAPen(FaceWindow->RPort, REDP);
  1412.          Move(FaceWindow->RPort,
  1413.           XMouthCenter - LipWidth, YMouthCenter);
  1414.          Draw(FaceWindow->RPort,
  1415.           XMouthCenter, YMouthCenter - LipHeight);
  1416.          Draw(FaceWindow->RPort,
  1417.           XMouthCenter + LipWidth, YMouthCenter);
  1418.          Draw(FaceWindow->RPort,
  1419.           XMouthCenter, YMouthCenter + LipHeight);
  1420.          Draw(FaceWindow->RPort,
  1421.           XMouthCenter - LipWidth, YMouthCenter);
  1422.          /* the narrator will give an error when the */
  1423.          /* write has completed and I've tried to read */
  1424.          /* so I stop trying when that happens */
  1425.          if (mouth_io.voice.message.io_Error == 0)
  1426.             SendIO(&mouth_io);
  1427.       }
  1428.     /* a REXX message has arrived */
  1429.     if(Signals & 1 << rexxport->mp_SigBit)
  1430.     {
  1431.         while(myrexmsg = (struct RexxMsg *)GetMsg(rexxport))
  1432.         {
  1433.             /* EMPTIES the port, good practice!! */
  1434.             ParseRexxStrings(myrexmsg);
  1435.         }
  1436.     }
  1437.  
  1438.    }  /* for */
  1439. }  /* main */
  1440.  
  1441. /* a MENUPICK has been received, this
  1442.  * routine takes the appropriate action
  1443.  */
  1444. void
  1445. menumessage(code, w)
  1446. USHORT code;
  1447. struct Window *w;
  1448. {
  1449.    int freq, rate, pitch, vol, sex, mode;
  1450.  
  1451.    char toolbuff[560];  /* 20 characters times 7 strings (7th is null) */
  1452.    int i,j;
  1453.    int success;
  1454.  
  1455.    j=0;
  1456.    for(i=0; i<7; i++)
  1457.    {
  1458.     toolstrings[i] = &toolbuff[j];
  1459.     j += 20;
  1460.    }
  1461.    switch (MENUNUM(code)) {
  1462.       case 0:
  1463.          switch (ITEMNUM(code)) {
  1464.             case 0:
  1465.                AutoRequest(w, &ReqText3, NULL,
  1466.                            &OKIText, 0, 0, 280, 47);
  1467.                break;
  1468.  
  1469.         case 1:
  1470.         sprintf(toolstrings[0],"FREQUENCY=%ld",DEFFREQ2);      
  1471.         sprintf(toolstrings[1],"RATE=%ld",DEFRATE2);        
  1472.         sprintf(toolstrings[2],"PITCH=%ld",DEFPITCH2);
  1473.         sprintf(toolstrings[3],"VOLUME=%ld",DEFVOL2);
  1474.         sprintf(toolstrings[4],"MODE=%ld",DEFMODE2);
  1475.         sprintf(toolstrings[5],"SEX=%ld",DEFSEX2);
  1476.  
  1477.         toolstrings[6] = NULL;
  1478.         /* NULL value terminates it */
  1479.  
  1480.         toolsave = diskobj->do_ToolTypes; /* save pointer */
  1481.         diskobj->do_ToolTypes = &toolstrings[0];
  1482.  
  1483.         if(foundicon)
  1484.         {
  1485.             success = WriteIcon(iconlock, iconname, diskobj);
  1486.         }
  1487.         diskobj->do_ToolTypes = toolsave; /* restore it */
  1488.  
  1489.         /* We restore it because the icon library routines
  1490.          * have allocated a block of memory associated with
  1491.          * this material and we have to give it all back at exit.
  1492.          */
  1493.         break;
  1494.      default:
  1495.         break;
  1496.          }
  1497.       break;
  1498.    }
  1499. }
  1500.  
  1501. /* Read the icon and if all of the tool strings are present, then
  1502.  * use them to set the default values for the speechtoy.  Return
  1503.  * values are as follows:  decimal 63 if all defaults are set, less
  1504.  * than 63 if at least one default is messed up.  Causes system to 
  1505.  * establish defaults on its own.   ... Rob Peck
  1506.  */
  1507. extern struct DiskObject *ReadIcon();
  1508.  
  1509. ULONG
  1510. GetDefaults(idir, iname)
  1511. struct FileLock *idir;
  1512. char        *iname;
  1513. {
  1514.     char *FindToolType();
  1515.     char **ts;
  1516.  
  1517.     /* Establish all defaults on entry, then change them
  1518.      * if new values are found in the toolstrings.
  1519.      */
  1520.  
  1521.     DEFSEX2    = DEFSEX;
  1522.     DEFMODE2   = DEFMODE;
  1523.     DEFPITCH2  = DEFPITCH;
  1524.     DEFVOL2    = DEFVOL;
  1525.     DEFFREQ2   = DEFFREQ;
  1526.     DEFRATE2   = DEFRATE;
  1527.     if(iname == NULL)
  1528.     {
  1529.         /* Started from the CLI, and NO ICON FILE
  1530.          * in the current directory.  So this is IT! */
  1531.         /* This is a successful initialization */
  1532.         return(TRUE);
  1533.     }
  1534. #ifdef DEBUG
  1535.    if(clistart)
  1536.       printf("Going to try to readicon now\n");
  1537. #endif
  1538.  
  1539.     diskobj = ReadIcon(idir, iname);    /* diskobj is a global */
  1540. #ifdef DEBUG
  1541.    if(clistart)
  1542.       printf("Returned from readicon with diskobj value: %lx\n",diskobj);
  1543. #endif
  1544.  
  1545.     if(diskobj == NULL) return(FALSE);
  1546.  
  1547.     foundicon = TRUE;            /* another global */
  1548.  
  1549.     ts = diskobj->do_ToolTypes; /* get ptr to tool strings */
  1550.  
  1551. return(ParseStrings(ts));
  1552. }
  1553.  
  1554. /* This routine is separated from the others to allow a command
  1555.  * from the outside world to affect the defaults.   Returns a mask
  1556.  * with 1 bits in the position indicating which parameters it
  1557.  * recognized and whose values it has set.  That is, a 1 in bit
  1558.  * position 0 means parameter 0 was recognized, a 1 in bit position
  1559.  * 1 means it set parameter 1 and so on.  ... Rob Peck
  1560.  *
  1561.  * Anything out of bounds results in setting things to their defaults.
  1562.  */
  1563.  
  1564. ULONG
  1565. ParseStrings(ts)
  1566. char **ts;
  1567. {
  1568.     ULONG rtnval;
  1569.     char *value;
  1570.     int temp;
  1571.  
  1572.     rtnval = 0;
  1573.  
  1574.     value = FindToolType(ts, "FREQUENCY");
  1575.     if(value)
  1576.     {
  1577.         DEFFREQ2 = atoi(value); 
  1578.         if(DEFFREQ2 < MINFREQ || DEFFREQ2 > MAXFREQ)
  1579.             DEFFREQ2 = DEFFREQ;
  1580.         rtnval |= 0x1;
  1581.     }
  1582.     value = FindToolType(ts, "RATE");
  1583.     if(value)
  1584.     {
  1585.         DEFRATE2 = atoi(value);
  1586.         if(DEFRATE2 < MINRATE || DEFRATE2 > MAXRATE)
  1587.             DEFRATE2 = DEFRATE;
  1588.         rtnval |=0x02;
  1589.     }
  1590.     value = FindToolType(ts, "PITCH");
  1591.     if(value)
  1592.     {
  1593.         DEFPITCH2 = atoi(value);
  1594.         if(DEFPITCH2 < MINPITCH || DEFPITCH2 > MAXPITCH)
  1595.             DEFPITCH2 = DEFPITCH;
  1596.         rtnval |=0x04;
  1597.     }
  1598.     value = FindToolType(ts, "VOLUME");
  1599.     if(value)
  1600.     {
  1601.         DEFVOL2 = atoi(value);
  1602.         if(DEFVOL2 < MINVOL || DEFVOL2 > MAXVOL)
  1603.             DEFVOL2 = DEFVOL;
  1604.         rtnval |=0x08;
  1605.     }
  1606.     value = FindToolType(ts, "MODE");
  1607.     if(value)
  1608.     {
  1609.         temp = atoi(value);
  1610.         if(DEFMODE2 < 0 || DEFMODE2 > 1)
  1611.             DEFMODE2 = DEFMODE;
  1612.         if(temp != DEFMODE2)
  1613.         {
  1614.             /* time for a change in the display */
  1615.             rtnval |= 0x10;
  1616.             DEFMODE2 = temp;
  1617.         }
  1618.     }
  1619.     value = FindToolType(ts, "SEX");
  1620.     if(value)
  1621.     {
  1622.         temp = atoi(value);
  1623.         if(DEFSEX2 < 0 || DEFSEX2 > 1)
  1624.             DEFSEX2 = DEFSEX;
  1625.         if(temp != DEFSEX2)
  1626.         {
  1627.             /* time for a change in the display */
  1628.             rtnval |= 0x20;
  1629.             DEFSEX2 = temp;
  1630.         }
  1631.     }
  1632.     /* for AREXX support, accept a string to be said */
  1633.     value = FindToolType(ts, "WORDS");
  1634.     if(value)
  1635.     {
  1636.         EnglBuffer[0] = '\0';
  1637.         strncat(EnglBuffer, value, ESTRINGSIZE);
  1638.         rtnval |= 0x40;
  1639.     }
  1640.     value = FindToolType(ts, "TRANS");
  1641.     if(value)
  1642.     {
  1643.         rtnval |= 0x80;
  1644.     }
  1645.     value = FindToolType(ts, "SPEAK");
  1646.     if(value)
  1647.     {
  1648.         rtnval |= 0x100;
  1649.     }
  1650.     value = FindToolType(ts, "PHON");
  1651.     if(value)
  1652.     {
  1653.         PhonBuffer[0] = '\0';
  1654.         strncat(PhonBuffer, value, PSTRINGSIZE);
  1655.         rtnval |= 0x200;
  1656.     }
  1657.  
  1658. return(rtnval);
  1659. }
  1660.  
  1661. /* Maximum total length of string passed from REXX is 1024 bytes,
  1662.  * including the terminating null (my own arbitrary limit, from
  1663.  * the declaration of rexxstrings[maxstringsize] in the global area.
  1664.  */
  1665. /* Only one argument, ARG0, is accepted by this program,
  1666.  * passed with a command (RX) from AREXX.
  1667.  */
  1668.  
  1669. void
  1670. ParseRexxStrings(rxmsg)
  1671. struct RexxMsg *rxmsg;
  1672. {
  1673.     int timeout;    /* only wait for just SO long, then quit */
  1674.  
  1675.     timeout = 0;
  1676.     /* parseresult is a global ULONG */
  1677.  
  1678.     rexxstrings[0] = (char *)rxmsg->rm_Args[0];
  1679.     rexxstrings[1] = NULL;
  1680.  
  1681.     parseresult = ParseStrings(&rexxstrings[0]);
  1682.  
  1683.     if(speakdone)
  1684.     {
  1685.         SetValues();
  1686.         rxmsg->rm_Result1 = 0;
  1687.     }
  1688.     else
  1689.     {
  1690.         /* TRIED this, but changed my mind...
  1691.            New method is to HANG this task until
  1692.            the speech I/O has completed!  Might
  1693.            as well if we want to assure that
  1694.            an external AREXX program can get
  1695.            all of its commands executed!
  1696.            Some of you may want to go thru the work
  1697.            to build a queue of commands, or to add
  1698.            more voice_io blocks and queue THEM.
  1699.            I just wanted to get the project DONE.
  1700.            Up to you.
  1701.          */
  1702.  
  1703.         /* rxmsg->rm_Result1 = 5;  */
  1704.         /* AmigaDOS "warn" value, this one did not speak */
  1705.  
  1706.         /* NEW method, hang if speaking */
  1707.         WaitIO(&voice_io);  /* HANG and wait */
  1708.         speakdone = TRUE;   
  1709.         SetValues();
  1710.             /* we KNOW this otherwise hung forever */
  1711.     }
  1712.     ReplyMsg(rxmsg);
  1713. }
  1714.  
  1715.  
  1716.  
  1717. /* a GADGETUP has been received, this
  1718.  * routine takes the appropriate action
  1719.  */
  1720. void
  1721. gadgetmessage(address, w)
  1722. APTR address;
  1723. struct Window *w;
  1724. {
  1725.    USHORT i;
  1726.    long PropRange;
  1727.    if (address == (APTR)&ModeGadget) {
  1728.       if (ModeGadget.Flags & SELECTED)
  1729.          DEFMODE2 = ROBOTICF0;
  1730.       else
  1731.          DEFMODE2 = NATURALF0;
  1732.    }
  1733.    else if (address == (APTR)&FaceGadget) {
  1734.       /* tell the write that reads will be forthcomming */
  1735.       if (FaceGadget.Flags & SELECTED) {
  1736.          voice_io.mouths = 1;
  1737.          if ((FaceWindow = (struct Window *)
  1738.           OpenWindow(&NewFaceWindow)) == NULL) {
  1739. #ifdef DEBUG
  1740.    if(clistart)
  1741.             printf("Couldn't open the face window.\n");
  1742. #endif
  1743.             MyCleanup(13);
  1744.             exit(FALSE);
  1745.          }
  1746.          SetMenuStrip(FaceWindow, &MyMenu);
  1747.          DrawFace();
  1748.       }
  1749.       else { /* FaceGadget de-SELECTed */
  1750.          voice_io.mouths = 0;
  1751.          NewFaceWindow.LeftEdge = FaceWindow->LeftEdge;
  1752.          NewFaceWindow.TopEdge = FaceWindow->TopEdge;
  1753.          NewFaceWindow.Width = FaceWindow->Width;
  1754.          NewFaceWindow.Height = FaceWindow->Height;
  1755.          CloseWindow(FaceWindow);
  1756.          FaceWindow = NULL;
  1757.       }
  1758.    }
  1759.    else if (address == (APTR)&StopGadget) {
  1760.       AbortIO(&voice_io);
  1761.       voice_io.message.io_Error = 0;
  1762.       mouth_io.voice.message.io_Error = 0;
  1763.    }
  1764.    /* Since this program changes a flag that intuition expects
  1765.     * only the user to change (SELECTED bit), this program has
  1766.     * to remove, then change, then add this gadget. Then by
  1767.     * passing the address of this gadget to RefreshGadgets(),
  1768.     * only the gadgets from here to the start of the list will
  1769.     * be refreshed, which minimizes the visible flash that
  1770.     * RefreshGadgets() can introduce.
  1771.     * If one of the two gadgets (female/male) is hit, toggle
  1772.     * the selection of the other gadget (since the gadget hit
  1773.     * was toggled by intuition when it was hit).
  1774.     */
  1775.    else if (address == (APTR)&FemaleGadget) {
  1776.       if (FemaleGadget.Flags & SELECTED)
  1777.       DEFSEX2 = FEMALE;
  1778.       else
  1779.       DEFSEX2 = MALE;
  1780.       ModGadget(&MaleGadget);
  1781.    }
  1782.    else if (address == (APTR)&MaleGadget) {
  1783.       if (MaleGadget.Flags & SELECTED)
  1784.       DEFSEX2 = MALE;
  1785.       else
  1786.       DEFSEX2 = FEMALE;
  1787.       ModGadget(&FemaleGadget);
  1788.    }
  1789.    /* Since the program changes the contents of the string
  1790.     * gadgets' buffer and it's size, which is something else
  1791.     * intuition doesn't expect a program (as opposed to the
  1792.     * user) to do. The program must remove, then change, then
  1793.     * add this gadget, and then by passing the address of this
  1794.     * gadget to RefreshGadgets(), only the gadgets from here
  1795.     * to the start of the list will be refreshed, which
  1796.     * minimizes the visible flash that RefreshGadgets() can
  1797.     * introduce.
  1798.     */
  1799.    else if (address == (APTR)&TranslateGadget) {
  1800.       i = RemoveGadget(ControlWindow, &PhonStrGadget);
  1801.       if ((TranslatorError = Translate((APTR)EnglBuffer,
  1802.        EnglInfo.NumChars, (APTR)PhonBuffer, PhonInfo.MaxChars))
  1803.        != 0) {
  1804. #ifdef DEBUG
  1805.    if(clistart)
  1806.          printf("Translator won't. (%lx)\n",TranslatorError);
  1807. #endif
  1808.          /* flash this screen */
  1809.          DisplayBeep(ControlWindow->WScreen);
  1810.       }
  1811.       /* Hey! NumChars includes the terminating NULL. */
  1812.       /* This must be done. */
  1813.       PhonInfo.NumChars = voice_io.message.io_Length + 1;
  1814.       if (PhonInfo.DispPos > voice_io.message.io_Length)
  1815.           PhonInfo.DispPos = voice_io.message.io_Length;
  1816.       AddGadget(ControlWindow, &PhonStrGadget, i);
  1817.       RefreshGadgets(&PhonStrGadget, ControlWindow, NULL);
  1818.    }
  1819.    else if (address == (APTR)&SpeakGadget) {
  1820. /*    SpeakGadget.Flags ^= GADGDISABLED;
  1821.       FaceGadget.Flags ^= GADGDISABLED;
  1822. */
  1823.       OffGadget(&SpeakGadget, ControlWindow, NULL);
  1824.       OffGadget(&FaceGadget,  ControlWindow, NULL);
  1825.  
  1826.       voice_io.message.io_Length = strlen(PhonBuffer);
  1827.  
  1828.       InitVoiceValues();    /* Rob Peck - before any new
  1829.                  * speech output, copy the
  1830.                  * current values into the
  1831.                  * I/O request block
  1832.                  */
  1833.       speakdone = FALSE;    /* once start to speak, dont blow it */
  1834.       SendIO(&voice_io);
  1835.       if (voice_io.mouths == 1) {
  1836.          mouth_io.voice.message.io_Error = 0;
  1837.          SendIO(&mouth_io);
  1838.       }
  1839.    }
  1840.    else if (address == (APTR)&EnglStrGadget);  /* do nothing */
  1841.    else if (address == (APTR)&PhonStrGadget);  /* do nothing */
  1842.    else if (address == (APTR)&Props[0]) {
  1843.       PropRange = RNGFREQ;
  1844.       DEFFREQ2 = (( (PInfos[0].HorizPot >> 1)
  1845.        * PropRange) >> 15) + MINFREQ;
  1846. #ifdef DEBUG
  1847.    if(clistart)
  1848.       printf("Freq. = %ld\n", DEFFREQ2);
  1849. #endif
  1850.    }
  1851.    else if (address == (APTR)&Props[1]) {
  1852.       PropRange = RNGRATE;
  1853.       DEFRATE2 = (((PInfos[1].HorizPot >> 1)
  1854.        * PropRange) >> 15) + MINRATE;
  1855. #ifdef DEBUG
  1856.    if(clistart)
  1857.       printf("Rate  = %ld\n", DEFRATE2);
  1858. #endif
  1859.    }
  1860.    else if (address == (APTR)&Props[2]) {
  1861.       PropRange = RNGPITCH;
  1862.       DEFPITCH2 = (((PInfos[2].HorizPot >> 1)
  1863.        * PropRange) >> 15) + MINPITCH;
  1864. #ifdef DEBUG
  1865.    if(clistart)
  1866.       printf("Pitch = %ld\n", DEFPITCH2);
  1867. #endif
  1868.    }
  1869.    else if (address == (APTR)&Props[3]) {
  1870.       PropRange = RNGVOL;
  1871.       DEFVOL2 = (((PInfos[3].HorizPot >> 1)
  1872.        * PropRange) >> 15) + MINVOL;
  1873. #ifdef DEBUG
  1874.    if(clistart)
  1875.       printf("Vol.  = %ld\n", DEFVOL2);
  1876. #endif
  1877.    }
  1878. #ifdef DEBUG
  1879.    else if (clistart) printf("Unhandled gadget up received!\n");
  1880. #endif
  1881. }
  1882.  
  1883. /* This calculates variables used to draw the mouth
  1884.  * and eyes, as well as redrawing the face.
  1885.  * Proportionality makes it very wierd, but it's
  1886.  * wierder if you don't use a GimmeZeroZero window
  1887.  * and GZZWidth/GZZHeight.
  1888.  */
  1889. void
  1890. DrawFace() {
  1891.    XMouthCenter =  FaceWindow->GZZWidth >> 1;
  1892.    /* set left edge of left eye */
  1893.    EyesLeft = FaceWindow->GZZWidth >> 2;
  1894.    /* multiplier for mouth width */
  1895.    MouthWMult = FaceWindow->GZZWidth >> 6;
  1896.  
  1897.    EyesTop = (FaceWindow->GZZHeight >> 2)
  1898.     - (FaceWindow->GZZHeight >> 4);
  1899.    EyesBottom = EyesTop + (FaceWindow->GZZHeight >> 3) + 1;
  1900.    yaw = FaceWindow->GZZHeight - EyesBottom;
  1901.    YMouthCenter = ((yaw >> 1) + EyesBottom);
  1902.    MouthHMult = yaw >> 5;
  1903.  
  1904.    /* Set pen to White */
  1905.    SetAPen(FaceWindow->RPort, WHTP);
  1906.    RectFill(FaceWindow->RPort, 0, 0,
  1907.     FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1908.  
  1909.    /* Set pen to Blue */
  1910.    SetAPen(FaceWindow->RPort, BLUP);
  1911.    RectFill(FaceWindow->RPort,
  1912.     EyesLeft, EyesTop,
  1913.     EyesLeft + (FaceWindow->GZZWidth >> 3),
  1914.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1915.    RectFill(FaceWindow->RPort,
  1916.     (FaceWindow->GZZWidth >> 1)
  1917.     + (FaceWindow->GZZWidth >> 3),
  1918.     EyesTop,
  1919.     (FaceWindow->GZZWidth >> 1)
  1920.      + (FaceWindow->GZZWidth >> 3) /* two >> 3, not one >> 2 */
  1921.      + (FaceWindow->GZZWidth >> 3),/* so eyes are same width */
  1922.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1923.  
  1924.     SetAPen(FaceWindow->RPort, REDP);  /* Set pen to Red */
  1925.     Move(FaceWindow->RPort,
  1926.      XMouthCenter - (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1927.     Draw(FaceWindow->RPort,
  1928.      XMouthCenter + (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1929.  
  1930. }
  1931.  
  1932. /* Deallocate any memory, and close all of the
  1933.  * windows/screens/devices/libraries in reverse order to
  1934.  * make things work smoothly. And be sure to check
  1935.  * that the open/allocation was successful before
  1936.  * closing/deallocating.
  1937.  */
  1938. MyCleanup(n)
  1939. SHORT n;
  1940. {
  1941. #ifdef DEBUG
  1942.    if(clistart)
  1943.     printf("Exit reason = %ld\n",n);
  1944. #endif
  1945.  
  1946.    if (clistart)
  1947.       if(iconlock) UnLock(iconlock);  /* Rob Peck */
  1948.    if (rexxport)
  1949.       DeletePort(rexxport);    /* RAP */
  1950.    if (diskobj != 0)
  1951.       FreeDiskObject(diskobj);
  1952.    if (read_port.mp_SigBit != -1)
  1953.       FreeSignal(read_port.mp_SigBit);
  1954.    if (talk_port.mp_SigBit != -1)
  1955.       FreeSignal(talk_port.mp_SigBit);
  1956.    if (FaceWindow != NULL)
  1957.       CloseWindow(FaceWindow);
  1958.    if (ControlWindow != NULL)
  1959.       CloseWindow(ControlWindow);
  1960.    /* freeimages makes sure image allocation was successful */
  1961.    freeimages();
  1962.    if (NarratorOpenError == 0)
  1963.       CloseDevice(&voice_io);
  1964.    if (TranslatorBase != 0)
  1965.       CloseLibrary(TranslatorBase);
  1966.    if (GfxBase != 0)
  1967.       CloseLibrary(GfxBase);
  1968.    if (IntuitionBase != 0)
  1969.       CloseLibrary(IntuitionBase);
  1970.    if (IconBase != 0)
  1971.       CloseLibrary(IconBase);
  1972.    return(0);
  1973. }
  1974.  
  1975. /* Allocate chip memory for gadget images, and set the
  1976.  * pointers in the corresponding image structures to point
  1977.  * to these images. This must be done because the program
  1978.  * could be loaded into expansion memory (off the side of
  1979.  * the box), which the custom chips cannot access.
  1980.  * And images must be in chip ram (that's memory that the
  1981.  * custom chips can access, the internal 512K).
  1982.  */
  1983. InitImages()
  1984. {
  1985.    /* the images were staticly initialized above main */
  1986.    extern USHORT *FemaleIData_chip;
  1987.    extern USHORT *MaleIData_chip;
  1988.    extern USHORT *HumanIData_chip;
  1989.    extern USHORT *RobotIData_chip;
  1990.    extern USHORT *FaceIData_chip;
  1991.    extern USHORT *StopIData_chip;
  1992.    int i;
  1993.  
  1994.    /* Allocate them all, stop and return false on failure */
  1995.    if ((FemaleIData_chip = (USHORT *)
  1996.     AllocMem(sizeof(FemaleIData),MEMF_CHIP)) == 0)
  1997.       return(FALSE);
  1998.    if ((MaleIData_chip = (USHORT *)
  1999.     AllocMem(sizeof(MaleIData),MEMF_CHIP)) == 0)
  2000.       return(FALSE);
  2001.    if ((HumanIData_chip = (USHORT *)
  2002.     AllocMem(sizeof(HumanIData),MEMF_CHIP)) == 0)
  2003.       return(FALSE);
  2004.    if ((RobotIData_chip = (USHORT *)
  2005.     AllocMem(sizeof(RobotIData),MEMF_CHIP)) == 0)
  2006.       return(FALSE);
  2007.    if ((FaceIData_chip = (USHORT *)
  2008.     AllocMem(sizeof(FaceIData),MEMF_CHIP)) == 0)
  2009.       return(FALSE);
  2010.    if ((StopIData_chip = (USHORT *)
  2011.     AllocMem(sizeof(StopIData),MEMF_CHIP)) == 0)
  2012.       return(FALSE);
  2013.  
  2014.    for (i=0; i<20; i++)
  2015.       FemaleIData_chip[i] = FemaleIData[i];
  2016.    for (i=0; i<20; i++)
  2017.       MaleIData_chip[i] = MaleIData[i];
  2018.    for (i=0; i<60; i++)
  2019.       HumanIData_chip[i] = HumanIData[i];
  2020.    for (i=0; i<60; i++)
  2021.       RobotIData_chip[i] = RobotIData[i];
  2022.    for (i=0; i<30; i++)
  2023.       FaceIData_chip[i] = FaceIData[i];
  2024.    for (i=0; i<30; i++)
  2025.       StopIData_chip[i] = StopIData[i];
  2026.  
  2027.    FemaleImage.ImageData = FemaleIData_chip;
  2028.    MaleImage.ImageData = MaleIData_chip;
  2029.    HumanImage.ImageData = HumanIData_chip;
  2030.    RobotImage.ImageData = RobotIData_chip;
  2031.    FaceImage.ImageData = FaceIData_chip;
  2032.    StopImage.ImageData = StopIData_chip;
  2033.  
  2034.    return(TRUE);
  2035. }
  2036.  
  2037. /* Deallocate the memory that was used for images,
  2038.  * See initimages for more details.
  2039.  */
  2040. void
  2041. freeimages()
  2042. {
  2043.    /* the images were staticly initialized above main */
  2044.    extern USHORT *FemaleIData_chip;
  2045.    extern USHORT *MaleIData_chip;
  2046.    extern USHORT *HumanIData_chip;
  2047.    extern USHORT *RobotIData_chip;
  2048.    extern USHORT *FaceIData_chip;
  2049.    extern USHORT *StopIData_chip;
  2050.  
  2051.    /* Deallocate only if the pointer is really there. */
  2052.    if (RobotIData_chip != 0)
  2053.       FreeMem(RobotIData_chip, sizeof(RobotIData));
  2054.    if (HumanIData_chip != 0)
  2055.       FreeMem(HumanIData_chip, sizeof(HumanIData));
  2056.    if (MaleIData_chip != 0)
  2057.       FreeMem(MaleIData_chip, sizeof(MaleIData));
  2058.    if (FemaleIData_chip != 0)
  2059.       FreeMem(FemaleIData_chip, sizeof(FemaleIData));
  2060.    if (FaceIData_chip != 0)
  2061.       FreeMem(FaceIData_chip, sizeof(FaceIData));
  2062.    if (StopIData_chip != 0)
  2063.       FreeMem(StopIData_chip, sizeof(StopIData));
  2064. }
  2065.  
  2066.  
  2067. /* ReadIcon:
  2068.  * input  = lock on the directory where the icon resides
  2069.  *          (program only gets this if called from WBench)
  2070.  *         and name of the .info file to be read.
  2071.  * returns a pointer to a DiskObject structure if success,
  2072.  *          or NULL if not.
  2073.  */
  2074.  
  2075. struct DiskObject *
  2076. ReadIcon(icondirlock, iconfilename)
  2077. struct FileLock *icondirlock;   /* lock on dir where icon is located */
  2078. char *iconfilename;        /* name of this icon */
  2079. {
  2080.  
  2081.     struct FileLock *olddir;
  2082.     struct DiskObject *dobj;
  2083.  
  2084.     dobj   = NULL;                /* assume failure */
  2085.     olddir = CurrentDir(icondirlock);       /* Move where icon is */
  2086.     dobj   = GetDiskObject(iconfilename);   /* Only then can read it */
  2087.  
  2088.     CurrentDir(olddir);  /* Return to original dir */
  2089.     return(dobj);        /* If successful, returns a pointer
  2090.                   * to a memory area allocated by 
  2091.                   * the icon.library
  2092.                   */
  2093.  
  2094. /* ... REMEMBER to FreeDiskObject when done with it. */
  2095. }
  2096.  
  2097. /* WriteIcon */
  2098.  
  2099. /* input = lock on the directory where to write and name of 
  2100.  *         file to write, and a disk object pointer, 
  2101.  *         
  2102.  * output = nonzero if ok, but if value over 100, then error.
  2103.  */
  2104.  
  2105. long
  2106. WriteIcon(icondirlock, iconfilename, dobj)
  2107. struct FileLock *icondirlock;
  2108. char *iconfilename;
  2109. struct DiskObject *dobj;
  2110. {
  2111.     struct FileLock *olddir;
  2112.     long status;
  2113.     status = -1;    /* assume failure */
  2114.  
  2115.     olddir = CurrentDir(icondirlock);  /* move to target directory */
  2116.  
  2117.     status = PutDiskObject(iconfilename, dobj);
  2118.     if(status == 0)
  2119.     {
  2120.        status = IoErr();   /* let AmigaDOS say why if possible */
  2121.     }
  2122.     CurrentDir(olddir);
  2123.     return(status);
  2124. }
  2125.  
  2126. void
  2127. SetValues()
  2128. {
  2129.    USHORT i;
  2130.    if(parseresult & 0x20)
  2131.    {
  2132.     if(
  2133.        ((DEFSEX2 == 1) && ((FemaleGadget.Flags & SELECTED) == 0)) ||
  2134.        ((DEFSEX2 == 0) && ((MaleGadget.Flags   & SELECTED) == 0))    
  2135.       )
  2136.       {
  2137.           gadgetmessage(&FemaleGadget,ControlWindow);
  2138.           gadgetmessage(&MaleGadget,ControlWindow);
  2139.       }
  2140.    }
  2141.  
  2142.    if(parseresult & 0x10) ModGadget(&ModeGadget);
  2143.    if(parseresult & 0x40) ModGadget(&EnglStrGadget);
  2144.    if(parseresult & 0x80) IssueTranslate();
  2145.    if(parseresult & 0x100) IssueSpeak();
  2146.    if(parseresult & 0x200) ModGadget(&PhonStrGadget);
  2147. }
  2148.