Merge branch 'tildearrow:master' into master
							
								
								
									
										
											BIN
										
									
								
								demos/genesis/mm5_boss.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -33,6 +33,6 @@ Everything from the instrument list applies here also, with one major difference
 | 
			
		|||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
Everything from the wavetables list applies here also, with the addition of two buttons:
 | 
			
		||||
Everything from the wavetables list applies here also, with the addition of two buttons before the Delete button:
 | 
			
		||||
- **Preview**: Plays the selected sample at its default note.
 | 
			
		||||
- **Stop preview**: Stops the sample playback.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
		 Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 42 KiB  | 
| 
		 Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 43 KiB  | 
| 
		 Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 44 KiB  | 
| 
		 Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 27 KiB  | 
| 
						 | 
				
			
			@ -1,11 +1,3 @@
 | 
			
		|||
# instrument list
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
click on an instrument to select it.
 | 
			
		||||
 | 
			
		||||
double-click to open the instrument editor.
 | 
			
		||||
 | 
			
		||||
# instrument editor
 | 
			
		||||
 | 
			
		||||
every instrument can be renamed and have its type changed.
 | 
			
		||||
| 
						 | 
				
			
			@ -66,14 +58,16 @@ Some macros are "bitmap" style. They represent a number of "bits" that can be to
 | 
			
		|||
 | 
			
		||||
The number between the macro type label and the macro type button is the macro length in steps. The `-` and `+` buttons change the length of the macro. Start out by adding at least a few steps.
 | 
			
		||||
 | 
			
		||||
The values of the macro can be drawn in the "bar graph box". Just beneath the box is shorter bar graph.
 | 
			
		||||
- Click to set the start point of a loop; the end point is the last value or release point. Right-click to remove the loop.
 | 
			
		||||
- Shift-click to set the release point. When played, the macro will hold here until the note is released. Right-click to remove the release point.
 | 
			
		||||
The values of the macro can be drawn in the "bar graph" box.
 | 
			
		||||
 | 
			
		||||
Just beneath the box is a shorter bar that controls looping.
 | 
			
		||||
- Click to set the start point of a loop; the end point is the last value or release point. It appears as half-height bars. Right-click to remove the loop.
 | 
			
		||||
- Shift-click to set the release point. When played, the macro will hold here until the note is released. It appears as a full-height bar. Right-click to remove the release point.
 | 
			
		||||
 | 
			
		||||
Finally, the sequence of values can be directly edited in the text box at the bottom.
 | 
			
		||||
- The loop start is entered as a `|`.
 | 
			
		||||
- The release point is entered as a `/`.
 | 
			
		||||
- In arpeggio macros, a value starting with a `@` is an absolute note (instead of a relative shift). No matter the note played, `@` values will be played at that exact note. This is especially useful for noise instruments with preset periods.
 | 
			
		||||
- In arpeggio macros, a value starting with a `@` is an absolute note (instead of a relative shift). No matter the note entered in the pattern, `@` values will be played at that exact note. This is especially useful for noise instruments with preset periods.
 | 
			
		||||
 | 
			
		||||
### ADSR
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,15 +94,29 @@ Finally, the sequence of values can be directly edited in the text box at the bo
 | 
			
		|||
- **Phase** is which part of the waveform the macro will start at, measured in 1/1024 increments.
 | 
			
		||||
- **Shape** is the waveform used. Triangle is the default, and Saw and Square are exactly as they say.
 | 
			
		||||
 | 
			
		||||
# samples
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# wavetable
 | 
			
		||||
 | 
			
		||||
This tab appears for PC Engine, FDS, Namco WSG, and other wavetable-based instruments.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
When **Enable synthesizer** is off, the only option is to select a wavetable entry with the text entry box beneath the **Wave 1** preview.
 | 
			
		||||
 | 
			
		||||
To use the wavetable synthesizer, refer to the bottom part of [the wavetable documentation](../5-wave/README.md).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# sample
 | 
			
		||||
 | 
			
		||||
This tab appears for Generic PCM, SNES, Amiga, and other sample-based instruments.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
- **Initial Sample**: the sample that the instrument will use.
 | 
			
		||||
- **Use wavetable**: instead of samples, use wavetables. this causes the [Wavetables](../5-wave/README.md) tab to appear next to Sample.
 | 
			
		||||
  - depending on the system and use of the wavetable synthesizer, this may or may not be reproducible on hardware.
 | 
			
		||||
- **Use sample map**: assigns a sample to each note.
 | 
			
		||||
  - samples will be played at their default pitch.
 | 
			
		||||
  - to set a note's sample, click the list entry in the `#` column then type the number of the sample.
 | 
			
		||||
  - to set a note's sample, click the list entry in the "#" column then type the number of the sample.
 | 
			
		||||
  - to set the pitch at which a sample is played, click the list entry in the "note" column and press the key for the new note.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
		 Before Width: | Height: | Size: 128 KiB  | 
| 
		 Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 135 KiB  | 
