Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

IntelliFile - An Alternative Windows Version to the Famous Total Commander

4.91/5 (46 votes)
11 Oct 2024GPL37 min read 138.4K  
This article is about the IntelliFile application which is a free alternative Windows version to Total Commander and uses many components that have been published on CodeProject.

Image 1

Feature List

The application is free as in free speech/free beer, and the final version will have the following features:

  • File handling
    • Extended copying, moving, renaming and deleting of entire trees
    • Compare files by content, with built-in text editor
    • Encode/Decode files in base64 format
    • Show/select files with specific search pattern, size, date or contents
    • Enhanced search function with full text search in any files across multiple drives, even inside archives
    • Supports Drag & Drop with Explorer/the Desktop
  • FTP client
    • Built-in FTP client supports most public FTP servers
    • Secure FTP over SSL/TLS, enter the URL as follows: ftps://ftp.servername.com
    • Download in the background (separate thread)
  • Archive handling
    • Archives are handled like subdirectories. You can easily copy files to and from archives.
    • Built-in ZIP-compatible packer, supports long filenames! This packer is based on ZLIB by Info-Zip.
    • Pack archives in the background (separate thread)

For now, only the basic file operations are implemented: edit, copy, move, rename, and delete!
Some of the above features are still under development!

The Architecture

Each file definition is contained in a CFileData class, with the following interface:

  • DWORD GetFileAttributes(); - returns file's attributes
  • void SetFileAttributes(DWORD dwFileAttributes); - sets file's attributes
  • COleDateTime GetCreationTime(); - return file's creation date/time
  • void SetCreationTime(COleDateTime ftCreationTime); - sets file's creation date/time
  • COleDateTime GetLastAccessTime(); - return file's last read date/time
  • void SetLastAccessTime(COleDateTime ftLastAccessTime); - sets file's last read date/time
  • COleDateTime GetLastWriteTime(); - returns file's last write date/time
  • void SetLastWriteTime(COleDateTime ftLastWriteTime); - sets file's last write date/time
  • ULONGLONG GetFileSize(); - returns file's size
  • void SetFileSize(ULONGLONG nFileSize); - sets file's size
  • CString GetFileName(); - returns file's name
  • void SetFileName(CString strFileName); - sets file's name
  • CString GetAlternate(); - returns file's alternate name
  • void SetAlternate(CString strAlternateFileName); - sets file's alternate name

Then, we define CFileList as typedef CArray<cfiledata*> CFileList;

This list is managed inside the CFileSystem class, with the following interface:

  • BOOL RemoveAll(); - removes all files from list
  • int GetSize(); - returns the count of files in list
  • CFileData* GetAt(int nIndex); - returns a file definition from list
  • int GetSystemType(); - returns file system type (FAT, FTP, ZIP)
  • void SetSystemType(int nSystemType); - sets file system type (FAT, FTP, ZIP)
  • CString GetFolder(); - returns current folder path
  • BOOL SetFolder(CString strFolder); - sets current folder path
  • BOOL Refresh(); - updates the file definitions from list
  • BOOL ViewFile(CString strFilePath); - allows viewing the selected file
  • BOOL EditFile(CString strFilePath); - allows editing the selected file
  • BOOL CopyFile(CFileSystem* pDestination, CFileList* arrSelection); - copies the selected files and folders
  • BOOL MoveFile(CFileSystem* pDestination, CFileList* arrSelection); - moves the selected files and folders
  • BOOL NewFolder(CFileSystem* pDestination, CFileList* arrSelection); - creates a new folder
  • BOOL DeleteFile(CFileSystem* pDestination, CFileList* arrSelection); - deletes the selected files and folders

How to Edit Files in Windows?

