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