| 
		 Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								doc/4-instrument/wavetable.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 59 KiB  | 
							
								
								
									
										416
									
								
								extern/igfd/ImGuiFileDialog.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -800,138 +800,138 @@ namespace IGFD
 | 
			
		|||
 | 
			
		||||
  // will be called internally 
 | 
			
		||||
  // will not been exposed to IGFD API
 | 
			
		||||
  bool IGFD::FilterManager::prFillFileStyle(std::shared_ptr<FileInfos> vFileInfos) const
 | 
			
		||||
  bool IGFD::FilterManager::prFillFileStyle(FileInfos& vFileInfos) const
 | 
			
		||||
  {
 | 
			
		||||
    if (vFileInfos.use_count() && !prFilesStyle.empty())
 | 
			
		||||
    if (!prFilesStyle.empty())
 | 
			
		||||
    {
 | 
			
		||||
      for (const auto& _flag : prFilesStyle)
 | 
			
		||||
      {
 | 
			
		||||
        for (const auto& _file : _flag.second)
 | 
			
		||||
        {
 | 
			
		||||
          if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd')
 | 
			
		||||
          if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd')
 | 
			
		||||
          {
 | 
			
		||||
            if (_file.first.empty()) // for all dirs
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
            else if (_file.first == vFileInfos->fileNameExt) // for dirs who are equal to style criteria
 | 
			
		||||
            else if (_file.first == vFileInfos.fileNameExt) // for dirs who are equal to style criteria
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f')
 | 
			
		||||
          else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f')
 | 
			
		||||
          {
 | 
			
		||||
            if (_file.first.empty()) // for all files
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
            else if (_file.first == vFileInfos->fileNameExt) // for files who are equal to style criteria
 | 
			
		||||
            else if (_file.first == vFileInfos.fileNameExt) // for files who are equal to style criteria
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l')
 | 
			
		||||
          else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l')
 | 
			
		||||
          {
 | 
			
		||||
            if (_file.first.empty()) // for all links
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
            else if (_file.first == vFileInfos->fileNameExt) // for links who are equal to style criteria
 | 
			
		||||
            else if (_file.first == vFileInfos.fileNameExt) // for links who are equal to style criteria
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (_flag.first & IGFD_FileStyleByExtention)
 | 
			
		||||
          {
 | 
			
		||||
            if (_file.first == vFileInfos->fileExt)
 | 
			
		||||
            if (_file.first == vFileInfos.fileExt)
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // can make sense for some dirs like the hidden by ex ".git"
 | 
			
		||||
            if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd')
 | 
			
		||||
            if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd')
 | 
			
		||||
            {
 | 
			
		||||
              if (_file.first == vFileInfos->fileExt)
 | 
			
		||||
              if (_file.first == vFileInfos.fileExt)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f')
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f')
 | 
			
		||||
            {
 | 
			
		||||
              if (_file.first == vFileInfos->fileExt)
 | 
			
		||||
              if (_file.first == vFileInfos.fileExt)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l')
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l')
 | 
			
		||||
            {
 | 
			
		||||
              if (_file.first == vFileInfos->fileExt)
 | 
			
		||||
              if (_file.first == vFileInfos.fileExt)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          if (_flag.first & IGFD_FileStyleByFullName)
 | 
			
		||||
          {
 | 
			
		||||
            if (_file.first == vFileInfos->fileNameExt)
 | 
			
		||||
            if (_file.first == vFileInfos.fileNameExt)
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd')
 | 
			
		||||
            if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd')
 | 
			
		||||
            {
 | 
			
		||||
              if (_file.first == vFileInfos->fileNameExt)
 | 
			
		||||
              if (_file.first == vFileInfos.fileNameExt)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f')
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f')
 | 
			
		||||
            {
 | 
			
		||||
              if (_file.first == vFileInfos->fileNameExt)
 | 
			
		||||
              if (_file.first == vFileInfos.fileNameExt)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l')
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l')
 | 
			
		||||
            {
 | 
			
		||||
              if (_file.first == vFileInfos->fileNameExt)
 | 
			
		||||
              if (_file.first == vFileInfos.fileNameExt)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          if (_flag.first & IGFD_FileStyleByContainedInFullName)
 | 
			
		||||
          {
 | 
			
		||||
            if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
            if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
            {
 | 
			
		||||
              vFileInfos->fileStyle = _file.second;
 | 
			
		||||
              vFileInfos.fileStyle = _file.second;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos->fileType == 'd')
 | 
			
		||||
            if (_flag.first & IGFD_FileStyleByTypeDir && vFileInfos.fileType == 'd')
 | 
			
		||||
            {
 | 
			
		||||
              if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
              if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos->fileType == 'f')
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeFile && vFileInfos.fileType == 'f')
 | 
			
		||||
            {
 | 
			
		||||
              if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
              if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos->fileType == 'l')
 | 
			
		||||
            else if (_flag.first & IGFD_FileStyleByTypeLink && vFileInfos.fileType == 'l')
 | 
			
		||||
            {
 | 
			
		||||
              if (vFileInfos->fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
              if (vFileInfos.fileNameExt.find(_file.first) != std::string::npos)
 | 
			
		||||
              {
 | 
			
		||||
                vFileInfos->fileStyle = _file.second;
 | 
			
		||||
                vFileInfos.fileStyle = _file.second;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (vFileInfos->fileStyle.use_count())
 | 
			
		||||
          if (vFileInfos.fileStyle.use_count())
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -1142,6 +1142,7 @@ namespace IGFD
 | 
			
		|||
                for (int i=1; i<4; i++) {
 | 
			
		||||
                  puSortingDirection[i]=false;
 | 
			
		||||
                }
 | 
			
		||||
    invalidFile.isValid=false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void IGFD::FileManager::OpenCurrentPath(const FileDialogInternal& vFileDialogInternal)
 | 
			
		||||
| 
						 | 
				
			
			@ -1191,29 +1192,24 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileName = tableHeaderDescendingIcon + puHeaderFileName;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (a==NULL || b==NULL)
 | 
			
		||||
              return false;
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            // this code fail in c:\\Users with the link "All users". got a invalid comparator
 | 
			
		||||
            /*
 | 
			
		||||
            // use code from https://github.com/jackm97/ImGuiFileDialog/commit/bf40515f5a1de3043e60562dc1a494ee7ecd3571
 | 
			
		||||
            // strict ordering for file/directory types beginning in '.'
 | 
			
		||||
            // common on Linux platforms
 | 
			
		||||
            if (a->fileNameExt[0] == '.' && b->fileNameExt[0] != '.')
 | 
			
		||||
            if (a.fileNameExt[0] == '.' && b.fileNameExt[0] != '.')
 | 
			
		||||
              return false;
 | 
			
		||||
            if (a->fileNameExt[0] != '.' && b->fileNameExt[0] == '.')
 | 
			
		||||
            if (a.fileNameExt[0] != '.' && b.fileNameExt[0] == '.')
 | 
			
		||||
              return true;
 | 
			
		||||
            if (a->fileNameExt[0] == '.' && b->fileNameExt[0] == '.')
 | 
			
		||||
            if (a.fileNameExt[0] == '.' && b.fileNameExt[0] == '.')
 | 
			
		||||
            {
 | 
			
		||||
              return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) < 0); // sort in insensitive case
 | 
			
		||||
              return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) < 0); // sort in insensitive case
 | 
			
		||||
            }
 | 
			
		||||
            */
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first
 | 
			
		||||
            return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) < 0); // sort in insensitive case
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first
 | 
			
		||||
            return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) < 0); // sort in insensitive case
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
| 
						 | 
				
			
			@ -1222,28 +1218,23 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileName = tableHeaderAscendingIcon + puHeaderFileName;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (a==NULL || b==NULL)
 | 
			
		||||
              return false;
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            // this code fail in c:\\Users with the link "All users". got a invalid comparator
 | 
			
		||||
            /*
 | 
			
		||||
            // use code from https://github.com/jackm97/ImGuiFileDialog/commit/bf40515f5a1de3043e60562dc1a494ee7ecd3571
 | 
			
		||||
            // strict ordering for file/directory types beginning in '.'
 | 
			
		||||
            // common on Linux platforms
 | 
			
		||||
            if (a->fileNameExt[0] == '.' && b->fileNameExt[0] != '.')
 | 
			
		||||
            if (a.fileNameExt[0] == '.' && b.fileNameExt[0] != '.')
 | 
			
		||||
              return false;
 | 
			
		||||
            if (a->fileNameExt[0] != '.' && b->fileNameExt[0] == '.')
 | 
			
		||||
            if (a.fileNameExt[0] != '.' && b.fileNameExt[0] == '.')
 | 
			
		||||
              return true;
 | 
			
		||||
            if (a->fileNameExt[0] == '.' && b->fileNameExt[0] == '.')
 | 
			
		||||
            if (a.fileNameExt[0] == '.' && b.fileNameExt[0] == '.')
 | 
			
		||||
            {
 | 
			
		||||
              return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) > 0); // sort in insensitive case
 | 
			
		||||
              return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) > 0); // sort in insensitive case
 | 
			
		||||
            }
 | 
			
		||||
            */
 | 
			
		||||
            return (stricmp(a->fileNameExt.c_str(), b->fileNameExt.c_str()) > 0); // sort in insensitive case
 | 
			
		||||
            return (stricmp(a.fileNameExt.c_str(), b.fileNameExt.c_str()) > 0); // sort in insensitive case
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1259,13 +1250,10 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileType = tableHeaderDescendingIcon + puHeaderFileType;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first
 | 
			
		||||
            return (a->fileExt < b->fileExt); // else
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first
 | 
			
		||||
            return (a.fileExt < b.fileExt); // else
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
| 
						 | 
				
			
			@ -1274,15 +1262,10 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileType = tableHeaderAscendingIcon + puHeaderFileType;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (a==NULL || b==NULL)
 | 
			
		||||
              return false;
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last
 | 
			
		||||
            return (a->fileExt > b->fileExt); // else
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last
 | 
			
		||||
            return (a.fileExt > b.fileExt); // else
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1298,15 +1281,10 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileSize = tableHeaderDescendingIcon + puHeaderFileSize;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (a==NULL || b==NULL)
 | 
			
		||||
              return false;
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first
 | 
			
		||||
            return (a->fileSize < b->fileSize); // else
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first
 | 
			
		||||
            return (a.fileSize < b.fileSize); // else
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
| 
						 | 
				
			
			@ -1315,15 +1293,10 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileSize = tableHeaderAscendingIcon + puHeaderFileSize;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (a==NULL || b==NULL)
 | 
			
		||||
              return false;
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last
 | 
			
		||||
            return (a->fileSize > b->fileSize); // else
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last
 | 
			
		||||
            return (a.fileSize > b.fileSize); // else
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1339,15 +1312,10 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileDate = tableHeaderDescendingIcon + puHeaderFileDate;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (a==NULL || b==NULL)
 | 
			
		||||
              return false;
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first
 | 
			
		||||
            return (a->fileModifDate < b->fileModifDate); // else
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first
 | 
			
		||||
            return (a.fileModifDate < b.fileModifDate); // else
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
| 
						 | 
				
			
			@ -1356,15 +1324,10 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileDate = tableHeaderAscendingIcon + puHeaderFileDate;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (a==NULL || b==NULL)
 | 
			
		||||
              return false;
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last
 | 
			
		||||
            return (a->fileModifDate > b->fileModifDate); // else
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last
 | 
			
		||||
            return (a.fileModifDate > b.fileModifDate); // else
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1384,15 +1347,12 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileThumbnails = tableHeaderDescendingIcon + puHeaderFileThumbnails;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType == 'd'); // directory in first
 | 
			
		||||
            if (a->thumbnailInfo.textureWidth == b->thumbnailInfo.textureWidth)
 | 
			
		||||
              return (a->thumbnailInfo.textureHeight < b->thumbnailInfo.textureHeight);
 | 
			
		||||
            return (a->thumbnailInfo.textureWidth < b->thumbnailInfo.textureWidth);
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType == 'd'); // directory in first
 | 
			
		||||
            if (a.thumbnailInfo.textureWidth == b.thumbnailInfo.textureWidth)
 | 
			
		||||
              return (a.thumbnailInfo.textureHeight < b.thumbnailInfo.textureHeight);
 | 
			
		||||
            return (a.thumbnailInfo.textureWidth < b.thumbnailInfo.textureWidth);
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1402,15 +1362,12 @@ namespace IGFD
 | 
			
		|||
        puHeaderFileThumbnails = tableHeaderAscendingIcon + puHeaderFileThumbnails;
 | 
			
		||||
#endif // USE_CUSTOM_SORTING_ICON
 | 
			
		||||
        std::sort(prFileList.begin(), prFileList.end(),
 | 
			
		||||
          [](const std::shared_ptr<FileInfos>& a, const std::shared_ptr<FileInfos>& b) -> bool
 | 
			
		||||
          [](const FileInfos& a, const FileInfos& b) -> bool
 | 
			
		||||
          {
 | 
			
		||||
            if (!a.use_count() || !b.use_count())
 | 
			
		||||
              return false;
 | 
			
		||||
 | 
			
		||||
            if (a->fileType != b->fileType) return (a->fileType != 'd'); // directory in last
 | 
			
		||||
            if (a->thumbnailInfo.textureWidth == b->thumbnailInfo.textureWidth)
 | 
			
		||||
              return (a->thumbnailInfo.textureHeight > b->thumbnailInfo.textureHeight);
 | 
			
		||||
            return (a->thumbnailInfo.textureWidth > b->thumbnailInfo.textureWidth);
 | 
			
		||||
            if (a.fileType != b.fileType) return (a.fileType != 'd'); // directory in last
 | 
			
		||||
            if (a.thumbnailInfo.textureWidth == b.thumbnailInfo.textureWidth)
 | 
			
		||||
              return (a.thumbnailInfo.textureHeight > b.thumbnailInfo.textureHeight);
 | 
			
		||||
            return (a.thumbnailInfo.textureWidth > b.thumbnailInfo.textureWidth);
 | 
			
		||||
          });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1441,38 +1398,38 @@ namespace IGFD
 | 
			
		|||
    return fileNameExt;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void IGFD::FileManager::AddFile(const FileDialogInternal& vFileDialogInternal, const std::string& vPath, const std::string& vFileName, const char& vFileType, void* ent)
 | 
			
		||||
  void IGFD::FileManager::AddFile(const FileDialogInternal& vFileDialogInternal, const std::string& vPath, const std::string& vFileName, char vFileType, void* ent)
 | 
			
		||||
  {
 | 
			
		||||
    auto infos = std::make_shared<FileInfos>();
 | 
			
		||||
    FileInfos infos;
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    struct dirent* dent=(struct dirent*)ent;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    infos->filePath = vPath;
 | 
			
		||||
    infos->fileNameExt = vFileName;
 | 
			
		||||
    infos->fileNameExt_optimized = prOptimizeFilenameForSearchOperations(infos->fileNameExt);
 | 
			
		||||
    infos->fileType = vFileType;
 | 
			
		||||
    infos.filePath = vPath;
 | 
			
		||||
    infos.fileNameExt = vFileName;
 | 
			
		||||
    infos.fileNameExt_optimized = prOptimizeFilenameForSearchOperations(infos.fileNameExt);
 | 
			
		||||
    infos.fileType = vFileType;
 | 
			
		||||
 | 
			
		||||
    if (infos->fileNameExt.empty() || ((infos->fileNameExt == "." || infos->fileNameExt == "..") && !vFileDialogInternal.puFilterManager.puDLGFilters.empty())) return; // filename empty or filename is the current dir '.' //-V807
 | 
			
		||||
    if (infos->fileNameExt != ".." && (vFileDialogInternal.puDLGflags & ImGuiFileDialogFlags_DontShowHiddenFiles) && infos->fileNameExt[0] == '.') // dont show hidden files
 | 
			
		||||
      if (!vFileDialogInternal.puFilterManager.puDLGFilters.empty() || (vFileDialogInternal.puFilterManager.puDLGFilters.empty() && infos->fileNameExt != ".")) // except "." if in directory mode //-V728
 | 
			
		||||
    if (infos.fileNameExt.empty() || ((infos.fileNameExt == "." || infos.fileNameExt == "..") && !vFileDialogInternal.puFilterManager.puDLGFilters.empty())) return; // filename empty or filename is the current dir '.' //-V807
 | 
			
		||||
    if (infos.fileNameExt != ".." && (vFileDialogInternal.puDLGflags & ImGuiFileDialogFlags_DontShowHiddenFiles) && infos.fileNameExt[0] == '.') // dont show hidden files
 | 
			
		||||
      if (!vFileDialogInternal.puFilterManager.puDLGFilters.empty() || (vFileDialogInternal.puFilterManager.puDLGFilters.empty() && infos.fileNameExt != ".")) // except "." if in directory mode //-V728
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (infos->fileType == 'f' ||
 | 
			
		||||
      infos->fileType == 'l') // link can have the same extention of a file
 | 
			
		||||
    if (infos.fileType == 'f' ||
 | 
			
		||||
      infos.fileType == 'l') // link can have the same extention of a file
 | 
			
		||||
    {
 | 
			
		||||
      size_t lpt = infos->fileNameExt.find_last_of('.');
 | 
			
		||||
      size_t lpt = infos.fileNameExt.find_last_of('.');
 | 
			
		||||
      if (lpt != std::string::npos)
 | 
			
		||||
      {
 | 
			
		||||
        infos->fileExt = infos->fileNameExt.substr(lpt);
 | 
			
		||||
        infos.fileExt = infos.fileNameExt.substr(lpt);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (char& i: infos->fileExt) {
 | 
			
		||||
      for (char& i: infos.fileExt) {
 | 
			
		||||
        if (i>='A' && i<='Z') i+='a'-'A';
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!vFileDialogInternal.puFilterManager.IsCoveredByFilters(infos->fileExt))
 | 
			
		||||
      if (!vFileDialogInternal.puFilterManager.IsCoveredByFilters(infos.fileExt))
 | 
			
		||||
      {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -1483,16 +1440,16 @@ namespace IGFD
 | 
			
		|||
    SYSTEMTIME localTime;
 | 
			
		||||
    char timebuf[100];
 | 
			
		||||
 | 
			
		||||
    infos->fileSize=dent->dwin_size;
 | 
			
		||||
    infos.fileSize=dent->dwin_size;
 | 
			
		||||
    if (FileTimeToSystemTime(&dent->dwin_mtime,&systemTime)==TRUE) {
 | 
			
		||||
      if (SystemTimeToTzSpecificLocalTime(NULL,&systemTime,&localTime)==TRUE) {
 | 
			
		||||
        snprintf(timebuf,99,"%d/%.2d/%.2d %.2d:%.2d",localTime.wYear,localTime.wMonth,localTime.wDay,localTime.wHour,localTime.wMinute);
 | 
			
		||||
      } else {
 | 
			
		||||
        snprintf(timebuf,99,"%d/%.2d/%.2d %.2d:%.2d",systemTime.wYear,systemTime.wMonth,systemTime.wDay,systemTime.wHour,systemTime.wMinute);
 | 
			
		||||
      }
 | 
			
		||||
      infos->fileModifDate=timebuf;
 | 
			
		||||
      infos.fileModifDate=timebuf;
 | 
			
		||||
    } else {
 | 
			
		||||
      infos->fileModifDate="???";
 | 
			
		||||
      infos.fileModifDate="???";
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1534,7 +1491,7 @@ namespace IGFD
 | 
			
		|||
        {
 | 
			
		||||
          struct dirent* ent = files[i];
 | 
			
		||||
          std::string where = path + std::string(PATH_SEP_STR) + std::string(ent->d_name);
 | 
			
		||||
          char fileType = 0;
 | 
			
		||||
          char fileType = 'f';
 | 
			
		||||
#if defined(HAVE_DIRENT_TYPE) || defined(_WIN32)
 | 
			
		||||
          if (ent->d_type != DT_UNKNOWN)
 | 
			
		||||
          {
 | 
			
		||||
| 
						 | 
				
			
			@ -1544,7 +1501,7 @@ namespace IGFD
 | 
			
		|||
              fileType = 'f'; break;
 | 
			
		||||
            case DT_DIR:
 | 
			
		||||
              fileType = 'd'; break;
 | 
			
		||||
            case DT_LNK:
 | 
			
		||||
            case DT_LNK: {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
              fileType = 'f';
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -1557,7 +1514,8 @@ namespace IGFD
 | 
			
		|||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                  fileType = 'l';
 | 
			
		||||
                  // why does 'l' make it crash?
 | 
			
		||||
                  fileType = 'f';
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              else
 | 
			
		||||
| 
						 | 
				
			
			@ -1568,6 +1526,9 @@ namespace IGFD
 | 
			
		|||
#endif
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            default:
 | 
			
		||||
              fileType = 'f'; break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          else
 | 
			
		||||
#endif // HAVE_DIRENT_TYPE
 | 
			
		||||
| 
						 | 
				
			
			@ -1622,12 +1583,12 @@ namespace IGFD
 | 
			
		|||
      ClearFileLists();
 | 
			
		||||
      for (auto& drive : drives)
 | 
			
		||||
      {
 | 
			
		||||
        auto info = std::make_shared<FileInfos>();
 | 
			
		||||
        info->fileNameExt = drive;
 | 
			
		||||
        info->fileNameExt_optimized = prOptimizeFilenameForSearchOperations(drive);
 | 
			
		||||
        info->fileType = 'd';
 | 
			
		||||
        FileInfos info;
 | 
			
		||||
        info.fileNameExt = drive;
 | 
			
		||||
        info.fileNameExt_optimized = prOptimizeFilenameForSearchOperations(drive);
 | 
			
		||||
        info.fileType = 'd';
 | 
			
		||||
 | 
			
		||||
        if (!info->fileNameExt.empty())
 | 
			
		||||
        if (!info.fileNameExt.empty())
 | 
			
		||||
        {
 | 
			
		||||
          prFileList.push_back(info);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1658,11 +1619,11 @@ namespace IGFD
 | 
			
		|||
    return prFileList.size();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::shared_ptr<FileInfos> IGFD::FileManager::GetFullFileAt(size_t vIdx)
 | 
			
		||||
  const FileInfos& IGFD::FileManager::GetFullFileAt(size_t vIdx)
 | 
			
		||||
  {
 | 
			
		||||
    if (vIdx < prFileList.size())
 | 
			
		||||
      return prFileList[vIdx];
 | 
			
		||||
    return nullptr;
 | 
			
		||||
    return invalidFile;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool IGFD::FileManager::IsFilteredListEmpty()
 | 
			
		||||
| 
						 | 
				
			
			@ -1675,11 +1636,11 @@ namespace IGFD
 | 
			
		|||
    return prFilteredFileList.size();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::shared_ptr<FileInfos> IGFD::FileManager::GetFilteredFileAt(size_t vIdx)
 | 
			
		||||
  const FileInfos& IGFD::FileManager::GetFilteredFileAt(size_t vIdx)
 | 
			
		||||
  {
 | 
			
		||||
    if (vIdx < prFilteredFileList.size())
 | 
			
		||||
      return prFilteredFileList[vIdx];
 | 
			
		||||
    return nullptr;
 | 
			
		||||
    return invalidFile;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool IGFD::FileManager::IsFileNameSelected(const std::string& vFileName)
 | 
			
		||||
| 
						 | 
				
			
			@ -1706,14 +1667,12 @@ namespace IGFD
 | 
			
		|||
  void IGFD::FileManager::ApplyFilteringOnFileList(const FileDialogInternal& vFileDialogInternal)
 | 
			
		||||
  {
 | 
			
		||||
    prFilteredFileList.clear();
 | 
			
		||||
    for (const auto& file : prFileList)
 | 
			
		||||
    for (const FileInfos& file : prFileList)
 | 
			
		||||
    {
 | 
			
		||||
      if (!file.use_count())
 | 
			
		||||
        continue;
 | 
			
		||||
      bool show = true;
 | 
			
		||||
      if (!file->IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag))  // if search tag
 | 
			
		||||
      if (!file.IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag))  // if search tag
 | 
			
		||||
        show = false;
 | 
			
		||||
      if (puDLGDirectoryMode && file->fileType != 'd') // directory mode
 | 
			
		||||
      if (puDLGDirectoryMode && file.fileType != 'd') // directory mode
 | 
			
		||||
        show = false;
 | 
			
		||||
      if (show)
 | 
			
		||||
        prFilteredFileList.push_back(file);
 | 
			
		||||
| 
						 | 
				
			
			@ -1750,13 +1709,10 @@ namespace IGFD
 | 
			
		|||
    return "";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void IGFD::FileManager::prCompleteFileInfos(const std::shared_ptr<FileInfos>& vInfos)
 | 
			
		||||
  void IGFD::FileManager::prCompleteFileInfos(FileInfos& vInfos)
 | 
			
		||||
  {
 | 
			
		||||
    if (!vInfos.use_count())
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    if (vInfos->fileNameExt != "." &&
 | 
			
		||||
      vInfos->fileNameExt != "..")
 | 
			
		||||
    if (vInfos.fileNameExt != "." &&
 | 
			
		||||
      vInfos.fileNameExt != "..")
 | 
			
		||||
    {
 | 
			
		||||
      // _stat struct :
 | 
			
		||||
      //dev_t     st_dev;     /* ID of device containing file */
 | 
			
		||||
| 
						 | 
				
			
			@ -1774,25 +1730,25 @@ namespace IGFD
 | 
			
		|||
      //time_t    st_ctime;   /* time of last status change - not sure out of ntfs */
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
      if (vInfos->fileType != 'd')
 | 
			
		||||
      if (vInfos.fileType != 'd')
 | 
			
		||||
      {
 | 
			
		||||
        vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize);
 | 
			
		||||
        vInfos.formatedFileSize = prFormatFileSize(vInfos.fileSize);
 | 
			
		||||
      }
 | 
			
		||||
#else
 | 
			
		||||
      std::string fpn;
 | 
			
		||||
 | 
			
		||||
      if (vInfos->fileType == 'f' || vInfos->fileType == 'l' || vInfos->fileType == 'd') // file
 | 
			
		||||
        fpn = vInfos->filePath + std::string(1u, PATH_SEP) + vInfos->fileNameExt;
 | 
			
		||||
      if (vInfos.fileType == 'f' || vInfos.fileType == 'l' || vInfos.fileType == 'd') // file
 | 
			
		||||
        fpn = vInfos.filePath + std::string(1u, PATH_SEP) + vInfos.fileNameExt;
 | 
			
		||||
 | 
			
		||||
      struct stat statInfos = {};
 | 
			
		||||
      char timebuf[100];
 | 
			
		||||
      int result = stat(fpn.c_str(), &statInfos);
 | 
			
		||||
      if (result!=-1)
 | 
			
		||||
      {
 | 
			
		||||
        if (vInfos->fileType != 'd')
 | 
			
		||||
        if (vInfos.fileType != 'd')
 | 
			
		||||
        {
 | 
			
		||||
          vInfos->fileSize = (size_t)statInfos.st_size;
 | 
			
		||||
          vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize);
 | 
			
		||||
          vInfos.fileSize = (size_t)statInfos.st_size;
 | 
			
		||||
          vInfos.formatedFileSize = prFormatFileSize(vInfos.fileSize);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        size_t len = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1806,12 +1762,12 @@ namespace IGFD
 | 
			
		|||
#endif // MSVC
 | 
			
		||||
        if (len)
 | 
			
		||||
        {
 | 
			
		||||
          vInfos->fileModifDate = std::string(timebuf, len);
 | 
			
		||||
          vInfos.fileModifDate = std::string(timebuf, len);
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        vInfos->fileSize=0;
 | 
			
		||||
        vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize);
 | 
			
		||||
        vInfos->fileModifDate="???";
 | 
			
		||||
        vInfos.fileSize=0;
 | 
			
		||||
        vInfos.formatedFileSize = prFormatFileSize(vInfos.fileSize);
 | 
			
		||||
        vInfos.fileModifDate="???";
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1994,14 +1950,11 @@ namespace IGFD
 | 
			
		|||
    IGFD::Utils::SetBuffer(puFileNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER, vFileName);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool IGFD::FileManager::SelectDirectory(const std::shared_ptr<FileInfos>& vInfos)
 | 
			
		||||
  bool IGFD::FileManager::SelectDirectory(const FileInfos& vInfos)
 | 
			
		||||
  {
 | 
			
		||||
    if (!vInfos.use_count())
 | 
			
		||||
      return false;
 | 
			
		||||
 | 
			
		||||
    bool pathClick = false;
 | 
			
		||||
 | 
			
		||||
    if (vInfos->fileNameExt == "..")
 | 
			
		||||
    if (vInfos.fileNameExt == "..")
 | 
			
		||||
    {
 | 
			
		||||
      pathClick = SetPathOnParentDirectoryIfAny();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2011,23 +1964,23 @@ namespace IGFD
 | 
			
		|||
 | 
			
		||||
      if (puShowDrives)
 | 
			
		||||
      {
 | 
			
		||||
        newPath = vInfos->fileNameExt + std::string(1u, PATH_SEP);
 | 
			
		||||
        newPath = vInfos.fileNameExt + std::string(1u, PATH_SEP);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
        if (puFsRoot == prCurrentPath)
 | 
			
		||||
          newPath = prCurrentPath + vInfos->fileNameExt;
 | 
			
		||||
          newPath = prCurrentPath + vInfos.fileNameExt;
 | 
			
		||||
        else
 | 
			
		||||
#endif // __linux__
 | 
			
		||||
          newPath = prCurrentPath + std::string(1u, PATH_SEP) + vInfos->fileNameExt;
 | 
			
		||||
          newPath = prCurrentPath + std::string(1u, PATH_SEP) + vInfos.fileNameExt;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (IGFD::Utils::IsDirectoryExist(newPath))
 | 
			
		||||
      {
 | 
			
		||||
        if (puShowDrives)
 | 
			
		||||
        {
 | 
			
		||||
          prCurrentPath = vInfos->fileNameExt;
 | 
			
		||||
          prCurrentPath = vInfos.fileNameExt;
 | 
			
		||||
          puFsRoot = prCurrentPath;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
| 
						 | 
				
			
			@ -2041,35 +1994,32 @@ namespace IGFD
 | 
			
		|||
    return pathClick;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void IGFD::FileManager::SelectFileName(const FileDialogInternal& vFileDialogInternal, const std::shared_ptr<FileInfos>& vInfos)
 | 
			
		||||
  void IGFD::FileManager::SelectFileName(const FileDialogInternal& vFileDialogInternal, const FileInfos& vInfos)
 | 
			
		||||
  {
 | 
			
		||||
    if (!vInfos.use_count())
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    if (ImGui::GetIO().KeyCtrl)
 | 
			
		||||
    {
 | 
			
		||||
      if (puDLGcountSelectionMax == 0) // infinite selection
 | 
			
		||||
      {
 | 
			
		||||
        if (prSelectedFileNames.find(vInfos->fileNameExt) == prSelectedFileNames.end()) // not found +> add
 | 
			
		||||
        if (prSelectedFileNames.find(vInfos.fileNameExt) == prSelectedFileNames.end()) // not found +> add
 | 
			
		||||
        {
 | 
			
		||||
          prAddFileNameInSelection(vInfos->fileNameExt, true);
 | 
			
		||||
          prAddFileNameInSelection(vInfos.fileNameExt, true);
 | 
			
		||||
        }
 | 
			
		||||
        else // found +> remove
 | 
			
		||||
        {
 | 
			
		||||
          prRemoveFileNameInSelection(vInfos->fileNameExt);
 | 
			
		||||
          prRemoveFileNameInSelection(vInfos.fileNameExt);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      else // selection limited by size
 | 
			
		||||
      {
 | 
			
		||||
        if (prSelectedFileNames.size() < puDLGcountSelectionMax)
 | 
			
		||||
        {
 | 
			
		||||
          if (prSelectedFileNames.find(vInfos->fileNameExt) == prSelectedFileNames.end()) // not found +> add
 | 
			
		||||
          if (prSelectedFileNames.find(vInfos.fileNameExt) == prSelectedFileNames.end()) // not found +> add
 | 
			
		||||
          {
 | 
			
		||||
            prAddFileNameInSelection(vInfos->fileNameExt, true);
 | 
			
		||||
            prAddFileNameInSelection(vInfos.fileNameExt, true);
 | 
			
		||||
          }
 | 
			
		||||
          else // found +> remove
 | 
			
		||||
          {
 | 
			
		||||
            prRemoveFileNameInSelection(vInfos->fileNameExt);
 | 
			
		||||
            prRemoveFileNameInSelection(vInfos.fileNameExt);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -2081,18 +2031,15 @@ namespace IGFD
 | 
			
		|||
        prSelectedFileNames.clear();
 | 
			
		||||
        // we will iterate filelist and get the last selection after the start selection
 | 
			
		||||
        bool startMultiSelection = false;
 | 
			
		||||
        std::string fileNameToSelect = vInfos->fileNameExt;
 | 
			
		||||
        std::string fileNameToSelect = vInfos.fileNameExt;
 | 
			
		||||
        std::string savedLastSelectedFileName; // for invert selection mode
 | 
			
		||||
        for (const auto& file : prFileList)
 | 
			
		||||
        for (const FileInfos& file : prFileList)
 | 
			
		||||
        {
 | 
			
		||||
          if (!file.use_count())
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
          bool canTake = true;
 | 
			
		||||
          if (!file->IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag)) canTake = false;
 | 
			
		||||
          if (!file.IsTagFound(vFileDialogInternal.puSearchManager.puSearchTag)) canTake = false;
 | 
			
		||||
          if (canTake) // if not filtered, we will take files who are filtered by the dialog
 | 
			
		||||
          {
 | 
			
		||||
            if (file->fileNameExt == prLastSelectedFileName)
 | 
			
		||||
            if (file.fileNameExt == prLastSelectedFileName)
 | 
			
		||||
            {
 | 
			
		||||
              startMultiSelection = true;
 | 
			
		||||
              prAddFileNameInSelection(prLastSelectedFileName, false);
 | 
			
		||||
| 
						 | 
				
			
			@ -2101,13 +2048,13 @@ namespace IGFD
 | 
			
		|||
            {
 | 
			
		||||
              if (puDLGcountSelectionMax == 0) // infinite selection
 | 
			
		||||
              {
 | 
			
		||||
                prAddFileNameInSelection(file->fileNameExt, false);
 | 
			
		||||
                prAddFileNameInSelection(file.fileNameExt, false);
 | 
			
		||||
              }
 | 
			
		||||
              else // selection limited by size
 | 
			
		||||
              {
 | 
			
		||||
                if (prSelectedFileNames.size() < puDLGcountSelectionMax)
 | 
			
		||||
                {
 | 
			
		||||
                  prAddFileNameInSelection(file->fileNameExt, false);
 | 
			
		||||
                  prAddFileNameInSelection(file.fileNameExt, false);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -2119,7 +2066,7 @@ namespace IGFD
 | 
			
		|||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (file->fileNameExt == fileNameToSelect)
 | 
			
		||||
            if (file.fileNameExt == fileNameToSelect)
 | 
			
		||||
            {
 | 
			
		||||
              if (!startMultiSelection) // we are before the last Selected FileName, so we must inverse
 | 
			
		||||
              {
 | 
			
		||||
| 
						 | 
				
			
			@ -2145,7 +2092,7 @@ namespace IGFD
 | 
			
		|||
    {
 | 
			
		||||
      prSelectedFileNames.clear();
 | 
			
		||||
      IGFD::Utils::ResetBuffer(puFileNameBuffer);
 | 
			
		||||
      prAddFileNameInSelection(vInfos->fileNameExt, true);
 | 
			
		||||
      prAddFileNameInSelection(vInfos.fileNameExt, true);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3922,11 +3869,8 @@ namespace IGFD
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  // returns 0 if not break loop, 1 if break loop, 2 if exit dialog
 | 
			
		||||
  int IGFD::FileDialog::prSelectableItem(int vidx, std::shared_ptr<FileInfos> vInfos, bool vSelected, const char* vFmt, ...)
 | 
			
		||||
  int IGFD::FileDialog::prSelectableItem(int vidx, const FileInfos& vInfos, bool vSelected, const char* vFmt, ...)
 | 
			
		||||
  {
 | 
			
		||||
    if (!vInfos.use_count())
 | 
			
		||||
      return 0;
 | 
			
		||||
 | 
			
		||||
    auto& fdi = prFileDialogInternal.puFileManager;
 | 
			
		||||
 | 
			
		||||
    static ImGuiSelectableFlags selectableFlags = ImGuiSelectableFlags_AllowDoubleClick |
 | 
			
		||||
| 
						 | 
				
			
			@ -3957,7 +3901,7 @@ namespace IGFD
 | 
			
		|||
#endif // USE_EXPLORATION_BY_KEYS
 | 
			
		||||
    if (res)
 | 
			
		||||
    {
 | 
			
		||||
      if (vInfos->fileType == 'd')
 | 
			
		||||
      if (vInfos.fileType == 'd')
 | 
			
		||||
      {
 | 
			
		||||
        bool isSelectingDir=false;
 | 
			
		||||
        // nav system, selectebale cause open directory or select directory
 | 
			
		||||
| 
						 | 
				
			
			@ -4012,27 +3956,27 @@ namespace IGFD
 | 
			
		|||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void IGFD::FileDialog::prBeginFileColorIconStyle(std::shared_ptr<FileInfos> vFileInfos, bool& vOutShowColor, std::string& vOutStr, ImFont** vOutFont)
 | 
			
		||||
  void IGFD::FileDialog::prBeginFileColorIconStyle(const FileInfos& vFileInfos, bool& vOutShowColor, std::string& vOutStr, ImFont** vOutFont)
 | 
			
		||||
  {
 | 
			
		||||
    vOutStr.clear();
 | 
			
		||||
    vOutShowColor = false;
 | 
			
		||||
 | 
			
		||||
    if (vFileInfos->fileStyle.use_count()) //-V807 //-V522
 | 
			
		||||
    if (vFileInfos.fileStyle.use_count()) //-V807 //-V522
 | 
			
		||||
    {
 | 
			
		||||
      vOutShowColor = true;
 | 
			
		||||
 | 
			
		||||
      *vOutFont = vFileInfos->fileStyle->font;
 | 
			
		||||
      *vOutFont = vFileInfos.fileStyle->font;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (vOutShowColor && !vFileInfos->fileStyle->icon.empty()) vOutStr = vFileInfos->fileStyle->icon;
 | 
			
		||||
    else if (vFileInfos->fileType == 'd') vOutStr = dirEntryString;
 | 
			
		||||
    else if (vFileInfos->fileType == 'l') vOutStr = linkEntryString;
 | 
			
		||||
    else if (vFileInfos->fileType == 'f') vOutStr = fileEntryString;
 | 
			
		||||
    if (vOutShowColor && !vFileInfos.fileStyle->icon.empty()) vOutStr = vFileInfos.fileStyle->icon;
 | 
			
		||||
    else if (vFileInfos.fileType == 'd') vOutStr = dirEntryString;
 | 
			
		||||
    else if (vFileInfos.fileType == 'l') vOutStr = linkEntryString;
 | 
			
		||||
    else if (vFileInfos.fileType == 'f') vOutStr = fileEntryString;
 | 
			
		||||
 | 
			
		||||
    vOutStr += " " + vFileInfos->fileNameExt;
 | 
			
		||||
    vOutStr += " " + vFileInfos.fileNameExt;
 | 
			
		||||
 | 
			
		||||
    if (vOutShowColor)
 | 
			
		||||
      ImGui::PushStyleColor(ImGuiCol_Text, vFileInfos->fileStyle->color);
 | 
			
		||||
      ImGui::PushStyleColor(ImGuiCol_Text, vFileInfos.fileStyle->color);
 | 
			
		||||
    if (*vOutFont)
 | 
			
		||||
      ImGui::PushFont(*vOutFont);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -4126,13 +4070,13 @@ namespace IGFD
 | 
			
		|||
          {
 | 
			
		||||
            if (i < 0) continue;
 | 
			
		||||
 | 
			
		||||
            auto infos = fdi.GetFilteredFileAt((size_t)i);
 | 
			
		||||
            if (!infos.use_count())
 | 
			
		||||
            const FileInfos& infos = fdi.GetFilteredFileAt((size_t)i);
 | 
			
		||||
            if (!infos.isValid)
 | 
			
		||||
              continue;
 | 
			
		||||
 | 
			
		||||
            prBeginFileColorIconStyle(infos, _showColor, _str, &_font);
 | 
			
		||||
          
 | 
			
		||||
            bool selected = fdi.IsFileNameSelected(infos->fileNameExt); // found
 | 
			
		||||
            bool selected = fdi.IsFileNameSelected(infos.fileNameExt); // found
 | 
			
		||||
 | 
			
		||||
            ImGui::TableNextRow();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4147,13 +4091,13 @@ namespace IGFD
 | 
			
		|||
            }
 | 
			
		||||
            if (ImGui::TableNextColumn()) // file type
 | 
			
		||||
            {
 | 
			
		||||
              ImGui::Text("%s", infos->fileExt.c_str());
 | 
			
		||||
              ImGui::Text("%s", infos.fileExt.c_str());
 | 
			
		||||
            }
 | 
			
		||||
            if (ImGui::TableNextColumn()) // file size
 | 
			
		||||
            {
 | 
			
		||||
              if (infos->fileType != 'd')
 | 
			
		||||
              if (infos.fileType != 'd')
 | 
			
		||||
              {
 | 
			
		||||
                ImGui::Text("%s ", infos->formatedFileSize.c_str());
 | 
			
		||||
                ImGui::Text("%s ", infos.formatedFileSize.c_str());
 | 
			
		||||
              }
 | 
			
		||||
              else
 | 
			
		||||
              {
 | 
			
		||||
| 
						 | 
				
			
			@ -4162,7 +4106,7 @@ namespace IGFD
 | 
			
		|||
            }
 | 
			
		||||
            if (ImGui::TableNextColumn()) // file date + time
 | 
			
		||||
            {
 | 
			
		||||
              ImGui::Text("%s", infos->fileModifDate.c_str());
 | 
			
		||||
              ImGui::Text("%s", infos.fileModifDate.c_str());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            prEndFileColorIconStyle(_showColor, _font);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								extern/igfd/ImGuiFileDialog.h
									
									
									
									
										vendored
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -766,7 +766,7 @@ namespace IGFD
 | 
			
		|||
    void ParseFilters(const char* vFilters);                              // Parse filter syntax, detect and parse filter collection
 | 
			
		||||
    void SetSelectedFilterWithExt(const std::string& vFilter);                      // Select filter
 | 
			
		||||
    
 | 
			
		||||
    bool prFillFileStyle(std::shared_ptr<FileInfos> vFileInfos)  const;                  // fill with the good style
 | 
			
		||||
    bool prFillFileStyle(FileInfos& vFileInfos)  const;                  // fill with the good style
 | 
			
		||||
    
 | 
			
		||||
    void SetFileStyle(
 | 
			
		||||
      const IGFD_FileStyleFlags& vFlags,
 | 
			
		||||
| 
						 | 
				
			
			@ -812,6 +812,7 @@ namespace IGFD
 | 
			
		|||
#ifdef USE_THUMBNAILS
 | 
			
		||||
    IGFD_Thumbnail_Info thumbnailInfo;    // structre for the display for image file tetxure
 | 
			
		||||
#endif // USE_THUMBNAILS
 | 
			
		||||
    bool isValid = true;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    bool IsTagFound(const std::string& vTag) const;
 | 
			
		||||
| 
						 | 
				
			
			@ -824,6 +825,7 @@ namespace IGFD
 | 
			
		|||
  class FileManager
 | 
			
		||||
  {
 | 
			
		||||
  public: // types
 | 
			
		||||
    FileInfos invalidFile;
 | 
			
		||||
    enum class SortingFieldEnum    // sorting for filetering of the file lsit
 | 
			
		||||
    {
 | 
			
		||||
      FIELD_NONE = 0,        // no sorting preference, result indetermined haha..
 | 
			
		||||
| 
						 | 
				
			
			@ -839,8 +841,8 @@ namespace IGFD
 | 
			
		|||
  private:
 | 
			
		||||
    std::string prCurrentPath;                      // current path (to be decomposed in prCurrentPathDecomposition
 | 
			
		||||
    std::vector<std::string> prCurrentPathDecomposition;        // part words
 | 
			
		||||
    std::vector<std::shared_ptr<FileInfos>> prFileList;          // base container
 | 
			
		||||
    std::vector<std::shared_ptr<FileInfos>> prFilteredFileList;      // filtered container (search, sorting, etc..)
 | 
			
		||||
    std::vector<FileInfos> prFileList;          // base container
 | 
			
		||||
    std::vector<FileInfos> prFilteredFileList;      // filtered container (search, sorting, etc..)
 | 
			
		||||
    std::string prLastSelectedFileName;                  // for shift multi selection
 | 
			
		||||
    std::set<std::string> prSelectedFileNames;              // the user selection of FilePathNames
 | 
			
		||||
    bool prCreateDirectoryMode = false;                  // for create directory widget
 | 
			
		||||
| 
						 | 
				
			
			@ -879,11 +881,11 @@ namespace IGFD
 | 
			
		|||
    static std::string prRoundNumber(double vvalue, int n);                      // custom rounding number
 | 
			
		||||
    static std::string prFormatFileSize(size_t vByteSize);                      // format file size field
 | 
			
		||||
    static std::string prOptimizeFilenameForSearchOperations(const std::string& vFileNameExt);    // turn all text in lower case for search facilitie
 | 
			
		||||
    static void prCompleteFileInfos(const std::shared_ptr<FileInfos>& FileInfos);          // set time and date infos of a file (detail view mode)
 | 
			
		||||
    static void prCompleteFileInfos(FileInfos& FileInfos);          // set time and date infos of a file (detail view mode)
 | 
			
		||||
    void prRemoveFileNameInSelection(const std::string& vFileName);                  // selection : remove a file name
 | 
			
		||||
    void prAddFileNameInSelection(const std::string& vFileName, bool vSetLastSelectionFileName);  // selection : add a file name
 | 
			
		||||
    void AddFile(const FileDialogInternal& vFileDialogInternal, 
 | 
			
		||||
      const std::string& vPath, const std::string& vFileName, const char& vFileType, void* ent);        // add file called by scandir
 | 
			
		||||
      const std::string& vPath, const std::string& vFileName, char vFileType, void* ent);        // add file called by scandir
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    FileManager();
 | 
			
		||||
| 
						 | 
				
			
			@ -892,9 +894,9 @@ namespace IGFD
 | 
			
		|||
    bool IsFileListEmpty();
 | 
			
		||||
    bool IsFilteredListEmpty();
 | 
			
		||||
    size_t GetFullFileListSize();
 | 
			
		||||
    std::shared_ptr<FileInfos> GetFullFileAt(size_t vIdx);
 | 
			
		||||
    const FileInfos& GetFullFileAt(size_t vIdx);
 | 
			
		||||
    size_t GetFilteredListSize();
 | 
			
		||||
    std::shared_ptr<FileInfos> GetFilteredFileAt(size_t vIdx);
 | 
			
		||||
    const FileInfos& GetFilteredFileAt(size_t vIdx);
 | 
			
		||||
    bool IsFileNameSelected(const std::string& vFileName);
 | 
			
		||||
    std::string GetBack();
 | 
			
		||||
    void ClearComposer();
 | 
			
		||||
| 
						 | 
				
			
			@ -912,9 +914,9 @@ namespace IGFD
 | 
			
		|||
    void SetCurrentPath(const std::string& vCurrentPath);                      // set the current path
 | 
			
		||||
    static bool IsFileExist(const std::string& vFile);
 | 
			
		||||
    void SetDefaultFileName(const std::string& vFileName);
 | 
			
		||||
    bool SelectDirectory(const std::shared_ptr<FileInfos>& vInfos);                    // enter directory
 | 
			
		||||
    bool SelectDirectory(const FileInfos& vInfos);                    // enter directory
 | 
			
		||||
    void SelectFileName(const FileDialogInternal& vFileDialogInternal, 
 | 
			
		||||
      const std::shared_ptr<FileInfos>& vInfos);                              // select filename
 | 
			
		||||
      const FileInfos& vInfos);                              // select filename
 | 
			
		||||
    
 | 
			
		||||
    //depend of dirent.h
 | 
			
		||||
    void SetCurrentDir(const std::string& vPath);                          // define current directory for scan
 | 
			
		||||
| 
						 | 
				
			
			@ -1311,7 +1313,7 @@ namespace IGFD
 | 
			
		|||
    // widgets components
 | 
			
		||||
    virtual void prDrawSidePane(float vHeight);          // draw side pane
 | 
			
		||||
    virtual int prSelectableItem(int vidx, 
 | 
			
		||||
      std::shared_ptr<FileInfos> vInfos, 
 | 
			
		||||
      const FileInfos& vInfos, 
 | 
			
		||||
      bool vSelected, const char* vFmt, ...);          // draw a custom selectable behavior item
 | 
			
		||||
    virtual bool prDrawFileListView(ImVec2 vSize);        // draw file list view (default mode)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1325,7 +1327,7 @@ namespace IGFD
 | 
			
		|||
    // - prDrawThumbnailsListView
 | 
			
		||||
    // - prDrawThumbnailsGridView
 | 
			
		||||
    void prBeginFileColorIconStyle(
 | 
			
		||||
      std::shared_ptr<FileInfos> vFileInfos, 
 | 
			
		||||
      const FileInfos& vFileInfos, 
 | 
			
		||||
      bool& vOutShowColor, 
 | 
			
		||||
      std::string& vOutStr, 
 | 
			
		||||
      ImFont** vOutFont);                    // begin style apply of filter with color an icon if any
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3851,6 +3851,23 @@ void DivEngine::delSample(int index) {
 | 
			
		|||
    song.sampleLen=song.sample.size();
 | 
			
		||||
    removeAsset(song.sampleDir,index);
 | 
			
		||||
    checkAssetDir(song.sampleDir,song.sample.size());
 | 
			
		||||
 | 
			
		||||
    // compensate
 | 
			
		||||
    for (DivInstrument* i: song.ins) {
 | 
			
		||||
      if (i->amiga.initSample==index) {
 | 
			
		||||
        i->amiga.initSample=-1;
 | 
			
		||||
      } else if (i->amiga.initSample>index) {
 | 
			
		||||
        i->amiga.initSample--;
 | 
			
		||||
      }
 | 
			
		||||
      for (int j=0; j<120; j++) {
 | 
			
		||||
        if (i->amiga.noteMap[j].map==index) {
 | 
			
		||||
          i->amiga.noteMap[j].map=-1;
 | 
			
		||||
        } else if (i->amiga.noteMap[j].map>index) {
 | 
			
		||||
          i->amiga.noteMap[j].map--;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    renderSamples();
 | 
			
		||||
  }
 | 
			
		||||
  saveLock.unlock();
 | 
			
		||||
| 
						 | 
				
			
			@ -4042,6 +4059,27 @@ void DivEngine::exchangeIns(int one, int two) {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DivEngine::exchangeWave(int one, int two) {
 | 
			
		||||
  // TODO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DivEngine::exchangeSample(int one, int two) {
 | 
			
		||||
  for (DivInstrument* i: song.ins) {
 | 
			
		||||
    if (i->amiga.initSample==one) {
 | 
			
		||||
      i->amiga.initSample=two;
 | 
			
		||||
    } else if (i->amiga.initSample==two) {
 | 
			
		||||
      i->amiga.initSample=one;
 | 
			
		||||
    }
 | 
			
		||||
    for (int j=0; j<120; j++) {
 | 
			
		||||
      if (i->amiga.noteMap[j].map==one) {
 | 
			
		||||
        i->amiga.noteMap[j].map=two;
 | 
			
		||||
      } else if (i->amiga.noteMap[j].map==two) {
 | 
			
		||||
        i->amiga.noteMap[j].map=one;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DivEngine::moveInsUp(int which) {
 | 
			
		||||
  if (which<1 || which>=(int)song.ins.size()) return false;
 | 
			
		||||
  BUSY_BEGIN;
 | 
			
		||||
| 
						 | 
				
			
			@ -4064,6 +4102,7 @@ bool DivEngine::moveWaveUp(int which) {
 | 
			
		|||
  song.wave[which]=song.wave[which-1];
 | 
			
		||||
  song.wave[which-1]=prev;
 | 
			
		||||
  moveAsset(song.waveDir,which,which-1);
 | 
			
		||||
  exchangeWave(which,which-1);
 | 
			
		||||
  saveLock.unlock();
 | 
			
		||||
  BUSY_END;
 | 
			
		||||
  return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -4080,6 +4119,7 @@ bool DivEngine::moveSampleUp(int which) {
 | 
			
		|||
  song.sample[which]=song.sample[which-1];
 | 
			
		||||
  song.sample[which-1]=prev;
 | 
			
		||||
  moveAsset(song.sampleDir,which,which-1);
 | 
			
		||||
  exchangeSample(which,which-1);
 | 
			
		||||
  saveLock.unlock();
 | 
			
		||||
  renderSamples();
 | 
			
		||||
  BUSY_END;
 | 
			
		||||
| 
						 | 
				
			
			@ -4107,6 +4147,7 @@ bool DivEngine::moveWaveDown(int which) {
 | 
			
		|||
  saveLock.lock();
 | 
			
		||||
  song.wave[which]=song.wave[which+1];
 | 
			
		||||
  song.wave[which+1]=prev;
 | 
			
		||||
  exchangeWave(which,which+1);
 | 
			
		||||
  moveAsset(song.waveDir,which,which+1);
 | 
			
		||||
  saveLock.unlock();
 | 
			
		||||
  BUSY_END;
 | 
			
		||||
| 
						 | 
				
			
			@ -4123,6 +4164,7 @@ bool DivEngine::moveSampleDown(int which) {
 | 
			
		|||
  saveLock.lock();
 | 
			
		||||
  song.sample[which]=song.sample[which+1];
 | 
			
		||||
  song.sample[which+1]=prev;
 | 
			
		||||
  exchangeSample(which,which+1);
 | 
			
		||||
  moveAsset(song.sampleDir,which,which+1);
 | 
			
		||||
  saveLock.unlock();
 | 
			
		||||
  renderSamples();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -531,6 +531,9 @@ class DivEngine {
 | 
			
		|||
  void initSongWithDesc(const char* description, bool inBase64=true, bool oldVol=false);
 | 
			
		||||
 | 
			
		||||
  void exchangeIns(int one, int two);
 | 
			
		||||
  void exchangeWave(int one, int two);
 | 
			
		||||
  void exchangeSample(int one, int two);
 | 
			
		||||
 | 
			
		||||
  void swapChannels(int src, int dest);
 | 
			
		||||
  void stompChannel(int ch);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1937,8 +1937,8 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
 | 
			
		|||
      ds.system[i]=systemFromFileFur(sysID);
 | 
			
		||||
      logD("- %d: %.2x (%s)",i,sysID,getSystemName(ds.system[i]));
 | 
			
		||||
      if (sysID!=0 && systemToFileFur(ds.system[i])==0) {
 | 
			
		||||
        logE("unrecognized system ID %.2x",ds.system[i]);
 | 
			
		||||
        lastError=fmt::sprintf("unrecognized system ID %.2x!",ds.system[i]);
 | 
			
		||||
        logE("unrecognized system ID %.2x",sysID);
 | 
			
		||||
        lastError=fmt::sprintf("unrecognized system ID %.2x!",sysID);
 | 
			
		||||
        delete[] file;
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -360,26 +360,6 @@ void DivPlatformES5506::tick(bool sysTick) {
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (chan[i].pcm.isNoteMap) {
 | 
			
		||||
    // note map macros
 | 
			
		||||
      if (chan[i].std.wave.had) {
 | 
			
		||||
        if (chan[i].std.wave.val>=0 && chan[i].std.wave.val<120) {
 | 
			
		||||
          if (chan[i].pcm.next!=chan[i].std.wave.val) {
 | 
			
		||||
            chan[i].pcm.next=chan[i].std.wave.val;
 | 
			
		||||
            chan[i].pcmChanged.index=1;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } else if (!chan[i].pcm.isNoteMap) {
 | 
			
		||||
      if (chan[i].std.wave.had) {
 | 
			
		||||
        if (chan[i].std.wave.val>=0 && chan[i].std.wave.val<parent->song.sampleLen) {
 | 
			
		||||
          if (chan[i].pcm.next!=chan[i].std.wave.val) {
 | 
			
		||||
            chan[i].pcm.next=chan[i].std.wave.val;
 | 
			
		||||
            chan[i].pcmChanged.index=1;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // update registers
 | 
			
		||||
    if (chan[i].volChanged.changed) {
 | 
			
		||||
      // calculate volume (16 bit)
 | 
			
		||||
| 
						 | 
				
			
			@ -432,7 +412,7 @@ void DivPlatformES5506::tick(bool sysTick) {
 | 
			
		|||
              off=(double)center/8363.0;
 | 
			
		||||
            }
 | 
			
		||||
            if (ins->amiga.useNoteMap) {
 | 
			
		||||
              chan[i].pcm.note=next;
 | 
			
		||||
              //chan[i].pcm.note=next;
 | 
			
		||||
            }
 | 
			
		||||
            // get loop mode
 | 
			
		||||
            DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
 | 
			
		||||
| 
						 | 
				
			
			@ -748,13 +728,13 @@ int DivPlatformES5506::dispatch(DivCommand c) {
 | 
			
		|||
      if (((ins->amiga.useNoteMap) && (c.value>=0 && c.value<120)) ||
 | 
			
		||||
          ((!ins->amiga.useNoteMap) && (ins->amiga.initSample>=0 && ins->amiga.initSample<parent->song.sampleLen))) {
 | 
			
		||||
        int sample=ins->amiga.getSample(c.value);
 | 
			
		||||
        c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
        if (sample>=0 && sample<parent->song.sampleLen) {
 | 
			
		||||
          sampleValid=true;
 | 
			
		||||
          chan[c.chan].volMacroMax=ins->type==DIV_INS_AMIGA?64:0xfff;
 | 
			
		||||
          chan[c.chan].panMacroMax=ins->type==DIV_INS_AMIGA?127:0xfff;
 | 
			
		||||
          chan[c.chan].pcm.note=c.value;
 | 
			
		||||
          chan[c.chan].pcm.next=ins->amiga.useNoteMap?c.value:sample;
 | 
			
		||||
          c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
          chan[c.chan].pcm.note=c.value;
 | 
			
		||||
          chan[c.chan].filter=ins->es5506.filter;
 | 
			
		||||
          chan[c.chan].envelope=ins->es5506.envelope;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -870,20 +850,6 @@ int DivPlatformES5506::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].pitch=c.value;
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    // sample commands
 | 
			
		||||
    case DIV_CMD_WAVE:
 | 
			
		||||
      if (!chan[c.chan].useWave) {
 | 
			
		||||
        if (chan[c.chan].active) {
 | 
			
		||||
          DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_ES5506);
 | 
			
		||||
          if (((ins->amiga.useNoteMap) && (c.value>=0 && c.value<120)) ||
 | 
			
		||||
              ((!ins->amiga.useNoteMap) && (c.value>=0 && c.value<parent->song.sampleLen))) {
 | 
			
		||||
            chan[c.chan].pcm.next=c.value;
 | 
			
		||||
            chan[c.chan].pcmChanged.index=1;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      // reserved for useWave
 | 
			
		||||
      break;
 | 
			
		||||
    // Filter commands
 | 
			
		||||
    case DIV_CMD_ES5506_FILTER_MODE:
 | 
			
		||||
      if (!chan[c.chan].active) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -386,6 +386,9 @@ int DivPlatformMSM6258::init(DivEngine* p, int channels, int sugRate, const DivC
 | 
			
		|||
    oscBuf[i]=new DivDispatchOscBuffer;
 | 
			
		||||
  }
 | 
			
		||||
  msm=new okim6258_device(4000000);
 | 
			
		||||
  msm->set_start_div(okim6258_device::FOSC_DIV_BY_1024);
 | 
			
		||||
  msm->set_type(okim6258_device::TYPE_4BITS);
 | 
			
		||||
  msm->set_outbits(okim6258_device::OUTPUT_12BITS);
 | 
			
		||||
  msm->device_start();
 | 
			
		||||
  setFlags(flags);
 | 
			
		||||
  reset();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,7 +47,6 @@ class DivPlatformMSM6258: public DivDispatch {
 | 
			
		|||
    };
 | 
			
		||||
    FixedQueue<QueuedWrite,256> writes;
 | 
			
		||||
    okim6258_device* msm;
 | 
			
		||||
    unsigned char lastBusy;
 | 
			
		||||
 | 
			
		||||
    unsigned char sampleBank, msmPan, msmDivider, rateSel, msmClock, clockSel;
 | 
			
		||||
    signed char msmDividerCount, msmClockCount;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -130,9 +130,9 @@ void DivPlatformNES::acquire_NSFPlay(short** buf, size_t len) {
 | 
			
		|||
  for (size_t i=0; i<len; i++) {
 | 
			
		||||
    doPCM;
 | 
			
		||||
  
 | 
			
		||||
    nes1_NP->Tick(1);
 | 
			
		||||
    nes2_NP->TickFrameSequence(1);
 | 
			
		||||
    nes2_NP->Tick(1);
 | 
			
		||||
    nes1_NP->Tick(8);
 | 
			
		||||
    nes2_NP->TickFrameSequence(8);
 | 
			
		||||
    nes2_NP->Tick(8);
 | 
			
		||||
    nes1_NP->Render(out1);
 | 
			
		||||
    nes2_NP->Render(out2);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +140,7 @@ void DivPlatformNES::acquire_NSFPlay(short** buf, size_t len) {
 | 
			
		|||
    if (sample>32767) sample=32767;
 | 
			
		||||
    if (sample<-32768) sample=-32768;
 | 
			
		||||
    buf[0][i]=sample;
 | 
			
		||||
    if (++writeOscBuf>=32) {
 | 
			
		||||
    if (++writeOscBuf>=4) {
 | 
			
		||||
      writeOscBuf=0;
 | 
			
		||||
      oscBuf[0]->data[oscBuf[0]->needle++]=nes1_NP->out[0]<<11;
 | 
			
		||||
      oscBuf[1]->data[oscBuf[1]->needle++]=nes1_NP->out[1]<<11;
 | 
			
		||||
| 
						 | 
				
			
			@ -749,8 +749,11 @@ void DivPlatformNES::setFlags(const DivConfig& flags) {
 | 
			
		|||
  }
 | 
			
		||||
  CHECK_CUSTOM_CLOCK;
 | 
			
		||||
  rate=chipClock;
 | 
			
		||||
  if (useNP) {
 | 
			
		||||
    rate/=8;
 | 
			
		||||
  }
 | 
			
		||||
  for (int i=0; i<5; i++) {
 | 
			
		||||
    oscBuf[i]->rate=rate/32;
 | 
			
		||||
    oscBuf[i]->rate=rate/(useNP?4:32);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  dpcmModeDefault=flags.getBool("dpcmMode",true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -356,12 +356,12 @@ void DivPlatformTIA::poke(std::vector<DivRegWrite>& wlist) {
 | 
			
		|||
 | 
			
		||||
void DivPlatformTIA::setFlags(const DivConfig& flags) {
 | 
			
		||||
  if (flags.getInt("clockSel",0)) {
 | 
			
		||||
    rate=COLOR_PAL*4.0/5.0;
 | 
			
		||||
    chipClock=COLOR_PAL*4.0/5.0;
 | 
			
		||||
  } else {
 | 
			
		||||
    rate=COLOR_NTSC;
 | 
			
		||||
    chipClock=COLOR_NTSC;
 | 
			
		||||
  }
 | 
			
		||||
  CHECK_CUSTOM_CLOCK;
 | 
			
		||||
  chipClock=rate;
 | 
			
		||||
  rate=chipClock;
 | 
			
		||||
  mixingType=flags.getInt("mixingType",0)&3;
 | 
			
		||||
  for (int i=0; i<2; i++) {
 | 
			
		||||
    oscBuf[i]->rate=rate/114;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1542,7 +1542,6 @@ void DivEngine::registerSystems() {
 | 
			
		|||
  );
 | 
			
		||||
 | 
			
		||||
  EffectHandlerMap es5506PreEffectHandlerMap={
 | 
			
		||||
      {0x10, {DIV_CMD_WAVE, "10xx: Change waveform (00 to FF)",effectVal}},
 | 
			
		||||
      {0x11, {DIV_CMD_ES5506_FILTER_MODE, "11xx: Set filter mode (00 to 03)",effectValAnd<3>}},
 | 
			
		||||
      {0x14, {DIV_CMD_ES5506_FILTER_K1, "14xx: Set filter coefficient K1 low byte (00 to FF)",effectValShift<0>,constVal<0x00ff>}},
 | 
			
		||||
      {0x15, {DIV_CMD_ES5506_FILTER_K1, "15xx: Set filter coefficient K1 high byte (00 to FF)",effectValShift<8>,constVal<0xff00>}},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,6 +121,7 @@ const char* aboutLine[]={
 | 
			
		|||
  "SwapXFO",
 | 
			
		||||
  "TakuikaNinja",
 | 
			
		||||
  "TCORPStudios",
 | 
			
		||||
  "Teuthida",
 | 
			
		||||
  "The Blender Fiddler",
 | 
			
		||||
  "TheDuccinator",
 | 
			
		||||
  "theloredev",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -330,9 +330,6 @@ void FurnaceGUI::insListItem(int i, int dir, int asset) {
 | 
			
		|||
      if (ImGui::MenuItem("save")) {
 | 
			
		||||
        doAction(GUI_ACTION_INS_LIST_SAVE);
 | 
			
		||||
      }
 | 
			
		||||
      if (ImGui::MenuItem("save (legacy .fui)")) {
 | 
			
		||||
        doAction(GUI_ACTION_INS_LIST_SAVE_OLD);
 | 
			
		||||
      }
 | 
			
		||||
      if (ImGui::MenuItem("save (.dmp)")) {
 | 
			
		||||
        doAction(GUI_ACTION_INS_LIST_SAVE_DMP);
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -642,9 +642,6 @@ void FurnaceGUI::doAction(int what) {
 | 
			
		|||
    case GUI_ACTION_INS_LIST_SAVE:
 | 
			
		||||
      if (curIns>=0 && curIns<(int)e->song.ins.size()) openFileDialog(GUI_FILE_INS_SAVE);
 | 
			
		||||
      break;
 | 
			
		||||
    case GUI_ACTION_INS_LIST_SAVE_OLD:
 | 
			
		||||
      if (curIns>=0 && curIns<(int)e->song.ins.size()) openFileDialog(GUI_FILE_INS_SAVE_OLD);
 | 
			
		||||
      break;
 | 
			
		||||
    case GUI_ACTION_INS_LIST_SAVE_DMP:
 | 
			
		||||
      if (curIns>=0 && curIns<(int)e->song.ins.size()) openFileDialog(GUI_FILE_INS_SAVE_DMP);
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1653,16 +1653,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
 | 
			
		|||
        dpiScale
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
    case GUI_FILE_INS_SAVE_OLD:
 | 
			
		||||
      if (!dirExists(workingDirIns)) workingDirIns=getHomeDir();
 | 
			
		||||
      hasOpened=fileDialog->openSave(
 | 
			
		||||
        "Save Instrument",
 | 
			
		||||
        {"Furnace instrument", "*.fui"},
 | 
			
		||||
        "Furnace instrument{.fui}",
 | 
			
		||||
        workingDirIns,
 | 
			
		||||
        dpiScale
 | 
			
		||||
      );
 | 
			
		||||
      break;
 | 
			
		||||
    case GUI_FILE_INS_SAVE_DMP:
 | 
			
		||||
      if (!dirExists(workingDirIns)) workingDirIns=getHomeDir();
 | 
			
		||||
      hasOpened=fileDialog->openSave(
 | 
			
		||||
| 
						 | 
				
			
			@ -4592,7 +4582,6 @@ bool FurnaceGUI::loop() {
 | 
			
		|||
        case GUI_FILE_INS_OPEN:
 | 
			
		||||
        case GUI_FILE_INS_OPEN_REPLACE:
 | 
			
		||||
        case GUI_FILE_INS_SAVE:
 | 
			
		||||
        case GUI_FILE_INS_SAVE_OLD:
 | 
			
		||||
        case GUI_FILE_INS_SAVE_DMP:
 | 
			
		||||
          workingDirIns=fileDialog->getPath()+DIR_SEPARATOR_STR;
 | 
			
		||||
          break;
 | 
			
		||||
| 
						 | 
				
			
			@ -4695,9 +4684,6 @@ bool FurnaceGUI::loop() {
 | 
			
		|||
          if (curFileDialog==GUI_FILE_INS_SAVE) {
 | 
			
		||||
            checkExtension(".fui");
 | 
			
		||||
          }
 | 
			
		||||
          if (curFileDialog==GUI_FILE_INS_SAVE_OLD) {
 | 
			
		||||
            checkExtension(".fui");
 | 
			
		||||
          }
 | 
			
		||||
          if (curFileDialog==GUI_FILE_INS_SAVE_DMP) {
 | 
			
		||||
            checkExtension(".dmp");
 | 
			
		||||
          }
 | 
			
		||||
| 
						 | 
				
			
			@ -4791,11 +4777,6 @@ bool FurnaceGUI::loop() {
 | 
			
		|||
                e->song.ins[curIns]->save(copyOfName.c_str(),false,&e->song);
 | 
			
		||||
              }
 | 
			
		||||
              break;
 | 
			
		||||
            case GUI_FILE_INS_SAVE_OLD:
 | 
			
		||||
              if (curIns>=0 && curIns<(int)e->song.ins.size()) {
 | 
			
		||||
                e->song.ins[curIns]->save(copyOfName.c_str(),true);
 | 
			
		||||
              }
 | 
			
		||||
              break;
 | 
			
		||||
            case GUI_FILE_INS_SAVE_DMP:
 | 
			
		||||
              if (curIns>=0 && curIns<(int)e->song.ins.size()) {
 | 
			
		||||
                if (!e->song.ins[curIns]->saveDMP(copyOfName.c_str())) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -402,7 +402,6 @@ enum FurnaceGUIFileDialogs {
 | 
			
		|||
  GUI_FILE_INS_OPEN,
 | 
			
		||||
  GUI_FILE_INS_OPEN_REPLACE,
 | 
			
		||||
  GUI_FILE_INS_SAVE,
 | 
			
		||||
  GUI_FILE_INS_SAVE_OLD,
 | 
			
		||||
  GUI_FILE_INS_SAVE_DMP,
 | 
			
		||||
  GUI_FILE_WAVE_OPEN,
 | 
			
		||||
  GUI_FILE_WAVE_OPEN_REPLACE,
 | 
			
		||||
| 
						 | 
				
			
			@ -607,7 +606,6 @@ enum FurnaceGUIActions {
 | 
			
		|||
  GUI_ACTION_INS_LIST_OPEN,
 | 
			
		||||
  GUI_ACTION_INS_LIST_OPEN_REPLACE,
 | 
			
		||||
  GUI_ACTION_INS_LIST_SAVE,
 | 
			
		||||
  GUI_ACTION_INS_LIST_SAVE_OLD,
 | 
			
		||||
  GUI_ACTION_INS_LIST_SAVE_DMP,
 | 
			
		||||
  GUI_ACTION_INS_LIST_MOVE_UP,
 | 
			
		||||
  GUI_ACTION_INS_LIST_MOVE_DOWN,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -641,7 +641,6 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
 | 
			
		|||
  D("INS_LIST_OPEN", "Open", 0),
 | 
			
		||||
  D("INS_LIST_OPEN_REPLACE", "Open (replace current)", 0),
 | 
			
		||||
  D("INS_LIST_SAVE", "Save", 0),
 | 
			
		||||
  D("INS_LIST_SAVE_OLD", "Save (legacy .fui)", 0),
 | 
			
		||||
  D("INS_LIST_SAVE_DMP", "Save (.dmp)", 0),
 | 
			
		||||
  D("INS_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP),
 | 
			
		||||
  D("INS_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2288,9 +2288,6 @@ void FurnaceGUI::drawInsEdit() {
 | 
			
		|||
          ImGui::SetTooltip("Save");
 | 
			
		||||
        }
 | 
			
		||||
        if (ImGui::BeginPopupContextItem("InsSaveFormats",ImGuiMouseButton_Right)) {
 | 
			
		||||
          if (ImGui::MenuItem("save in legacy format...")) {
 | 
			
		||||
            doAction(GUI_ACTION_INS_LIST_SAVE_OLD);
 | 
			
		||||
          }
 | 
			
		||||
          if (ImGui::MenuItem("save as .dmp...")) {
 | 
			
		||||
            doAction(GUI_ACTION_INS_LIST_SAVE_DMP);
 | 
			
		||||
          }
 | 
			
		||||
| 
						 | 
				
			
			@ -5563,6 +5560,7 @@ void FurnaceGUI::drawInsEdit() {
 | 
			
		|||
          if (ins->type==DIV_INS_MSM6295) waveMax=0;
 | 
			
		||||
          if (ins->type==DIV_INS_SEGAPCM) waveMax=0;
 | 
			
		||||
          if (ins->type==DIV_INS_K007232) waveMax=0;
 | 
			
		||||
          if (ins->type==DIV_INS_ES5506) waveMax=0;
 | 
			
		||||
          if (ins->type==DIV_INS_GA20) waveMax=0;
 | 
			
		||||
          if (ins->type==DIV_INS_K053260) waveMax=0;
 | 
			
		||||
          if (ins->type==DIV_INS_POKEMINI) waveMax=0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -991,7 +991,7 @@ void FurnaceGUI::initSystemPresets() {
 | 
			
		|||
    }
 | 
			
		||||
  );
 | 
			
		||||
  ENTRY(
 | 
			
		||||
    "PC + AdLib/Sound Blaster (drums mode)", {
 | 
			
		||||
    "PC + Sound Blaster (drums mode)", {
 | 
			
		||||
      CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""),
 | 
			
		||||
      CH(DIV_SYSTEM_PCSPKR, 1.0f, 0, ""),
 | 
			
		||||
      CH(DIV_SYSTEM_PCM_DAC, 1.0f, 0, 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||