home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.74_stereo.zip / src / gfile.c < prev    next >
C/C++ Source or Header  |  2014-07-23  |  13KB  |  531 lines

  1. //
  2. // GOATTRACKER v2 file selector
  3. //
  4.  
  5. #define GFILE_C
  6.  
  7. #ifdef __WIN32__
  8. #include <windows.h>
  9. #endif
  10.  
  11. #include "goattrk2.h"
  12.  
  13. DIRENTRY direntry[MAX_DIRFILES];
  14.  
  15. void initpaths(void)
  16. {
  17.   int c;
  18.   
  19.   for (c = 0; c < MAX_DIRFILES; c++)
  20.      direntry[c].name = NULL;
  21.  
  22.   memset(loadedsongfilename, 0, sizeof loadedsongfilename);
  23.   memset(songfilename, 0, sizeof songfilename);
  24.   memset(instrfilename, 0, sizeof instrfilename);
  25.   memset(songpath, 0, sizeof songpath);
  26.   memset(instrpath, 0, sizeof instrpath);
  27.   memset(packedpath, 0, sizeof packedpath);
  28.   strcpy(songfilter, "*.sng");
  29.   strcpy(instrfilter, "*.ins");
  30.  
  31.   getcwd(songpath, MAX_PATHNAME);
  32.   strcpy(instrpath, songpath);
  33.   strcpy(packedpath, songpath);
  34. }
  35.  
  36. int fileselector(char *name, char *path, char *filter, char *title, int filemode)
  37. {
  38.   int c, d, scrrep;
  39.   int color;
  40.   int files;
  41.   int filepos = 0;
  42.   int fileview = 0;
  43.   int lastclick = 0;
  44.   int lastfile = 0;
  45.   int lowest;
  46.   int exitfilesel;
  47.  
  48.   DIR *dir;
  49.   struct dirent *de;
  50.   struct stat st;
  51.   #ifdef __WIN32__
  52.   char drivestr[] = "A:\\";
  53.   char driveexists[26];
  54.   #endif
  55.   char cmpbuf[MAX_PATHNAME];
  56.   char tempname[MAX_PATHNAME];
  57.  
  58.   // Set initial path (if any)
  59.   if (strlen(path)) chdir(path);
  60.  
  61.   // Scan for all existing drives
  62.   #ifdef __WIN32__
  63.   for (c = 0; c < 26; c++)
  64.   {
  65.     drivestr[0] = 'A'+c;
  66.     if (GetDriveType(drivestr) > 1) driveexists[c] = 1;
  67.     else driveexists[c] = 0;
  68.   }
  69.   #endif
  70.  
  71.   // Read new directory
  72.   NEWPATH:
  73.   getcwd(path, MAX_PATHNAME);
  74.   files = 0;
  75.   // Deallocate old names
  76.   for (c = 0; c < MAX_DIRFILES; c++)
  77.   {
  78.     if (direntry[c].name)
  79.     {
  80.       free(direntry[c].name);
  81.       direntry[c].name = NULL;
  82.     }
  83.   }
  84.   #ifdef __WIN32__
  85.   // Create drive letters
  86.   for (c = 0; c < 26; c++)
  87.   {
  88.     if (driveexists[c])
  89.     {
  90.       drivestr[0] = 'A'+c;
  91.       direntry[files].name = strdup(drivestr);
  92.       direntry[files].attribute = 2;
  93.       files++;
  94.     }
  95.   }
  96.   #endif
  97.  
  98.   // Process directory
  99.   #ifdef __amigaos__
  100.   dir = opendir("");
  101.   #else
  102.   dir = opendir(".");
  103.   #endif
  104.   if (dir)
  105.   {
  106.     char *filtptr = strstr(filter, "*");
  107.     if (!filtptr) filtptr = filter;
  108.     else filtptr++;
  109.     for (c = 0; c < strlen(filter); c++)
  110.       filter[c] = tolower(filter[c]);
  111.  
  112.     while ((de = readdir(dir)))
  113.     {
  114.       if ((files < MAX_DIRFILES) && (strlen(de->d_name) < MAX_FILENAME))
  115.       {
  116.         direntry[files].name = strdup(de->d_name);
  117.         direntry[files].attribute = 0;
  118.         stat(de->d_name, &st);
  119.         if (st.st_mode & S_IFDIR)
  120.         {
  121.           direntry[files].attribute = 1;
  122.           files++;
  123.         }
  124.         else
  125.         {
  126.           int c;
  127.           // If a file, must match filter
  128.           strcpy(cmpbuf, de->d_name);
  129.           if ((!strcmp(filtptr, "*")) || (!strcmp(filtptr, ".*")))
  130.             files++;
  131.           else
  132.           {
  133.             for (c = 0; c < strlen(cmpbuf); c++)
  134.               cmpbuf[c] = tolower(cmpbuf[c]);
  135.             if (strstr(cmpbuf, filtptr))
  136.               files++;
  137.             else
  138.             {
  139.               free(direntry[files].name);
  140.               direntry[files].name = NULL;
  141.             }
  142.           }
  143.         }
  144.       }
  145.     }
  146.     closedir(dir);
  147.   }
  148.   // Sort the filelist in a most horrible fashion
  149.   for (c = 0; c < files; c++)
  150.   {
  151.     lowest = c;
  152.     for (d = c+1; d < files; d++)
  153.     {
  154.       if (direntry[d].attribute < direntry[lowest].attribute)
  155.       {
  156.         lowest = d;
  157.       }
  158.       else
  159.       {
  160.         if (direntry[d].attribute == direntry[lowest].attribute)
  161.         {
  162.           if (cmpname(direntry[d].name, direntry[lowest].name) < 0)
  163.           {
  164.             lowest = d;
  165.           }
  166.         }
  167.       }
  168.     }
  169.     if (lowest != c)
  170.     {
  171.       DIRENTRY swaptemp = direntry[c];
  172.       direntry[c] = direntry[lowest];
  173.       direntry[lowest] = swaptemp;
  174.     }
  175.   }
  176.  
  177.   // Search for the current filename
  178.   fileview = 0;
  179.   filepos = 0;
  180.   for (c = 0; c < files; c++)
  181.   {
  182.     if ((!direntry[c].attribute) && (!cmpname(name, direntry[c].name)))
  183.     {
  184.       filepos = c;
  185.     }
  186.   }
  187.  
  188.   exitfilesel = -1;
  189.   while (exitfilesel < 0)
  190.   {
  191.     int cc = cursorcolortable[cursorflash];
  192.     if (cursorflashdelay >= 6)
  193.     {
  194.       cursorflashdelay %= 6;
  195.       cursorflash++;
  196.       cursorflash &= 3;
  197.     }
  198.     fliptoscreen();
  199.     getkey();
  200.     if (lastclick) lastclick--;
  201.  
  202.     if (win_quitted)
  203.     {
  204.       exitprogram = 1;
  205.       for (c = 0; c < MAX_DIRFILES; c++)
  206.       {
  207.         if (direntry[c].name)
  208.         {
  209.           free(direntry[c].name);
  210.           direntry[c].name = NULL;
  211.         }
  212.       }
  213.       return 0;
  214.     }
  215.  
  216.     if (mouseb)
  217.     {
  218.       // Cancel (click outside)
  219.       if ((mousey < 3) || (mousey > 3+VISIBLEFILES+6) || (mousex <= 4+10) || (mousex >= 75+10))
  220.       {
  221.         if ((!prevmouseb) && (lastclick)) exitfilesel = 0;
  222.       }
  223.  
  224.       // Select dir,name,filter
  225.       if ((mousey >= 3+VISIBLEFILES+3) && (mousey <= 3+VISIBLEFILES+5) && (mousex >= 14+10) && (mousex <= 73+10))
  226.       {
  227.         filemode = mousey - (3+VISIBLEFILES+3) + 1;
  228.         if ((filemode == 3) && (!prevmouseb) && (lastclick)) goto ENTERFILE;
  229.       }
  230.  
  231.       // Select file from list
  232.       if ((mousey >= 3) && (mousey <= 3+VISIBLEFILES+2) && (mousex >= 6+10) && (mousex <= 73+10))
  233.       {
  234.         filemode = 0;
  235.         filepos = mousey - 4 - 1 + fileview;
  236.         if (filepos < 0) filepos = 0;
  237.         if (filepos > files-1) filepos = files - 1;
  238.  
  239.         if (!direntry[filepos].attribute)
  240.           strcpy(name, direntry[filepos].name);
  241.  
  242.         if ((!prevmouseb) && (lastclick) && (lastfile == filepos)) goto ENTERFILE;
  243.       }
  244.     }
  245.  
  246.     if (!filemode)
  247.     {
  248.       if (((key >= '0') && (key <= '0')) || ((key >= 'a') && (key <= 'z')) || ((key >= 'A') && (key <= 'Z')))
  249.       {
  250.         char k = tolower(key);
  251.         int oldfilepos = filepos;
  252.  
  253.         for (filepos = oldfilepos + 1; filepos < files; filepos++)
  254.           if (tolower(direntry[filepos].name[0]) == k) break;
  255.         if (filepos >= files)
  256.         {
  257.           for (filepos = 0; filepos < oldfilepos; filepos++)
  258.              if (tolower(direntry[filepos].name[0]) == k) break;
  259.         }
  260.  
  261.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  262.       }
  263.     }
  264.  
  265.     switch(rawkey)
  266.     {
  267.       case KEY_ESC:
  268.       exitfilesel = 0;
  269.       break;
  270.  
  271.       case KEY_BACKSPACE:
  272.       if (!filemode)
  273.       {
  274.       #ifdef __amigaos__
  275.         chdir("/");
  276.       #else
  277.         chdir("..");
  278.       #endif
  279.         goto NEWPATH;
  280.       }
  281.       break;
  282.  
  283.       case KEY_HOME:
  284.       if (!filemode)
  285.       {
  286.         filepos = 0;
  287.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  288.       }
  289.       break;
  290.  
  291.       case KEY_END:
  292.       if (!filemode)
  293.       {
  294.         filepos = files-1;
  295.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  296.       }
  297.       break;
  298.  
  299.       case KEY_PGUP:
  300.       for (scrrep = PGUPDNREPEAT; scrrep; scrrep--)
  301.       {
  302.         if ((!filemode) && (filepos > 0))
  303.         {
  304.           filepos--;
  305.           if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  306.         }
  307.       }
  308.       break;
  309.  
  310.       case KEY_UP:
  311.       if ((!filemode) && (filepos > 0))
  312.       {
  313.         filepos--;
  314.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  315.       }
  316.       break;
  317.  
  318.       case KEY_PGDN:
  319.       for (scrrep = PGUPDNREPEAT; scrrep; scrrep--)
  320.       {
  321.         if ((!filemode) && (filepos < files-1))
  322.         {
  323.           filepos++;
  324.           if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  325.         }
  326.       }
  327.       break;
  328.  
  329.       case KEY_DOWN:
  330.       if ((!filemode) && (filepos < files-1))
  331.       {
  332.         filepos++;
  333.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  334.       }
  335.       break;
  336.  
  337.       case KEY_TAB:
  338.       if (!shiftpressed)
  339.       {
  340.         filemode++;
  341.         if (filemode > 3) filemode = 0;
  342.       }
  343.       else
  344.       {
  345.         filemode--;
  346.         if (filemode < 0) filemode = 3;
  347.       }
  348.       break;
  349.  
  350.       case KEY_ENTER:
  351.       ENTERFILE:
  352.       switch(filemode)
  353.       {
  354.         case 0:
  355.         switch (direntry[filepos].attribute)
  356.         {
  357.           case 0:
  358.           strcpy(name, direntry[filepos].name);
  359.           exitfilesel = 1;
  360.           break;
  361.  
  362.           case 1:
  363.           chdir(direntry[filepos].name);
  364.           goto NEWPATH;
  365.  
  366.           case 2:
  367.           strcpy(tempname, direntry[filepos].name);
  368.           if (strlen(tempname))
  369.           {
  370.             if (tempname[strlen(tempname)-1] != '\\')
  371.               strcat(tempname, "\\");
  372.           }
  373.           chdir(tempname);
  374.           goto NEWPATH;
  375.         }
  376.         break;
  377.  
  378.         case 1:
  379.         chdir(path);
  380.         case 2:
  381.         filemode = 0;
  382.         goto NEWPATH;
  383.  
  384.         case 3:
  385.         exitfilesel = 1;
  386.         break;
  387.       }
  388.       break;
  389.     }
  390.  
  391.     switch(filemode)
  392.     {
  393.       case 1:
  394.       editstring(path, MAX_PATHNAME);
  395.       break;
  396.  
  397.       case 2:
  398.       editstring(filter, MAX_FILENAME);
  399.       break;
  400.  
  401.       case 3:
  402.       editstring(name, MAX_FILENAME);
  403.       break;
  404.     }
  405.  
  406.     // Validate filelist view
  407.     if (filepos < fileview) fileview = filepos;
  408.     if (filepos - fileview >= VISIBLEFILES) fileview = filepos - VISIBLEFILES + 1;
  409.  
  410.     // Refresh fileselector display
  411.     if (isplaying()) printstatus();
  412.     for (c = 0; c < VISIBLEFILES+7; c++)
  413.     {
  414.       printblank(50-(MAX_FILENAME+10)/2, 3+c, MAX_FILENAME+10);
  415.     }
  416.     drawbox(50-(MAX_FILENAME+10)/2, 3, 15, MAX_FILENAME+10, VISIBLEFILES+7);
  417.     printblankc(50-(MAX_FILENAME+10)/2+1, 4, 15+16,MAX_FILENAME+8);
  418.     printtext(50-(MAX_FILENAME+10)/2+1, 4, 15+16, title);
  419.  
  420.     for (c = 0; c < VISIBLEFILES; c++)
  421.     {
  422.       if ((fileview+c >= 0) && (fileview+c < files))
  423.       {
  424.         switch (direntry[fileview+c].attribute)
  425.         {
  426.           case 0:
  427.           sprintf(textbuffer, "%-60s        ", direntry[fileview+c].name);
  428.           break;
  429.  
  430.           case 1:
  431.           sprintf(textbuffer, "%-60s   <DIR>", direntry[fileview+c].name);
  432.           break;
  433.  
  434.           case 2:
  435.           sprintf(textbuffer, "%-60s   <DRV>", direntry[fileview+c].name);
  436.           break;
  437.         }
  438.       }
  439.       else
  440.       {
  441.         sprintf(textbuffer, "                                                                    ");
  442.       }
  443.       color = CNORMAL;
  444.       if ((fileview+c) == filepos) color = CEDIT;
  445.       textbuffer[68] = 0;
  446.       printtext(50-(MAX_FILENAME+10)/2+1, 5+c, color, textbuffer);
  447.       if ((!filemode) && ((fileview+c) == filepos)) printbg(50-(MAX_FILENAME+10)/2+1, 5+c, cc, 68);
  448.     }
  449.  
  450.     printtext(50-(MAX_FILENAME+10)/2+1, 6+VISIBLEFILES, 15, "PATH:   ");
  451.     sprintf(textbuffer, "%-60s", path);
  452.     textbuffer[MAX_FILENAME] = 0;
  453.     color = CNORMAL;
  454.     if (filemode == 1) color = CEDIT;
  455.     printtext(50-(MAX_FILENAME+10)/2+9, 6+VISIBLEFILES, color, textbuffer);
  456.     if ((filemode == 1) && (strlen(path) < MAX_FILENAME)) printbg(50-(MAX_FILENAME+10)/2+9+strlen(path), 6+VISIBLEFILES, cc, 1);
  457.  
  458.     printtext(50-(MAX_FILENAME+10)/2+1, 7+VISIBLEFILES, 15, "FILTER: ");
  459.     sprintf(textbuffer, "%-60s", filter);
  460.     textbuffer[MAX_FILENAME] = 0;
  461.     color = CNORMAL;
  462.     if (filemode == 2) color = CEDIT;
  463.     printtext(50-(MAX_FILENAME+10)/2+9, 7+VISIBLEFILES, color, textbuffer);
  464.     if (filemode == 2) printbg(50-(MAX_FILENAME+10)/2+9+strlen(filter), 7+VISIBLEFILES, cc, 1);
  465.  
  466.     printtext(50-(MAX_FILENAME+10)/2+1, 8+VISIBLEFILES, 15, "NAME:   ");
  467.     sprintf(textbuffer, "%-60s", name);
  468.     textbuffer[MAX_FILENAME] = 0;
  469.     color = CNORMAL;
  470.     if (filemode == 3) color = CEDIT;
  471.     printtext(50-(MAX_FILENAME+10)/2+9, 8+VISIBLEFILES, color, textbuffer);
  472.     if (filemode == 3) printbg(50-(MAX_FILENAME+10)/2+9+strlen(name), 8+VISIBLEFILES, cc, 1);
  473.  
  474.     if (win_quitted) exitfilesel = 0;
  475.  
  476.     if ((mouseb) && (!prevmouseb))
  477.     {
  478.       lastclick = DOUBLECLICKDELAY;
  479.       lastfile = filepos;
  480.     }
  481.   }
  482.  
  483.   // Deallocate all used names
  484.   for (c = 0; c < MAX_DIRFILES; c++)
  485.   {
  486.     if (direntry[c].name)
  487.     {
  488.       free(direntry[c].name);
  489.       direntry[c].name = NULL;
  490.     }
  491.   }
  492.  
  493.   // Restore screen & exit
  494.   printmainscreen();
  495.   return exitfilesel;
  496. }
  497.  
  498. void editstring(char *buffer, int maxlength)
  499. {
  500.   int len = strlen(buffer);
  501.  
  502.   if (key)
  503.   {
  504.     if ((key >= 32) && (key < 256))
  505.     {
  506.       if (len < maxlength-1)
  507.       {
  508.         buffer[len] = key;
  509.         buffer[len+1] = 0;
  510.       }
  511.     }
  512.     if ((key == 8) && (len > 0))
  513.     {
  514.       buffer[len-1] = 0;
  515.     }
  516.   }
  517. }
  518.  
  519. int cmpname(char *string1, char *string2)
  520. {
  521.   for (;;)
  522.   {
  523.     unsigned char char1 = tolower(*string1++);
  524.     unsigned char char2 = tolower(*string2++);
  525.     if (char1 < char2) return -1;
  526.     if (char1 > char2) return 1;
  527.     if ((!char1) || (!char2)) return 0;
  528.   }
  529. }
  530.  
  531.