C++
BOOL CFileSystem::EditFile(CString strFilePath)
{
    const int nDot = strFilePath.ReverseFind(_T('.'));
    if ((nDot != -1) && !IsApplication(strFilePath))
    {
        CString strExtension = strFilePath.Mid(nDot);

        CString strApplication;
        TCHAR lpszBuffer[0x1000] = { 0 };
        DWORD cbLength = sizeof(lpszBuffer);
        if (SUCCEEDED(AssocQueryString(0, ASSOCSTR_COMMAND, 
                      strExtension, _T("open"), lpszBuffer, &cbLength)))
        {
            lpszBuffer[cbLength] = 0;
            strApplication = lpszBuffer;
        }

        if (strApplication.IsEmpty())
        {
            MessageBox(m_hWndParent, _T("There is no application associated with 
            this type of file."), _T("IntelliFile"), MB_OK | MB_ICONEXCLAMATION);
            return FALSE;
        }

        if (strApplication.Find(_T("%1")) != -1)
        {
            strApplication.Replace(_T("\"%1\""), (_T("\"") + strFilePath + _T("\"")));
            strApplication.Replace(_T("%1"), (_T("\"") + strFilePath + _T("\"")));
        }
        else
        {
            strApplication += _T(" ") + (_T("\"") + strFilePath + _T("\""));
        }

        CString strExe;
        CString strParam;
        if (strApplication.Find(_T("rundll32.exe")) != -1)
        {
            if ((int) ShellExecute(m_hWndParent, _T("open"), 
                      strFilePath, NULL, NULL, SW_SHOWNORMAL) <= 32)
            {
                DisplayErrorBox(m_wndCaptionBar, _T("ShellExecute"), GetLastError());
                return FALSE;
            }
        }
        else
        {
            if (strApplication[0] == _T('"'))
            {
                int nPos = strApplication.Find('"', 1);
                if (nPos != -1)
                {
                    strExe = strApplication.Left(nPos+1);
                    strParam = strApplication.Mid(nPos+1);
                }
                else
                {
                    ASSERT(0);
                }
            }
            else
            {
                int nPos = strApplication.Find(' ', 1);
                if (nPos != -1)
                {
                    strExe = strApplication.Left(nPos+1);
                    strParam = strApplication.Mid(nPos+1);
                }
                else
                {
                    ASSERT(0);
                }
            }

            strExe.Trim(_T(" \r\n\t"));
            strParam.Trim(_T(" \r\n\t"));

            SHELLEXECUTEINFO pShellExecuteInfo;
            pShellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
            pShellExecuteInfo.fMask = SEE_MASK_FLAG_DDEWAIT | 
            SEE_MASK_NOCLOSEPROCESS | SEE_MASK_DOENVSUBST;
            pShellExecuteInfo.hwnd = m_hWndParent;
            pShellExecuteInfo.lpVerb = NULL;
            pShellExecuteInfo.lpFile = (LPCWSTR)(strExe);
            pShellExecuteInfo.lpParameters = (LPCWSTR)(strParam);
            pShellExecuteInfo.lpDirectory = NULL;
            pShellExecuteInfo.nShow = SW_SHOWNORMAL;

            if (!ShellExecuteEx(&pShellExecuteInfo))
            {
                DisplayErrorBox(m_wndCaptionBar, _T("ShellExecute"), GetLastError());
                return FALSE;
            }
        }
        return TRUE;
    }

    return FALSE;
}

How to Copy Files in Windows?

C++
bool CFileSystem::CopyFile(CFileSystem* pDestination, CFileList* arrSelection)
{
	bool bRetVal = false;
	HRESULT hResult = S_OK;
	IFileOperation* pFileOperation = nullptr;
	IShellItem* pFolderItem = nullptr;
	IShellItem* pShellItem = nullptr;
	IShellItemArray* pShellItemArray = nullptr;
	CString strDestination = pDestination->GetCurrentFolder();

	ASSERT(pDestination != nullptr);
	ASSERT(arrSelection != nullptr);
	if ((SUCCEEDED(hResult = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOwnerWindow(m_hWndParent))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOperationFlags(FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOFX_SHOWELEVATIONPROMPT))) &&
		(SUCCEEDED(hResult = SHCreateItemFromParsingName(strDestination, nullptr, IID_PPV_ARGS(&pFolderItem)))))
	{
		if (arrSelection->GetCount() == 1)
		{
			CFileData* pFileData = arrSelection->GetAt(0);
			ASSERT_VALID(pFileData);
			CString strFileName = pFileData->GetFileName();
			CString strFolder = GetCurrentFolder();
			CString strFilePath = strFolder + strFileName;

			if ((SUCCEEDED(hResult = SHCreateItemFromParsingName(strFilePath, nullptr, IID_PPV_ARGS(&pShellItem)))) &&
				(SUCCEEDED(hResult = pFileOperation->CopyItem(pShellItem, pFolderItem, nullptr, nullptr))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::CopyFile"), hResult);
			}
		}
		else
		{
			const int nCount = (int)arrSelection->GetCount();
			LPCITEMIDLIST* arrItemIDList = new LPCITEMIDLIST[nCount];
			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				CFileData* pFileData = arrSelection->GetAt(nIndex);
				ASSERT_VALID(pFileData);
				CString strFileName = pFileData->GetFileName();
				CString strFolder = GetCurrentFolder();
				CString strFilePath = strFolder + strFileName;

				arrItemIDList[nIndex] = ILCreateFromPath(strFilePath);
			}

			if ((SUCCEEDED(hResult = SHCreateShellItemArrayFromIDLists(nCount, arrItemIDList, &pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->CopyItems(pShellItemArray, pFolderItem))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::CopyFile"), hResult);
			}

			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				ILFree((LPITEMIDLIST)arrItemIDList[nIndex]);
			}
			delete arrItemIDList;
			arrItemIDList = nullptr;
		}
	}
	else
	{
		DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::CopyFile"), hResult);
	}

	if (pShellItemArray != nullptr)
	{
		pShellItemArray->Release();
		pShellItemArray = nullptr;
	}

	if (pShellItem != nullptr)
	{
		pShellItem->Release();
		pShellItem = nullptr;
	}

	if (pFolderItem != nullptr)
	{
		pFolderItem->Release();
		pFolderItem = nullptr;
	}

	if (pFileOperation != nullptr)
	{
		pFileOperation->Release();
		pFileOperation = nullptr;
	}

	return bRetVal;
}

How to Move/Rename Files in Windows?

C++
bool CFileSystem::MoveFile(CFileSystem* pDestination, CFileList* arrSelection)
{
	bool bRetVal = false;
	HRESULT hResult = S_OK;
	IFileOperation* pFileOperation = nullptr;
	IShellItem* pFolderItem = nullptr;
	IShellItem* pShellItem = nullptr;
	IShellItemArray* pShellItemArray = nullptr;
	CString strDestination = pDestination->GetCurrentFolder();

	ASSERT(pDestination != nullptr);
	ASSERT(arrSelection != nullptr);
	if ((SUCCEEDED(hResult = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOwnerWindow(m_hWndParent))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOperationFlags(FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOFX_SHOWELEVATIONPROMPT))) &&
		(SUCCEEDED(hResult = SHCreateItemFromParsingName(strDestination, nullptr, IID_PPV_ARGS(&pFolderItem)))))
	{
		if (arrSelection->GetCount() == 1)
		{
			CFileData* pFileData = arrSelection->GetAt(0);
			ASSERT_VALID(pFileData);
			CString strFileName = pFileData->GetFileName();
			CString strFolder = GetCurrentFolder();
			CString strFilePath = strFolder + strFileName;

			if ((SUCCEEDED(hResult = SHCreateItemFromParsingName(strFilePath, nullptr, IID_PPV_ARGS(&pShellItem)))) &&
				(SUCCEEDED(hResult = pFileOperation->MoveItem(pShellItem, pFolderItem, nullptr, nullptr))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;

			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::MoveFile"), hResult);
			}
		}
		else
		{
			const int nCount = (int)arrSelection->GetCount();
			LPCITEMIDLIST* arrItemIDList = new LPCITEMIDLIST[nCount];
			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				CFileData* pFileData = arrSelection->GetAt(nIndex);
				ASSERT_VALID(pFileData);
				CString strFileName = pFileData->GetFileName();
				CString strFolder = GetCurrentFolder();
				CString strFilePath = strFolder + strFileName;

				arrItemIDList[nIndex] = ILCreateFromPath(strFilePath);
			}

			if ((SUCCEEDED(hResult = SHCreateShellItemArrayFromIDLists(nCount, arrItemIDList, &pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->MoveItems(pShellItemArray, pFolderItem))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::MoveFile"), hResult);
			}

			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				ILFree((LPITEMIDLIST)arrItemIDList[nIndex]);
			}
			delete arrItemIDList;
			arrItemIDList = nullptr;
		}
	}
	else
	{
		DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::MoveFile"), hResult);
	}

	if (pShellItemArray != nullptr)
	{
		pShellItemArray->Release();
		pShellItemArray = nullptr;
	}

	if (pShellItem != nullptr)
	{
		pShellItem->Release();
		pShellItem = nullptr;
	}

	if (pFolderItem != nullptr)
	{
		pFolderItem->Release();
		pFolderItem = nullptr;
	}

	if (pFileOperation != nullptr)
	{
		pFileOperation->Release();
		pFileOperation = nullptr;
	}

	return bRetVal;
}

How to Delete Files in Windows?

C++
bool CFileSystem::DeleteFile(CFileSystem* pDestination, CFileList* arrSelection)
{
	bool bRetVal = false;
	HRESULT hResult = S_OK;
	IFileOperation* pFileOperation = nullptr;
	IShellItem* pShellItem = nullptr;
	IShellItemArray* pShellItemArray = nullptr;
	CString strDestination = pDestination->GetCurrentFolder();

	ASSERT(pDestination != nullptr);
	ASSERT(arrSelection != nullptr);
	if ((SUCCEEDED(hResult = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOwnerWindow(m_hWndParent))) &&
		(SUCCEEDED(hResult = pFileOperation->SetOperationFlags(FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOFX_SHOWELEVATIONPROMPT))))
	{
		if (arrSelection->GetCount() == 1)
		{
			CFileData* pFileData = arrSelection->GetAt(0);
			ASSERT_VALID(pFileData);
			CString strFileName = pFileData->GetFileName();
			CString strFolder = GetCurrentFolder();
			CString strFilePath = strFolder + strFileName;

			if ((SUCCEEDED(hResult = SHCreateItemFromParsingName(strFilePath, nullptr, IID_PPV_ARGS(&pShellItem)))) &&
				(SUCCEEDED(hResult = pFileOperation->DeleteItem(pShellItem, nullptr))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;

			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::DeleteFile"), hResult);
			}
		}
		else
		{
			const int nCount = (int)arrSelection->GetCount();
			LPCITEMIDLIST* arrItemIDList = new LPCITEMIDLIST[nCount];
			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				CFileData* pFileData = arrSelection->GetAt(nIndex);
				ASSERT_VALID(pFileData);
				CString strFileName = pFileData->GetFileName();
				CString strFolder = GetCurrentFolder();
				CString strFilePath = strFolder + strFileName;

				arrItemIDList[nIndex] = ILCreateFromPath(strFilePath);
			}

			if ((SUCCEEDED(hResult = SHCreateShellItemArrayFromIDLists(nCount, arrItemIDList, &pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->DeleteItems(pShellItemArray))) &&
				(SUCCEEDED(hResult = pFileOperation->PerformOperations())))
			{
				bRetVal = true;
			}
			else
			{
				DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::DeleteFile"), hResult);
			}

			for (int nIndex = 0; nIndex < nCount; nIndex++)
			{
				ILFree((LPITEMIDLIST)arrItemIDList[nIndex]);
			}
			delete arrItemIDList;
			arrItemIDList = nullptr;
		}
	}
	else
	{
		DisplayErrorBox(m_wndCaptionBar, _T("CFileSystem::DeleteFile"), hResult);
	}

	if (pShellItemArray != nullptr)
	{
		pShellItemArray->Release();
		pShellItemArray = nullptr;
	}

	if (pShellItem != nullptr)
	{
		pShellItem->Release();
		pShellItem = nullptr;
	}

	if (pFileOperation != nullptr)
	{
		pFileOperation->Release();
		pFileOperation = nullptr;
	}

	return bRetVal;
}

Final Words

IntelliFile application uses many components that have been published on CodeProject. Many thanks to:

  • My CMFCListView form view (see source code)
  • Armen Hakobyan for his CFolderDialog class
  • Paul DiLascia for his CHtmlCtrl class
  • PJ Naughter for his CInstanceChecker class
  • PJ Naughter for his CVersionInfo class
  • Mizan Rahman for his CWndResizer class

History

  • Version 1.01 (May 13th, 2022): Initial release
  • Version 1.02 (May 20th, 2022): Implemented "New folder" functionality
  • Version 1.03 (May 23rd, 2022): Implemented "Change drive" functionality
  • Version 1.04 (May 24th, 2022): Implemented "View text file" functionality
  • Version 1.05 (May 27th, 2022):
    • Implemented "View RTF file" functionality
    • Implemented "View XML file" functionality
    • Implemented "Context menu" functionality
  • Version 1.06 (August 21st, 2022): Added "Change drive..." icon
  • Version 1.07 (September 9th, 2022): Added Contributors hyperlink to AboutBox dialog
  • Version 1.08 (January 23rd, 2023): Updated PJ Naughter's CVersionInfo library to the latest version available
    Updated the code to use C++ uniform initialization for all variable declarations
  • Version 1.09 (January 24rd, 2023): Updated PJ Naughter's CInstanceChecker library to the latest version available
    Updated the code to use C++ uniform initialization for all variable declarations
  • Replaced NULL throughout the codebase with nullptr
    Replaced BOOL throughout the codebase with bool
    This means that the minimum requirement for the application is now Microsoft Visual C++ 2010.
  • Version 1.10 (April 25th, 2023): Added base64 encode/decode functions
  • Version 1.11 (May 13th, 2023): Added new changes suggested by Rick Dishman: Reset View, and save last folder
  • Version 1.12 (May 15th, 2023): Added rename of file name on clicking its label in MFC ListView
  • Version 1.13 (May 18th, 2023): Fixed an issue regarding editing image files reported by Rick Dishman
  • Version 1.14 (May 19th, 2023): Fixed an issue regarding statusbar reported by Rick Dishman
  • Version 1.15 (May 21st, 2023): Changed the double click implementation to open a file in EDIT mode
  • Version 1.16 (May 27th, 2023): Updated About dialog with GPLv3 notice
  • Version 1.17 (June 17th, 2023): Added quick access dialog for favorite folders
  • Version 1.18 (June 25th, 2023):
    • Implemented "Command prompt" functionality
    • Replaced old CHyperlinkStatic class with PJ Naughter's CHLinkCtrl library
  • Version 1.19 (August 17th, 2023):
    • Implemented "Switch views" functionality (Switches source view with target view)
    • Added social media links: Twitter, LinkedIn, Facebook, and Instagram
    • Added shortcuts to GitHub repository's Issues, Discussions, and Wiki
  • Version 1.20 (August 26th, 2023):
    • Refactored CopyFile, MoveFile and DeleteFile functions
    • Changed article's download link. Updated the About dialog (email & website)
  • Version 1.21 (September 22nd, 2023): Switched to Visual Studio Enterprise 2022 (some changes were made in the source code of the project)
  • Version 1.22 (September 30th, 2023): Added SCINTILLA control to view source code with syntax highlighting
  • Version 1.23 (December 10th, 2023): Updated PJ Naughter's CScintillaCtrl library to the latest version available
    Removed the SetCallDirect & GetCallDirect methods. Instead, now the CScintillaCtrl class will call the m_DirectStatusFunction if the calling thread is the same as the thread on which the Scintilla control was created. Thanks to Markus Nissl for this update.
  • Version 1.24 (December 29th, 2023): Updated PJ Naughter's CScintillaCtrl library to the latest version available
    Updated class to work with Scintilla v5.4.1. New messages wrapped include: SCI_CHANGESELECTIONMODE, SCI_SETMOVEEXTENDSSELECTION & SCI_SELECTIONFROMPOINT. Also updated the signatures of the following methods: GetDocPointer, SetDocPointer, CreateDocument, AddRefDocument and ReleaseDocument.
  • Version 1.25 (January 28th, 2024):
    • Added ReleaseNotes.html and SoftwareContentRegister.html to GitHub repo
    • Replaced old CFileDialogST class with Armen Hakobyan's CFolderDialog library
  • Version 1.26 (February 21st, 2024): Switched MFC application' theme back to native Windows.
  • Version 1.27.1 (March 31st, 2024):
    • Updated LEXILLA library to version 5.3.1 and SCINTILLA library to version 5.4.3.
    • Updated PJ Naughter's CScintillaCtrl library to the latest version available.
      Updated class to work with Scintilla v5.4.3. New messages wrapped include: SCI_GETUNDOACTIONS, SCI_GETUNDOSAVEPOINT, SCI_SETUNDODETACH, SCI_SETUNDOTENTATIVE, SCI_SETUNDOCURRENT, SCI_PUSHUNDOACTIONTYPE, SCI_CHANGELASTUNDOACTIONTEXT, SCI_GETUNDOACTIONTYPE, SCI_GETUNDOACTIONPOSITION & SCI_GETUNDOACTIONTEXT.
  • Version 1.28 (April 26th, 2024):
    • Updated LEXILLA library to version 5.3.2 and SCINTILLA library to version 5.5.0.
    • Updated PJ Naughter's CScintillaCtrl library to the latest version available.
  • Version 1.29 (July 21st, 2024):
    • Implemented "View text file" functionality for C/C++ programming language.
    • Implemented selection of files with specific search pattern, size, date or contents.
    • Implemented enhanced search function with full text search & replace.
  • Version 1.30 (July 26th, 2024):
    • Implemented "View text file" functionality for HTML / CSS / XML / JavaScript.
    • Implemented "View text file" functionality for Java programming language.
    • Implemented "View text file" functionality for Python programming language.
    • Updated LEXILLA library to version 5.3.3 and SCINTILLA library to version 5.5.1.
    • Updated PJ Naughter's CScintillaCtrl library to the latest version available.
      Updated class to work with Scintilla v5.5.1. New messages wrapped include: SCI_AUTOCSETSTYLE, SCI_AUTOCGETSTYLE & SCI_CUTALLOWLINE.
  • Version 1.31 (August 24th, 2024):
    • Updated LEXILLA library to version 5.4.0 and SCINTILLA library to version 5.5.2.
    • Updated PJ Naughter's CScintillaCtrl library to the latest version available.
      Updated class to work with Scintilla v5.5.2. New messages wrapped include: SCI_STYLESETSTRETCH, SCI_STYLEGETSTRETCH, SCI_GETUNDOSEQUENCE, SCI_LINEINDENT, SCI_LINEDEDENT, SCI_SETCOPYSEPARATOR & SCI_GETCOPYSEPARATOR.
  • Version 1.32 (September 3rd, 2024):
    • Enabled syntax highlighting for the following Programming Languages:
      • Bash
      • Batch
      • CMake
      • Groovy
      • JavaScript
      • JSON
      • Makefile
      • MATLAB
      • R
      • Rust
    • Implemented User Manual option into Help menu.
    • Implemented Check for updates... option into Help menu.
  • Version 1.33 (September 14th, 2024): Implemented "View binary file" functionality using Jovibor's HexCtrl library.
  • Version 1.34 (October 11th, 2024):
    • Fixed access to Google Drive (bug reported by simon mago).
    • Fixed access to Favorite Folders (bug reported by markjuggles).
    • Fixed a situation when viewing a text file would result in a crash.
    • Enabled syntax highlighting for TCL/TK Programming Language.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)