home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / glib / part13 / glib.c
Encoding:
C/C++ Source or Header  |  1989-05-21  |  40.7 KB  |  2,119 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Id: glib.c,v 1.6 89/05/06 17:13:24 lee Exp $";
  3. #endif
  4. /*
  5.  * GLIB - a Generic LIBrarian and editor for synths
  6.  *
  7.  * Tim Thompson's original with modifications by Michael Kesti,
  8.  *    Greg Lee, Alan Bland, Scott Snyder, Mark Rinfret
  9.  * $Log:    glib.c,v $
  10.  * Revision 1.6  89/05/06  17:13:24  lee
  11.  * rel. to comp.sources.misc
  12.  * 
  13.  */
  14.  
  15. #include "glib.h"
  16. #include <ctype.h>
  17.  
  18. char *Reason = "";
  19.  
  20. int Currrow = 0;    /* at top of screen, for messages */
  21. int Libbank = 0;    /* from 0 to LIBBANKS-1, is the current library bank*/
  22. int Nsynths = 0;
  23.  
  24. int Lastvalue = 0;
  25.  
  26. char *Currdata;
  27. char *Yankdata;        /* current 'yank' buffer (middle of screen) */
  28.  
  29. struct peredinfo *PE;    /* array of per-editor miscellany */
  30.  
  31. char Buff[BUFSIZ];
  32. int Redraw = 0;        /* if non-0, edit screen is completely redrawn. */
  33.             /* parameter functions can make use of this. */
  34. int Changed = 0;
  35. int DataID = 0;        /* Data Id for file write and read operations */
  36.  
  37. /* All the global values below are set as appropriate for the */
  38. /* synthesizer currently being dealt with. */
  39.  
  40. int Nvoices = 0;
  41. int Voicesize =0;
  42. int Namesize = 0;
  43. int Libindex;        /* from 0 to Nvoices-1 */
  44. int Synindex;        /* from 0 to Nvoices-1 */
  45. int Channel;
  46. int Editrow;        /* from 0 to NUMONSCREEN-1 */
  47. int Editcol;        /* 0==synth, 1==library */
  48. char *Libdata;        /* current library data (includes all LIBBANKS) */
  49.             /* ie. the stuff on the right side of the screen */
  50. char *Syndata;        /* current synth data (1 bank), ie. the left side */
  51. struct paraminfo *P;    /* list of parameter info */
  52. struct labelinfo *L;    /* arbitrary screen labels for edit screen */
  53. char *Synthname;
  54. #ifdef SSS
  55. int *scr_p;
  56. int NParams;
  57. #endif
  58. #ifdef KAWAIK1
  59. char sngnames[64][11];
  60. #endif
  61.  
  62. int synthinfileflag = 0;
  63. int synthoutfileflag = 0;
  64. char Syinfname[100], Syofname[100];
  65.  
  66. int (*Sendedit)();    /* function to send parameters to synth's edit buffer*/
  67. int (*Datain)();    /* convert data from file-storage format to the */
  68.             /* format stored in the P[] parameter array (p_val) */
  69. int (*Dataout)();    /* reverse of Datain */
  70. int (*Sendone)();    /* function to send one (permanent) voice to synth */
  71. int (*Sendbulk)();    /* function to send bulk dump to synth */
  72. int (*Getbulk)();    /* reverse of Sendbulk */
  73. char *(*Nameof)();    /* pulls voice name out of file-storage data */
  74. int (*Setnameof)();    /* reverse of Nameof */
  75. char *(*Numof)();    /* convert voice number to on-screen text */
  76. int (*Cvtnum)();    /* convert visible voice number to std. format */
  77. int (*Cvtanum)();    /* convert alphanumeric voice number to std. format */
  78.             /* should never define both Cvtnum and Cvtanum */
  79.  
  80. #ifdef SSS
  81. # define PARAMAT(r, c) (*(scr_p + Cols*(r) + (c)))
  82. #endif
  83.  
  84. main()
  85. {
  86.     int n;
  87.  
  88.     hello();
  89.     windinit();
  90.     initstuff();
  91.  
  92.     if ( Nsynths == 0 )
  93.         windstr("Hey, the E array is empty?");
  94.     else if ( Nsynths == 1 ) {
  95.         /* If there's only 1 synth, don't bother asking */
  96.         setedit(0);
  97.         libinteract();
  98.     }
  99.     else {
  100.         while ( (n=choosesynth()) >= 0 ) {
  101.             setedit(n);
  102.             libinteract();
  103.             unsetedit(n);
  104.         }
  105.     }
  106.     bye();
  107. }
  108.  
  109. /* choose a synth, returning its position in the E array */
  110. choosesynth()
  111. {
  112.     int n, pick;
  113.  
  114.     retry:
  115.     flushconsole();
  116.     windclear();
  117.     windgoto(2,23);
  118. #ifdef KAWAIK1
  119.     windstr("Kawai K1 Librarian/Editor");
  120. #else
  121. #ifdef ROLANDD10
  122.     windstr("Roland D-10 Librarian/Editor");
  123. #else
  124.     windstr("GLIB - A Generic Librarian/Editor");
  125. #endif
  126. #endif
  127.  
  128.     for ( n=1; n<=Nsynths; n++ )
  129.         libchoice(n);
  130.     windgoto(8+Nsynths,27);
  131.     windstr("q  -  Quit");
  132.     windgoto(11+Nsynths,27);
  133.     windstr("Make selection --> ");
  134.     windrefresh();
  135.     pick = mouseorkey();
  136.     if ( pick == 'q' || pick == EOF )
  137.         return(-1);
  138.     if ( pick != MOUSE )
  139.         pick = pick - '0';
  140.     else {
  141.         int row, col;
  142.         getmouse(&row,&col);
  143.         /* wait until mouse goes down */
  144.         while ( statmouse() > 0 )
  145.             ;
  146.         pick = row - 6; 
  147.     }
  148.     if ( pick < 1 || pick > Nsynths )
  149.         goto retry;
  150.     return(pick-1);
  151. }
  152.  
  153. libchoice(n)
  154. {
  155.     windgoto(6+n,27);
  156.     (void)sprintf(Buff,"%d  -  %s",n,E[n-1].ed_name);
  157.     windstr(Buff);
  158. }
  159.  
  160. #ifndef SINGLEDATA
  161.  
  162. initstuff()
  163. {
  164.     int n, banksize, maxvsize;
  165.     
  166.     maxvsize = 0;
  167.     for ( n=0; E[n].ed_name != NULL; n++ ) {
  168.         if ( maxvsize < E[n].ed_vsize )
  169.             maxvsize = E[n].ed_vsize;
  170.     }
  171.     Nsynths = n;
  172.     Currdata = alloc( maxvsize );
  173.  
  174.     /* allocate an array of peredinfo structs */
  175.     PE =(struct peredinfo *)alloc((int)(Nsynths*sizeof(struct peredinfo)));
  176.     for ( n=0; n<Nsynths; n++ ) {
  177.         banksize =  E[n].ed_nvoices * E[n].ed_vsize;
  178.  
  179.         PE[n].ed_libdata = alloc(LIBBANKS * banksize);
  180.         clrdata(PE[n].ed_libdata, LIBBANKS * banksize);
  181.  
  182.         PE[n].ed_syndata = alloc(banksize);
  183.         clrdata(PE[n].ed_syndata, banksize);
  184.  
  185.         PE[n].ed_yankdata = alloc(E[n].ed_vsize);
  186.         clrdata(PE[n].ed_yankdata, E[n].ed_vsize);
  187.  
  188.         PE[n].ed_libindex = 0;
  189.         PE[n].ed_synindex = 0;
  190.         PE[n].ed_channel = 1;
  191.         PE[n].ed_erow = 0;
  192.         PE[n].ed_ecol = 0;
  193.     }
  194. }
  195.  
  196. #else
  197.  
  198. initstuff()
  199. {
  200.     int n, banksize, maxvsize;
  201.     char *lib, *syn, *yank;
  202.     
  203.     maxvsize = 0;
  204.     for ( n=0; E[n].ed_name != NULL; n++ ) {
  205.         if ( maxvsize < E[n].ed_vsize )
  206.             maxvsize = E[n].ed_vsize;
  207.     }
  208.     Nsynths = n;
  209.     Currdata = alloc( maxvsize );
  210.  
  211.     PE =(struct peredinfo *)alloc((int)(Nsynths*sizeof(struct peredinfo)));
  212.  
  213.     /* allocate common data areas */
  214.     banksize =  E[0].ed_nvoices * E[0].ed_vsize;
  215.  
  216.     lib = alloc(LIBBANKS * banksize);
  217.     clrdata(lib, LIBBANKS * banksize);
  218.  
  219.     syn = alloc(banksize);
  220.     clrdata(syn, banksize);
  221.  
  222.     yank = alloc(E[0].ed_vsize);
  223.     clrdata(yank, E[0].ed_vsize);
  224.  
  225.     for ( n=0; n<Nsynths; n++ ) {
  226.         PE[n].ed_libdata = lib;
  227.         PE[n].ed_syndata = syn;
  228.         PE[n].ed_yankdata = yank;
  229.         PE[n].ed_libindex = 0;
  230.         PE[n].ed_synindex = 0;
  231.         PE[n].ed_channel = 1;
  232.         PE[n].ed_erow = 0;
  233.         PE[n].ed_ecol = 0;
  234.     }
  235. }
  236.  
  237. #endif
  238.  
  239. clrdata(data,size)
  240. char *data;
  241. {
  242.     register char *p, *endp;
  243.  
  244.     p = data;
  245.     endp = data+size;
  246.  
  247.     while ( p<endp )
  248.         *p++ = 0;
  249. }
  250.  
  251. #ifdef SSS
  252. int paramcmp(p1, p2)
  253. struct paraminfo *p1, *p2;
  254. {
  255.   return strcmp(p1->p_name, p2->p_name);
  256. }
  257.  
  258. init_params()
  259. {
  260.   int i;
  261.  
  262.   for (NParams=0; P[NParams].p_name != NULL; NParams++)
  263.     ;
  264.   qsort((void *)P, NParams, sizeof(struct paraminfo), paramcmp);
  265.  
  266.   scr_p = (int *)alloc(Rows * Cols * sizeof(int));
  267.   clrdata((char *)scr_p, Rows * Cols * sizeof(int));
  268.   for (i=0; i<NParams; i++) {
  269.     int r = P[i].p_vrow;
  270.     int c = P[i].p_vcol;
  271.  
  272.     if (r >= 0 && r < Rows && c >= 0 && c < Cols)
  273.       PARAMAT(r, c) = i+1;
  274.   }
  275. }
  276. #endif
  277.  
  278. #ifndef SINGLEDATA
  279.  
  280. setedit(n)
  281. {
  282.     Synthname = E[n].ed_name;
  283.     Datain = E[n].ed_din;
  284.     Dataout = E[n].ed_dout;
  285.     Nvoices = E[n].ed_nvoices;
  286.     Sendedit = E[n].ed_sedit;
  287.     Sendone = E[n].ed_sone;
  288.     Sendbulk = E[n].ed_sbulk;
  289.     Getbulk = E[n].ed_gbulk;
  290.     Nameof = E[n].ed_nof;
  291.     Numof = E[n].ed_numof;
  292.     Cvtnum = E[n].ed_cvtnum;
  293.     Cvtanum = E[n].ed_cvtanum;
  294.     Setnameof = E[n].ed_snof;
  295.     Voicesize = E[n].ed_vsize;
  296.     Namesize = E[n].ed_nsize;
  297.     DataID = E[n].ed_dataid;
  298.     Libdata = PE[n].ed_libdata;
  299.     Syndata = PE[n].ed_syndata;
  300.     Yankdata = PE[n].ed_yankdata;
  301.     Libindex = PE[n].ed_libindex;
  302.     Synindex = PE[n].ed_synindex;
  303.     Channel = PE[n].ed_channel;
  304.     Editrow = PE[n].ed_erow;
  305.     Editcol = PE[n].ed_ecol;
  306.     clrdata(Currdata,Voicesize);
  307.     P = E[n].ed_params;
  308.     L = E[n].ed_labels;
  309.  
  310. #ifdef SSS
  311.         init_params();
  312. #endif
  313. }
  314.  
  315. unsetedit(n)
  316. {
  317.     int k;
  318.  
  319.     DataID = 0;
  320.     PE[n].ed_libindex = Libindex;
  321.     PE[n].ed_synindex = Synindex;
  322.     PE[n].ed_channel = Channel;
  323.     PE[n].ed_erow = Editrow;
  324.     PE[n].ed_ecol = Editcol;
  325.     for ( k=0; k<Voicesize; k++ )
  326.         PE[n].ed_yankdata[k] = Yankdata[k];
  327. }
  328.  
  329. #else
  330.  
  331. setedit(n)
  332. {
  333.     Synthname = E[n].ed_name;
  334.     Datain = E[n].ed_din;
  335.     Dataout = E[n].ed_dout;
  336.     Nvoices = E[n].ed_nvoices;
  337.     Sendedit = E[n].ed_sedit;
  338.     Sendone = E[n].ed_sone;
  339.     Sendbulk = E[n].ed_sbulk;
  340.     Getbulk = E[n].ed_gbulk;
  341.     Nameof = E[n].ed_nof;
  342.     Numof = E[n].ed_numof;
  343.     Cvtnum = E[n].ed_cvtnum;
  344.     Cvtanum = E[n].ed_cvtanum;
  345.     Setnameof = E[n].ed_snof;
  346.     Voicesize = E[n].ed_vsize;
  347.     Namesize = E[n].ed_nsize;
  348.     DataID = E[n].ed_dataid;
  349.     Libdata = PE[n].ed_libdata;
  350.     Syndata = PE[n].ed_syndata;
  351.     Yankdata = PE[n].ed_yankdata;
  352.     Libindex = PE[n].ed_libindex;
  353.     Synindex = PE[n].ed_synindex;
  354.     Channel = PE[n].ed_channel;
  355.     Editrow = PE[n].ed_erow;
  356.     Editcol = PE[n].ed_ecol;
  357.     clrdata(Currdata,Voicesize);
  358.     P = E[n].ed_params;
  359.     L = E[n].ed_labels;
  360. #ifdef SSS
  361.         init_params();
  362. #endif
  363. }
  364.  
  365. unsetedit(n)
  366. {
  367.     int j, k;
  368.  
  369.     DataID = 0;
  370.     for(j=0; j < Nsynths; j++) {
  371.         PE[j].ed_libindex = Libindex;
  372.         PE[j].ed_synindex = Synindex;
  373.         PE[j].ed_channel = Channel;
  374.         PE[j].ed_erow = Editrow;
  375.         PE[j].ed_ecol = Editcol;
  376.         for ( k=0; k<Voicesize; k++ ) {
  377.             PE[j].ed_yankdata[k] = Yankdata[k];
  378.         }
  379.     }
  380. }
  381.  
  382. #endif
  383.  
  384. /* template - show the boxes and such on the main library screen */
  385. template()
  386. {
  387.     int n, k, r;
  388.  
  389.     r = FIRSTROW-1;
  390.     (void)sprintf(Buff,"%s",Synthname);
  391.     n = 13 - strlen(Buff)/2;    /* center it */
  392.     windgoto(r,n<0?0:n);
  393.     windstr(Buff);
  394.     r++;
  395.     windgoto(r,0);
  396.     for ( n=0; n<25; n++ )
  397.         windputc('=');
  398.     windgoto(r,53);
  399.     for ( n=0; n<25; n++ )
  400.         windputc('=');
  401.     for ( n=r+1; n<(r+13); n++ ) {
  402.         windgoto(n,0);
  403.         windputc('|');
  404.         windgoto(n,5);
  405.         windputc('|');
  406.         windgoto(n,24);
  407.         windputc('|');
  408.  
  409.         k=53;
  410.         windgoto(n,k);
  411.         windputc('|');
  412.         windgoto(n,k+5);
  413.         windputc('|');
  414.         windgoto(n,k+24);
  415.         windputc('|');
  416.     }
  417.     windgoto(r+13,0);
  418.     for ( n=0; n<25; n++ )
  419.         windputc('=');
  420.     windgoto(r+13,53);
  421.     for ( n=0; n<25; n++ )
  422.         windputc('=');
  423.  
  424.     windgoto(YANKROW-2,YANKCOL);
  425.     windstr("  Yank Buffer");
  426.     windgoto(YANKROW-1,YANKCOL);
  427.     windstr(" ------------- ");
  428.     windgoto(YANKROW,YANKCOL);
  429.     windstr("               ");
  430.     windgoto(YANKROW+1,YANKCOL);
  431.     windstr(" ------------- ");
  432.     windrefresh();
  433. }
  434.  
  435. /* clear the message area */
  436. clearmess()
  437. {
  438.     int n;
  439.     for(n=1;n<(FIRSTROW-1);n++)
  440.         winderaserow(n);
  441.     Currrow = 0;
  442. }
  443.  
  444. /* set the current voice (ie. the synth's edit buffer) to the indicated */
  445. /* voice.  c==0 is the synth (left) side, c==1 is the library (right) side. */
  446. editto(r,c)
  447. {
  448.     int voicenum;
  449.  
  450.     /* Clear the existing '*' */
  451.     editchar(' ',Editrow,Editcol);
  452.     editchar('*',Editrow=r,Editcol=c);
  453.     if ( Editcol==0 ) {
  454.         /* we're on the synth side */
  455.         voicenum = Editrow+Synindex;
  456.         tocurrent(Syndata,voicenum);
  457.     }
  458.     else {
  459.         /* we're on the lib side */
  460.         voicenum = Editrow+Libindex;
  461.         tocurrent(bankvoice(0),voicenum);
  462.     }
  463. }
  464.  
  465. editchar(ec,r,c)
  466. {
  467.     r = r + FIRSTROW + 1;
  468.     if ( c == 0 )
  469.         c = LEFTSIDE-1;
  470.     else
  471.         c = RIGHTSIDE-1;
  472.     windgoto(r,c);
  473.     windputc(ec);
  474.     windrefresh();
  475. }
  476.  
  477. /* control interaction on the main library bank screen */
  478. libinteract()
  479. {
  480.     int c, n, swap, voicenum, maxindex, q;
  481.     char *p, *data;
  482.  
  483.     flushmidi();
  484.     drawall();
  485.     for ( ;; ) {
  486.         Currrow = 0;
  487.         winderaserow(Currrow);
  488.         windgoto(Currrow,0);
  489.         windstr("Command --> ");
  490.         windrefresh();
  491.         
  492.         c = mouseorkey();
  493.         if ( c == MOUSE ) {
  494.             libmouse();
  495.             continue;
  496.         }
  497.  
  498.         if ( isprint(c) )
  499.             windputc(c);
  500.         clearmess();
  501.         switch ( c ) {
  502.         case ' ':
  503.             playnote(1);
  504.             break;
  505.         case '\n':
  506. #ifndef macintosh
  507.         case '\r':
  508. #endif
  509.             /* ignore */
  510.             break;
  511.         case EOF:
  512.         case 'q':
  513.             return;
  514.         case CH_REDRAW:
  515.             drawall();
  516.             break;
  517.         case 's':
  518.         case 'p':
  519.             swap = (c=='s')?1:0;
  520.             if ( Editcol==0 )
  521.                 tosyn(Synindex+Editrow,Yankdata,swap);
  522.             else
  523.                 tolib(Libindex+Editrow,Yankdata,swap);
  524.             updatedisplay();
  525.             pryankname();
  526.             break;
  527.         case 'y':
  528.             for(n=0;n<Voicesize;n++)
  529.                 Yankdata[n] = Currdata[n];
  530.             pryankname();
  531.             break;
  532.         case '?':
  533.             helpmessage();
  534.             break;
  535.         case SCR_DOWN:
  536.             if(Nvoices < NUMONSCREEN)
  537.                 q = Nvoices;
  538.             else
  539.                 q = NUMONSCREEN;
  540.  
  541.             maxindex = Nvoices - q;
  542.             if ( Editcol==0 ) {
  543.                 /* we're on the synth side */
  544.                 if ( (Synindex+=q/2) > maxindex )
  545.                     Synindex = maxindex;
  546.             }
  547.             else {
  548.                 /* we're on the lib side */
  549.                 if ( (Libindex+=q/2) > maxindex )
  550.                     Libindex = maxindex;
  551.             }
  552.             updatedisplay();
  553.             break;
  554.         case SCR_UP:
  555.             if ( Editcol==0 ) {
  556.                 /* we're on the synth side */
  557.                 if ( (Synindex-=NUMONSCREEN/2) < 0 )
  558.                     Synindex = 0;
  559.             }
  560.             else {
  561.                 /* we're on the lib side */
  562.                 if ( (Libindex-=NUMONSCREEN/2) < 0 )
  563.                     Libindex = 0;
  564.             }
  565.             updatedisplay();
  566.             break;
  567.         case '\033':
  568.         case '`':
  569.             allnotesoff();
  570.             break;
  571.         case 't':
  572.             transcmd();
  573.             editto(Editrow,Editcol);
  574.             break;
  575.         case 'D':    /* download FROM file */
  576.             synthinfileflag = 1;
  577.         case 'd':    /* download FROM synth */
  578.             clrdata(Syndata,Nvoices*Voicesize);
  579.             if ( readsynth(Syndata) == 0 ) {
  580.                 syntodisplay(Synindex=0);
  581.                 if(Editcol == 0)
  582.                     editto(Editrow,Editcol);
  583.             }
  584.             synthinfileflag = 0;
  585.             break;
  586.         case 'U':    /* upload to file */
  587.             synthoutfileflag = 1;
  588.         case 'u':    /* upload TO synth */
  589.             if ( Editcol==0 ) {
  590.                 voicenum = Editrow+Synindex;
  591.                 data = &(VOICEBYTE(Syndata,voicenum,0));
  592.             }
  593.             else
  594.                 data = bankvoice(Editrow+Libindex);
  595.             upload(data);
  596.             synthoutfileflag = 0;
  597.             break;
  598.         case 'r':
  599.             readall();
  600.             if(Editcol == 1)
  601.                 editto(Editrow,Editcol);
  602.             break;
  603.         case 'R':
  604.             readprintable();
  605.             if(Editcol == 1)
  606.                 editto(Editrow,Editcol);
  607.             break;
  608.         case 'w':
  609.             writeall();
  610.             break;
  611.         case 'W':
  612.             writeprintable();
  613.             break;
  614.         case 'c':
  615.             setchan();
  616.             break;
  617.         case 'b':
  618.             /* cycle through banks, from 0 to LIBBANKS-1 */
  619.             if ( ++Libbank >= LIBBANKS )
  620.                 Libbank = 0;
  621.             libtodisplay(Libindex);
  622.             updatedisplay();
  623.             break;
  624.         case 'e':
  625.             if ( Namesize == 0)
  626.                 p = NULL;
  627.             else
  628.                 p = (*Nameof)(Currdata);
  629.             if ( Editcol==0 ) {
  630.                 voicenum = Editrow+Synindex;
  631.                 data = &(VOICEBYTE(Syndata,voicenum,0));
  632.                 editdata(p,data);
  633.                 windclear();
  634.                 /* Update Currdata */
  635.                 for ( n=0; n<Voicesize; n++ )
  636.                     Currdata[n] = VOICEBYTE(Syndata,voicenum,n);
  637.             }
  638.             else {
  639.                 data = bankvoice(Editrow+Libindex);
  640.                 editdata(p,data);
  641.             }
  642.             drawall();
  643.             break;
  644.         case 'g': /* goto a specific voice */
  645.             do_goto();
  646.             break;
  647.         case CH_LEFT:
  648.         case ALTCH_LEFT:
  649.             if ( Editcol==1 )
  650.                 editto(Editrow,0);
  651.             break;
  652.         case CH_DOWN:
  653.         case ALTCH_DOWN:
  654.             if(Nvoices < NUMONSCREEN)
  655.                 q = Nvoices;
  656.             else
  657.                 q = NUMONSCREEN;
  658.             if ( Editrow < (q-1) )
  659.                 editto(Editrow+1,Editcol);
  660.             else {
  661.                 /* we're at the bottom, so try to scroll */
  662.                 if ( Editcol==0 ) {
  663.                     /* we're on the synth side */
  664.                     if (Synindex<(Nvoices-q))
  665.                         Synindex++;
  666.                 }
  667.                 else {
  668.                     /* we're on the lib side */
  669.                     if (Libindex<(Nvoices-q))
  670.                         Libindex++;
  671.                 }
  672.                 updatedisplay();
  673.             }
  674.             break;
  675.         case CH_UP:
  676.         case ALTCH_UP:
  677.             if ( Editrow>0 )
  678.                 editto(Editrow-1,Editcol);
  679.             else {
  680.                 /* we're at the top, so try to scroll */
  681.                 if ( Editcol==0 ) {
  682.                     /* we're on the synth side */
  683.                     if (Synindex>0)
  684.                         Synindex--;
  685.                 }
  686.                 else {
  687.                     /* we're on the lib side */
  688.                     if (Libindex>0)
  689.                         Libindex--;
  690.                 }
  691.                 updatedisplay();
  692.             }    
  693.             break;
  694.         case CH_RIGHT:
  695.         case ALTCH_RIGHT:
  696.             if ( Editcol==0 )
  697.                 editto(Editrow,1);
  698.             break;
  699.         case 'f':
  700.             filelist();
  701.             break;
  702.         default:
  703.             message("Unrecognized command!  Press '?' for help.");
  704.             break;
  705.         }
  706.     }
  707. }
  708.  
  709. filelist()
  710. {
  711.     char *p, *q, buff[BUFSIZ];
  712.     int n, ninline = 0, nprinted = 0;
  713.  
  714.     clearmess();
  715.     Currrow = -1;    /* To start message on top line */
  716.     openls();
  717.     message("Files in current directory:");
  718.     strcpy(buff,"  ");
  719.     while ( (p=nextls()) != NULL ) {
  720.         /* add the next file to the line being constructed */
  721.         q = &buff[strlen(buff)];
  722.         strcpy(q,p);
  723.         q += (n=strlen(p));
  724.         while ( n++ < 15 )
  725.             *q++ = ' ';
  726.         *q = '\0';
  727.         if ( ninline++ > 3 ) {
  728.             message(buff);
  729.             if ( nprinted++ > 4 ) {
  730.                 message("Press any key to continue ...");
  731.                 (void)getconsole();
  732.                 clearmess();
  733.                 nprinted = 0;
  734.             }
  735.             strcpy(buff,"  ");
  736.             ninline = 0;
  737.         }
  738.     }
  739.     if ( ninline > 0 )
  740.         message(buff);
  741.     closels();
  742. }
  743.  
  744. libmouse()
  745. {
  746.     int row, col, q;
  747.  
  748.     getmouse(&row,&col);
  749.     if(Nvoices < NUMONSCREEN)
  750.         q = Nvoices;
  751.     else
  752.         q = NUMONSCREEN;
  753.     if ( row <= FIRSTROW || row > FIRSTROW+q+1 )
  754.         goto getout;
  755.     if ( col < Cols/2 )
  756.         col = 0;
  757.     else
  758.         col = 1;
  759.     row = row - FIRSTROW - 1;
  760.     editto(row,col);
  761. getout:
  762.     /* wait until mouse button is released */
  763.     while ( statmouse() > 0 )
  764.         ;
  765. }
  766.  
  767. do_goto()
  768. {
  769.     int n, r, maxindex, new_ecol,q;
  770.     char sbuf[100], *sp;
  771.     
  772.     message("");
  773.     message("Where to? ");
  774.     windgets(sbuf);
  775.     
  776.     sp = sbuf;
  777.     switch(*sp++) {
  778.       case 's': /* synth side */
  779.         new_ecol = 0;
  780.         break;
  781.       case 'l': /* library side */
  782.         new_ecol = 1;
  783.         break;
  784.       default: /* no change in side */
  785.           new_ecol = Editcol;
  786.         sp--;    /* but don't trash the first character */
  787.         break;
  788.     }
  789.     
  790.     clearmess();
  791.     r = sscanf(sp, "%d", &n); /* this may fail - we handle it later */
  792.     if(Cvtnum != NULL) { /* convert to internal format if needed */
  793.         n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
  794.     }
  795.     if (Cvtanum != NULL) { /* convert using alphanumeric voice number */
  796.         n = (*Cvtanum)(sp) + 1;
  797.         if (n) r = 1;
  798.     }
  799.     if(r != 1) {
  800.         message("type one of: sn, ln, or n");
  801.         message("  s = synth side (literal character 's')");
  802.         message("  l = library side (literal character 'l')");
  803. #ifdef KAWAIK1
  804.         message("  n = voice number to select (letter + number)");
  805. #else
  806. #ifdef KAWAIK5
  807.         message("  n = voice number to select (letter + number)");
  808. #else
  809.         message("  n = voice number to select (an integer)");
  810. #endif
  811. #endif
  812.         return;
  813.     }
  814.     if(n <= 0 || n > Nvoices) { /* 1-based */
  815.         message("Bad voice number!");
  816.         return;
  817.     }
  818.     
  819.     /* it can be done.  nuke the old '*' and change columes (if needed) */
  820.     editchar(' ', Editrow, Editcol);
  821.     Editcol = new_ecol;
  822.     
  823.     /* try to center it */
  824.     if(Nvoices < NUMONSCREEN)
  825.         q = Nvoices;
  826.     else
  827.         q = NUMONSCREEN;
  828.     maxindex = Nvoices - q;
  829.     if(Editcol == 0) {
  830.         Synindex = (n - 1) - q/2; /* 0-based */
  831.         if(Synindex < 0) { /* impossible to center */
  832.             Synindex = 0; /* so do your best */
  833.         } else if(Synindex > maxindex) {
  834.             Synindex = maxindex;
  835.         }
  836.         Editrow = (n - 1) - Synindex; /* and put a '*' on it */
  837.     } else {
  838.         Libindex = (n - 1) - q/2; /* 0-based */
  839.         if(Libindex < 0) {
  840.             Libindex = 0;
  841.         } else if(Libindex > maxindex) {
  842.             Libindex = maxindex;
  843.         }
  844.         Editrow = (n - 1) - Libindex;
  845.     }
  846.     
  847.     updatedisplay(); /* do the real work */
  848.     return;
  849. }
  850.  
  851. upload(data)
  852. char *data;
  853. {
  854.     int c, n;
  855.     char num[16];
  856.  
  857.     message("");
  858.     if (synthoutfileflag) {
  859.         message("Upload to synth file:");
  860.         message("Output synth file --> ");
  861.         windgets(Syofname);
  862.         flushmidi();
  863.     }
  864.     else message("Upload TO synth:");
  865.     message("                 c - current voice");
  866.     message("                 a - ALL voices");
  867.     message("Choose --> ");
  868.     c = getconsole();
  869.     if ( c == 'c' ) {
  870.         clearmess();
  871.         if ( Sendone == NULL ) {
  872.             if (synthoutfileflag) (*Sendedit)(data);
  873.             else
  874.             message("Single voices can't be sent to that synth!");
  875.             return;
  876.         }
  877.         message("What voice number to you want to send it TO? --> ");
  878.         windgets(num);
  879.         clearmess();
  880.         n = atoi(num);
  881.         if(Cvtnum != NULL) { /* convert to internal format if needed */
  882.             n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
  883.         }
  884.         if (Cvtanum != NULL) { /* howzabout alphanumeric format? */
  885.             n = (*Cvtanum)(num) + 1;
  886.         }
  887.         if ( n > 0 && n <= Nvoices ) {
  888.             if ( (*Sendone)(n-1,data) != 0 ) { /* 0-based on calls -SAF */
  889.                 message("Unable to write data to synth!");
  890.                 (void)sprintf(Buff,"Reason: %s",Reason);
  891.                 message(Buff);
  892.                 return;
  893.             }
  894.         } else {
  895.             message("Bad voice number!");
  896.         }
  897.     }
  898.     else if ( c == 'a' ) {
  899.         clearmess();
  900.         if ( Sendbulk != NULL ) {
  901.             message("Uploading to synth using bulk routine.");
  902.             if ( (*Sendbulk)(Syndata) != 0 ) {
  903.                 message("Upload failure!");
  904.                 (void)sprintf(Buff,"Reason: %s\n",Reason);
  905.                 message(Buff);
  906.                 return;
  907.             }
  908.         } else {
  909.             message("Uploading to synth using single routine.");
  910.             for ( n=0; n<Nvoices; n++ ) {
  911.                 if ( (*Sendone)(n, &(VOICEBYTE(Syndata,n,0)) ) != 0 ) {
  912.                     message("Unable to write data to synth!");
  913.                     (void)sprintf(Buff,"Reason: %s",Reason);
  914.                     message(Buff);
  915.                     return;
  916.                 }
  917.             }
  918.         }
  919.         /* clearmess(); */
  920.     }
  921.     else {
  922.         clearmess();
  923.         message("Bad choice!");
  924.     }
  925. }
  926.  
  927. helpmessage()
  928. {
  929. clearmess();
  930. (void)sprintf(Buff,"%s,%s,%s,%s - move around              e - edit current voice",
  931.     STR_LEFT,STR_DOWN,STR_UP,STR_RIGHT);
  932. message(Buff);
  933. message("r - read voices from a file        y - yank into buffer");
  934. message("w - write voices to a file         p - put from buffer");
  935. message("b - cycle through library banks    s - swap current voice with yank buffer");
  936. message("t - transfer all voices            f - list files in current directory");
  937. message("d - download voices from synth     c - set MIDI channel");
  938. message("u - upload voices to synth         g - 'goto' form of moving around");
  939. message("q - quit                           <space> - play a note");
  940. }
  941.  
  942. updatedisplay()
  943. {
  944.     if ( Editcol==0 ) {
  945.         /* we're on the synth side */
  946.         syntodisplay(Synindex);
  947.         editto(Editrow,Editcol);
  948.     }
  949.     else {
  950.         /* we're on the lib side */
  951.         libtodisplay(Libindex);
  952.         editto(Editrow,Editcol);
  953.     }
  954. }
  955.  
  956. pryankname()
  957. {
  958.     char ybuff[33];
  959.     char *p;
  960.  
  961.     if ( Namesize == 0 )
  962.         return;
  963.  
  964.     windgoto(YANKROW,YANKCOL-4);
  965.     windstr("                    ");
  966.     strcpy(ybuff,(*Nameof)(Yankdata));
  967.     /* take off trailing blanks */
  968.     p = ybuff + strlen(ybuff) - 1;
  969.     while ( p>ybuff && *p == ' ' )
  970.         *p-- = '\0';
  971.     windgoto(YANKROW,YANKCOL+7-strlen(ybuff)/2);
  972.     windstr(ybuff);
  973.     windrefresh();
  974. }
  975.  
  976. transcmd()
  977. {
  978.     int fromc;
  979.  
  980.     message("");
  981.     message("Transfer ALL voices:");
  982.     message("                       1:   <<-----   from library bank to synth bank");
  983.     message("                       2:   ----->>   from synth bank to library bank");
  984.     message("1 or 2 --> ");
  985.     fromc = getconsole();
  986.     windputc(fromc);
  987.     if ( fromc!='1' && fromc!='2' ) {
  988.         clearmess();
  989.         return;
  990.     }
  991.     switch ( fromc ) {
  992.     case '1':
  993.         copyall(bankvoice(0),Syndata);
  994.         syntodisplay(Synindex);
  995.         clearmess();
  996.         message("Use the 'u'pload command to actually send the synth bank voices to the synth.");
  997.         break;
  998.     case '2':
  999.         copyall(Syndata,bankvoice(0));
  1000.         libtodisplay(Libindex);
  1001.         clearmess();
  1002.         break;
  1003.     }
  1004. }
  1005.  
  1006. copyall(fromdata,todata)
  1007. char *fromdata;
  1008. char *todata;
  1009. {
  1010.     int n, v;
  1011.  
  1012.     for ( v=0; v<Nvoices; v++ )
  1013.         for ( n=0; n<Voicesize; n++ )
  1014.             VOICEBYTE(todata,v,n) = VOICEBYTE(fromdata,v,n);
  1015. }
  1016.  
  1017. message(s)
  1018. char *s;
  1019. {
  1020.     windgoto(++Currrow,0);
  1021.     windstr(s);
  1022.     windrefresh();
  1023. }
  1024.  
  1025. setchan()
  1026. {
  1027.     int c;
  1028.  
  1029.     message("New MIDI channel --> ");
  1030.     windgets(Buff);
  1031.     if ( (c=atoi(Buff)) <= 0 || c > 16 ) {
  1032.         clearmess();
  1033.         message("Invalid channel!");
  1034.     }
  1035.     else {
  1036.         clearmess();
  1037.         Channel = c;
  1038.         showchan();
  1039.     }
  1040. }
  1041.  
  1042. showchan()
  1043. {
  1044.     windgoto(20,31);
  1045.     windstr("MIDI Channel: ");
  1046.     (void)sprintf(Buff,"%d ",Channel);
  1047.     windstr(Buff);
  1048.     windrefresh();
  1049. }
  1050.  
  1051. #ifdef DX7
  1052. #include <sys/types.h>
  1053. #include <sys/stat.h>
  1054. long flength(handle)
  1055. int handle;
  1056. {
  1057.   struct stat buf;
  1058.   fstat(handle, &buf);
  1059.   return buf.st_size;
  1060. }
  1061. #endif
  1062.  
  1063. /* read data from a file, filling the current library bank. */
  1064. readall()
  1065. {
  1066.     char fname[100];
  1067.     FILE *f;
  1068.     int v, n, r;
  1069.     char *p;
  1070.  
  1071.     message("File name --> ");
  1072.     windgets(fname);
  1073. #ifdef BSD
  1074.     OPENBINFILE(f,fname,"r");
  1075. #else
  1076.     OPENBINFILE(f,fname,"rb");
  1077. #endif
  1078.     if (f == NULL ) {
  1079.         (void)sprintf(Buff,"Can't open '%s'!",fname);
  1080.         message(Buff);
  1081.         return;
  1082.     }
  1083.     /* If the first byte matches DataID, then the format is OK. */
  1084.     if (DataID) n = (getc(f) & 0xff);
  1085.     else n = 0;
  1086.  
  1087. #ifndef ROLANDD10
  1088. # ifndef KAWAIIK1
  1089. /* If we are running the Aztec C compiler, it's not yet ANSII.  The
  1090.    abominable kludge that follows is therefore necessary.           */
  1091. #  ifdef AZTEC_C
  1092. #    ifdef DX7
  1093. #     define SKIP_IT
  1094. #    endif
  1095. #    ifdef DX7S
  1096. #     define SKIP_IT
  1097. #    endif
  1098. #    ifndef SKIP_IT
  1099.     if (n != DataID && n <= 31) {
  1100.         (void)ungetc(n,f);
  1101.         n = DataID;
  1102.     }
  1103. #    endif
  1104. #    undef SKIP_IT
  1105. #  else
  1106. #   if !defined(DX7) && !defined(DX7S)
  1107.         if (n != DataID && n <= 31) {
  1108.                 (void)ungetc(n,f);
  1109.                 n = DataID;
  1110.         }
  1111. #   endif
  1112. #  endif
  1113. # endif
  1114. #endif
  1115.  
  1116. #ifdef DX7S
  1117.  
  1118. /* check for reading a DX7 file in DX7s mode */
  1119.  
  1120.         if ( strcmp(Synthname, "DX7s") == 0 )
  1121.           if (flength(fileno(f)) == 4096) {
  1122.             (void)ungetc(n, f);
  1123.             dx7Sread_dx7(f, bankvoice(0));
  1124.             r = 0;
  1125.             goto done;
  1126.           }
  1127.  
  1128. /* check for reading a DX7S file in DX7 mode */
  1129.  
  1130.           if ( strcmp(Synthname, "DX7") == 0 ) {
  1131.             n = getc(f) & 0xff;
  1132.             if (n == 0xd7) {    /* DX7s dataID */
  1133.               dx7read_dx7S(f, bankvoice(0));
  1134.               r = 0;
  1135.               goto done;
  1136.             }
  1137.             (void)ungetc(n, f);
  1138.             n = 0;
  1139.           }
  1140. #endif
  1141.  
  1142. #ifdef DX7
  1143.  
  1144. /* validate a DX7 file based on length */
  1145.  
  1146.         if ( strcmp(Synthname, "DX7") == 0 ) {
  1147.           if (flength(fileno(f)) != Nvoices * Voicesize)
  1148.             n = DataID + 1;
  1149.         }
  1150.  
  1151. #endif
  1152.  
  1153.     if ( n == DataID ) {
  1154.         p = bankvoice(0);
  1155.         for ( v=0; v<Nvoices; v++ ) {
  1156.             for ( n=0; n<Voicesize; n++ )
  1157. #ifdef CZ1
  1158.                 *p++ = getc(f);
  1159. #else
  1160. #ifdef CZ101
  1161.                 *p++ = getc(f);
  1162. #else
  1163.                 *p++ = (getc(f) & 0x7f);
  1164. #endif
  1165. #endif
  1166.         }
  1167.         r = 0;
  1168.     } else {
  1169.         (void)sprintf(Buff, "'%s' is invalid for this function!\n", fname);
  1170.         message(Buff);
  1171.         r = 1;
  1172.     }
  1173. #ifdef DX7S
  1174. done:
  1175. #endif
  1176.     (void)fclose(f);
  1177.     if ( r==0 ) {
  1178.         libtodisplay(Libindex=0);
  1179.         clearmess();
  1180.     }
  1181. }
  1182.  
  1183. /* read printable data from a textfile, filling the current library bank. */
  1184. readprintable()
  1185. {
  1186.     char fname[100];
  1187.     FILE *pfin;
  1188.     int v, n, r, val;
  1189.     char *p = NULL;
  1190.     char vname[20];
  1191.  
  1192.     message("File name --> ");
  1193.     windgets(fname);
  1194. #ifdef BSD
  1195.     OPENBINFILE(pfin,fname,"r");
  1196. #else
  1197.     OPENBINFILE(pfin,fname,"rb");
  1198. #endif
  1199.     if (pfin == NULL ) {
  1200.         (void)sprintf(Buff,"Can't open '%s'!",fname);
  1201.         message(Buff);
  1202.         return;
  1203.     }
  1204.     /* If the first byte matches DataID, then the format is OK. */
  1205.     r = fscanf(pfin, "BANK TYPE %d", &n);
  1206.  
  1207.     v = -1;
  1208.     if ( r == 1 && n == DataID ) while (r) {
  1209.         r = fscanf(pfin, " %s ", vname);
  1210.  
  1211.         if (r == 1) {
  1212.         if (strcmp(vname, "voice") == 0) {
  1213.             if (v > 0) (*Dataout)(p);
  1214.             r = fscanf(pfin,"%d = %[ !-~]", &v, vname);
  1215.             if (r == 2 && v > 0) {
  1216.                 p = bankvoice(v-1);
  1217.                 (*Setnameof)(p, vname);
  1218.             }
  1219.         } else {
  1220.             r = fscanf(pfin, "= %d", &val);
  1221.             if (r == 1) setval(vname, val);
  1222.         }
  1223.         }
  1224.         if (r == EOF) r = 0;
  1225.     } else {
  1226.         (void)sprintf(Buff, "'%s' is invalid for this function!\n", fname);
  1227.         message(Buff);
  1228.         r = 1;
  1229.     }
  1230.     if (v > 0) (*Dataout)(p);
  1231.     (void)fclose(pfin);
  1232.     if ( r==0 ) {
  1233.         libtodisplay(Libindex=0);
  1234.         clearmess();
  1235.     }
  1236. }
  1237.  
  1238. /* write current library bank to a file */
  1239. writeall()
  1240. {
  1241.     char fname[100];
  1242.     FILE *f;
  1243.     int v, n;
  1244.     char *p;
  1245.  
  1246.     message("File name --> ");
  1247.     windgets(fname);
  1248. #ifdef BSD
  1249.     OPENBINFILE(f,fname,"w");
  1250. #else
  1251.     OPENBINFILE(f,fname,"wb");
  1252. #endif
  1253.     if ( f == NULL ) {
  1254.         (void)sprintf(Buff,"Can't open '%s'!",fname);
  1255.         message(Buff);
  1256.         return;
  1257.     }
  1258.     if (DataID) putc(DataID,f);        /* write data identifier */
  1259.  
  1260.     p = bankvoice(0);
  1261.     for ( v=0; v<Nvoices; v++ ) {
  1262.         for ( n=0; n<Voicesize; n++ )
  1263.             putc(*p++,f);
  1264.     }
  1265.     (void)fclose(f);
  1266.     clearmess();
  1267. }
  1268.  
  1269.  
  1270. FILE *pfout;
  1271. int pfoutflag = 0;
  1272.  
  1273. /* write current library bank to a file in printable form */
  1274. writeprintable()
  1275. {
  1276.     char fname[100];
  1277.     int v;
  1278.     char *p, *q;
  1279.  
  1280.     message("File name --> ");
  1281.     windgets(fname);
  1282. #ifdef BSD
  1283.     OPENBINFILE(pfout,fname,"w");
  1284. #else
  1285.     OPENBINFILE(pfout,fname,"wb");
  1286. #endif
  1287.     if ( pfout == NULL ) {
  1288.         (void)sprintf(Buff,"Can't open '%s'!",fname);
  1289.         message(Buff);
  1290.         return;
  1291.     }
  1292.     fprintf(pfout, "BANK TYPE %d\n", DataID);
  1293.  
  1294.     for (v=0; v<Nvoices; v++) {
  1295.         p = bankvoice(v);
  1296.         q = (*Nameof)(p);
  1297.         if (q[0] > ' ') {
  1298.             (*Datain)(p);
  1299.             fprintf(pfout, "voice %d = %s\n", v+1, q);
  1300.             pfoutflag = 1;
  1301.             (*Dataout)(p);
  1302.             pfoutflag = 0;
  1303.         }
  1304.     }
  1305.     (void)fclose(pfout);
  1306.     clearmess();
  1307. }
  1308.  
  1309. /* draw main library/synth voice bank screen */
  1310. drawall()
  1311. {
  1312.     windclear();
  1313.     template();
  1314.     libtodisplay(Libindex);
  1315.     syntodisplay(Synindex);
  1316.     editto(Editrow,Editcol);
  1317.     pryankname();
  1318.     showchan();
  1319. }
  1320.  
  1321. /*
  1322.  * tosyn
  1323.  *
  1324.  * Store the given 'data' in in voice 'voicenum' (both in Syndata
  1325.  * AND on the synth itself).  If swap is non-zero, the voice is swapped
  1326.  * with the current voice in Syndata.
  1327.  */
  1328.  
  1329. tosyn(voicenum,data,swap)
  1330. char *data;
  1331. {
  1332.     int n, t;
  1333.  
  1334.     for ( n=0; n<Voicesize; n++ ) {
  1335.         if ( swap ) {
  1336.             t = VOICEBYTE(Syndata,voicenum,n);
  1337.             VOICEBYTE(Syndata,voicenum,n) = data[n];
  1338.             data[n] = t;
  1339.         }
  1340.         else
  1341.             VOICEBYTE(Syndata,voicenum,n) = data[n];
  1342.     }
  1343. }
  1344.  
  1345. tolib(voicenum,data,swap)
  1346. char *data;
  1347. {
  1348.     int n, t;
  1349.     char *p = bankvoice(voicenum);
  1350.  
  1351.     for ( n=0; n<Voicesize; n++ ) {
  1352.         if ( swap ) {
  1353.             t = *p;
  1354.             *p = data[n];
  1355.             data[n] = t;
  1356.         }
  1357.         else
  1358.             *p = data[n];
  1359.         p++;
  1360.     }
  1361. }
  1362.  
  1363. tocurrent(data,voicenum)
  1364. char *data;
  1365. int voicenum;
  1366. {
  1367.     int n, f = 0;
  1368.  
  1369.     for ( n=0; n<Voicesize; n++ )
  1370.         if ( (Currdata[n] = VOICEBYTE(data,voicenum,n)) != 0) f = 1;
  1371.     if( f == 1 && !synthoutfileflag) (*Sendedit)(Currdata);
  1372. }
  1373.  
  1374. /*
  1375.  * readsynth
  1376.  *
  1377.  * Read a bulk dump from the synth, with some tolerance for errors.
  1378.  */
  1379. readsynth(data)
  1380. char *data;
  1381. {
  1382.     if ( Getbulk == NULL ) {
  1383.         message("That synth is unable to dump anything!!");
  1384.         return(1);
  1385.     }
  1386.     if (synthinfileflag) {
  1387.         message("Input synth file --> ");
  1388.         windgets(Syinfname);
  1389.         synthoutfileflag = 1;
  1390.         flushmidi();
  1391.         synthoutfileflag = 0;
  1392.     }
  1393.     else message("Downloading from synth");
  1394.  
  1395.     if ( (*Getbulk)(data) == 0 )
  1396.         return(0);
  1397.  
  1398.     message("Unable to read data from synth!");
  1399.     (void)sprintf(Buff,"Reason: %s",Reason);
  1400.     message(Buff);
  1401.     message("Perhaps connections are amiss?");
  1402.     return(1);
  1403. }
  1404.  
  1405. char *
  1406. vnumtext(n)
  1407. {
  1408.     static char vnbuff[6];
  1409.  
  1410.     if ( Numof == NULL ) {
  1411.         (void)sprintf(vnbuff,"%2d",n);
  1412.         return(vnbuff);
  1413.     }
  1414.     else
  1415.         return((*Numof)(n - 1)); /* keep this 0-based */
  1416. }
  1417.  
  1418. /*
  1419.  * syntodisplay(n)
  1420.  *
  1421.  * Tranfer Syndata names to dialog boxes (Dxvoices) starting at n.
  1422.  */
  1423. syntodisplay(n)
  1424. {
  1425.     int k, r, q;
  1426.  
  1427.     if(Nvoices < NUMONSCREEN)
  1428.         q = Nvoices;
  1429.     else
  1430.         q = NUMONSCREEN;
  1431.     for ( k=0; k<q; k++ ) {
  1432.         r = FIRSTROW+1+k;
  1433.         windgoto(r,LEFTSIDE);
  1434.         (void)sprintf(Buff,"%s |                 ",vnumtext(n+k+1));
  1435.         windstr(Buff);
  1436.         /* pull the name out of the Syndata */
  1437.         if ( Namesize != 0 ) {
  1438.             windgoto(r,LEFTSIDE+5);
  1439.             windstr((*Nameof)( & (VOICEBYTE(Syndata,n+k,0) )) );
  1440.         }
  1441.     }
  1442.     windrefresh();
  1443. #ifdef KAWAIK1
  1444.     synnames();
  1445. #endif
  1446. }
  1447.  
  1448. #ifdef KAWAIK1
  1449. /*
  1450.  * synnames()
  1451.  *
  1452.  * Tranfer Syndata names to array.
  1453.  */
  1454. synnames()
  1455. {    int i, k;
  1456.     char *p, *q;
  1457.  
  1458.     if (Nvoices != 64) return;
  1459.  
  1460.     for ( k=0; k < 64; k++ ) {
  1461.         p = (*Nameof)( & (VOICEBYTE(Syndata,k,0) ));
  1462.         q = sngnames[k];
  1463.         for (i=0; i < 10; i++) *q++ = *p++;
  1464.         *q = 0;
  1465.     }
  1466. }
  1467. #endif
  1468.  
  1469. /*
  1470.  * libtodisplay
  1471.  *
  1472.  * Tranfer Libdata names to the screen, starting at voice 'firstv'.
  1473.  */
  1474.  
  1475. libtodisplay(firstv)
  1476. {
  1477.     int k, r, q;
  1478.  
  1479.     windgoto(FIRSTROW-1,RIGHTSIDE+2);
  1480.     (void)sprintf(Buff,"Library (Bank %d)",Libbank+1);
  1481.     windstr(Buff);
  1482.  
  1483.     if(Nvoices < NUMONSCREEN)
  1484.         q = Nvoices;
  1485.     else
  1486.         q = NUMONSCREEN;
  1487.     for ( k=0; k<q; k++ ) {
  1488.         r = FIRSTROW+1+k;
  1489.         windgoto(r,RIGHTSIDE);
  1490.         (void)sprintf(Buff,"%s |                 ",vnumtext(firstv+k+1));
  1491.         windstr(Buff);
  1492.         /* pull the name out of the Libdata */
  1493.         if ( Namesize != 0 ) {
  1494.             windgoto(r,RIGHTSIDE+5);
  1495.             windstr((*Nameof)(bankvoice(firstv+k)));
  1496.         }
  1497.     }
  1498.     windrefresh();
  1499. }
  1500.  
  1501. allnotesoff()
  1502. {
  1503.     int n;
  1504.  
  1505.     /* Go through all channels. */
  1506.     for ( n=0; n<15; n++ ) {
  1507.         sendmidi(n | 0xb0);
  1508.         sendmidi(0x7b);
  1509.         sendmidi(0x00);
  1510.     }
  1511. }
  1512.  
  1513. /*
  1514.  * Below are generic edit routines, which manage a screen display
  1515.  * showing parameter values, and let you roam around and make changes.
  1516.  * The display is managed by the contents of the P array, which
  1517.  * contains the name, screen location, min/max values, etc. of
  1518.  * each parameter.
  1519.  */
  1520.  
  1521. int Prow = 0;
  1522. int Pcol = 0;
  1523. int Parm = 0;
  1524.  
  1525. /* redraw the parameter screen */
  1526. showallparms(name)
  1527. char *name;
  1528. {
  1529.     int n;
  1530.     char *s;
  1531.  
  1532.     windclear();
  1533.  
  1534.     if( Namesize != 0 ) {
  1535.         showname(name);
  1536.         windgoto(1,0);
  1537.         for(n=strlen(name)+6;n>0;n--)
  1538.             windputc('=');
  1539.     }
  1540.  
  1541.     /* The L array contains arbitrary screen labels */
  1542.     for ( n=0; L[n].l_text != NULL; n++ ) {
  1543.         windgoto(L[n].l_row,L[n].l_col);
  1544.         windstr(L[n].l_text);
  1545.     }
  1546.     /* Display each parameter value, and a label if there is one. */
  1547.     for ( n=0; P[n].p_name != NULL; n++ ) {
  1548.         if ( P[n].p_flags != 0 )
  1549.             continue;
  1550.         if ( (s=P[n].p_label) != NULL )
  1551.             showstr(s,P[n].p_lrow,P[n].p_lcol,0);
  1552.         showparam(n,0);
  1553.     }
  1554.     windrefresh();
  1555. }
  1556.  
  1557. showname(name)
  1558. char *name;
  1559. {
  1560.     windgoto(0,0);
  1561.     windstr("Name:                 ");
  1562.     windgoto(0,6);
  1563.     windstr(name);
  1564. }
  1565.  
  1566. showparam(n,eras)
  1567. {
  1568.     char *p;
  1569.  
  1570.     /* The p_tovis element of the P array is a function which, given */
  1571.     /* the parameter value as an argument, returns a string which is */
  1572.     /* what should be displayed on the screen. */
  1573. #ifdef DX7
  1574.         if (P[n].p_vrow < 0 || P[n].p_vcol < 0) return;
  1575.     p = (*(P[n].p_tovis))(P[n].p_val, eras);
  1576. #else
  1577.     p = (*(P[n].p_tovis))(P[n].p_val);
  1578. #endif
  1579.     showstr(p,P[n].p_vrow,P[n].p_vcol,eras);
  1580. }
  1581.  
  1582. #ifdef DX7
  1583.  
  1584. /*
  1585.  * define defaults for the graphics characters, if they haven't been specified
  1586.  * in machdep.
  1587.  */
  1588.  
  1589. # ifndef DRAW_VERT
  1590. #  define DRAW_VERT      '|'
  1591. #  define DRAW_HORIZ     '-'
  1592. #  define DRAW_CROSS     '+'
  1593. #  define DRAW_UPTEE     '+'
  1594. #  define DRAW_DOWNTEE   '+'
  1595. #  define DRAW_LEFTTEE   '+'
  1596. #  define DRAW_RIGHTTEE  '+'
  1597. #  define DRAW_UPLEFT    '+'
  1598. #  define DRAW_UPRIGHT   '+'
  1599. #  define DRAW_DOWNLEFT  '+'
  1600. #  define DRAW_DOWNRIGHT '+'
  1601. # endif
  1602.  
  1603. showstr(p,row,col,eras)
  1604. register char *p;
  1605. register int col;
  1606. {
  1607.   register int c;
  1608.   int rept, mincol;
  1609.  
  1610.   mincol = col;
  1611.  
  1612.   windgoto(row,col);
  1613.   while ( (c=(*p++)) != '\0' ) {
  1614.     switch(c){
  1615.       case '~':
  1616.         c = *p++;
  1617.         if (isdigit(c)) {
  1618.           rept = 0;
  1619.           while (isdigit(c)) {
  1620.             rept = 10*rept + (c-'0');
  1621.             c = *p++;
  1622.           }
  1623.         }
  1624.         else
  1625.           rept = 1;
  1626.  
  1627.         while (rept--) {
  1628.           switch( c ) {
  1629.             case 'n': row++; col=mincol; goto wgoto;
  1630.             case 'u': row--; goto wgoto;
  1631.             case 'd': row++; goto wgoto;
  1632.             case 'l': col--; if (col < mincol) mincol = col; goto wgoto;
  1633.             case 'r': col++;
  1634.               wgoto:
  1635.                 windgoto(row,col);
  1636.                 break;
  1637.             case '|': c=DRAW_VERT;      goto wput;
  1638.             case '-': c=DRAW_HORIZ;     goto wput;
  1639.             case '+': c=DRAW_CROSS;     goto wput;
  1640.             case 'T': c=DRAW_UPTEE;     goto wput;
  1641.             case '^': c=DRAW_DOWNTEE;   goto wput;
  1642.             case '<': c=DRAW_RIGHTTEE;  goto wput;
  1643.             case '>': c=DRAW_LEFTTEE;   goto wput;
  1644.             case '{': c=DRAW_UPLEFT;    goto wput;
  1645.             case '}': c=DRAW_UPRIGHT;   goto wput;
  1646.             case '[': c=DRAW_DOWNLEFT;  goto wput;
  1647.             case ']': c=DRAW_DOWNRIGHT;
  1648.               wput:
  1649.                 windputc(eras?' ':c);
  1650.                 col++;
  1651.                 break;
  1652.             default:
  1653.               windputc(eras?' ':c);
  1654.               col++;
  1655.               break;
  1656.           }
  1657.         }
  1658.         break;
  1659.       default:
  1660.         windputc(eras?' ':c);
  1661.         col++;
  1662.         break;
  1663.     }
  1664.   }
  1665. }
  1666.  
  1667. #else  /* DX7 */
  1668.  
  1669. showstr(p,row,col,eras)
  1670. register char *p;
  1671. register int col;
  1672. {
  1673.     register int c;
  1674.  
  1675.     windgoto(row,col);
  1676.     while ( (c=(*p++)) != '\0' ) {
  1677.         switch(c){
  1678.         case '~':
  1679.             switch( (c=(*p++)) ) {
  1680.             case 'u': row--; goto wgoto;
  1681.             case 'd': row++; goto wgoto;
  1682.             case 'l': col--; goto wgoto;
  1683.             case 'r': col++;
  1684.                 wgoto:
  1685.                 windgoto(row,col);
  1686.                 break;
  1687.             default:
  1688.                 windputc(eras?' ':c);
  1689.                 col++;
  1690.                 break;
  1691.             }
  1692.             break;
  1693.         default:
  1694.             windputc(eras?' ':c);
  1695.             col++;
  1696.             break;
  1697.         }
  1698.     }
  1699. }
  1700. #endif
  1701.  
  1702. /* Allow roaming around and changing of parameter values. */
  1703. editdata(name,data)
  1704. char *name;
  1705. char *data;    /* vmem format */
  1706. {
  1707.     int c, n;
  1708.  
  1709.     windclear();
  1710.     windrefresh();
  1711.     /* enable all the parameters */
  1712.     for ( n=0; P[n].p_name != NULL; n++ )
  1713.         enableparm(n);
  1714.  
  1715.     /* Take the voice data and put it into P */
  1716.     (*Datain)(data);
  1717.  
  1718.     Prow = Pcol = 0;
  1719.     Changed = 0;
  1720.     Redraw = 1;
  1721.     Lastvalue = 0;
  1722.     gotoparm(CH_RIGHT);    /* Get to the first parameter */
  1723.     for ( ;; ) {
  1724.         if ( Redraw ) {
  1725.             showallparms(name);
  1726.             Redraw = 0;
  1727.         }
  1728.         windgoto(Prow,Pcol);
  1729.         windrefresh();
  1730.         c = mouseorkey();
  1731.         if ( c == MOUSE ) {
  1732.             editmouse();
  1733.             continue;
  1734.         }
  1735.         switch(c){
  1736.         case CH_RIGHT:
  1737.         case ALTCH_RIGHT:
  1738.         case CH_UP:
  1739.         case ALTCH_UP:
  1740.         case CH_DOWN:
  1741.         case ALTCH_DOWN:
  1742.         case CH_LEFT:
  1743.         case ALTCH_LEFT:
  1744.             gotoparm(c);
  1745.             break;
  1746.         case CH_SAME:
  1747.             sameparm();
  1748.             break;
  1749.         case CH_REDRAW:
  1750.             showallparms(name);
  1751.             break;
  1752.         case 'N':
  1753.             if ( Namesize != 0 ) {
  1754.             /* Allow changing of voice name */
  1755.                 windgoto(0,5);
  1756.                 windstr("                ");
  1757.                 windgoto(0,6);
  1758.                 windrefresh();
  1759.                 windgets(Buff);
  1760.                 if ( Buff[0]!='\0' && Buff[0]!='\n' )
  1761.                     (*Setnameof)(data,Buff);
  1762.                 showname(name=(*Nameof)(data));
  1763.                 Changed = 1;
  1764.             }
  1765.             break;
  1766.  
  1767.         case CH_INC:
  1768.             adjuparm(1);
  1769.             break;
  1770.         case CH_INC2:
  1771.             adjuparm(4);
  1772.             break;
  1773.         case CH_INC3:
  1774.             adjuparm(P[Parm].p_max - P[Parm].p_min);
  1775.             break;
  1776.         case CH_DEC:
  1777.             adjuparm(-1);
  1778.             break;
  1779.         case CH_DEC2:
  1780.             adjuparm(-4);
  1781.             break;
  1782.         case CH_DEC3:
  1783.             adjuparm(P[Parm].p_min - P[Parm].p_max);
  1784.             break;
  1785. #ifdef OLDSTUFF
  1786.         case 'a':
  1787.             sendaced(data);
  1788.             playnote(0);
  1789.             break;
  1790. #endif
  1791.         case ' ':
  1792.         case '\n':
  1793. #ifndef macintosh
  1794.         case '\r':
  1795. #endif
  1796.             if ( Changed ) {
  1797.                 (*Dataout)(data);
  1798.                 (*Sendedit)(data);
  1799.                 Changed = 0;
  1800.             }
  1801.             playnote(0);
  1802.             break;
  1803.         case '\033':
  1804.         case '`':
  1805.             allnotesoff();
  1806.             break;
  1807.         case 'q':
  1808.         case EOF:
  1809.             if ( Changed ) {
  1810.                 (*Dataout)(data);
  1811.                 (*Sendedit)(data);
  1812.             }
  1813.             return;
  1814.         default:
  1815.             break;
  1816.         }
  1817.     }
  1818. }
  1819.  
  1820. adjuparm(incdec)
  1821. {
  1822.     int v, n;
  1823.  
  1824.     v = P[Parm].p_val + incdec;
  1825.     if ( v < (n=P[Parm].p_min) )
  1826.         v = n;
  1827.     if ( v > (n=P[Parm].p_max) )
  1828.         v = n;
  1829.     Lastvalue = v;
  1830.     Changed = 1;
  1831.     showparam(Parm,1);    /* erase the old val */
  1832.     P[Parm].p_val = v;
  1833.     showparam(Parm,0);    /* show the new val */
  1834. }
  1835.  
  1836. sameparm()
  1837. {
  1838.     int v, n;
  1839.  
  1840.     v = Lastvalue;
  1841.     if ( v < (n=P[Parm].p_min) )
  1842.         v = n;
  1843.     if ( v > (n=P[Parm].p_max) )
  1844.         v = n;
  1845.     Changed = 1;
  1846.     showparam(Parm,1);    /* erase the old val */
  1847.     P[Parm].p_val = v;
  1848.     showparam(Parm,0);    /* show the new val */
  1849. }
  1850.  
  1851. editmouse()
  1852. {
  1853.     int row, col, thisparm;
  1854.  
  1855.     getmouse(&row,&col);
  1856.     thisparm = closeparm(row,col);
  1857.     if ( thisparm == Parm ) {
  1858.         if ( statmouse() > 1 )
  1859.             adjuparm(-1);    /* right button */
  1860.         else if ( statmouse() == 1 ) /* added by mab - bug fix */
  1861.             adjuparm(1);    /* left button */
  1862.     }
  1863.     else {
  1864.         Parm = thisparm;
  1865.         Prow = P[Parm].p_vrow;
  1866.         Pcol = P[Parm].p_vcol;
  1867.     }
  1868. }
  1869.  
  1870. /* closeparm - Find the closest parameter */
  1871. closeparm(row,col)
  1872. {
  1873.     register struct paraminfo *pp;
  1874.     register int n;
  1875.     int dist, mindist, minparm, dr, dc;
  1876.  
  1877.     minparm = 0;
  1878.     mindist = Rows + Cols;
  1879.     for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
  1880.         if ( pp->p_flags != 0 )
  1881.             continue;
  1882.         if ( (dr=row-(pp->p_vrow)) < 0 )
  1883.             dr = -dr;
  1884.         if ( (dc=col-(pp->p_vcol)) < 0 )
  1885.             dc = -dc;
  1886.         if ( (dist=dr*dr+dc*dc) < mindist ) {
  1887.             minparm = n;
  1888.             mindist = dist;
  1889.         }
  1890.     }
  1891.     return(minparm);
  1892. }
  1893.  
  1894. /* playnote - play the 'auto' note */
  1895. playnote(i)
  1896. {
  1897.     int pitch, vol, dur, chan;
  1898.     long endtime;
  1899.  
  1900.     pitch = getval("autopitch");
  1901.     if(i == 0) { /* called from inside edit-mode */
  1902.         chan = getval("autochan");
  1903.     } else { /* called from the top level */
  1904.         chan = Channel;
  1905.     }
  1906.     vol = getval("autovol");
  1907.     dur = getval("autodur");
  1908.     endtime = milliclock() + dur * 100;
  1909.     midinote(1,chan,pitch,vol);
  1910.     while ( milliclock() < endtime )
  1911.         ;
  1912.     midinote(0,chan,pitch,vol);
  1913. }
  1914.  
  1915. /* gotoparm - search for the next parameter in the specified direction */
  1916. gotoparm(dir)
  1917. {
  1918.     int n, k, inc, pm, orig, r = Prow, c = Pcol;
  1919.  
  1920.     switch(dir) {
  1921.     case ALTCH_UP:        dir = CH_UP;    break;
  1922.     case ALTCH_DOWN:    dir = CH_DOWN;    break;
  1923.     case ALTCH_LEFT:    dir = CH_LEFT;    break;
  1924.     case ALTCH_RIGHT:    dir = CH_RIGHT;    break;
  1925.     }
  1926.  
  1927.     if ( dir==CH_LEFT || dir==CH_RIGHT ) {
  1928.         if ( dir==CH_LEFT )
  1929.             c--;
  1930.         else
  1931.             c++;
  1932.         orig = c;
  1933.         inc = 0;
  1934.         pm = -1;
  1935.         /* look up and down, alternately */
  1936.         for ( n=2*Rows; n>0; n-- ) {
  1937.             r += (pm * inc++);
  1938.             pm = -pm;
  1939.             if ( r < 0 || r >= Rows )
  1940.                 continue;
  1941.             if ( dir == CH_LEFT ) {
  1942.                 for ( c=orig; c>=0; c-- ) {
  1943.                     if ( parmat(r,c) )
  1944.                         return;
  1945.                 }
  1946.             }
  1947.             else {
  1948.                 for ( c=orig; c<Cols; c++ ) {
  1949.                     if ( parmat(r,c) )
  1950.                         return;
  1951.                 }
  1952.             }
  1953.         }
  1954.         return;
  1955.     }
  1956.     if ( dir==CH_DOWN || dir==CH_UP ) {
  1957.         if ( dir==CH_DOWN )
  1958.             r++;
  1959.         else
  1960.             r--;
  1961.         orig = c;
  1962.         while ( r >= 0 && r < Rows ) {
  1963.             /* look toward both sides at the same time */
  1964.             inc = 0;
  1965.             pm = -1;
  1966.             for ( k=2*Cols; k>0; k-- ) {
  1967.                 c += (pm * inc++);
  1968.                 pm = -pm;
  1969.                 if ( c < 0 || c >= Cols )
  1970.                     continue;
  1971.                 if ( parmat(r,c) )
  1972.                     return;
  1973.             }
  1974.             if ( dir==CH_DOWN )
  1975.                 r++;
  1976.             else
  1977.                 r--;
  1978.             c = orig;
  1979.         }
  1980.         return;
  1981.     }
  1982. }
  1983.  
  1984. /* paramat - return non-zero if a parameter value is at position r,c */
  1985. parmat(r,c)
  1986. register int r, c;
  1987. {
  1988. #ifdef SSS
  1989.   int p = PARAMAT(r, c);
  1990.  
  1991.   if (p == 0 || P[p-1].p_flags)
  1992.     return 0;
  1993.   else {
  1994.     Parm = p-1;
  1995.     Prow = r;
  1996.     Pcol = c;
  1997.     return 1;
  1998.   }
  1999. #else
  2000.     register int n;
  2001.     register struct paraminfo *pp;
  2002.  
  2003.     for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
  2004.         if ( pp->p_flags != 0 )
  2005.             continue;
  2006.         if ( pp->p_vrow==r && pp->p_vcol==c ) {
  2007.             Prow = r;
  2008.             Pcol = c;
  2009.             Parm = n;
  2010.             return(1);
  2011.         }
  2012.     }
  2013.     return(0);
  2014. #endif
  2015. }
  2016.  
  2017. /* parmindex - return index (in P) of a given parameter name. */
  2018. parmindex(name)
  2019. char *name;
  2020. {
  2021. #ifdef SSS
  2022.   struct paraminfo key, *p;
  2023.   extern char *bsearch();
  2024.  
  2025.   key.p_name = name;
  2026.   p = (struct paraminfo *)bsearch((void *)&key, (void *)P, NParams,
  2027.         sizeof(struct paraminfo), paramcmp);
  2028.   if (p == 0) {
  2029.     (void)sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!\n",name);
  2030.     windstr(Buff);
  2031.     windrefresh();
  2032.     return(-1);
  2033.   }
  2034.   else
  2035.     return p-P;
  2036. #else
  2037.     int n;
  2038.     char *s;
  2039.  
  2040.     for ( n=0; (s=P[n].p_name) != NULL; n++ ) {
  2041.         if ( strcmp(s,name) == 0 )
  2042.             return(n);
  2043.     }
  2044.     (void)sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!\n",name);
  2045.     windstr(Buff);
  2046.     windrefresh();
  2047.     return(-1);
  2048. #endif
  2049. }
  2050.  
  2051. void
  2052. setval(name,v)
  2053. INT16 v;
  2054. char *name;
  2055. {
  2056.     int n;
  2057.  
  2058.     if ( (n=parmindex(name)) < 0 )
  2059.         return;
  2060.     P[n].p_val = v;
  2061. }
  2062.  
  2063. int
  2064. getval(name)
  2065. char *name;
  2066. {
  2067.     int n;
  2068.  
  2069.     if ( (n=parmindex(name)) < 0 )
  2070.         return(0);
  2071.  
  2072.     if (pfoutflag)
  2073.         fprintf(pfout, "%s = %d\n", name, P[n].p_val);
  2074.  
  2075.     return(P[n].p_val);
  2076. }
  2077.  
  2078.  
  2079. enableparm(n)
  2080. {
  2081.     if ( P[n].p_flags != 0 )
  2082.         P[n].p_flags = 0;
  2083. }
  2084.  
  2085. disableparm(n)
  2086. {
  2087.     if ( P[n].p_flags == 0 )
  2088.         P[n].p_flags = 1;
  2089. }
  2090.  
  2091. midinote(onoff,chan,pitch,vol)
  2092. {
  2093.     sendmidi( ((onoff==1)?(0x90):(0x80)) | ((chan-1)&0xf) );
  2094.     sendmidi( pitch & 0x7f );
  2095.     sendmidi( vol & 0x7f );
  2096. }
  2097.  
  2098. static char Nbuff[16];
  2099.  
  2100. char *visnum(v)
  2101. {
  2102.     (void)sprintf(Nbuff,"%d",v);
  2103.     return(Nbuff);
  2104. }
  2105. char *visonoff(v)
  2106. {
  2107.     if ( v==0 )
  2108.         return("OFF");
  2109.     else
  2110.         return("ON ");
  2111. }
  2112.  
  2113. char *
  2114. bankvoice(voice)
  2115. {
  2116.     int offset = Libbank * Nvoices * Voicesize + voice * Voicesize;
  2117.     return(Libdata + offset);
  2118. }
  2119.