home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.70_stereo.zip / src / gfile.c < prev    next >
C/C++ Source or Header  |  2008-04-01  |  13KB  |  524 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.   dir = opendir(".");
  100.   if (dir)
  101.   {
  102.     char *filtptr = strstr(filter, "*");
  103.     if (!filtptr) filtptr = filter;
  104.     else filtptr++;
  105.     for (c = 0; c < strlen(filter); c++)
  106.       filter[c] = tolower(filter[c]);
  107.  
  108.     while ((de = readdir(dir)))
  109.     {
  110.       if ((files < MAX_DIRFILES) && (strlen(de->d_name) < MAX_FILENAME))
  111.       {
  112.         direntry[files].name = strdup(de->d_name);
  113.         direntry[files].attribute = 0;
  114.         stat(de->d_name, &st);
  115.         if (st.st_mode & S_IFDIR)
  116.         {
  117.           direntry[files].attribute = 1;
  118.           files++;
  119.         }
  120.         else
  121.         {
  122.           int c;
  123.           // If a file, must match filter
  124.           strcpy(cmpbuf, de->d_name);
  125.           if ((!strcmp(filtptr, "*")) || (!strcmp(filtptr, ".*")))
  126.             files++;
  127.           else
  128.           {
  129.             for (c = 0; c < strlen(cmpbuf); c++)
  130.               cmpbuf[c] = tolower(cmpbuf[c]);
  131.             if (strstr(cmpbuf, filtptr))
  132.               files++;
  133.             else
  134.             {
  135.               free(direntry[files].name);
  136.               direntry[files].name = NULL;
  137.             }
  138.           }
  139.         }
  140.       }
  141.     }
  142.     closedir(dir);
  143.   }
  144.   // Sort the filelist in a most horrible fashion
  145.   for (c = 0; c < files; c++)
  146.   {
  147.     lowest = c;
  148.     for (d = c+1; d < files; d++)
  149.     {
  150.       if (direntry[d].attribute < direntry[lowest].attribute)
  151.       {
  152.         lowest = d;
  153.       }
  154.       else
  155.       {
  156.         if (direntry[d].attribute == direntry[lowest].attribute)
  157.         {
  158.           if (cmpname(direntry[d].name, direntry[lowest].name) < 0)
  159.           {
  160.             lowest = d;
  161.           }
  162.         }
  163.       }
  164.     }
  165.     if (lowest != c)
  166.     {
  167.       DIRENTRY swaptemp = direntry[c];
  168.       direntry[c] = direntry[lowest];
  169.       direntry[lowest] = swaptemp;
  170.     }
  171.   }
  172.  
  173.   // Search for the current filename
  174.   fileview = 0;
  175.   filepos = 0;
  176.   for (c = 0; c < files; c++)
  177.   {
  178.     if ((!direntry[c].attribute) && (!cmpname(name, direntry[c].name)))
  179.     {
  180.       filepos = c;
  181.     }
  182.   }
  183.  
  184.   exitfilesel = -1;
  185.   while (exitfilesel < 0)
  186.   {
  187.     int cc = cursorcolortable[cursorflash];
  188.     if (cursorflashdelay >= 6)
  189.     {
  190.       cursorflashdelay %= 6;
  191.       cursorflash++;
  192.       cursorflash &= 3;
  193.     }
  194.     fliptoscreen();
  195.     getkey();
  196.     if (lastclick) lastclick--;
  197.  
  198.     if (win_quitted)
  199.     {
  200.       exitprogram = 1;
  201.       for (c = 0; c < MAX_DIRFILES; c++)
  202.       {
  203.         if (direntry[c].name)
  204.         {
  205.           free(direntry[c].name);
  206.           direntry[c].name = NULL;
  207.         }
  208.       }
  209.       return 0;
  210.     }
  211.  
  212.     if (mouseb)
  213.     {
  214.       // Cancel (click outside)
  215.       if ((mousey < 3) || (mousey > 3+VISIBLEFILES+6) || (mousex <= 4+10) || (mousex >= 75+10))
  216.       {
  217.         if ((!prevmouseb) && (lastclick)) exitfilesel = 0;
  218.       }
  219.  
  220.       // Select dir,name,filter
  221.       if ((mousey >= 3+VISIBLEFILES+3) && (mousey <= 3+VISIBLEFILES+5) && (mousex >= 14+10) && (mousex <= 73+10))
  222.       {
  223.         filemode = mousey - (3+VISIBLEFILES+3) + 1;
  224.         if ((filemode == 3) && (!prevmouseb) && (lastclick)) goto ENTERFILE;
  225.       }
  226.  
  227.       // Select file from list
  228.       if ((mousey >= 3) && (mousey <= 3+VISIBLEFILES+2) && (mousex >= 6+10) && (mousex <= 73+10))
  229.       {
  230.         filemode = 0;
  231.         filepos = mousey - 4 - 1 + fileview;
  232.         if (filepos < 0) filepos = 0;
  233.         if (filepos > files-1) filepos = files - 1;
  234.  
  235.         if (!direntry[filepos].attribute)
  236.           strcpy(name, direntry[filepos].name);
  237.  
  238.         if ((!prevmouseb) && (lastclick) && (lastfile == filepos)) goto ENTERFILE;
  239.       }
  240.     }
  241.  
  242.     if (!filemode)
  243.     {
  244.         if (((key >= '0') && (key <= '0')) || ((key >= 'a') && (key <= 'z')) || ((key >= 'A') && (key <= 'Z')))
  245.         {
  246.         char k = tolower(key);
  247.         int oldfilepos = filepos;
  248.  
  249.             for (filepos = oldfilepos + 1; filepos < files; filepos++)
  250.             if (tolower(direntry[filepos].name[0]) == k) break;
  251.           if (filepos >= files)
  252.           {
  253.               for (filepos = 0; filepos < oldfilepos; filepos++)
  254.                  if (tolower(direntry[filepos].name[0]) == k) break;
  255.           }
  256.  
  257.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  258.       }
  259.     }
  260.  
  261.     switch(rawkey)
  262.     {
  263.       case KEY_ESC:
  264.       exitfilesel = 0;
  265.       break;
  266.  
  267.       case KEY_BACKSPACE:
  268.       if (!filemode)
  269.       {
  270.         chdir("..");
  271.         goto NEWPATH;
  272.       }
  273.       break;
  274.  
  275.       case KEY_HOME:
  276.       if (!filemode)
  277.       {
  278.         filepos = 0;
  279.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  280.       }
  281.       break;
  282.  
  283.       case KEY_END:
  284.       if (!filemode)
  285.       {
  286.         filepos = files-1;
  287.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  288.       }
  289.       break;
  290.  
  291.       case KEY_PGUP:
  292.       for (scrrep = PGUPDNREPEAT; scrrep; scrrep--)
  293.       {
  294.         if ((!filemode) && (filepos > 0))
  295.         {
  296.           filepos--;
  297.           if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  298.         }
  299.       }
  300.       break;
  301.  
  302.       case KEY_UP:
  303.       if ((!filemode) && (filepos > 0))
  304.       {
  305.         filepos--;
  306.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  307.       }
  308.       break;
  309.  
  310.       case KEY_PGDN:
  311.       for (scrrep = PGUPDNREPEAT; scrrep; scrrep--)
  312.       {
  313.         if ((!filemode) && (filepos < files-1))
  314.         {
  315.           filepos++;
  316.           if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  317.         }
  318.       }
  319.       break;
  320.  
  321.       case KEY_DOWN:
  322.       if ((!filemode) && (filepos < files-1))
  323.       {
  324.         filepos++;
  325.         if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name);
  326.       }
  327.       break;
  328.  
  329.       case KEY_TAB:
  330.       if (!shiftpressed)
  331.       {
  332.         filemode++;
  333.         if (filemode > 3) filemode = 0;
  334.       }
  335.       else
  336.       {
  337.         filemode--;
  338.         if (filemode < 0) filemode = 3;
  339.       }
  340.       break;
  341.  
  342.       case KEY_ENTER:
  343.       ENTERFILE:
  344.       switch(filemode)
  345.       {
  346.         case 0:
  347.         switch (direntry[filepos].attribute)
  348.         {
  349.           case 0:
  350.           strcpy(name, direntry[filepos].name);
  351.           exitfilesel = 1;
  352.           break;
  353.  
  354.           case 1:
  355.           chdir(direntry[filepos].name);
  356.           goto NEWPATH;
  357.  
  358.           case 2:
  359.           strcpy(tempname, direntry[filepos].name);
  360.           if (strlen(tempname))
  361.           {
  362.             if (tempname[strlen(tempname)-1] != '\\')
  363.               strcat(tempname, "\\");
  364.           }
  365.           chdir(tempname);
  366.           goto NEWPATH;
  367.         }
  368.         break;
  369.  
  370.         case 1:
  371.         chdir(path);
  372.         case 2:
  373.         filemode = 0;
  374.         goto NEWPATH;
  375.  
  376.         case 3:
  377.         exitfilesel = 1;
  378.         break;
  379.       }
  380.       break;
  381.     }
  382.  
  383.     switch(filemode)
  384.     {
  385.       case 1:
  386.       editstring(path, MAX_PATHNAME);
  387.       break;
  388.  
  389.       case 2:
  390.       editstring(filter, MAX_FILENAME);
  391.       break;
  392.  
  393.       case 3:
  394.       editstring(name, MAX_FILENAME);
  395.       break;
  396.     }
  397.  
  398.     // Validate filelist view
  399.     if (filepos < fileview) fileview = filepos;
  400.     if (filepos - fileview >= VISIBLEFILES) fileview = filepos - VISIBLEFILES + 1;
  401.  
  402.     // Refresh fileselector display
  403.     if (isplaying()) printstatus();
  404.     for (c = 0; c < VISIBLEFILES+7; c++)
  405.     {
  406.       printblank(50-(MAX_FILENAME+10)/2, 3+c, MAX_FILENAME+10);
  407.     }
  408.     drawbox(50-(MAX_FILENAME+10)/2, 3, 15, MAX_FILENAME+10, VISIBLEFILES+7);
  409.     printblankc(50-(MAX_FILENAME+10)/2+1, 4, 15+16,MAX_FILENAME+8);
  410.     printtext(50-(MAX_FILENAME+10)/2+1, 4, 15+16, title);
  411.  
  412.     for (c = 0; c < VISIBLEFILES; c++)
  413.     {
  414.       if ((fileview+c >= 0) && (fileview+c < files))
  415.       {
  416.         switch (direntry[fileview+c].attribute)
  417.         {
  418.           case 0:
  419.           sprintf(textbuffer, "%-60s        ", direntry[fileview+c].name);
  420.           break;
  421.  
  422.           case 1:
  423.           sprintf(textbuffer, "%-60s   <DIR>", direntry[fileview+c].name);
  424.           break;
  425.  
  426.           case 2:
  427.           sprintf(textbuffer, "%-60s   <DRV>", direntry[fileview+c].name);
  428.           break;
  429.         }
  430.       }
  431.       else
  432.       {
  433.         sprintf(textbuffer, "                                                                    ");
  434.       }
  435.       color = CNORMAL;
  436.       if ((fileview+c) == filepos) color = CEDIT;
  437.       textbuffer[68] = 0;
  438.       printtext(50-(MAX_FILENAME+10)/2+1, 5+c, color, textbuffer);
  439.       if ((!filemode) && ((fileview+c) == filepos)) printbg(50-(MAX_FILENAME+10)/2+1, 5+c, cc, 68);
  440.     }
  441.  
  442.     printtext(50-(MAX_FILENAME+10)/2+1, 6+VISIBLEFILES, 15, "PATH:   ");
  443.     sprintf(textbuffer, "%-60s", path);
  444.     textbuffer[MAX_FILENAME] = 0;
  445.     color = CNORMAL;
  446.     if (filemode == 1) color = CEDIT;
  447.     printtext(50-(MAX_FILENAME+10)/2+9, 6+VISIBLEFILES, color, textbuffer);
  448.     if ((filemode == 1) && (strlen(path) < MAX_FILENAME)) printbg(50-(MAX_FILENAME+10)/2+9+strlen(path), 6+VISIBLEFILES, cc, 1);
  449.  
  450.     printtext(50-(MAX_FILENAME+10)/2+1, 7+VISIBLEFILES, 15, "FILTER: ");
  451.     sprintf(textbuffer, "%-60s", filter);
  452.     textbuffer[MAX_FILENAME] = 0;
  453.     color = CNORMAL;
  454.     if (filemode == 2) color = CEDIT;
  455.     printtext(50-(MAX_FILENAME+10)/2+9, 7+VISIBLEFILES, color, textbuffer);
  456.     if (filemode == 2) printbg(50-(MAX_FILENAME+10)/2+9+strlen(filter), 7+VISIBLEFILES, cc, 1);
  457.  
  458.     printtext(50-(MAX_FILENAME+10)/2+1, 8+VISIBLEFILES, 15, "NAME:   ");
  459.     sprintf(textbuffer, "%-60s", name);
  460.     textbuffer[MAX_FILENAME] = 0;
  461.     color = CNORMAL;
  462.     if (filemode == 3) color = CEDIT;
  463.     printtext(50-(MAX_FILENAME+10)/2+9, 8+VISIBLEFILES, color, textbuffer);
  464.     if (filemode == 3) printbg(50-(MAX_FILENAME+10)/2+9+strlen(name), 8+VISIBLEFILES, cc, 1);
  465.  
  466.     if (win_quitted) exitfilesel = 0;
  467.  
  468.     if ((mouseb) && (!prevmouseb))
  469.     {
  470.       lastclick = DOUBLECLICKDELAY;
  471.       lastfile = filepos;
  472.     }
  473.   }
  474.  
  475.   // Deallocate all used names
  476.   for (c = 0; c < MAX_DIRFILES; c++)
  477.   {
  478.     if (direntry[c].name)
  479.     {
  480.       free(direntry[c].name);
  481.       direntry[c].name = NULL;
  482.     }
  483.   }
  484.  
  485.   // Restore screen & exit
  486.   printmainscreen();
  487.   return exitfilesel;
  488. }
  489.  
  490. void editstring(char *buffer, int maxlength)
  491. {
  492.   int len = strlen(buffer);
  493.  
  494.   if (key)
  495.   {
  496.     if ((key >= 32) && (key < 256))
  497.     {
  498.       if (len < maxlength-1)
  499.       {
  500.         buffer[len] = key;
  501.         buffer[len+1] = 0;
  502.       }
  503.     }
  504.     if ((key == 8) && (len > 0))
  505.     {
  506.       buffer[len-1] = 0;
  507.     }
  508.   }
  509. }
  510.  
  511. int cmpname(char *string1, char *string2)
  512. {
  513.   for (;;)
  514.   {
  515.     unsigned char char1 = tolower(*string1++);
  516.     unsigned char char2 = tolower(*string2++);
  517.     if (char1 < char2) return -1;
  518.     if (char1 > char2) return 1;
  519.     if ((!char1) || (!char2)) return 0;
  520.   }
  521. }
  522.  
  523.  
  524.