Olav SørensenPushed v1.66 codef56d9f63 years agoHistory
2540 lines · 55.4 KB · C
RawDownload
// for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #define _FILE_OFFSET_BITS 64 #include <stdint.h>#include <stdio.h>#include <math.h>#ifdef _WIN32#define WIN32_MEAN_AND_LEAN#include <shlwapi.h>#include <windows.h>#include <direct.h>#include <shlobj.h> // SHGetFolderPathW()#else#include <sys/types.h>#include <sys/stat.h>#include <fts.h> // for fts_open() and stuff in recursiveDelete()#include <unistd.h>#include <dirent.h>#endif#include <wchar.h>#include <sys/stat.h>#include "ft2_header.h"#include "ft2_unicode.h"#include "ft2_config.h"#include "ft2_mouse.h"#include "ft2_gui.h"#include "ft2_pattern_ed.h"#include "ft2_sample_loader.h"#include "ft2_sample_saver.h"#include "ft2_diskop.h"#include "ft2_wav_renderer.h"#include "ft2_module_loader.h"#include "ft2_module_saver.h"#include "ft2_events.h"#include "ft2_video.h"#include "ft2_inst_ed.h"#include "ft2_structs.h" // hide POSIX warnings for chdir()#ifdef _MSC_VER#pragma warning(disable: 4996)#endif #define FILENAME_TEXT_X 170#define FILESIZE_TEXT_X 295#define DISKOP_MAX_DRIVE_BUTTONS 8 #ifdef _WIN32#define PARENT_DIR_STR L".."static HANDLE hFind;#else#define PARENT_DIR_STR ".."static DIR *hFind;#endif // "look for file" flagsenum{	LFF_DONE = 0,	LFF_SKIP = 1,	LFF_OK = 2}; typedef struct DirRec{	UNICHAR *nameU;	bool isDir;	int32_t filesize;} DirRec; static char FReq_SysReqText[256], *FReq_FileName, *FReq_NameTemp;static char *modTmpFName, *insTmpFName, *smpTmpFName, *patTmpFName, *trkTmpFName;static char *modTmpFNameUTF8; // for window titlestatic uint8_t FReq_Item;static bool FReq_ShowAllFiles, insPathSet, smpPathSet, patPathSet, trkPathSet, firstTimeOpeningDiskOp = true;static int32_t FReq_EntrySelected = -1, FReq_FileCount, FReq_DirPos, lastMouseY;static UNICHAR *FReq_CurPathU, *FReq_ModCurPathU, *FReq_InsCurPathU, *FReq_SmpCurPathU, *FReq_PatCurPathU, *FReq_TrkCurPathU;static DirRec *FReq_Buffer;static SDL_Thread *thread; static void setDiskOpItem(uint8_t item); bool setupExecutablePath(void){	editor.binaryPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));	if (editor.binaryPathU == NULL)	{		showErrorMsgBox("Not enough memory!");		return false;	} 	editor.binaryPathU[0] = 0;	UNICHAR_GETCWD(editor.binaryPathU, PATH_MAX); 	return true;} int32_t getFileSize(UNICHAR *fileNameU) // returning -1 = filesize over 2GB{	int64_t fSize; #ifdef _WIN32	FILE *f = UNICHAR_FOPEN(fileNameU, "rb");	if (f == NULL)		return 0; 	_fseeki64(f, 0, SEEK_END);	fSize = _ftelli64(f);	fclose(f);#else	struct stat st;	if (stat(fileNameU, &st) != 0)		return 0; 	fSize = (int64_t)st.st_size;#endif	if (fSize < 0)		fSize = 0; 	if (fSize > INT32_MAX)		return -1; // -1 = ">2GB" flag		return (int32_t)fSize;} uint8_t getDiskOpItem(void){	return FReq_Item;} char *getCurrSongFilename(void) // for window title{	return modTmpFNameUTF8;} void updateCurrSongFilename(void) // for window title{	if (modTmpFNameUTF8 != NULL)	{		free(modTmpFNameUTF8);		modTmpFNameUTF8 = NULL;	} 	if (modTmpFName == NULL)		return; 	modTmpFNameUTF8 = cp437ToUtf8(modTmpFName);} // drive buttons for Windows#ifdef _WIN32static char logicalDriveNames[26][3] = {	"A:", "B:", "C:", "D:", "E:", "F:", "G:", "H:", "I:", "J:", "K:", "L:", "M:",	"N:", "O:", "P:", "Q:", "R:", "S:", "T:", "U:", "V:", "W:", "X:", "Y:", "Z:"};static uint32_t numLogicalDrives;static uint32_t driveIndexes[DISKOP_MAX_DRIVE_BUTTONS];#endif char *getDiskOpFilename(void){	return FReq_FileName;} const UNICHAR *getDiskOpCurPath(void){	return FReq_CurPathU;} const UNICHAR *getDiskOpModPath(void){	return FReq_ModCurPathU;} const UNICHAR *getDiskOpSmpPath(void){	return FReq_SmpCurPathU;} static void setupInitialPaths(void){	// the UNICHAR paths are already zeroed out #ifdef _WIN32	if (config.modulesPath[0] != '\0')	{		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.modulesPath, -1, FReq_ModCurPathU, 80);		FReq_ModCurPathU[80] = 0;	} 	if (config.instrPath[0] != '\0')	{		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.instrPath, -1, FReq_InsCurPathU, 80);		FReq_InsCurPathU[80] = 0;		insPathSet = true;	} 	if (config.samplesPath[0] != '\0')	{		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.samplesPath, -1, FReq_SmpCurPathU, 80);		FReq_SmpCurPathU[80] = 0;		smpPathSet = true;	} 	if (config.patternsPath[0] != '\0')	{		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.patternsPath, -1, FReq_PatCurPathU, 80);		FReq_PatCurPathU[80] = 0;		patPathSet = true;	} 	if (config.tracksPath[0] != '\0')	{		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.tracksPath, -1, FReq_TrkCurPathU, 80);		FReq_TrkCurPathU[80] = 0;		trkPathSet = true;	}#else	if (config.modulesPath[0] != '\0')	{		strncpy(FReq_ModCurPathU, config.modulesPath, 80);		FReq_ModCurPathU[80] = 0;	} 	if (config.instrPath[0] != '\0')	{		strncpy(FReq_InsCurPathU, config.instrPath, 80);		FReq_InsCurPathU[80] = 0;		insPathSet = true;	} 	if (config.samplesPath[0] != '\0')	{		strncpy(FReq_SmpCurPathU, config.samplesPath, 80);		FReq_SmpCurPathU[80] = 0;		smpPathSet = true;	} 	if (config.patternsPath[0] != '\0')	{		strncpy(FReq_PatCurPathU, config.patternsPath, 80);		FReq_PatCurPathU[80] = 0;		patPathSet = true;	} 	if (config.tracksPath[0] != '\0')	{		strncpy(FReq_TrkCurPathU, config.tracksPath, 80);		FReq_TrkCurPathU[80] = 0;		trkPathSet = true;	}#endif} static void freeDirRecBuffer(void){	if (FReq_Buffer != NULL)	{		for (int32_t i = 0; i < FReq_FileCount; i++)		{			if (FReq_Buffer[i].nameU != NULL)				free(FReq_Buffer[i].nameU);		} 		free(FReq_Buffer);		FReq_Buffer = NULL;	} 	FReq_FileCount = 0;} void freeDiskOp(void){	if (editor.tmpFilenameU != NULL)	{		free(editor.tmpFilenameU);		editor.tmpFilenameU = NULL;	} 	if (editor.tmpInstrFilenameU != NULL)	{		free(editor.tmpInstrFilenameU);		editor.tmpInstrFilenameU = NULL;	} 	if (modTmpFName != NULL) { free(modTmpFName); modTmpFName = NULL; }	if (insTmpFName != NULL) { free(insTmpFName); insTmpFName = NULL; }	if (smpTmpFName != NULL) { free(smpTmpFName); smpTmpFName = NULL; }	if (patTmpFName != NULL) { free(patTmpFName); patTmpFName = NULL; }	if (trkTmpFName != NULL) { free(trkTmpFName); trkTmpFName = NULL; }	if (FReq_NameTemp != NULL) { free(FReq_NameTemp); FReq_NameTemp = NULL; }	if (FReq_ModCurPathU != NULL) { free(FReq_ModCurPathU); FReq_ModCurPathU = NULL; }	if (FReq_InsCurPathU != NULL) { free(FReq_InsCurPathU); FReq_InsCurPathU = NULL; }	if (FReq_SmpCurPathU != NULL) { free(FReq_SmpCurPathU); FReq_SmpCurPathU = NULL; }	if (FReq_PatCurPathU != NULL) { free(FReq_PatCurPathU); FReq_PatCurPathU = NULL; }	if (FReq_TrkCurPathU != NULL) { free(FReq_TrkCurPathU); FReq_TrkCurPathU = NULL; }	if (modTmpFNameUTF8 != NULL) { free(modTmpFNameUTF8); modTmpFNameUTF8 = NULL; } 	freeDirRecBuffer();} bool setupDiskOp(void){	modTmpFName = (char *)malloc((PATH_MAX + 1) * sizeof (char));	insTmpFName = (char *)malloc((PATH_MAX + 1) * sizeof (char));	smpTmpFName = (char *)malloc((PATH_MAX + 1) * sizeof (char));	patTmpFName = (char *)malloc((PATH_MAX + 1) * sizeof (char));	trkTmpFName = (char *)malloc((PATH_MAX + 1) * sizeof (char));	FReq_NameTemp = (char *)malloc((PATH_MAX + 1) * sizeof (char)); 	FReq_ModCurPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));	FReq_InsCurPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));	FReq_SmpCurPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));	FReq_PatCurPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));	FReq_TrkCurPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR)); 	if (modTmpFName      == NULL || insTmpFName      == NULL || smpTmpFName      == NULL ||		patTmpFName      == NULL || trkTmpFName      == NULL || FReq_NameTemp    == NULL ||		FReq_ModCurPathU == NULL || FReq_InsCurPathU == NULL || FReq_SmpCurPathU == NULL ||		FReq_PatCurPathU == NULL || FReq_TrkCurPathU == NULL)	{		// allocated memory is free'd lateron		showErrorMsgBox("Not enough memory!");		return false;	} 	// clear first entry of strings	modTmpFName[0] = '\0';	insTmpFName[0] = '\0';	smpTmpFName[0] = '\0';	patTmpFName[0] = '\0';	trkTmpFName[0] = '\0';	FReq_NameTemp[0] = '\0';	FReq_ModCurPathU[0] = 0;	FReq_InsCurPathU[0] = 0;	FReq_SmpCurPathU[0] = 0;	FReq_PatCurPathU[0] = 0;	FReq_TrkCurPathU[0] = 0; 	strcpy(modTmpFName, "untitled.xm");	strcpy(insTmpFName, "untitled.xi");	strcpy(smpTmpFName, "untitled.wav");	strcpy(patTmpFName, "untitled.xp");	strcpy(trkTmpFName, "untitled.xt"); 	setupInitialPaths();	setDiskOpItem(0); 	updateCurrSongFilename(); // for window title	updateWindowTitle(true); 	return true;} int32_t getExtOffset(char *s, int32_t stringLen) // get byte offset of file extension (last '.'){	if (s == NULL || stringLen < 1)		return -1; 	for (int32_t i = stringLen - 1; i >= 0; i--)	{		if (i != 0 && s[i] == '.')			return i;	} 	return -1;} static void removeQuestionmarksFromString(char *s){	if (s == NULL || *s == '\0')		return; 	const int32_t len = (int32_t)strlen(s);	for (int32_t i = 0; i < len; i++)	{		if (s[i] == '?')			s[i] = ' ' ;	}} #ifdef _WIN32 // WINDOWS SPECIFIC FILE OPERATION ROUTINES bool fileExistsAnsi(char *str){	UNICHAR *strU = cp437ToUnichar(str);	if (strU == NULL)		return false; 	bool retVal = PathFileExistsW(strU);	free(strU); 	return retVal;} static bool deleteDirRecursive(UNICHAR *strU){	SHFILEOPSTRUCTW shfo; 	memset(&shfo, 0, sizeof (shfo));	shfo.wFunc = FO_DELETE;	shfo.fFlags = FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION;	shfo.pFrom = strU; 	return (SHFileOperationW(&shfo) == 0);} static bool makeDirAnsi(char *str){	UNICHAR *strU = cp437ToUnichar(str);	if (strU == NULL)		return false; 	int32_t retVal = _wmkdir(strU);	free(strU); 	return (retVal == 0);} static bool renameAnsi(UNICHAR *oldNameU, char *newName){	UNICHAR *newNameU = cp437ToUnichar(newName);	if (newNameU == NULL)		return false; 	int32_t retVal = UNICHAR_RENAME(oldNameU, newNameU);	free(newNameU); 	return (retVal == 0);} static void setupDiskOpDrives(void) // Windows only{	fillRect(134, 29, 31, 111, PAL_DESKTOP);	numLogicalDrives = 0; 	// get number of drives and drive names	const uint32_t drivesBitmask = GetLogicalDrives();	for (int32_t i = 0; i < 8*sizeof (uint32_t); i++)	{		if ((drivesBitmask & (1 << i)) != 0)		{			driveIndexes[numLogicalDrives++] = i;			if (numLogicalDrives == DISKOP_MAX_DRIVE_BUTTONS)				break;		}	} 	// hide all buttons	for (uint16_t i = 0; i < DISKOP_MAX_DRIVE_BUTTONS; i++)		hidePushButton(PB_DISKOP_DRIVE1 + i); 	// set button names and show buttons	for (uint16_t i = 0; i < numLogicalDrives; i++)	{		pushButtons[PB_DISKOP_DRIVE1 + i].caption = logicalDriveNames[driveIndexes[i]];		showPushButton(PB_DISKOP_DRIVE1 + i);	}} static void openDrive(char *str) // Windows only{	if (mouse.mode == MOUSE_MODE_DELETE)	{		okBox(8, "System complaint", "Very funny.");		return;	} 	if (str == NULL || *str == '\0')	{		okBox(0, "System message", "Couldn't open drive!");		return;	} 	if (chdir(str) != 0)		okBox(0, "System message", "Couldn't open drive! Please make sure there's a disk in it.");	else		editor.diskOpReadDir = true;} #else // NON-WINDOWS SPECIFIC FILE OPERATION ROUTINES bool fileExistsAnsi(char *str){	UNICHAR *strU = cp437ToUnichar(str);	if (strU == NULL)		return false; 	int32_t retVal = access(strU, F_OK);	free(strU); 	return (retVal != -1);} static bool deleteDirRecursive(UNICHAR *strU)

Lines 1–500 of 2540.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t