home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Sound / MidI / BARS&PIPESPROF2,0-2.DMS / in.adf / Yak Source Code / YakSource.LZH / Yak.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-16  |  23.5 KB  |  1,010 lines

  1. #include <proto/exec.h>
  2. #include <proto/intuition.h>
  3. #include <proto/dos.h>
  4. #include <proto/graphics.h>
  5. #include <graphics/gfxmacros.h>
  6. #include <exec/memory.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <tools.h>
  10. #include <proto/translator.h>
  11. #include <devices/narrator.h>
  12. #include "bppro.h"
  13.  
  14. #define MakeID(a,b,c,d)  ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) )
  15.  
  16. #define ID_YAKK   MakeID('Y','A','K','K')
  17.  
  18. /*
  19. ** include PowerWindows window definition
  20. */
  21. #pragma msg 62 ignore push
  22.  
  23. #include "yakpw.c"
  24.  
  25. #pragma msg 62 pop
  26.  
  27. extern struct Functions *functions;
  28.  
  29. /*
  30. **  The Tool's icon
  31. */
  32. static UWORD chip Yak[]=
  33. {
  34. /*-------- plane # 0 --------*/
  35.  
  36.   0x0000,  0x0000,
  37.   0x3fff,  0xff00,
  38.   0x3000,  0x0300,
  39.   0x37e1,  0xfb00,
  40.   0x3e73,  0x9f00,
  41.   0x37e1,  0xfb00,
  42.   0x3000,  0x0300,
  43.   0x3000,  0x0300,
  44.   0x3000,  0x0300,
  45.   0x3000,  0x0300,
  46.   0x3fff,  0xff00,
  47.   0x0000,  0x0000,
  48.  
  49. /*-------- plane # 1 --------*/
  50.  
  51.   0x0000,  0x0000,
  52.   0x0000,  0x0100,
  53.   0x081e,  0x0700,
  54.   0x081e,  0x0700,
  55.   0xc00c,  0x0300,
  56.   0xc81e,  0x0700,
  57.   0xcfff,  0xff00,
  58.   0xcfff,  0xff00,
  59.   0x0fff,  0xff00,
  60.   0x0fff,  0xff00,
  61.   0x1fff,  0xff00,
  62.   0x0000,  0x0000,
  63.  
  64. /*-------- plane # 2 --------*/
  65.  
  66.   0x0000,  0x0000,
  67.   0x0000,  0x0000,
  68.   0x0000,  0x0000,
  69.   0x0000,  0x0000,
  70.   0x0180,  0x6000,
  71.   0x0000,  0x0000,
  72.   0x003f,  0x0000,
  73.   0x0040,  0x8000,
  74.   0x0040,  0x8000,
  75.   0x003f,  0x0000,
  76.   0x0000,  0x0000,
  77.   0x0000,  0x0000
  78. };
  79.  
  80. static struct Image Yakimage=
  81. {
  82.   0,0,24,12,3,
  83.   Yak,
  84.   0x7,0x0,NULL
  85. };
  86.  
  87. #define STRINGSIZE        100   /* max size for each string */
  88. #define COMMENTSIZE       30    /* max size for label */
  89. #define ITEMHEIGHT        10    /* vertical size in display list */
  90.  
  91. typedef struct YakTool
  92. {
  93.   struct Tool tool;
  94.   char *strings[128];
  95.   char *comments[128];
  96.   unsigned char topindent;
  97.   unsigned char selectedvalue;
  98. } YakTool;
  99.  
  100. #pragma msg 72 ignore push
  101. struct Library *TranslatorBase;   /* need this to call Translate() */
  102. #pragma msg 72 pop
  103. static struct ToolMaster master;  /* out ToolMaster struct */
  104. static struct MsgPort *yakport;   /* port for process to receive messages */
  105.  
  106. typedef struct YakMessage
  107. {
  108.   struct Message message;       /* Exec message. */
  109.   YakTool *tool;                /* Tool to perform io. */
  110.   unsigned char value;          /* Note value. */
  111.   unsigned char vel;            /* Note velocity */
  112. } YakMessage;
  113.  
  114. #define PORTNAME   "YakPort"
  115.  
  116. /*
  117. ** void talk(char *string,short vel)
  118. **
  119. ** char *string;      string to "speak"
  120. ** char *vel;         velocity of the note, used for a volume
  121. **
  122. */
  123. void talk(char *string,short vel)
  124. {
  125.   char speech[200];                 /* translate buffer */
  126.   struct MsgPort *WPort;
  127.   struct narrator_rb *wmes;
  128.   static char masks[]={3,5,10,12};  /* audio channel masks to try */
  129.  
  130.   Translate(string,strlen(string),speech,sizeof(speech));
  131.   WPort=(struct MsgPort *)CreatePort(NULL,0);
  132.   if(WPort)
  133.   {
  134.       wmes=(struct narrator_rb *)CreateExtIO(WPort,sizeof(struct narrator_rb));
  135.     if(wmes)
  136.     {
  137.         wmes->ch_masks=masks;
  138.         wmes->nm_masks=sizeof(masks);
  139.         if(!(OpenDevice("narrator.device",0,(struct IORequest *)wmes,0)))
  140.       {
  141.         wmes->mouths=1;
  142.         wmes->volume=(vel+1)>>1;
  143. /*
  144.   set up for default values
  145. */
  146.         wmes->rate=DEFRATE;
  147.         wmes->pitch=DEFPITCH;
  148.         wmes->mode=DEFMODE;
  149.         wmes->sex=DEFSEX;
  150.         wmes->sampfreq=DEFFREQ;
  151.         wmes->message.io_Command=CMD_WRITE;
  152.         wmes->message.io_Data=speech;
  153.         wmes->message.io_Length=strlen(speech);
  154.         DoIO((struct IORequest *)wmes);
  155.         CloseDevice((struct IORequest *)wmes);
  156.       }
  157.       DeleteExtIO((struct IORequest *)wmes);
  158.     }
  159.     DeletePort(WPort);
  160.   }
  161. }
  162.  
  163. /*
  164. **  void yakprocess(void)
  165. **
  166. **  This is the process started up by the Yak Tool.  It does all
  167. **  I/O to the narrator device.
  168. */
  169. static void yakprocess(void)
  170. {
  171.   YakMessage *mm;
  172.   YakTool *tool;
  173.   char value,vel;
  174.  
  175.   TranslatorBase=OpenLibrary("translator.library",0);
  176.   if(TranslatorBase==NULL)
  177.       return;
  178.   yakport=CreatePort(PORTNAME,0);
  179.   if(yakport==NULL)
  180.   {
  181.     CloseLibrary(TranslatorBase);
  182.     return;
  183.   }
  184.   for(;;)
  185.   {
  186.     mm=(YakMessage *)GetMsg(yakport);
  187.     if(mm==NULL)
  188.     {
  189.       WaitPort(yakport);
  190.       mm=(YakMessage *)GetMsg(yakport);
  191.     }
  192.     tool=mm->tool;
  193.     value=mm->value;
  194.     vel=mm->vel;
  195.  
  196. /* don't reply - I can free it since I created it */
  197.  
  198.     functions->myfree((void *)mm,sizeof(YakMessage));
  199.  
  200.     if(tool==NULL)    /* message to quit process */
  201.         break;
  202.     talk(tool->strings[value],vel);
  203.   }
  204.   DeletePort(yakport);
  205.   CloseLibrary(TranslatorBase);
  206.  
  207. /* set yakport to NULL to indicate that this process has ended */
  208.   yakport=NULL;
  209. }
  210.  
  211. /*
  212. **  ret=sendcommand(YakTool *tool,unsigned char value,unsigned char vel);
  213. **
  214. **  YakTool *tool;        the tool sending the message
  215. **  unsigned char value;  the note value
  216. **  unsigned char vel;    the note velocity
  217. **
  218. **  Sends a message to our process.  returns non-zero on success.
  219. */
  220. static long sendcommand(YakTool *tool,unsigned char value,unsigned char vel)
  221. {
  222.   YakMessage *message;
  223.   struct MsgPort *iport=(struct MsgPort *)FindPort(PORTNAME);
  224.  
  225.   if(iport)
  226.   {
  227.     message=(YakMessage *)functions->myalloc(sizeof(YakMessage),MEMF_CLEAR);
  228.     if(message)
  229.     {
  230.       message->tool=tool;
  231.       message->value=value;
  232.       message->vel=vel;
  233.       PutMsg(iport,(struct Message *)message);
  234.       return 1;
  235.     }
  236.   }
  237.   return 0;
  238. }
  239.  
  240. /*
  241. **  struct Event *processeventcode(struct Event *event);
  242. **
  243. **  The Tool's processevent routine.
  244. */
  245. static struct Event *processeventcode(struct Event *event)
  246. {
  247.   YakTool *tool=(YakTool *)event->tool;
  248.  
  249. /*
  250.    if the event is a NOTE ON and the string to speak is not blank or NULL,
  251.    send a command to speak it.
  252. */
  253.   if(event->status==MIDI_NOTEON &&
  254.      tool->strings[event->byte1]!=NULL && tool->strings[event->byte1][0]!='\0')
  255.       sendcommand(tool,event->byte1,event->byte2);
  256.   event->tool=tool->tool.next;
  257.   return event;
  258. }
  259.  
  260. /*
  261. ** static void computenewsize(struct Window *window);
  262. **
  263. ** adjusts the height of the display list gadget after a window
  264. ** resixe operation.
  265. */
  266. static void computenewsize(struct Window *window)
  267. {
  268.   struct Gadget *gadget;
  269.   struct RastPort *rp=window->RPort;
  270.  
  271.   gadget=(struct Gadget *)functions->GetGadget(window,4);
  272.   SetDrMd(rp,JAM2);
  273.   SetAPen(rp,0);
  274.   BNDRYOFF(rp);
  275.   RectFill(rp,gadget->LeftEdge-2,gadget->TopEdge,1+gadget->LeftEdge+gadget->Width,
  276.            gadget->TopEdge+gadget->Height);
  277.   functions->EmbossOff(window,4);
  278.   gadget->Height=window->Height-gadget->TopEdge-4;
  279.   functions->EmbossOn(window,4,0);
  280. }
  281.  
  282. /*
  283. ** static void setscrollbar(struct Window *window,YakTool *tool);
  284. **
  285. ** sets the scroll bar for the display list to the proper level.
  286. */
  287. static void setscrollbar(struct Window *window,YakTool *tool)
  288. {
  289.   struct Gadget *gadget=(struct Gadget *)functions->GetGadget(window,4);
  290.   unsigned long height=(window->Height-gadget->TopEdge)/ITEMHEIGHT;
  291.  
  292.   if((tool->topindent+height)>=128)
  293.       tool->topindent=128-height;
  294.   functions->ModifyWindowProps(window,0,tool->topindent,0,128,0,height);
  295.   functions->RefreshEmbossedWindowFrame(window);
  296. }
  297.  
  298. /*
  299. ** static void drawstringlist(struct Window *window,YakTool *tool);
  300. **
  301. ** draws the display list.
  302. */
  303. static void drawstringlist(struct Window *window,YakTool *tool)
  304. {
  305.   struct RastPort *rp=window->RPort;
  306.   struct Gadget *gadget=(struct Gadget *)functions->GetGadget(window,4);
  307.   short y=gadget->TopEdge+ITEMHEIGHT-1;
  308.   short index;
  309.   short bottom=window->Height-ITEMHEIGHT-3;
  310.   char name[8],*p;
  311.   char text[120];
  312.  
  313.   SetDrMd(rp,JAM2);
  314.   SetBPen(rp,2);
  315.   for(index=tool->topindent ; index<128 ; ++index)
  316.   {
  317.     Move(rp,10,y-2);
  318.     if(index==tool->selectedvalue)
  319.         SetAPen(rp,6);
  320.     else
  321.         SetAPen(rp,4);
  322.     functions->notetostring(0,index,name);
  323.  
  324. /* if there's a label, use that */
  325.  
  326.     if(tool->comments[index] && tool->comments[index][0])
  327.         p=tool->comments[index];
  328.  
  329. /* else if there's text to speak, use that */
  330.  
  331.     else if(tool->strings[index] && tool->strings[index][0])
  332.         p=tool->strings[index];
  333.  
  334. /* otherwise, it's empty */
  335.  
  336.     else
  337.         p="« empty »";
  338.  
  339.     sprintf(text,"%4s:%-22.22s",name,p);
  340.     Text(rp,text,27);
  341.     if(y>=bottom)
  342.         break;
  343.     y+=ITEMHEIGHT;
  344.   }
  345. }
  346.  
  347. static YakTool *dragtool;
  348.  
  349. /*
  350. ** static vroutine(struct Window *window,struct Gadget *gadget,unsigned long x,unsigned long y);
  351. **
  352. ** callback routine for dragging the scrollbar of the display list.
  353. */
  354. static vroutine(struct Window *window,struct Gadget *gadget,unsigned long x,unsigned long y)
  355. {
  356.   if(dragtool)
  357.   {
  358.     if(dragtool->topindent!=y)
  359.     {
  360.       dragtool->topindent=y;
  361.       drawstringlist(window,dragtool);
  362.     }
  363.   }
  364.   return (long)y;
  365. }
  366.  
  367. /*
  368. ** static void setstrings(YakTool *tool);
  369. **
  370. ** This routine makes sure that the current string and label are non-NULL
  371. ** and also frees any blank strings it finds elsewhere.
  372. */
  373. static void setstrings(YakTool *tool)
  374. {
  375.   short index;
  376.   char *s;
  377.  
  378.   for(index=0 ; index<128 ; ++index)
  379.   {
  380.     if(index==tool->selectedvalue)
  381.     {
  382.       if(!tool->strings[index]) 
  383.           tool->strings[index]=(void *)functions->myalloc(STRINGSIZE,MEMF_CLEAR);
  384.       if(!tool->comments[index]) 
  385.           tool->comments[index]=(void *)functions->myalloc(COMMENTSIZE,MEMF_CLEAR);
  386.     }
  387.     else
  388.     {
  389.       if(s=tool->strings[index])
  390.       {
  391.         if(!s[0])
  392.         {
  393.           functions->myfree(s,STRINGSIZE);
  394.           tool->strings[index]=NULL;
  395.         }
  396.       }
  397.       if(s=tool->comments[index])
  398.       {
  399.         if(!s[0])
  400.         {
  401.           functions->myfree(s,COMMENTSIZE);
  402.           tool->comments[index]=NULL;
  403.         }
  404.       }
  405.     }
  406.   }
  407. }
  408.  
  409. /*
  410. ** static short indextostring(struct Window *window,YakTool *tool,short y);
  411. **
  412. ** based on the mouse Y position, return the item # in the display list
  413. ** that was selected.
  414. */
  415. static short indextostring(struct Window *window,YakTool *tool,short y)
  416. {
  417.   struct Gadget *gadget=(struct Gadget *)functions->GetGadget(window,4);
  418.  
  419.   y-=gadget->TopEdge;
  420.   y/=ITEMHEIGHT;
  421.   y+=tool->topindent;
  422.   return y;
  423. }
  424.  
  425. /*
  426. ** static long sizetool(YakTool *tool);
  427. **
  428. ** return the total size of the tool for save purposes.
  429. */
  430. static long sizetool(YakTool *tool)
  431. {
  432.   long size=sizeof(YakTool);
  433.   short id;
  434.  
  435.   for(id=0 ; id<128 ; ++id)
  436.   {
  437.     if(tool->strings[id])
  438.         size+=STRINGSIZE;
  439.     if(tool->comments[id])
  440.         size+=COMMENTSIZE;
  441.   }
  442.   return size;
  443. }
  444.  
  445. /*
  446. ** static long savetool(long file,YakTool *tool);
  447. **
  448. ** save the tool and the dynamically allocated strings to the file
  449. */
  450. static long savetool(long file,YakTool *tool)
  451. {
  452.   long id=ID_YAKK;
  453.  
  454.   functions->fastwrite(file,(char *)&id,4);
  455.   id=sizetool(tool);
  456.   functions->fastwrite(file,(char *)&id,4);
  457.   if(functions->fastwrite(file,(char *)tool,sizeof(YakTool))==-1)
  458.       return 1;
  459.   for(id=0 ; id<128 ; ++id)
  460.   {
  461.     if(tool->strings[id])
  462.     {
  463.       if(functions->fastwrite(file,tool->strings[id],STRINGSIZE)==-1)
  464.           return 1;
  465.     }
  466.   }
  467.   for(id=0 ; id<128 ; ++id)
  468.   {
  469.     if(tool->comments[id])
  470.     {
  471.       if(functions->fastwrite(file,tool->comments[id],COMMENTSIZE)==-1)
  472.           return 1;
  473.     }
  474.   }
  475.   return 0;
  476. }
  477.  
  478. /*
  479. ** static struct Tool *loadtool(long file,long size);
  480. **
  481. ** load the tool and read in strings as necessary.
  482. */
  483. static struct Tool *loadtool(long file,long size)
  484. {
  485.   YakTool *tool=(YakTool *)functions->myalloc(sizeof(YakTool),MEMF_CLEAR);
  486.   short i;
  487.  
  488.   if(tool)
  489.   {
  490.     functions->fastread(file,(char *)tool,sizeof(YakTool));
  491.     size-=sizeof(YakTool);
  492.     for(i=0 ; i<128 ; ++i)
  493.     {
  494.       if(tool->strings[i])
  495.       {
  496.         tool->strings[i]=(void *)functions->myalloc(STRINGSIZE,0);
  497.         if(tool->strings[i])
  498.         {
  499.           functions->fastread(file,tool->strings[i],STRINGSIZE);
  500.           size-=STRINGSIZE;
  501.         }
  502.       }
  503.     }
  504.     for(i=0 ; i<128 ; ++i)
  505.     {
  506.       if(tool->comments[i])
  507.       {
  508.         tool->comments[i]=(void *)functions->myalloc(COMMENTSIZE,0);
  509.         if(tool->comments[i])
  510.         {
  511.           functions->fastread(file,tool->comments[i],COMMENTSIZE);
  512.           size-=COMMENTSIZE;
  513.         }
  514.       }
  515.     }
  516.   }
  517.   functions->fastseek(file,size,0);
  518.   return (struct Tool *)tool;
  519. }
  520.  
  521. /*
  522. ** static void cleartool(YakTool *tool);
  523. **
  524. ** reset all strings to be blank and free their memory.
  525. */
  526. static void cleartool(YakTool *tool)
  527. {
  528.   short i;
  529.  
  530.   for(i=0 ; i<128 ; ++i)
  531.   {
  532.     if(tool->strings[i])
  533.     {
  534.       functions->myfree(tool->strings[i],STRINGSIZE);
  535.       tool->strings[i]=NULL;
  536.     }
  537.     if(tool->comments[i])
  538.     {
  539.       functions->myfree(tool->comments[i],COMMENTSIZE);
  540.       tool->comments[i]=NULL;
  541.     }
  542.   }
  543. }
  544.  
  545. /*
  546. ** static struct Tool *createtool(YakTool *copy);
  547. **
  548. ** create a tool and handle making a copy
  549. */
  550. static struct Tool *createtool(YakTool *copy)
  551. {
  552.   YakTool *tool=(YakTool *)functions->myalloc(sizeof(YakTool),MEMF_CLEAR);
  553.   short i;
  554.  
  555.   if(tool)
  556.   {
  557.     if(copy)
  558.     {
  559.       *tool=*copy;
  560.       tool->tool.next=NULL;
  561.       for(i=0 ; i<128 ; ++i)
  562.       {
  563.         if(copy->strings[i])
  564.         {
  565.           tool->strings[i]=(void *)functions->myalloc(STRINGSIZE,MEMF_CLEAR);
  566.           if(tool->strings[i])
  567.               memcpy(tool->strings[i],copy->strings[i],STRINGSIZE);
  568.         }
  569.         if(copy->comments[i])
  570.         {
  571.           tool->comments[i]=(void *)functions->myalloc(COMMENTSIZE,MEMF_CLEAR);
  572.           if(tool->comments[i])
  573.               memcpy(tool->comments[i],copy->comments[i],COMMENTSIZE);
  574.         }
  575.       }
  576.     }
  577.   }
  578.   return (struct Tool *)tool;
  579. }
  580.  
  581. /*
  582. ** static void deletetool(YakTool *tool);
  583. **
  584. ** delete a tool and free all dynamically allocated memory
  585. */
  586. static void deletetool(YakTool *tool)
  587. {
  588.   cleartool(tool);
  589.   functions->myfree((char *)tool,sizeof(YakTool));
  590. }
  591.  
  592. /*
  593. ** static long loadYakTool(YakTool *tool);
  594. **
  595. ** load a list of text previously saved.
  596. **
  597. ** To save time and code this is implemented by just saving the whole
  598. ** tool, loading it in, grabbing what is needed from the loaded in tool,
  599. ** and then freeing the loaded tool.
  600. */
  601. static long loadYakTool(YakTool *tool)
  602. {
  603.   long file;
  604.   char filename[100];
  605.   YakTool *newtool=NULL;
  606.   long id, size;
  607.  
  608.   functions->FileName(filename,"Load List:","yaklist",functions->screen,
  609.                       FILES_OPEN|FILES_DELETE,0,0);
  610.   if(filename[0])
  611.   {
  612.     file=functions->fastopen(filename,MODE_OLDFILE);
  613.     if(file)
  614.     {
  615.       functions->openwait();
  616.       functions->fastread(file,(char *)&id,4);
  617.       functions->fastread(file,(char *)&size,4);
  618.       if(id==ID_YAKK)
  619.       {
  620.         newtool=(struct YakTool *)loadtool(file,size);
  621.         if(newtool)
  622.         {
  623.           cleartool(tool);
  624.           for(id=0 ; id<128 ; ++id)
  625.               tool->strings[id]=newtool->strings[id];
  626.           for(id=0 ; id<128 ; ++id)
  627.               tool->comments[id]=newtool->comments[id];
  628.           functions->myfree((char *)newtool,sizeof(struct YakTool));
  629.         }
  630.       }
  631.       functions->fastclose(file);
  632.       functions->closewait();
  633.     }
  634.   }
  635.   return (newtool!=NULL);
  636. }
  637.  
  638. /*
  639. ** static void saveYakTool(YakTool *tool);
  640. **
  641. ** saves the list of text currently defined.  (see loadYakTool).
  642. */
  643. static void saveYakTool(YakTool *tool)
  644. {
  645.   char filename[100];
  646.   long file;
  647.  
  648.   functions->FileName(filename,"Save List:","yaklist",functions->screen,
  649.                       FILES_SAVE|FILES_DELETE,0,0);
  650.   if(filename[0])
  651.   {
  652.     file=functions->fastopen(filename,MODE_NEWFILE);
  653.     if(file)
  654.     {
  655.       functions->openwait();
  656.       savetool(file,tool);
  657.       functions->closewait();
  658.       functions->fastclose(file);
  659.     }
  660.   }
  661. }
  662.  
  663. /*
  664. ** void assignhits(YakTool *tool);
  665. **
  666. ** This assigns the hitlist based on the text stored in the tool.
  667. */
  668. void assignhits(YakTool *tool)
  669. {
  670.   struct HitName *top,*prev,*hn,*hp;
  671.   short i;
  672.   char *p;
  673.  
  674.   top=NULL;
  675.   for(i=0 ; i<128 ; ++i)
  676.   {
  677. /* If there's a label, use that */
  678.     if(tool->comments[i] && tool->comments[i][0])
  679.         p=tool->comments[i];
  680.  
  681. /* otherwise just use the text */
  682.     else if(tool->strings[i] && tool->strings[i][0])
  683.         p=tool->strings[i];
  684.  
  685. /* if no text, skip this note */
  686.     else
  687.         p=NULL;
  688.     if(p)
  689.     {
  690.       hn=(void *)functions->myalloc(sizeof(struct HitName),MEMF_CLEAR);
  691.       if(hn)
  692.       {
  693.  
  694. /* insert the hit into the list sorted by the hit name */
  695.  
  696.         hn->note=i;
  697.         strncpy(hn->name,p,sizeof(hn->name)-1);
  698.         if(top==NULL)
  699.             top=hn;
  700.         else
  701.         {
  702.           prev=NULL;
  703.           for(hp=top ; hp!=NULL ; hp=hp->next)
  704.           {
  705.             if(stricmp(hp->name,hn->name)>=0)
  706.                 break;
  707.             prev=hp;
  708.           }
  709.           if(prev)
  710.           {
  711.             hn->next=prev->next;
  712.             prev->next=hn;
  713.           }
  714.           else
  715.           {
  716.             hn->next=top;
  717.             top=hn;
  718.           }
  719.         }
  720.       }
  721.     }
  722.   }
  723.  
  724. /* install the hit list */
  725.  
  726.   functions->installhitlist(tool->tool.track,top);
  727. }
  728.  
  729. /*
  730. ** void edittoolcode(YakTool *tool);
  731. **
  732. ** open the YakTool editing window & edit the tool info.
  733. */
  734. void edittoolcode(YakTool *tool)
  735. {
  736.   struct IntuiMessage *message;
  737.   struct Window *window;
  738.   long class,code;
  739.   struct Gadget *gadget;
  740.   struct NewWindow *newwindow;
  741.   char refresh=1;
  742.   short mousey,menunum,itemnum;
  743.   struct MenuItem *item;
  744.   char notename[20];
  745.   struct StringInfo *stringinfo;
  746.  
  747.   if(!tool->tool.touched)
  748.   {
  749.     tool->topindent=tool->selectedvalue=60;
  750.   }
  751.   yakNewWindowStructure1.Screen=functions->screen;
  752.   if(tool->tool.touched & TOUCH_EDIT)
  753.   {
  754.     yakNewWindowStructure1.LeftEdge=tool->tool.left;
  755.     yakNewWindowStructure1.TopEdge=tool->tool.top;
  756.   }
  757.  
  758. /*
  759.   duplicate the newwindow struct since each tool needs it's own copy
  760. */
  761.   newwindow=(struct NewWindow *)functions->DupeNewWindow(&yakNewWindowStructure1);
  762.   if(!newwindow)
  763.       return;
  764.  
  765. /*
  766.   set up newwindow flags for B&P Pro look
  767. */
  768.   newwindow->Title=NULL;
  769.   newwindow->Flags|=BORDERLESS;
  770.   newwindow->Flags&=~0xF;
  771.   newwindow->DetailPen=0;
  772.   newwindow->BlockPen=0;
  773.   window=(struct Window *)functions->FlashyOpenWindow(newwindow);
  774.   if(!window)
  775.   {
  776.     functions->DeleteNewWindow(newwindow);
  777.     return;
  778.   }
  779.   SetMenuStrip(window,&yakMenu1);
  780.   tool->tool.window=window;
  781.  
  782. /*
  783.   turn on the B&P Pro border
  784. */
  785.   functions->EmbossWindowOn(window,WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG|WINDOWSIZING,
  786.                             "Yak",(short)-1,38,0,(void *)vroutine);
  787.   functions->EmbossOn(window,1,3);
  788.   functions->EmbossOn(window,3,3);
  789.   functions->EmbossOn(window,4,0);
  790.   computenewsize(window);
  791.   for(;;)
  792.   {
  793.     if(refresh)
  794.     {
  795.       setstrings(tool);
  796. /*
  797.   refresh the string gadgets to reflect the currently
  798.   selected note
  799. */
  800.       functions->notetostring(0,tool->selectedvalue,notename);
  801.       gadget=(struct Gadget *)functions->GetGadget(window,1);
  802.       sprintf(gadget->GadgetText->IText,"%4s:",notename);
  803.       stringinfo=(void *)functions->GetStringInfo(window,1);
  804.       stringinfo->Buffer=tool->strings[tool->selectedvalue];
  805.       functions->RefreshGadget(window,1);
  806.       stringinfo=(void *)functions->GetStringInfo(window,3);
  807.       stringinfo->Buffer=tool->comments[tool->selectedvalue];
  808.       functions->RefreshGadget(window,3);
  809. /*
  810.   make sure the display list is displayed properly
  811. */
  812.       setscrollbar(window,tool);
  813.       drawstringlist(window,tool);
  814.       if(refresh==2)
  815.           ActivateGadget((struct Gadget *)functions->GetGadget(window,1),window,0);
  816.       refresh=0;
  817.     }
  818.     message=(struct IntuiMessage *)functions->GetIntuiMessage(window);
  819.     class=message->Class;
  820.     code=message->Code;
  821.     mousey=message->MouseY;
  822.     gadget=(struct Gadget *)message->IAddress;
  823.     dragtool=tool;
  824. /*
  825.   call B&P Pro system gadget handler - it handles thing like the
  826.   close gadget & the front/back gadget as well as scrollbars
  827. */
  828.     class=functions->SystemGadgets(window,class,gadget,code);
  829.     dragtool=NULL;
  830.     ReplyMsg((struct Message *)message);
  831.     if(class==CLOSEWINDOW)
  832.         break;
  833.     else if(class==NEWSIZE)
  834.     {
  835.       setscrollbar(window,tool);
  836.       computenewsize(window);
  837.       refresh=1;
  838.     }
  839.     else if(class==GADGETDOWN)
  840.     {
  841.       switch(gadget->GadgetID)
  842.       {
  843.       case 4:   /* clicked on the display list, select a new note */
  844.         tool->selectedvalue=indextostring(window,tool,mousey) & 0x7F;
  845.         refresh=2;
  846.         break;
  847.       }
  848.     }
  849.     else if(class==GADGETUP)
  850.     {
  851.       switch(gadget->GadgetID)
  852.       {
  853.       case 1:   /* the text string */
  854.         ActivateGadget((struct Gadget *)functions->GetGadget(window,3),window,0);
  855.         drawstringlist(window,tool);
  856.         assignhits(tool);
  857.         break;
  858.       case 3:   /* the label, increment the selected note */
  859.         ++tool->selectedvalue;
  860.         tool->selectedvalue&=0x7F;
  861.         tool->topindent=tool->selectedvalue;
  862.         if(tool->topindent>0)
  863.             --tool->topindent;
  864.         refresh=2;
  865.         assignhits(tool);
  866.         break;
  867.       }
  868.     }
  869.     else if(class==MENUPICK)
  870.     {
  871.       while(code!=MENUNULL)
  872.       {
  873.         menunum=MENUNUM(code); 
  874.         itemnum=ITEMNUM(code); 
  875.         item=(struct MenuItem *)ItemAddress(window->MenuStrip,code); 
  876.         code=item->NextSelect; 
  877.         if(menunum==0)
  878.         { 
  879.           switch(itemnum)
  880.           {
  881.           case 0:        /* New. */
  882.             if(functions->areyousure("Clear this list?"))
  883.             {
  884.               cleartool(tool);
  885.               refresh=1;
  886.             }
  887.             assignhits(tool);
  888.             break;
  889.           case 1:        /* Load. */
  890. /*
  891.   must do a functions->doscall() to do DOS functions since we
  892.   are only a lowly Task.
  893. */
  894.             if(functions->areyousure("Replace this list?"))
  895.                 refresh=functions->doscall(loadYakTool,tool);
  896.             assignhits(tool);
  897.             break;
  898.           case 2:        /* Save. */
  899.             functions->doscall(saveYakTool,tool);
  900.             break;
  901.           }
  902.         }
  903.       }            
  904.     }
  905.   }
  906. /*
  907.   turn off all B&P Pro embossed buttons & window embossing
  908. */
  909.   functions->EmbossOff(window,1);
  910.   functions->EmbossOff(window,3);
  911.   functions->EmbossOff(window,4);
  912.   functions->EmbossWindowOff(window);
  913.   tool->tool.window=0;
  914.   tool->tool.left=window->LeftEdge;
  915.   tool->tool.top=window->TopEdge;
  916.   tool->tool.touched=TOUCH_INIT|TOUCH_EDIT;
  917. /*
  918.   close the window & get out.
  919. */
  920.   ClearMenuStrip(window);
  921.   functions->FlashyCloseWindow(window);
  922.   functions->DeleteNewWindow(newwindow);
  923. }
  924.  
  925. /*
  926. ** void removetool(void);
  927. **
  928. ** handle removing the tool.
  929. */
  930. void removetool(void)
  931. {
  932.   sendcommand(NULL,0,0);    /* close down the process */
  933.   while(yakport!=NULL)
  934.       WaitTOF();            /* wait till the process is done */
  935.   WaitTOF();                /* just to make ABSOLUTELY sure */
  936. }
  937.  
  938. typedef struct CodeHdr
  939. {
  940.   ULONG SegSize;
  941.   ULONG NextSeg;
  942.   UWORD JumpInstr;
  943.   APTR  Function;
  944. } CodeHdr;
  945.  
  946. #define T_BPTR(x) ((BPTR)(((ULONG)(x))>>2))
  947.  
  948. /*
  949. ** static long StartProcess(char *name,short priority,APTR code,long stacksize);
  950. **
  951. ** this is a WB 1.3 compatible way to start a new process.
  952. */
  953. static long StartProcess(char *name,short priority,APTR code,long stacksize)
  954. {
  955.   static __aligned CodeHdr chead;
  956.  
  957.   chead.SegSize=sizeof(CodeHdr);
  958.   chead.JumpInstr=0x4EF9;
  959.   chead.Function=code;
  960.   return (long)CreateProc(name,priority,T_BPTR(&chead.NextSeg),stacksize);
  961. }
  962.  
  963. /*
  964. ** static long mmfunc(YakTool *tool,long cmd);
  965. **
  966. ** handle multimediafunc() commands
  967. */
  968. static long mmfunc(YakTool *tool,long cmd)
  969. {
  970.   if(cmd==MMCMD_INSTALLHITLIST)
  971.   {
  972.     assignhits(tool);
  973.     return 1;
  974.   }
  975.   return 0;
  976. }
  977.  
  978. /*
  979. ** struct ToolMaster *inittoolmaster(void);
  980. **
  981. ** initialize the Yak tool.
  982. */
  983. struct ToolMaster *inittoolmaster(void)
  984. {
  985.   if(FindPort(PORTNAME))  /* I'm already loaded, don't load again */
  986.       return NULL;
  987.  
  988.   strcpy(master.name,"Yak");
  989.   master.toolid      =ID_YAKK;
  990.   master.image       =&Yakimage;
  991.   master.edittool    =edittoolcode;
  992.   master.processevent=processeventcode;
  993.   master.deletetool  =deletetool;
  994.   master.loadtool    =loadtool;
  995.   master.savesize    =sizetool;
  996.   master.savetool    =savetool;
  997.   master.createtool  =createtool;
  998.   master.removetool  =removetool;
  999.   master.multimediafunc=mmfunc;
  1000.   master.tooltype    =TOOL_OUTPUT|TOOL_ONTIME;
  1001.   master.toolsize    =sizeof(YakTool);
  1002.  
  1003. /* start up the process to do narrator device I/O */
  1004.  
  1005.   if(!StartProcess("YakProc",0,yakprocess,6000))
  1006.       return NULL;
  1007.  
  1008.   return &master;
  1009. }
  1010.