home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / amiga / midi / med210.lhw / in.adf / Source / med210src.lzh / med-pathlist.c < prev    next >
C/C++ Source or Header  |  1990-06-27  |  17KB  |  654 lines

  1. /* MED - music editor ⌐ 1989, 1990 by Teijo Kinnunen */
  2. /* med-pathlist.c: pathlist handling.. */
  3. #include <ctype.h>
  4. #include <dos.h>
  5. #include "med.h"
  6. #include "medproto.h"
  7. #define DIRSIZE (sizeof(struct PSDir))
  8. #define NAMESIZE (sizeof(struct PSName))
  9.  
  10. extern struct Task *maintsk;
  11. extern struct Window *window;
  12. extern struct Kappale far song;
  13. extern struct Soitin *sample[];
  14. extern UBYTE samplenum,hakemisto[];
  15. extern UWORD nykyinenosio,chip mouse0[],chip mouse1[];
  16. extern struct RastPort *wrp;
  17. extern struct FData *firstfd;
  18. extern BPTR fh;
  19. static struct PSDir *firstdir = NULL,*lastdir = NULL,*dispdir = NULL;
  20. static struct PSName *dispname = NULL;
  21. static UBYTE *spaces = "                ",cdirn = 0,dirs = 0;
  22. static UWORD centr = 0;
  23. UWORD lastrep,lastreplen;
  24. UBYTE lastmidic,lastmidip;
  25.  
  26. static UWORD __regargs Getposnum(struct PSName *,struct PSName *);
  27. static struct PSDir * __regargs MakeNewDir(char *);
  28. static struct PSName * __regargs MakeNewEntry(char *);
  29. static void __regargs InsertSampleName(struct PSName *,struct PSDir *);
  30. static BOOL __regargs DirAvailable(char *);
  31. static void __regargs FindAvailDirs(void);
  32. static void __regargs RemoveDir(struct PSDir *);
  33. static void __regargs RemoveName(void);
  34. static void __regargs AddName(void);
  35. static void __regargs AddDir(void);
  36. static void __regargs GetRepVals(struct PSName *);
  37. static void __regargs StripRepNums(char *,char *);
  38. static char * __regargs SavePathFile(char *);
  39. static void __regargs DispEntry(UWORD);
  40. static BOOL __regargs SearchFromDir(struct PSDir *,char *);
  41. static struct PSDir * __regargs SearchDirNum(UBYTE);
  42. static BOOL __regargs ConstrName(char *,char *,BOOL,struct PSDir **);
  43.  
  44. static UWORD __regargs Getposnum(struct PSName *ptr,struct PSName *this)
  45. {
  46.     register UWORD pos = 0;
  47.     if(!ptr || !this) return(0);
  48.     while(ptr && ptr != this) { pos++; ptr = ptr->next; }
  49.     return(pos);
  50. }
  51.  
  52. static struct PSDir * __regargs MakeNewDir(char *name)
  53. {
  54.     UWORD dirlen = DIRSIZE + strlen(name) + 1;
  55.     struct PSDir *newdir = malloc(dirlen);
  56.     if(!newdir) return(0L);
  57.     newdir->namelen = strlen(name);
  58.     newdir->entries = newdir->diravail = 0;
  59.     strcpy((char *)newdir+DIRSIZE,name);
  60.     newdir->prev = newdir->next = 0L;
  61.     newdir->first = newdir->last = 0L;
  62.     dirs++;
  63.     return(newdir);
  64. }
  65.  
  66. static struct PSName * __regargs MakeNewEntry(char *name)
  67. {
  68.     UWORD entrylen = NAMESIZE + strlen(name) + 1;
  69.     struct PSName *newentry = malloc(entrylen);
  70.     if(!newentry) return(0L);
  71.     newentry->namelen = strlen(name);
  72.     newentry->firstletter = toupper(*name);
  73.     strcpy((char *)newentry+NAMESIZE,name);
  74.     return(newentry);
  75. }
  76.  
  77. static void __regargs InsertSampleName(struct PSName *entr,struct PSDir *dir)
  78. {
  79.     register struct PSName *first = dir->first;
  80.     dir->entries++;
  81.     if(!first) {
  82.         dir->first = dir->last = entr;
  83.         entr->next = entr->prev = 0L;
  84.         return;
  85.     }
  86.     for(;stricmp((char *)first + NAMESIZE,
  87.         (char *)entr + NAMESIZE) <= 0 && first->next;
  88.         first = first->next);
  89.     if(!first->next && stricmp((char *)first + NAMESIZE,
  90.         (char *)entr + NAMESIZE) < 0) {
  91.         entr->next = 0L;
  92.         first->next = entr;
  93.         entr->prev = first;
  94.         dir->last = entr;
  95.         return;
  96.     }
  97.     entr->next = first;
  98.     if(entr->prev = first->prev) entr->prev->next = entr;
  99.     else dir->first = entr;
  100.     first->prev = entr;
  101. }
  102.  
  103. static BOOL __regargs DirAvailable(char *name)
  104. {
  105.     BPTR lock;
  106.     char tstname[120];
  107.     APTR prevwptr;
  108.     struct Process *tpr = (struct Process *)maintsk;
  109.     prevwptr = tpr->pr_WindowPtr;
  110.     tpr->pr_WindowPtr = (APTR)-1;
  111.     strcpy(tstname,name);
  112.     if(tstname[strlen(name) - 1] == '/') tstname[strlen(name) - 1] = 0;
  113.     lock = Lock(tstname,ACCESS_READ);
  114.     tpr->pr_WindowPtr = prevwptr;
  115.     if(lock) {
  116.         UnLock(lock);
  117.         return(TRUE);
  118.     }
  119.     return(FALSE);
  120. }
  121.  
  122. static void __regargs FindAvailDirs()
  123. {
  124.     struct PSDir *dir = firstdir,*dir2 = dir;
  125.     char thisdskname[FMSIZE],cmpdskname[FMSIZE];
  126.     while(dir2) { dir2->diravail = 2; /* 2=don't know */ dir2 = dir2->next; }
  127.     while(dir) {
  128.         if(dir->diravail == 2) {
  129.             if(DirAvailable((char *)dir + DIRSIZE)) {
  130.                 dir->diravail = 1;
  131.                 strsfn((char *)dir + DIRSIZE,thisdskname,
  132.                     NULL,NULL,NULL);
  133.                 dir2 = dir->next;
  134.                 while(dir2) {
  135.                     strsfn((char *)dir2 + DIRSIZE,
  136.                         cmpdskname,NULL,NULL,NULL);
  137.                     if(!strcmp(thisdskname,cmpdskname))
  138.                         dir2->diravail = 1;
  139.                     dir2 = dir2->next; /* ^disk is available */
  140.                 }
  141.             } else dir->diravail = 0;
  142.         }
  143.         dir = dir->next;
  144.     }
  145. }
  146.  
  147. void LoadPathFile()
  148. {
  149.     UBYTE *scanptr,*pathlist;
  150.     ULONG pathlistlen;
  151.     BPTR fh;
  152.     struct PSDir *currentdir;
  153.     struct PSName *currname;
  154.     fh = Open("MED_paths",MODE_OLDFILE);
  155.     if(!fh) fh = Open("S:MED_paths",MODE_OLDFILE);
  156.     if(!fh) {
  157.         Ilmoita("MED_paths not found.");
  158.         return; /* ei l÷ytynyt */
  159.     }
  160.     Seek(fh,0,OFFSET_END);
  161.     pathlistlen = Seek(fh,0,OFFSET_BEGINNING);
  162.     if(!(pathlist = malloc(pathlistlen))) {
  163.         Close(fh);
  164.         fh = NULL;
  165.         Ilmoita("No memory for path list.");
  166.         return;
  167.     }
  168.     StartLoad();
  169.     Ilmoita("Loading MED_paths...");
  170.     Read(fh,pathlist,pathlistlen);
  171.     Close(fh);
  172.     fh = NULL;
  173.     Ilmoita("Sorting MED_paths...");
  174.     for(scanptr = pathlist;scanptr < pathlist+pathlistlen; scanptr++)
  175.         if(*scanptr == '\n') *scanptr = '\0';
  176.     /* and now begin to translate the information to structures */
  177.     scanptr = pathlist;
  178.     while(scanptr < pathlist + pathlistlen) {
  179.         if(*scanptr == '*') {
  180.             if(!(currentdir = MakeNewDir(scanptr+1))) goto lpferr;
  181.             if(!firstdir) firstdir = lastdir = currentdir;
  182.             else {
  183.                 lastdir->next = currentdir;
  184.                 currentdir->prev = lastdir;
  185.                 lastdir = currentdir;
  186.             }
  187.             scanptr += strlen(scanptr+1) + 1;
  188.         }
  189.         else if(currentdir) {
  190.             if(!(currname = MakeNewEntry(scanptr))) goto lpferr;
  191.             InsertSampleName(currname,currentdir);
  192.             scanptr += strlen(scanptr);
  193.         }
  194.         scanptr++;
  195.     }
  196. lpferr:    free(pathlist);
  197.     dispdir = firstdir;
  198.     if(firstdir) dispname = firstdir->first;
  199.     StopLoad();
  200.     Ilmoita(NULL);
  201.     return;
  202. }
  203.  
  204. static void __regargs AddDir()
  205. {
  206.     struct PSDir *newdir;
  207.     struct PSName *newname;
  208.     struct FData *scanptr;
  209.     char newdirname[FMSIZE],fc;
  210.     strcpy(newdirname,hakemisto);
  211.     if(!(fc = strlen(newdirname))) return;
  212.     fc = newdirname[fc - 1];
  213.     if(fc != ':') strcat(newdirname,"/");
  214.     if(!(newdir = MakeNewDir(newdirname))) return;
  215.     newdir->next = dispdir;
  216.     if(dispdir) {
  217.         if(dispdir->prev) {
  218.             newdir->prev = dispdir->prev;
  219.             dispdir->prev->next = newdir;
  220.         }
  221.         dispdir->prev = newdir;
  222.     }
  223.     if(firstdir == dispdir) firstdir = newdir;
  224.     dispdir = newdir;
  225.     dirs++;
  226.     for(scanptr = firstfd; scanptr; scanptr = scanptr->next) {
  227.         if(scanptr->type > 0) continue;
  228.         if(!(newname = MakeNewEntry(scanptr->fname))) break;
  229.         InsertSampleName(newname,newdir);
  230.     }
  231.     cdirn = Getposnum((struct PSName *)firstdir,(struct PSName *)dispdir);
  232.     dispname = dispdir ? dispdir->first : 0L;
  233.     centr = 0;
  234.     DisplayPathList();
  235.      DisplayDirName();
  236. }
  237.  
  238. static char * __regargs SavePathFile(char *name)
  239. {
  240.     struct PSDir *wrdir = firstdir;
  241.     struct PSName *wrname;
  242.     char *wptr,wsiz;
  243.     if(!firstdir) return("No path list!!");
  244.     if(!(fh = Open2(name,MODE_NEWFILE))) return(DISKERR);
  245.     Ilmoita("Saving path list...");
  246.     while(wrdir) {
  247.         wptr = (char *)wrdir + DIRSIZE;
  248.         wsiz = strlen(wptr);
  249.         if(Write(fh,"*",1) != 1) return(DISKERR);
  250.         if(Write(fh,wptr,wsiz) != wsiz) return(DISKERR);
  251.         if(Write(fh,"\n",1) != 1) return(DISKERR);
  252.         wrname = wrdir->last;
  253.         while(wrname) { /* write in Z - A order: it's faster to load */
  254.             wptr = (char *)wrname + NAMESIZE;
  255.             wsiz = strlen(wptr);
  256.             if(Write(fh,wptr,wsiz) != wsiz) return(DISKERR);
  257.             if(Write(fh,"\n",1) != 1) return(DISKERR);
  258.             wrname = wrname->prev;
  259.         }
  260.         wrdir = wrdir->next;
  261.     }
  262.     if(fh) { Close(fh); fh = 0L; }
  263.     Ilmoita("Saved.");
  264.     return(NOERR);
  265. }
  266.  
  267. static void __regargs RemoveDir(struct PSDir *dir)
  268. {
  269.     struct PSName *delname,*del2;
  270.     if(!dir) return;
  271.     delname = dir->first;
  272.     if(dir->next) dir->next->prev = dir->prev;
  273.     if(dir->prev) dir->prev->next = dir->next;
  274.     if(firstdir == dir) firstdir = dir->next;
  275.     dirs--;
  276.     if(dispdir == dir)
  277.         if(dispdir = (dir->next ? dir->next : dir->prev))
  278.             dispname = dispdir->first;
  279.         else    dispname = 0L;
  280.     while(delname) {
  281.         del2 = delname->next;
  282.         free((char *)delname);
  283.         delname = del2;
  284.     }
  285.     free((char *)dir);
  286.     cdirn = Getposnum((struct PSName *)firstdir,(struct PSName *)dispdir);
  287. }
  288.  
  289. void FreePaths()
  290. {
  291.     struct PSDir *deldir = firstdir,*ndeld;
  292.     Ilmoita("Freeing path list...");
  293.     while(deldir) {
  294.         ndeld = deldir->next;
  295.         RemoveDir(deldir);
  296.         deldir = ndeld;
  297.     }
  298. }
  299.  
  300. static void __regargs AddName()
  301. {
  302.     char newentry[100],*ptr;
  303.     struct PSName *newname;
  304.     struct SongSample *ss = &song.sample[samplenum];
  305.     if(!dispdir) return;
  306.     ptr = stpcpy(newentry,ss->sname);
  307.     if(ss->midich) {
  308.         *ptr++ = ':'; *ptr++ = ':'; *ptr++ = 'M';
  309.         ptr += stcu_d(ptr,ss->midich);
  310.         *ptr++ = '/';
  311.         ptr += stcu_d(ptr,ss->midipreset);
  312.     } else if(ss->rep || ss->replen > 1) {
  313.         *ptr++ = ':'; *ptr++ = ':';
  314.         ptr += stcu_d(ptr,ss->rep << 1);
  315.         *ptr++ = '/';
  316.         stcu_d(ptr,ss->replen << 1);
  317.     }
  318.     if(!(newname = MakeNewEntry(newentry))) return;
  319.     InsertSampleName(newname,dispdir);
  320.     dispname = newname;
  321.     DisplayPathList();
  322. }
  323.  
  324. static void __regargs RemoveName()
  325. {
  326.     struct PSDir *remdir = dispdir;
  327.     struct PSName *remptr = dispname;
  328.     if(!remptr || !remdir) return;
  329.     if(remptr->prev) remptr->prev->next = remptr->next;
  330.     if(remptr->next) {
  331.         remptr->next->prev = remptr->prev;
  332.         dispname = remptr->next;
  333.     } else dispname = remptr->prev;
  334.     remdir->entries--;
  335.     if(remdir->first == remptr) remdir->first = remptr->next;
  336.     if(remdir->last == remptr) remdir->last = remptr->prev;
  337.     free((char *)remptr);
  338.     centr = Getposnum(remdir->first,dispname);
  339. }
  340.  
  341. void DisplayDirName()
  342. {
  343.     UBYTE txt[2] = { '0','0' },*dspdirn,*dspdirs,ddnl;
  344.     if(nykyinenosio != 0xB) return;
  345.     SetAPen(wrp,1);
  346.     SetBPen(wrp,3);
  347.     Move(wrp,147,26);
  348.     if(!dispdir) {
  349.         Text(wrp,"----------",10);
  350.         txt[0] = txt[1] = '-';
  351.     } else {
  352.         dspdirs = dspdirn = (char *)dispdir + DIRSIZE;
  353.         dspdirn += strlen(dspdirn) - 2;
  354.         while(dspdirn >= dspdirs && *dspdirn != '/' && *dspdirn != ':')
  355.             dspdirn--;
  356.         dspdirn++;
  357.         if((ddnl = strlen(dspdirn)) >= 10)
  358.             Text(wrp,dspdirn,10);
  359.         else {
  360.             Text(wrp,dspdirn,ddnl);
  361.             Text(wrp,spaces,10 - ddnl);
  362.         }
  363.     }
  364.     Move(wrp,211,37);
  365.     txt[0] += cdirn /á10;
  366.     txt[1] += cdirn % 10;
  367.     Text(wrp,txt,2);
  368. }
  369.  
  370. void DisplayPathList()
  371. {
  372.     struct PSName *dptr;
  373.     UBYTE dispcnt;
  374.     if(nykyinenosio != 0xB) return;
  375.     SetAPen(wrp,0);
  376.     SetBPen(wrp,3);
  377.     wrp->Mask = 0x3;
  378.     if(!dispname || !dispdir) for(dispcnt = 0; dispcnt < 5; dispcnt++) {
  379.         Move(wrp,7,26 + 8 * dispcnt);
  380.         Text(wrp,spaces,16);
  381.     } else for(dispcnt = 0; dispcnt < 5; dispcnt++) {
  382.         Move(wrp,7,26 + 8 * dispcnt);
  383.         switch(dispcnt) {
  384.             case 0:    if(dptr = dispname->prev) dptr = dptr->prev;
  385.                 break;
  386.             case 1:    dptr = dispname->prev; break;
  387.             case 2:    dptr = dispname; SetBPen(wrp,1); break;
  388.             case 3: dptr = dispname->next; SetBPen(wrp,3); break;
  389.             case 4: if(dptr = dispname->next) dptr = dptr->next;
  390.         }
  391.         if(!dptr) Text(wrp,spaces,16);
  392.         else {
  393.             if(dptr->namelen >= 16)    Text(wrp,(char *)dptr +
  394.                 NAMESIZE,16);
  395.             else {
  396.                 Text(wrp,(char *)dptr + sizeof(struct
  397.                     PSName),dptr->namelen);
  398.                 Text(wrp,spaces,16 - dptr->namelen);
  399.             }
  400.             dptr = dptr->next;
  401.         }
  402.     }
  403.     wrp->Mask = 0xff;
  404. }
  405.  
  406. static void __regargs GetRepVals(struct PSName *name)
  407. {
  408.     UBYTE *tstchr,midi = 0;
  409.     ULONG rvals[2] = { 0,0 },*numptr = rvals;
  410.     if(!name) return;
  411.     lastrep = lastreplen = 0;
  412.     lastmidic = lastmidip = 0;
  413.     tstchr = (UBYTE *)name + NAMESIZE;
  414.     while(*tstchr && *tstchr != ':') tstchr++;
  415.     if(!(*tstchr) || *(tstchr+1) != ':') return;
  416.     tstchr += 2;
  417.     if(*tstchr == 'm' || *tstchr == 'M') { midi = 1; tstchr++; }
  418.     while(*tstchr) {
  419.         if(*tstchr == '/') numptr = &rvals[1]; /* now coming length */
  420.         if(isdigit(*tstchr)) {
  421.             *numptr *= 10;
  422.             *numptr += ((*tstchr) - '0');
  423.         }
  424.         tstchr++;
  425.     }
  426.     if(midi) { /* these numbers are not repeat/length, instead they */
  427.          /* are now midi channel and preset number */
  428.         if(lastrep <= 16) lastmidic = (UBYTE)rvals[0];
  429.         if(lastreplen <= 128) lastmidip = (UBYTE)rvals[1];
  430.     } else {
  431.         lastrep = (UWORD)(rvals[0] >> 1);
  432.         lastreplen = (UWORD)(rvals[1] >> 1);
  433.     }
  434. }
  435.  
  436. static void __regargs StripRepNums(char *name,char *to)
  437. {
  438.     while(*name && *name != ':') *to++ = *name++;
  439.     *to = 0;
  440. }
  441.  
  442. void LoadSelectedSample()
  443. {
  444.     char fullname[150],*nameptr;
  445.     if(!dispname || !dispdir) return;
  446.     StartLoad();
  447.     strcpy(fullname,(char *)dispdir + DIRSIZE);
  448.     nameptr = fullname + strlen(fullname);
  449.     StripRepNums((char *)dispname + NAMESIZE,nameptr);
  450.     GetRepVals(dispname);
  451.     strcpy(song.sample[samplenum].sname,nameptr);
  452.     nameptr =  LoadInstrument(fullname,FALSE);
  453.     PaivitaSoittimennimi();
  454.     StopLoad();
  455.     if(nameptr == NOERR) SampleLoaded();
  456.     diskerr(nameptr);
  457. }
  458.  
  459. static void __regargs DispEntry(UWORD num)
  460. {
  461.     dispname = dispdir->first;
  462.     centr = 0;
  463.     while(num-- && dispname->next) { dispname = dispname->next; centr++; }
  464.     DisplayPathList();
  465. }
  466.  
  467. void ScrollSLUp(BYTE steps)
  468. {
  469.     if(!dispname) return;
  470.     if(steps < 0) {
  471.         dispname = dispdir->first;
  472.         centr = 0;
  473.     }
  474.     else while(centr && steps--) { dispname = dispname->prev; centr--; }
  475.     DisplayPathList();
  476. }
  477.  
  478. void ScrollSLDown(BYTE steps)
  479. {
  480.     if(!dispname) return;
  481.     if(steps < 0) {
  482.         dispname = dispdir->last;
  483.         centr = dispdir->entries - 1;
  484.     } else while(centr < (dispdir->entries - 1) && steps--) {
  485.         dispname = dispname->next; centr++;
  486.     }
  487.     DisplayPathList();
  488. }
  489.  
  490. void HandleB(UWORD gid)
  491. {
  492.     switch(gid) {
  493.         case 0xB00:    ScrollSLUp(1);   break;
  494.         case 0xB02:    ScrollSLDown(1); break;
  495.         case 0xB03: case 0xB04:
  496.             if(!dispdir) break;
  497.             if(gid == 0xB03) { 
  498.                 if(dispdir->prev) {
  499.                     dispdir = dispdir->prev;
  500.                     cdirn--;
  501.                 }
  502.             } else {
  503.                 if(dispdir->next) {
  504.                     dispdir = dispdir->next;
  505.                     cdirn++;
  506.                 }
  507.             }
  508.             dispname = dispdir->first;
  509.             centr = 0;
  510.             DisplayPathList();
  511.             DisplayDirName();
  512.             break;
  513.         case 0xB01:    ScrollSLUp((BYTE)-1); break;
  514.         case 0xB0C:    ScrollSLDown((BYTE)-1); break;
  515.         case 0xB05:    LoadSelectedSample(); break;
  516.         case 0xB0A:    RemoveName(); DisplayPathList(); break;
  517.         case 0xB0B:    RemoveDir(dispdir);
  518.                  DisplayPathList(); DisplayDirName(); break;
  519.         case 0xB08:    AddName(); break;
  520.         case 0xB09:    AddDir(); break;
  521.         case 0xB06: case 0xB07:
  522.             StartLoad();
  523.             diskerr(SavePathFile(gid == 0xB06 ? "MED_paths" :
  524.                 "S:MED_paths"));
  525.             StopLoad();
  526.     }
  527. }
  528.  
  529. static BOOL __regargs SearchFromDir(struct PSDir *dir,char *name)
  530. {
  531.     UBYTE matchletter = toupper(*name),name2[110];
  532.     struct PSName *searchptr = (dir ? dir->first : 0L);
  533.     while(searchptr) {
  534.         if(searchptr->firstletter >= matchletter) {
  535.             if(searchptr->firstletter > matchletter) return(FALSE);
  536.             StripRepNums((char *)searchptr+NAMESIZE,name2);
  537.             if(!stricmp(name2,name)) {
  538.                 GetRepVals(searchptr);
  539.                 return(TRUE);
  540.             }
  541.         }
  542.         searchptr = searchptr->next;
  543.     }
  544.     return(FALSE);
  545. }
  546.  
  547. static struct PSDir * __regargs SearchDirNum(UBYTE num)
  548. {
  549.     struct PSDir *ptr = firstdir;
  550.     while(ptr && num--) ptr = ptr->next;
  551.     return(ptr);
  552. }
  553.  
  554. static BOOL __regargs ConstrName(char *fname,char *tname,
  555.     BOOL mustfind,struct PSDir **founddir)
  556. {
  557.     UBYTE dircnt;
  558.     char fpath[FMSIZE];
  559.     struct PSDir *tstdir,*found = 0L;
  560.     *tname = 0;
  561.     *founddir = 0L;
  562.     if(stcgfp(fpath,fname)) {
  563.         if(DirAvailable(fpath) || mustfind) {
  564.             strcpy(tname,fname);
  565.             return(TRUE);
  566.         }
  567.         return(FALSE);
  568.     }
  569.     for(dircnt = 0; dircnt < dirs; dircnt++) {
  570.         tstdir = SearchDirNum(dircnt);
  571.         if(tstdir->diravail && SearchFromDir(tstdir,fname)) {
  572.             found = tstdir;
  573.             break;
  574.         }
  575.     }
  576.     if(mustfind && !found) {
  577.         for(dircnt = 0; dircnt < dirs; dircnt++) {
  578.             tstdir = SearchDirNum(dircnt);
  579.             if(!tstdir->diravail && SearchFromDir(tstdir,fname)) {
  580.                 found = tstdir;
  581.                 break;
  582.             }
  583.         }
  584.     }
  585.     if(found) strcpy(tname,(char *)found + DIRSIZE);
  586.     *founddir = found;
  587.     strcat(tname,fname);
  588.     return((BOOL)found);
  589. }
  590.     
  591. void ConstructDirName(char *from,char *to)
  592. {
  593.     struct PSDir *dir = firstdir,*here = NULL;
  594.     while(dir) {
  595.         if(SearchFromDir(dir,from)) {
  596.             here = dir;
  597.             if(DirAvailable((char *)dir + DIRSIZE)) break;
  598.         }
  599.         dir = dir->next;
  600.     }
  601.     if(here) strcpy(to,(char *)here + DIRSIZE);
  602.     else *to = '\0';
  603.     strcat(to,from);
  604. }
  605.  
  606. char *LoadSongSamples() /* the intelligent sample loader */
  607. {
  608.     UBYTE samplelist[63],cnt,stl = 0,fullname[FMSIZE];
  609.     char *res = NOERR;
  610.     struct PSDir *dir;
  611.     FindAvailDirs();
  612.     for(cnt = 0; cnt < 63; cnt++) /* Find number of samples to load */
  613.         if(song.sample[cnt].sname[0] && !song.sample[cnt].midich
  614.             && !sample[cnt] && stcgfn(fullname,song.sample[cnt].sname)) {
  615.             samplelist[cnt] = 1;
  616.             stl++;
  617.         } else samplelist[cnt] = 0;
  618.     while(stl) {
  619.         for(cnt = 0; cnt < 63; cnt++) {
  620.             if(samplelist[cnt] == 1) {
  621.                 if(ConstrName(song.sample[cnt].sname,
  622. /* load everything that can be */    fullname,FALSE,&dir)) {
  623. /* loaded without disk swapping */    samplenum = cnt;
  624.                     PaivitaSoittimennimi();
  625.                     stl--;
  626.                     samplelist[cnt] = 0;
  627.                     if(res = LoadInstrument(fullname,FALSE)) {
  628.                         diskerr(res);
  629.                         if(!Continue()) goto stop;
  630.                     }
  631.                 }
  632.             }
  633.         }
  634.         for(cnt = 0; cnt < 63; cnt++) {
  635.             if(samplelist[cnt] == 1) {
  636. /* then load a sample which */    ConstrName(song.sample[cnt].sname,
  637. /* needs disk swapping */        fullname,TRUE,&dir);
  638.                 samplenum = cnt;
  639.                 PaivitaSoittimennimi();
  640.                 stl--;
  641.                 samplelist[cnt] = 0;
  642.                 if(res = LoadInstrument(fullname,FALSE)) {
  643.                     diskerr(res);
  644.                     if(!Continue()) goto stop;
  645.                 }
  646.                 if(dir) dir->diravail = 1;
  647. /* try again load without.. */    break;    /* ..swapping */
  648.             }
  649.         }
  650.     }
  651.     return(NOERR);
  652. stop:    return("Loading aborted.");
  653. }
  654.