ref: 8af2e42736b61a36a0d54bede93a47a1bab35f5d
parent: 6a594c824f0e29689297d1347faebaf451a1f382
author: Olav Sørensen <[email protected]>
date: Thu Apr 1 14:11:50 EDT 2021
Pushed v1.45 code - Fixed possible crash when starting the program on M1 Macs (thanks kode54) - Fixed possible mouse cursor corruption when hovering over text boxes on Linux - Fixed possibly buggy string operations - Refactored some code that was doing unnecessary/wrong stuff - Minor code cleanup - Updated help text
--- a/src/ft2_audio.c
+++ b/src/ft2_audio.c
@@ -20,6 +20,11 @@
#include "mixer/ft2_silence_mix.h"
// --------------------------------
+// hide POSIX warnings
+#ifdef _MSC_VER
+#pragma warning(disable: 4996)
+#endif
+
#define INITIAL_DITHER_SEED 0x12345000
static int8_t pmpCountDiv, pmpChannels = 2;
@@ -87,14 +92,7 @@
audio.currOutputDevice = NULL;
}
- const uint32_t stringLen = (uint32_t)strlen(audio.lastWorkingAudioDeviceName);
-
- audio.currOutputDevice = (char *)malloc(stringLen + 2);
- if (audio.currOutputDevice != NULL)
- {
- strcpy(audio.currOutputDevice, audio.lastWorkingAudioDeviceName);
- audio.currOutputDevice[stringLen + 1] = '\0'; // UTF-8 needs double null termination
- }
+ audio.currOutputDevice = strdup(audio.lastWorkingAudioDeviceName);
}
// also update config audio radio buttons if we're on that screen at the moment
@@ -1050,17 +1048,7 @@
}
if (audio.currOutputDevice != NULL)
- {
- const uint32_t stringLen = (uint32_t)strlen(audio.currOutputDevice);
-
- audio.lastWorkingAudioDeviceName = (char *)malloc(stringLen + 2);
- if (audio.lastWorkingAudioDeviceName != NULL)
- {
- if (stringLen > 0)
- strcpy(audio.lastWorkingAudioDeviceName, audio.currOutputDevice);
- audio.lastWorkingAudioDeviceName[stringLen + 1] = '\0'; // UTF-8 needs double null termination
- }
- }
+ audio.lastWorkingAudioDeviceName = strdup(audio.currOutputDevice);
}
bool setupAudio(bool showErrorMsg)
--- a/src/ft2_audioselector.c
+++ b/src/ft2_audioselector.c
@@ -13,53 +13,75 @@
#include "ft2_audioselector.h"
#include "ft2_structs.h"
-char *getAudioOutputDeviceFromConfig(void)
+enum
{
+ INPUT_DEVICE = 0,
+ OUTPUT_DEVICE = 1
+};
+
#define MAX_DEV_STR_LEN 256
- char *devString = (char *)calloc(MAX_DEV_STR_LEN + 1, sizeof (char));
- if (devString == NULL)
+// hide POSIX warnings
+#ifdef _MSC_VER
+#pragma warning(disable: 4996)
+#endif
+
+static char *getReasonableAudioDevice(int32_t iscapture) // can and will return NULL
+{
+ int32_t numAudioDevs = SDL_GetNumAudioDevices(iscapture);
+ if (numAudioDevs == 0 || numAudioDevs > 1)
+ return NULL; // we don't know which audio output device is the default device
+
+ const char *devName = SDL_GetAudioDeviceName(0, iscapture);
+ if (devName == NULL)
return NULL;
- FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocation, "r");
- if (f == NULL)
+ return strdup(devName);
+}
+
+char *getAudioOutputDeviceFromConfig(void)
+{
+ bool audioDeviceRead = false;
+ char *devString = NULL;
+
+ FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocationU, "r");
+ if (f != NULL)
{
-#if defined(__APPLE__)
- return NULL; // SDL doesn't return devices in any appreciable order, and device 0 is most certainly not guaranteed to be the current default device
-#else
- const char *devStringTmp = SDL_GetAudioDeviceName(0, false);
- if (devStringTmp == NULL)
+ devString = (char *)malloc(MAX_DEV_STR_LEN+1);
+ if (devString == NULL)
{
- free(devString);
- return NULL;
+ fclose(f);
+ return NULL; // out of memory
}
- const uint32_t devStringLen = (uint32_t)strlen(devStringTmp);
+ devString[0] = '\0';
+ fgets(devString, MAX_DEV_STR_LEN, f);
+ fclose(f);
+
+ const int32_t devStringLen = (int32_t)strlen(devString);
if (devStringLen > 0)
- strncpy(devString, devStringTmp, MAX_DEV_STR_LEN);
- devString[devStringLen+1] = '\0'; // UTF-8 needs double null termination
-#endif
+ {
+ if (devString[devStringLen-1] == '\n')
+ devString[devStringLen-1] = ' ';
+
+ if (!(devStringLen == 1 && devString[0] == ' ')) // space only = no device
+ audioDeviceRead = true;
+ }
}
- else
+
+ if (!audioDeviceRead)
{
- if (fgets(devString, MAX_DEV_STR_LEN, f) == NULL)
- {
+ if (devString != NULL)
free(devString);
- fclose(f);
- return NULL;
- }
- const uint32_t devStringLen = (uint32_t)strlen(devString);
- if (devString[devStringLen-1] == '\n')
- devString[devStringLen-1] = '\0';
- devString[devStringLen+1] = '\0'; // UTF-8 needs double null termination
+ devString = getReasonableAudioDevice(OUTPUT_DEVICE);
+ }
-#if defined(__APPLE__)
- if (devString[0] == '\0')
- return NULL; // macOS SDL2 locks up indefinitely if fed an empty string for device name
-#endif
-
- fclose(f);
+ // SDL_OpenAudioDevice() doesn't seem to like an empty audio device string
+ if (devString != NULL && devString[0] == '\0')
+ {
+ free(devString);
+ return NULL;
}
return devString;
@@ -67,50 +89,48 @@
char *getAudioInputDeviceFromConfig(void)
{
-#define MAX_DEV_STR_LEN 256
+ bool audioDeviceRead = false;
+ char *devString = NULL;
- char *devString = (char *)calloc(MAX_DEV_STR_LEN + 1, sizeof (char));
- if (devString == NULL)
- return NULL;
-
- FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocation, "r");
- if (f == NULL)
+ FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocationU, "r");
+ if (f != NULL)
{
- const char *devStringTmp = SDL_GetAudioDeviceName(0, true);
- if (devStringTmp == NULL)
+ devString = (char *)malloc(MAX_DEV_STR_LEN+1);
+ if (devString == NULL)
{
- free(devString);
- return NULL;
+ fclose(f);
+ return NULL; // out of memory
}
- const uint32_t devStringLen = (uint32_t)strlen(devStringTmp);
+ devString[0] = '\0';
+ fgets(devString, MAX_DEV_STR_LEN, f); // skip first line (we want the input device)
+ fgets(devString, MAX_DEV_STR_LEN, f);
+ fclose(f);
+
+ const int32_t devStringLen = (int32_t)strlen(devString);
if (devStringLen > 0)
- strncpy(devString, devStringTmp, MAX_DEV_STR_LEN);
- devString[devStringLen+1] = '\0'; // UTF-8 needs double null termination
- }
- else
- {
- if (fgets(devString, MAX_DEV_STR_LEN, f) == NULL)
{
- free(devString);
- fclose(f);
- return NULL;
+ if (devString[devStringLen-1] == '\n')
+ devString[devStringLen-1] = ' ';
+
+ if (!(devStringLen == 1 && devString[0] == ' ')) // space only = no device
+ audioDeviceRead = true;
}
+ }
- // do it one more time (next line)
- if (fgets(devString, MAX_DEV_STR_LEN, f) == NULL)
- {
+ if (!audioDeviceRead)
+ {
+ if (devString != NULL)
free(devString);
- fclose(f);
- return NULL;
- }
- const uint32_t devStringLen = (uint32_t)strlen(devString);
- if (devString[devStringLen-1] == '\n')
- devString[devStringLen-1] = '\0';
- devString[devStringLen+1] = '\0'; // UTF-8 needs double null termination
+ devString = getReasonableAudioDevice(INPUT_DEVICE);
+ }
- fclose(f);
+ // SDL_OpenAudioDevice() doesn't seem to like an empty audio device string
+ if (devString != NULL && devString[0] == '\0')
+ {
+ free(devString);
+ return NULL;
}
return devString;
@@ -118,15 +138,21 @@
bool saveAudioDevicesToConfig(const char *outputDevice, const char *inputDevice)
{
- FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocation, "w");
+ FILE *f = UNICHAR_FOPEN(editor.audioDevConfigFileLocationU, "w");
if (f == NULL)
return false;
if (outputDevice != NULL)
fputs(outputDevice, f);
+ else
+ fputc(' ', f);
+
fputc('\n', f);
+
if (inputDevice != NULL)
fputs(inputDevice, f);
+ else
+ fputc(' ', f);
fclose(f);
return true;
@@ -231,13 +257,14 @@
const uint32_t devStringLen = (uint32_t)strlen(devString);
- audio.currOutputDevice = (char *)malloc(devStringLen + 2);
+ audio.currOutputDevice = (char *)malloc(devStringLen+1);
if (audio.currOutputDevice == NULL)
return true;
+ audio.currOutputDevice[0] = '\0';
+
if (devStringLen > 0)
strcpy(audio.currOutputDevice, devString);
- audio.currOutputDevice[devStringLen+1] = '\0'; // UTF-8 needs double null termination
if (!setNewAudioSettings())
okBox(0, "System message", "Couldn't open audio input device!");
@@ -263,13 +290,14 @@
const uint32_t devStringLen = (uint32_t)strlen(devString);
- audio.currInputDevice = (char *)malloc(devStringLen + 2);
+ audio.currInputDevice = (char *)malloc(devStringLen+1);
if (audio.currInputDevice == NULL)
return true;
+ audio.currInputDevice[0] = '\0';
+
if (devStringLen > 0)
strcpy(audio.currInputDevice, devString);
- audio.currInputDevice[devStringLen+1] = '\0'; // UTF-8 needs double null termination
drawAudioInputList();
}
@@ -303,10 +331,10 @@
void freeAudioDeviceSelectorBuffers(void)
{
- if (editor.audioDevConfigFileLocation != NULL)
+ if (editor.audioDevConfigFileLocationU != NULL)
{
- free(editor.audioDevConfigFileLocation);
- editor.audioDevConfigFileLocation = NULL;
+ free(editor.audioDevConfigFileLocationU);
+ editor.audioDevConfigFileLocationU = NULL;
}
if (audio.currOutputDevice != NULL)
@@ -352,14 +380,12 @@
audio.currOutputDevice = NULL;
}
- audio.currOutputDevice = (char *)malloc(stringLen + 2);
+ audio.currOutputDevice = (char *)malloc(stringLen + 1);
if (audio.currOutputDevice == NULL)
return;
if (stringLen > 0)
strcpy(audio.currOutputDevice, devString);
-
- audio.currOutputDevice[stringLen+1] = '\0'; // UTF-8 needs double null termination
}
void setToDefaultAudioInputDevice(void)
@@ -384,14 +410,12 @@
audio.currInputDevice = NULL;
}
- audio.currInputDevice = (char *)malloc(stringLen + 2);
+ audio.currInputDevice = (char *)malloc(stringLen + 1);
if (audio.currInputDevice == NULL)
return;
if (stringLen > 0)
strcpy(audio.currInputDevice, devString);
-
- audio.currInputDevice[stringLen+1] = '\0'; // UTF-8 needs double null termination
}
void rescanAudioDevices(void)
@@ -417,14 +441,12 @@
const uint32_t stringLen = (uint32_t)strlen(deviceName);
- audio.outputDeviceNames[i] = (char *)malloc(stringLen + 2);
+ audio.outputDeviceNames[i] = (char *)malloc(stringLen + 1);
if (audio.outputDeviceNames[i] == NULL)
break;
if (stringLen > 0)
strcpy(audio.outputDeviceNames[i], deviceName);
-
- audio.outputDeviceNames[i][stringLen+1] = '\0'; // UTF-8 needs double null termination
}
// GET AUDIO INPUT DEVICES
@@ -444,14 +466,12 @@
const uint32_t stringLen = (uint32_t)strlen(deviceName);
- audio.inputDeviceNames[i] = (char *)malloc(stringLen + 2);
+ audio.inputDeviceNames[i] = (char *)malloc(stringLen + 1);
if (audio.inputDeviceNames[i] == NULL)
break;
if (stringLen > 0)
strcpy(audio.inputDeviceNames[i], deviceName);
-
- audio.inputDeviceNames[i][stringLen+1] = '\0'; // UTF-8 needs double null termination
}
setScrollBarEnd(SB_AUDIO_OUTPUT_SCROLL, audio.outputDeviceNum);
--- a/src/ft2_config.c
+++ b/src/ft2_config.c
@@ -264,7 +264,7 @@
}
#endif
- if (editor.configFileLocation == NULL)
+ if (editor.configFileLocationU == NULL)
{
if (showErrorFlag)
okBox(0, "System message", "Error opening config file for reading!");
@@ -272,7 +272,7 @@
return false;
}
- FILE *f = UNICHAR_FOPEN(editor.configFileLocation, "rb");
+ FILE *f = UNICHAR_FOPEN(editor.configFileLocationU, "rb");
if (f == NULL)
{
if (showErrorFlag)
@@ -353,7 +353,7 @@
bool saveConfig(bool showErrorFlag)
{
- if (editor.configFileLocation == NULL)
+ if (editor.configFileLocationU == NULL)
{
if (showErrorFlag)
okBox(0, "System message", "General I/O error during saving! Is the file in use?");
@@ -366,7 +366,7 @@
saveMidiInputDeviceToConfig();
#endif
- FILE *f = UNICHAR_FOPEN(editor.configFileLocation, "wb");
+ FILE *f = UNICHAR_FOPEN(editor.configFileLocationU, "wb");
if (f == NULL)
{
if (showErrorFlag)
@@ -410,14 +410,14 @@
saveConfig(CONFIG_SHOW_ERRORS);
}
-static UNICHAR *getFullAudDevConfigPath(void) // kinda hackish
+static UNICHAR *getFullAudDevConfigPathU(void) // kinda hackish
{
int32_t audiodevDotIniStrLen, ft2DotCfgStrLen;
- if (editor.configFileLocation == NULL)
+ if (editor.configFileLocationU == NULL)
return NULL;
- const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocation);
+ const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocationU);
#ifdef _WIN32
audiodevDotIniStrLen = (int32_t)UNICHAR_STRLEN(L"audiodev.ini");
@@ -427,31 +427,29 @@
ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG");
#endif
- UNICHAR *filePath = (UNICHAR *)calloc(ft2ConfPathLen + audiodevDotIniStrLen + 2, sizeof (UNICHAR));
+ UNICHAR *filePathU = (UNICHAR *)malloc((ft2ConfPathLen + audiodevDotIniStrLen + 1) * sizeof (UNICHAR));
+ filePathU[0] = 0;
- UNICHAR_STRCPY(filePath, editor.configFileLocation);
+ UNICHAR_STRCPY(filePathU, editor.configFileLocationU);
+ filePathU[ft2ConfPathLen-ft2DotCfgStrLen] = 0;
- const int32_t stringOffset = ft2ConfPathLen - ft2DotCfgStrLen;
- filePath[stringOffset+0] = '\0';
- filePath[stringOffset+1] = '\0';
-
#ifdef _WIN32
- UNICHAR_STRCAT(filePath, L"audiodev.ini");
+ UNICHAR_STRCAT(filePathU, L"audiodev.ini");
#else
- UNICHAR_STRCAT(filePath, "audiodev.ini");
+ UNICHAR_STRCAT(filePathU, "audiodev.ini");
#endif
- return filePath;
+ return filePathU;
}
-static UNICHAR *getFullMidiDevConfigPath(void) // kinda hackish
+static UNICHAR *getFullMidiDevConfigPathU(void) // kinda hackish
{
int32_t mididevDotIniStrLen, ft2DotCfgStrLen;
- if (editor.configFileLocation == NULL)
+ if (editor.configFileLocationU == NULL)
return NULL;
- const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocation);
+ const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocationU);
#ifdef _WIN32
mididevDotIniStrLen = (int32_t)UNICHAR_STRLEN(L"mididev.ini");
@@ -461,21 +459,19 @@
ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG");
#endif
- UNICHAR *filePath = (UNICHAR *)calloc(ft2ConfPathLen + mididevDotIniStrLen + 2, sizeof (UNICHAR));
+ UNICHAR *filePathU = (UNICHAR *)malloc((ft2ConfPathLen + mididevDotIniStrLen + 1) * sizeof (UNICHAR));
+ filePathU[0] = 0;
- UNICHAR_STRCPY(filePath, editor.configFileLocation);
+ UNICHAR_STRCPY(filePathU, editor.configFileLocationU);
+ filePathU[ft2ConfPathLen-ft2DotCfgStrLen] = 0;
- const int32_t stringOffset = ft2ConfPathLen - ft2DotCfgStrLen;
- filePath[stringOffset+0] = '\0';
- filePath[stringOffset+1] = '\0';
-
#ifdef _WIN32
- UNICHAR_STRCAT(filePath, L"mididev.ini");
+ UNICHAR_STRCAT(filePathU, L"mididev.ini");
#else
- UNICHAR_STRCAT(filePath, "mididev.ini");
+ UNICHAR_STRCAT(filePathU, "mididev.ini");
#endif
- return filePath;
+ return filePathU;
}
static void setConfigFileLocation(void) // kinda hackish
@@ -484,41 +480,44 @@
#ifdef _WIN32
int32_t ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN(L"FT2.CFG");
- UNICHAR *oldPath = (UNICHAR *)calloc(PATH_MAX + 8 + 2, sizeof (UNICHAR));
- UNICHAR *tmpPath = (UNICHAR *)calloc(PATH_MAX + 8 + 2, sizeof (UNICHAR));
- editor.configFileLocation = (UNICHAR *)calloc(PATH_MAX + ft2DotCfgStrLen + 2, sizeof (UNICHAR));
+ UNICHAR *oldPathU = (UNICHAR *)malloc((PATH_MAX + 8 + 1) * sizeof (UNICHAR));
+ UNICHAR *tmpPathU = (UNICHAR *)malloc((PATH_MAX + 8 + 1) * sizeof (UNICHAR));
+ editor.configFileLocationU = (UNICHAR *)malloc((PATH_MAX + ft2DotCfgStrLen + 1) * sizeof (UNICHAR));
- if (oldPath == NULL || tmpPath == NULL || editor.configFileLocation == NULL)
+ if (oldPathU == NULL || tmpPathU == NULL || editor.configFileLocationU == NULL)
{
- if (oldPath != NULL) free(oldPath);
- if (tmpPath != NULL) free(tmpPath);
- if (editor.configFileLocation != NULL) free(editor.configFileLocation);
+ if (oldPathU != NULL) free(oldPathU);
+ if (tmpPathU != NULL) free(tmpPathU);
+ if (editor.configFileLocationU != NULL) free(editor.configFileLocationU);
- editor.configFileLocation = NULL;
+ editor.configFileLocationU = NULL;
showErrorMsgBox("Error: Couldn't set config file location. You can't load/save the config!");
return;
}
- if (GetCurrentDirectoryW(PATH_MAX - ft2DotCfgStrLen - 1, oldPath) == 0)
+ oldPathU[0] = 0;
+ tmpPathU[0] = 0;
+
+ if (GetCurrentDirectoryW(PATH_MAX - ft2DotCfgStrLen - 1, oldPathU) == 0)
{
- free(oldPath);
- free(tmpPath);
- free(editor.configFileLocation);
+ free(oldPathU);
+ free(tmpPathU);
+ free(editor.configFileLocationU);
- editor.configFileLocation = NULL;
+ editor.configFileLocationU = NULL;
showErrorMsgBox("Error: Couldn't set config file location. You can't load/save the config!");
return;
}
- UNICHAR_STRCPY(editor.configFileLocation, oldPath);
+ UNICHAR_STRCPY(editor.configFileLocationU, oldPathU);
FILE *f = fopen("FT2.CFG", "rb");
if (f == NULL) // FT2.CFG not found in current dir, try default config dir
{
- int32_t result = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, tmpPath);
+ int32_t result = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, tmpPathU);
if (result == S_OK)
{
- if (SetCurrentDirectoryW(tmpPath) != 0)
+ if (SetCurrentDirectoryW(tmpPathU) != 0)
{
result = chdir("FT2 clone");
if (result != 0)
@@ -528,7 +527,7 @@
}
if (result == 0)
- GetCurrentDirectoryW(PATH_MAX - ft2DotCfgStrLen - 1, editor.configFileLocation); // we can, set it
+ GetCurrentDirectoryW(PATH_MAX - ft2DotCfgStrLen - 1, editor.configFileLocationU); // we can, set it
}
}
}
@@ -537,27 +536,29 @@
fclose(f);
}
- free(tmpPath);
- SetCurrentDirectoryW(oldPath);
- free(oldPath);
+ free(tmpPathU);
+ SetCurrentDirectoryW(oldPathU);
+ free(oldPathU);
- UNICHAR_STRCAT(editor.configFileLocation, L"\\FT2.CFG");
+ UNICHAR_STRCAT(editor.configFileLocationU, L"\\FT2.CFG");
// OS X / macOS
#elif defined __APPLE__
int32_t ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG");
- editor.configFileLocation = (UNICHAR *)calloc(PATH_MAX + ft2DotCfgStrLen + 2, sizeof (UNICHAR));
- if (editor.configFileLocation == NULL)
+ editor.configFileLocationU = (UNICHAR *)malloc((PATH_MAX + ft2DotCfgStrLen + 1) * sizeof (UNICHAR));
+ if (editor.configFileLocationU == NULL)
{
showErrorMsgBox("Error: Couldn't set config file location. You can't load/save the config!");
return;
}
- if (getcwd(editor.configFileLocation, PATH_MAX - ft2DotCfgStrLen - 1) == NULL)
+ editor.configFileLocationU[0] = 0;
+
+ if (getcwd(editor.configFileLocationU, PATH_MAX - ft2DotCfgStrLen - 1) == NULL)
{
- free(editor.configFileLocation);
- editor.configFileLocation = NULL;
+ free(editor.configFileLocationU);
+ editor.configFileLocationU = NULL;
showErrorMsgBox("Error: Couldn't set config file location. You can't load/save the config!");
return;
}
@@ -578,7 +579,7 @@
}
if (result == 0)
- getcwd(editor.configFileLocation, PATH_MAX - ft2DotCfgStrLen - 1);
+ getcwd(editor.configFileLocationU, PATH_MAX - ft2DotCfgStrLen - 1);
}
}
}
@@ -587,23 +588,25 @@
fclose(f);
}
- strcat(editor.configFileLocation, "/FT2.CFG");
+ strcat(editor.configFileLocationU, "/FT2.CFG");
// Linux etc
#else
int32_t ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG");
- editor.configFileLocation = (UNICHAR *)calloc(PATH_MAX + ft2DotCfgStrLen + 2, sizeof (UNICHAR));
- if (editor.configFileLocation == NULL)
+ editor.configFileLocationU = (UNICHAR *)malloc((PATH_MAX + ft2DotCfgStrLen + 1) * sizeof (UNICHAR));
+ if (editor.configFileLocationU == NULL)
{
showErrorMsgBox("Error: Couldn't set config file location. You can't load/save the config!");
return;
}
- if (getcwd(editor.configFileLocation, PATH_MAX - ft2DotCfgStrLen - 1) == NULL)
+ editor.configFileLocationU[0] = 0;
+
+ if (getcwd(editor.configFileLocationU, PATH_MAX - ft2DotCfgStrLen - 1) == NULL)
{
- free(editor.configFileLocation);
- editor.configFileLocation = NULL;
+ free(editor.configFileLocationU);
+ editor.configFileLocationU = NULL;
showErrorMsgBox("Error: Couldn't set config file location. You can't load/save the config!");
return;
}
@@ -632,7 +635,7 @@
}
if (result == 0)
- getcwd(editor.configFileLocation, PATH_MAX - ft2DotCfgStrLen - 1);
+ getcwd(editor.configFileLocationU, PATH_MAX - ft2DotCfgStrLen - 1);
}
}
else
@@ -640,23 +643,23 @@
fclose(f);
}
- strcat(editor.configFileLocation, "/FT2.CFG");
+ strcat(editor.configFileLocationU, "/FT2.CFG");
#endif
- editor.midiConfigFileLocation = getFullMidiDevConfigPath();
- editor.audioDevConfigFileLocation = getFullAudDevConfigPath();
+ editor.midiConfigFileLocationU = getFullMidiDevConfigPathU();
+ editor.audioDevConfigFileLocationU = getFullAudDevConfigPathU();
}
void loadConfigOrSetDefaults(void)
{
setConfigFileLocation();
- if (editor.configFileLocation == NULL)
+ if (editor.configFileLocationU == NULL)
{
setDefaultConfigSettings();
return;
}
- FILE *f = UNICHAR_FOPEN(editor.configFileLocation, "rb");
+ FILE *f = UNICHAR_FOPEN(editor.configFileLocationU, "rb");
if (f == NULL)
{
setDefaultConfigSettings();
--- a/src/ft2_diskop.c
+++ b/src/ft2_diskop.c
@@ -72,7 +72,7 @@
int32_t filesize;
} DirRec;
-static char FReq_SysReqText[196], *FReq_FileName, *FReq_NameTemp;
+static char FReq_SysReqText[256], *FReq_FileName, *FReq_NameTemp;
static char *modTmpFName, *insTmpFName, *smpTmpFName, *patTmpFName, *trkTmpFName;
static char *modTmpFNameUTF8; // for window title
static uint8_t FReq_Item;
@@ -84,6 +84,18 @@
static void setDiskOpItem(uint8_t item);
+bool setupExecutablePath(void)
+{
+ editor.binaryPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));
+ if (editor.binaryPathU == NULL)
+ 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;
@@ -173,11 +185,15 @@
#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;
}
@@ -184,6 +200,7 @@
if (config.samplesPath[0] != '\0')
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.samplesPath, -1, FReq_SmpCurPathU, 80);
+ FReq_SmpCurPathU[80] = 0;
smpPathSet = true;
}
@@ -190,6 +207,7 @@
if (config.patternsPath[0] != '\0')
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.patternsPath, -1, FReq_PatCurPathU, 80);
+ FReq_PatCurPathU[80] = 0;
patPathSet = true;
}
@@ -196,15 +214,20 @@
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;
}
@@ -211,6 +234,7 @@
if (config.samplesPath[0] != '\0')
{
strncpy(FReq_SmpCurPathU, config.samplesPath, 80);
+ FReq_SmpCurPathU[80] = 0;
smpPathSet = true;
}
@@ -217,6 +241,7 @@
if (config.patternsPath[0] != '\0')
{
strncpy(FReq_PatCurPathU, config.patternsPath, 80);
+ FReq_PatCurPathU[80] = 0;
patPathSet = true;
}
@@ -223,6 +248,7 @@
if (config.tracksPath[0] != '\0')
{
strncpy(FReq_TrkCurPathU, config.tracksPath, 80);
+ FReq_TrkCurPathU[80] = 0;
trkPathSet = true;
}
#endif
@@ -277,22 +303,23 @@
bool setupDiskOp(void)
{
- modTmpFName = (char *)calloc(PATH_MAX + 1, sizeof (char));
- insTmpFName = (char *)calloc(PATH_MAX + 1, sizeof (char));
- smpTmpFName = (char *)calloc(PATH_MAX + 1, sizeof (char));
- patTmpFName = (char *)calloc(PATH_MAX + 1, sizeof (char));
- trkTmpFName = (char *)calloc(PATH_MAX + 1, sizeof (char));
- FReq_NameTemp = (char *)calloc(PATH_MAX + 1, sizeof (char));
- FReq_ModCurPathU = (UNICHAR *)calloc(PATH_MAX + 2, sizeof (UNICHAR));
- FReq_InsCurPathU = (UNICHAR *)calloc(PATH_MAX + 2, sizeof (UNICHAR));
- FReq_SmpCurPathU = (UNICHAR *)calloc(PATH_MAX + 2, sizeof (UNICHAR));
- FReq_PatCurPathU = (UNICHAR *)calloc(PATH_MAX + 2, sizeof (UNICHAR));
- FReq_TrkCurPathU = (UNICHAR *)calloc(PATH_MAX + 2, sizeof (UNICHAR));
+ 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));
- 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)
+ 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!");
@@ -299,6 +326,19 @@
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");
@@ -602,7 +642,7 @@
char *filename = getFilenameFromPath(ansiPath);
uint32_t filenameLen = (uint32_t)strlen(filename);
- if (filenameLen > PATH_MAX-1)
+ if (filenameLen > PATH_MAX)
{
free(ansiPath);
return; // filename is too long, don't bother to copy it over
@@ -693,9 +733,9 @@
{
if (songModifiedCheck && song.isModified)
{
- // remove file selection
+ // remove file selection before okBox() opens up
FReq_EntrySelected = -1;
- diskOp_DrawDirectory();
+ diskOp_DrawFilelist();
if (okBox(2, "System request", "You have unsaved changes in your song. Load new song and lose all changes?") != 1)
return;
@@ -758,8 +798,6 @@
void diskOpChangeFilenameExt(char *ext)
{
changeFilenameExt(FReq_FileName, ext, PATH_MAX);
- if (ui.diskOpShown)
- diskOp_DrawDirectory();
}
void trimEntryName(char *name, bool isDir)
@@ -1011,7 +1049,7 @@
// remove file selection
FReq_EntrySelected = -1;
- diskOp_DrawDirectory();
+ diskOp_DrawFilelist();
DirRec *dirEntry = &FReq_Buffer[entryIndex];
switch (mode)
@@ -1077,15 +1115,16 @@
if (nameTmp == NULL)
break;
- strncpy(FReq_NameTemp, nameTmp, PATH_MAX - 1);
+ strncpy(FReq_NameTemp, nameTmp, PATH_MAX);
+ FReq_NameTemp[PATH_MAX] = '\0';
free(nameTmp);
// in case of UTF8 -> CP437 encoding failure, there can be question marks. Remove them...
removeQuestionmarksFromString(FReq_NameTemp);
- if (inputBox(1, dirEntry->isDir ? "Enter new directory name:" : "Enter new filename:", FReq_NameTemp, PATH_MAX - 1) == 1)
+ if (inputBox(1, dirEntry->isDir ? "Enter new directory name:" : "Enter new filename:", FReq_NameTemp, PATH_MAX) == 1)
{
- if ((FReq_NameTemp == NULL) || (FReq_NameTemp[0] == '\0'))
+ if (FReq_NameTemp == NULL || FReq_NameTemp[0] == '\0')
{
okBox(0, "System message", "New name can't be empty!");
break;
@@ -1120,7 +1159,7 @@
if (max > DISKOP_ENTRY_NUM) // needed kludge when mouse-scrolling
max = DISKOP_ENTRY_NUM;
- if (!mouseHeldDlown)
+ if (!mouseHeldDlown) // select file
{
FReq_EntrySelected = -1;
@@ -1130,7 +1169,7 @@
if (tmpEntry >= 0 && tmpEntry < max)
{
FReq_EntrySelected = tmpEntry;
- diskOp_DrawDirectory();
+ diskOp_DrawFilelist();
}
mouse.lastUsedObjectType = OBJECT_DISKOPLIST;
@@ -1161,7 +1200,7 @@
if (mouse.x < 169 || mouse.x > 331 || mouse.y < 4 || tmpEntry < 0 || tmpEntry >= max)
{
FReq_EntrySelected = -1;
- diskOp_DrawDirectory();
+ diskOp_DrawFilelist();
return true;
}
@@ -1169,7 +1208,7 @@
if (tmpEntry != FReq_EntrySelected)
{
FReq_EntrySelected = tmpEntry;
- diskOp_DrawDirectory();
+ diskOp_DrawFilelist();
}
return true;
@@ -1183,7 +1222,7 @@
fileListPressed((mouse.y - 4) / (FONT1_CHAR_H + 1));
FReq_EntrySelected = -1;
- diskOp_DrawDirectory();
+ diskOp_DrawFilelist();
}
}
@@ -1537,7 +1576,7 @@
return NULL;
}
- char *p = (char *)malloc(nameLen + 2);
+ char *p = (char *)malloc(nameLen+1+1);
if (p == NULL)
{
free(name);
@@ -1701,6 +1740,9 @@
{
fillRect(4, 145, 162, 10, PAL_DESKTOP);
+ if (FReq_CurPathU == NULL)
+ return;
+
const uint32_t pathLen = (uint32_t)UNICHAR_STRLEN(FReq_CurPathU);
if (pathLen == 0)
return;
@@ -1722,11 +1764,14 @@
{
// path doesn't fit, print drive + ".." + last directory
- memset(FReq_NameTemp, 0, PATH_MAX + 1);
#ifdef _WIN32
- strncpy(FReq_NameTemp, p, 3);
+ memcpy(FReq_NameTemp, p, 3); // get drive (f.ex. C:\)
+ FReq_NameTemp[3] = '\0';
+
strcat(FReq_NameTemp, ".\001"); // special character in font
+ FReq_NameTemp[5] = '\0';
#else
+ FReq_NameTemp[0] = '\0';
strcpy(FReq_NameTemp, "/");
strcat(FReq_NameTemp, "..");
#endif
@@ -1735,7 +1780,7 @@
if (delimiter != NULL)
{
#ifdef _WIN32
- strcat(FReq_NameTemp, delimiter + 1);
+ strcat(FReq_NameTemp, delimiter+1);
#else
strcat(FReq_NameTemp, delimiter);
#endif
@@ -1749,9 +1794,9 @@
p = FReq_NameTemp;
while (j >= 6 && textWidth(p) >= 162)
{
- p[j - 2] = '.';
- p[j - 1] = '.';
- p[j - 0] = '\0';
+ p[j-2] = '.';
+ p[j-1] = '.';
+ p[j-0] = '\0';
j--;
}
}
@@ -1762,11 +1807,14 @@
free(asciiPath);
}
-void diskOp_DrawDirectory(void)
+void diskOp_DrawFilelist(void)
{
- clearRect(FILENAME_TEXT_X - 1, 4, 162, 164);
- drawTextBox(TB_DISKOP_FILENAME);
+ clearRect(FILENAME_TEXT_X-1, 4, 162, 164);
+ if (FReq_FileCount == 0)
+ return;
+
+ // draw "selected file" rectangle
if (FReq_EntrySelected != -1)
{
const uint16_t y = 4 + (uint16_t)((FONT1_CHAR_H + 1) * FReq_EntrySelected);
@@ -1773,14 +1821,6 @@
fillRect(FILENAME_TEXT_X - 1, y, 162, FONT1_CHAR_H, PAL_PATTEXT);
}
- displayCurrPath();
-#ifdef _WIN32
- setupDiskOpDrives();
-#endif
-
- if (FReq_FileCount == 0)
- return;
-
for (uint16_t i = 0; i < DISKOP_ENTRY_NUM; i++)
{
const int32_t bufEntry = FReq_DirPos + i;
@@ -1817,9 +1857,21 @@
if (!FReq_Buffer[bufEntry].isDir)
printFormattedFilesize(FILESIZE_TEXT_X, y, bufEntry);
}
+}
- setScrollBarPos(SB_DISKOP_LIST, FReq_DirPos, true);
+void diskOp_DrawDirectory(void)
+{
+ drawTextBox(TB_DISKOP_FILENAME);
+
+ displayCurrPath();
+#ifdef _WIN32
+ setupDiskOpDrives();
+#endif
+
setScrollBarEnd(SB_DISKOP_LIST, FReq_FileCount);
+ setScrollBarPos(SB_DISKOP_LIST, FReq_DirPos, false);
+
+ diskOp_DrawFilelist();
}
static DirRec *bufferCreateEmptyDir(void) // special case: creates a dir entry with a ".." directory
@@ -2035,7 +2087,7 @@
// FReq_ModCurPathU is always set at this point
FReq_CurPathU = FReq_ModCurPathU;
- if (FReq_CurPathU != NULL)
+ if (FReq_CurPathU != NULL && FReq_CurPathU[0] != '\0')
UNICHAR_CHDIR(FReq_CurPathU);
}
break;
@@ -2044,7 +2096,7 @@
{
FReq_FileName = insTmpFName;
- if (!insPathSet)
+ if (!insPathSet && FReq_CurPathU != NULL && FReq_CurPathU[0] != '\0')
{
UNICHAR_STRCPY(FReq_InsCurPathU, FReq_CurPathU);
insPathSet = true;
@@ -2060,7 +2112,7 @@
{
FReq_FileName = smpTmpFName;
- if (!smpPathSet)
+ if (!smpPathSet && FReq_CurPathU != NULL && FReq_CurPathU[0] != '\0')
{
UNICHAR_STRCPY(FReq_SmpCurPathU, FReq_CurPathU);
smpPathSet = true;
@@ -2076,7 +2128,7 @@
{
FReq_FileName = patTmpFName;
- if (!patPathSet)
+ if (!patPathSet && FReq_CurPathU != NULL && FReq_CurPathU[0] != '\0')
{
UNICHAR_STRCPY(FReq_PatCurPathU, FReq_CurPathU);
patPathSet = true;
@@ -2092,7 +2144,7 @@
{
FReq_FileName = trkTmpFName;
- if (!trkPathSet)
+ if (!trkPathSet && FReq_CurPathU != NULL && FReq_CurPathU[0] != '\0')
{
UNICHAR_STRCPY(FReq_TrkCurPathU, FReq_CurPathU);
trkPathSet = true;
@@ -2105,15 +2157,13 @@
break;
}
- const int32_t pathLen = (int32_t)UNICHAR_STRLEN(FReq_CurPathU);
- if (pathLen == 0 && FReq_ModCurPathU[0] != '\0')
+ if (FReq_CurPathU != NULL && FReq_ModCurPathU != NULL)
{
- memset(FReq_CurPathU, 0, (PATH_MAX + 2) * sizeof (UNICHAR));
- UNICHAR_STRCPY(FReq_CurPathU, FReq_ModCurPathU);
+ if (FReq_CurPathU[0] == '\0' && FReq_ModCurPathU[0] != '\0')
+ UNICHAR_STRCPY(FReq_CurPathU, FReq_ModCurPathU);
}
textBoxes[TB_DISKOP_FILENAME].textPtr = FReq_FileName;
-
FReq_ShowAllFiles = false;
if (ui.diskOpShown)
@@ -2199,14 +2249,15 @@
assert(FReq_ModCurPathU != NULL);
// first test if we can change the dir to the one stored in the config (if present)
- if (UNICHAR_STRLEN(FReq_ModCurPathU) == 0 || UNICHAR_CHDIR(FReq_ModCurPathU) != 0)
+ if (FReq_ModCurPathU[0] == '\0' || UNICHAR_CHDIR(FReq_ModCurPathU) != 0)
{
// nope, couldn't do that, set Disk Op. path to user/home directory
#ifdef _WIN32
SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, FReq_ModCurPathU);
#else
- if (getenv("HOME") != NULL)
- UNICHAR_STRCPY(FReq_ModCurPathU, getenv("HOME"));
+ char *home = getenv("HOME");
+ if (home != NULL)
+ UNICHAR_STRCPY(FReq_ModCurPathU, home);
#endif
UNICHAR_CHDIR(FReq_ModCurPathU);
}
@@ -2285,7 +2336,7 @@
if ((int32_t)pos != FReq_DirPos && FReq_FileCount > DISKOP_ENTRY_NUM)
{
FReq_DirPos = (int32_t)pos;
- diskOp_DrawDirectory();
+ diskOp_DrawFilelist();
}
}
@@ -2345,7 +2396,7 @@
void pbDiskOpMakeDir(void)
{
FReq_NameTemp[0] = '\0';
- if (inputBox(1, "Enter directory name:", FReq_NameTemp, PATH_MAX - 1) == 1)
+ if (inputBox(1, "Enter directory name:", FReq_NameTemp, PATH_MAX) == 1)
{
if (FReq_NameTemp[0] == '\0')
{
@@ -2371,7 +2422,7 @@
void pbDiskOpSetPath(void)
{
FReq_NameTemp[0] = '\0';
- if (inputBox(1, "Enter new directory path:", FReq_NameTemp, PATH_MAX - 1) == 1)
+ if (inputBox(1, "Enter new directory path:", FReq_NameTemp, PATH_MAX) == 1)
{
if (FReq_NameTemp[0] == '\0')
{
--- a/src/ft2_diskop.h
+++ b/src/ft2_diskop.h
@@ -21,6 +21,7 @@
SMP_SAVE_MODE_WAV = 2
};
+bool setupExecutablePath(void);
int32_t getFileSize(UNICHAR *fileNameU);
uint8_t getDiskOpItem(void);
void updateCurrSongFilename(void); // for window title
@@ -41,6 +42,7 @@
bool testDiskOpMouseDown(bool mouseHeldDown);
void testDiskOpMouseRelease(void);
void diskOp_StartDirReadThread(void);
+void diskOp_DrawFilelist(void);
void diskOp_DrawDirectory(void);
void showDiskOpScreen(void);
void hideDiskOpScreen(void);
--- a/src/ft2_events.c
+++ b/src/ft2_events.c
@@ -35,13 +35,14 @@
#define CRASH_TEXT "Oh no!\nThe Fasttracker II clone has crashed...\n\nA backup .xm was hopefully " \
"saved to the current module directory.\n\nPlease report this bug if you can.\n" \
- "Try to mention what you did before the crash happened."
+ "Try to mention what you did before the crash happened.\n" \
+ "My email can be found at the bottom of 16-bits.org."
static bool backupMadeAfterCrash;
#ifdef _WIN32
-#define SYSMSG_FILE_ARG (WM_USER + 1)
-#define ARGV_SHARED_MEM_MAX_LEN ((MAX_PATH * 2) + 2)
+#define SYSMSG_FILE_ARG (WM_USER+1)
+#define ARGV_SHARED_MEM_MAX_LEN ((PATH_MAX+1) * sizeof (WCHAR))
#define SHARED_HWND_NAME TEXT("Local\\FT2CloneHwnd")
#define SHARED_FILENAME TEXT("Local\\FT2CloneFilename")
static HWND hWnd;
--- a/src/ft2_gui.c
+++ b/src/ft2_gui.c
@@ -127,20 +127,21 @@
bool setupGUI(void)
{
- int32_t i;
-
// all memory will be NULL-tested and free'd if we return false somewhere in this function
- editor.tmpFilenameU = (UNICHAR *)calloc(PATH_MAX + 1, sizeof (UNICHAR));
- editor.tmpInstrFilenameU = (UNICHAR *)calloc(PATH_MAX + 1, sizeof (UNICHAR));
+ editor.tmpFilenameU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));
+ editor.tmpInstrFilenameU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));
if (editor.tmpFilenameU == NULL || editor.tmpInstrFilenameU == NULL)
goto setupGUI_OOM;
+ editor.tmpFilenameU[0] = 0;
+ editor.tmpInstrFilenameU[0] = 0;
+
// set uninitialized GUI struct entries
textBox_t *t = &textBoxes[1]; // skip first entry, it's reserved for inputBox())
- for (i = 1; i < NUM_TEXTBOXES; i++, t++)
+ for (int32_t i = 1; i < NUM_TEXTBOXES; i++, t++)
{
t->visible = false;
t->bufOffset = 0;
@@ -156,7 +157,7 @@
}
pushButton_t *p = pushButtons;
- for (i = 0; i < NUM_PUSHBUTTONS; i++, p++)
+ for (int32_t i = 0; i < NUM_PUSHBUTTONS; i++, p++)
{
p->state = 0;
p->visible = false;
@@ -174,7 +175,7 @@
}
checkBox_t *c = checkBoxes;
- for (i = 0; i < NUM_CHECKBOXES; i++, c++)
+ for (int32_t i = 0; i < NUM_CHECKBOXES; i++, c++)
{
c->state = 0;
c->checked = false;
@@ -182,7 +183,7 @@
}
radioButton_t *r = radioButtons;
- for (i = 0; i < NUM_RADIOBUTTONS; i++, r++)
+ for (int32_t i = 0; i < NUM_RADIOBUTTONS; i++, r++)
{
r->state = 0;
r->visible = false;
@@ -189,7 +190,7 @@
}
scrollBar_t *s = scrollBars;
- for (i = 0; i < NUM_SCROLLBARS; i++, s++)
+ for (int32_t i = 0; i < NUM_SCROLLBARS; i++, s++)
{
s->visible = false;
s->state = 0;
--- a/src/ft2_keyboard.c
+++ b/src/ft2_keyboard.c
@@ -122,7 +122,8 @@
return; // do NOT repeat keys in Nibbles or if keyRepeat is disabled
}
- keyb.keyRepeat = true;
+ if (scancode != SDL_SCANCODE_ESCAPE)
+ keyb.keyRepeat = true;
// handle certain keys (home/end/left/right etc) when editing text
if (editor.editTextFlag)
@@ -669,6 +670,7 @@
case SDLK_KP_ENTER:
case SDLK_RETURN:
+ {
if (keyb.leftAltPressed)
{
toggleFullScreen();
@@ -679,9 +681,11 @@
#endif
return true;
}
- break;
+ }
+ break;
case SDLK_F9:
+ {
if (keyb.leftCtrlPressed)
{
startPlaying(PLAYMODE_PATT, editor.ptnJumpPos[0]);
@@ -692,9 +696,11 @@
editor.ptnJumpPos[0] = (uint8_t)editor.pattPos;
return true;
}
- break;
+ }
+ break;
case SDLK_F10:
+ {
if (keyb.leftCtrlPressed)
{
startPlaying(PLAYMODE_PATT, editor.ptnJumpPos[1]);
@@ -705,9 +711,11 @@
editor.ptnJumpPos[1] = (uint8_t)editor.pattPos;
return true;
}
- break;
+ }
+ break;
case SDLK_F11:
+ {
if (keyb.leftCtrlPressed)
{
startPlaying(PLAYMODE_PATT, editor.ptnJumpPos[2]);
@@ -718,9 +726,11 @@
editor.ptnJumpPos[2] = (uint8_t)editor.pattPos;
return true;
}
- break;
+ }
+ break;
case SDLK_F12:
+ {
if (keyb.leftCtrlPressed)
{
startPlaying(PLAYMODE_PATT, editor.ptnJumpPos[3]);
@@ -731,9 +741,11 @@
editor.ptnJumpPos[3] = (uint8_t)editor.pattPos;
return true;
}
- break;
+ }
+ break;
case SDLK_a:
+ {
if (keyb.leftCtrlPressed)
{
if (ui.sampleEditorShown)
@@ -752,9 +764,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_b:
+ {
if (keyb.leftCtrlPressed)
{
if (!ui.aboutScreenShown)
@@ -762,9 +776,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_c:
+ {
if (keyb.leftAltPressed)
{
if (ui.sampleEditorShown)
@@ -793,9 +809,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_d:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(10);
@@ -808,9 +826,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_e:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(2);
@@ -826,9 +846,11 @@
showSampleEditorExt();
return true;
}
- break;
+ }
+ break;
case SDLK_f:
+ {
#ifdef __APPLE__
if (keyb.leftCommandPressed && keyb.leftCtrlPressed)
{
@@ -854,17 +876,21 @@
jumpToChannel(11);
return true;
}
- break;
+ }
+ break;
case SDLK_g:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(12);
return true;
}
- break;
+ }
+ break;
case SDLK_h:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(13);
@@ -875,9 +901,11 @@
showHelpScreen();
return true;
}
- break;
+ }
+ break;
case SDLK_i:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(7);
@@ -888,25 +916,31 @@
showInstEditor();
return true;
}
- break;
+ }
+ break;
case SDLK_j:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(14);
return true;
}
- break;
+ }
+ break;
case SDLK_k:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(15);
return true;
}
- break;
+ }
+ break;
case SDLK_m:
+ {
if (keyb.leftCtrlPressed)
{
if (ui.aboutScreenShown) hideAboutScreen();
@@ -918,17 +952,21 @@
return true;
}
- break;
+ }
+ break;
case SDLK_n:
+ {
if (keyb.leftCtrlPressed)
{
showNibblesScreen();
return true;
}
- break;
+ }
+ break;
case SDLK_p:
+ {
if (keyb.leftCtrlPressed)
{
if (!ui.patternEditorShown)
@@ -942,17 +980,21 @@
return true;
}
- break;
+ }
+ break;
case SDLK_q:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(0);
return true;
}
- break;
+ }
+ break;
case SDLK_r:
+ {
if (keyb.leftAltPressed)
{
if (ui.sampleEditorShown)
@@ -967,9 +1009,11 @@
showTrimScreen();
return true;
}
- break;
+ }
+ break;
case SDLK_s:
+ {
if (keyb.leftAltPressed)
{
if (ui.sampleEditorShown)
@@ -984,9 +1028,11 @@
showSampleEditor();
return true;
}
- break;
+ }
+ break;
case SDLK_t:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(4);
@@ -997,17 +1043,21 @@
showTranspose();
return true;
}
- break;
+ }
+ break;
case SDLK_u:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(6);
return true;
}
- break;
+ }
+ break;
case SDLK_v:
+ {
if (keyb.leftAltPressed)
{
if (ui.sampleEditorShown)
@@ -1036,17 +1086,21 @@
return true;
}
- break;
+ }
+ break;
case SDLK_w:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(1);
return true;
}
- break;
+ }
+ break;
case SDLK_x:
+ {
if (keyb.leftAltPressed)
{
if (ui.sampleEditorShown)
@@ -1080,17 +1134,21 @@
return true;
}
- break;
+ }
+ break;
case SDLK_y:
+ {
if (keyb.leftAltPressed)
{
jumpToChannel(5);
return true;
}
- break;
+ }
+ break;
case SDLK_z:
+ {
if (keyb.leftAltPressed)
{
if (ui.sampleEditorShown)
@@ -1103,9 +1161,11 @@
togglePatternEditorExtended();
return true;
}
- break;
+ }
+ break;
case SDLK_1:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1123,9 +1183,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_2:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1143,9 +1205,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_3:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1163,9 +1227,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_4:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1185,9 +1251,11 @@
return true;
}
#endif
- break;
+ }
+ break;
case SDLK_5:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1197,9 +1265,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_6:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1209,9 +1279,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_7:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1221,9 +1293,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_8:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1233,9 +1307,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_9:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1245,9 +1321,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_0:
+ {
if (keyb.leftAltPressed)
{
if (keyb.leftShiftPressed)
@@ -1257,9 +1335,11 @@
return true;
}
- break;
+ }
+ break;
case SDLK_LEFT:
+ {
if (keyb.leftShiftPressed)
{
decSongPos();
@@ -1275,9 +1355,11 @@
keybPattMarkLeft();
return true;
}
- break;
+ }
+ break;
case SDLK_RIGHT:
+ {
if (keyb.leftShiftPressed)
{
incSongPos();
@@ -1293,7 +1375,8 @@
keybPattMarkRight();
return true;
}
- break;
+ }
+ break;
}
return false;
--- a/src/ft2_main.c
+++ b/src/ft2_main.c
@@ -147,9 +147,7 @@
#ifdef __APPLE__
osxSetDirToProgramDirFromArgs(argv);
#endif
- UNICHAR_GETCWD(editor.binaryPathU, PATH_MAX);
-
- if (!loadBMPs())
+ if (!setupExecutablePath() || !loadBMPs())
{
cleanUpAndExit();
return 1;
@@ -351,22 +349,28 @@
}
#endif
- if (editor.audioDevConfigFileLocation != NULL)
+ if (editor.audioDevConfigFileLocationU != NULL)
{
- free(editor.audioDevConfigFileLocation);
- editor.audioDevConfigFileLocation = NULL;
+ free(editor.audioDevConfigFileLocationU);
+ editor.audioDevConfigFileLocationU = NULL;
}
- if (editor.configFileLocation != NULL)
+ if (editor.configFileLocationU != NULL)
{
- free(editor.configFileLocation);
- editor.configFileLocation = NULL;
+ free(editor.configFileLocationU);
+ editor.configFileLocationU = NULL;
}
- if (editor.midiConfigFileLocation != NULL)
+ if (editor.midiConfigFileLocationU != NULL)
{
- free(editor.midiConfigFileLocation);
- editor.midiConfigFileLocation = NULL;
+ free(editor.midiConfigFileLocationU);
+ editor.midiConfigFileLocationU = NULL;
+ }
+
+ if (editor.binaryPathU != NULL)
+ {
+ free(editor.binaryPathU);
+ editor.binaryPathU = NULL;
}
#ifdef _WIN32
--- a/src/ft2_midi.c
+++ b/src/ft2_midi.c
@@ -18,6 +18,8 @@
#include "ft2_structs.h"
#include "rtmidi/rtmidi_c.h"
+#define MAX_DEV_STR_LEN 256
+
// hide POSIX warnings
#ifdef _MSC_VER
#pragma warning(disable: 4996)
@@ -265,7 +267,7 @@
if (midiInStr == NULL)
return false;
- FILE *f = UNICHAR_FOPEN(editor.midiConfigFileLocation, "w");
+ FILE *f = UNICHAR_FOPEN(editor.midiConfigFileLocationU, "w");
if (f == NULL)
{
free(midiInStr);
@@ -281,8 +283,6 @@
bool setMidiInputDeviceFromConfig(void)
{
-#define MAX_DEV_STR_LEN 1024
-
uint32_t i;
if (midi.inputDeviceName != NULL)
@@ -292,16 +292,18 @@
if (numDevices == 0)
goto setDefMidiInputDev;
- FILE *f = UNICHAR_FOPEN(editor.midiConfigFileLocation, "r");
+ FILE *f = UNICHAR_FOPEN(editor.midiConfigFileLocationU, "r");
if (f == NULL)
goto setDefMidiInputDev;
- char *devString = (char *)calloc(MAX_DEV_STR_LEN+4, sizeof (char));
+ char *devString = (char *)malloc((MAX_DEV_STR_LEN+4) * sizeof (char));
if (devString == NULL)
{
fclose(f);
goto setDefMidiInputDev;
}
+
+ devString[0] = '\0';
if (fgets(devString, MAX_DEV_STR_LEN, f) == NULL)
{
--- a/src/ft2_module_loader.c
+++ b/src/ft2_module_loader.c
@@ -526,10 +526,8 @@
bool handleModuleLoadFromArg(int argc, char **argv)
{
- UNICHAR tmpPathU[PATH_MAX+2];
+ // we always expect only one parameter, and that it is the module
- // this is crude, we always expect only one parameter, and that it is the module.
-
if (argc != 2 || argv[1] == NULL || argv[1][0] == '\0')
return false;
@@ -540,15 +538,26 @@
const uint32_t filenameLen = (const uint32_t)strlen(argv[1]);
- UNICHAR *filenameU = (UNICHAR *)calloc(filenameLen+1, sizeof (UNICHAR));
+ UNICHAR *tmpPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR));
+ if (tmpPathU == NULL)
+ {
+ okBox(0, "System message", "Not enough memory!");
+ return false;
+ }
+
+ UNICHAR *filenameU = (UNICHAR *)malloc((filenameLen + 1) * sizeof (UNICHAR));
if (filenameU == NULL)
{
+ free(tmpPathU);
okBox(0, "System message", "Not enough memory!");
return false;
}
+ tmpPathU[0] = 0;
+ filenameU[0] = 0;
+
#ifdef _WIN32
- MultiByteToWideChar(CP_UTF8, 0, argv[1], -1, filenameU, filenameLen);
+ MultiByteToWideChar(CP_UTF8, 0, argv[1], -1, filenameU, filenameLen+1);
#else
strcpy(filenameU, argv[1]);
#endif
@@ -562,9 +571,11 @@
const int32_t filesize = getFileSize(filenameU);
if (filesize == -1 || filesize >= 512L*1024*1024) // 1) >=2GB 2) >=512MB
{
- okBox(0, "System message", "Error: The module is too big to be loaded!");
free(filenameU);
UNICHAR_CHDIR(tmpPathU); // set old path back
+ free(tmpPathU);
+
+ okBox(0, "System message", "Error: The module is too big to be loaded!");
return false;
}
@@ -572,6 +583,8 @@
free(filenameU);
UNICHAR_CHDIR(tmpPathU); // set old path back
+ free(tmpPathU);
+
return result;
}
@@ -642,7 +655,7 @@
if (fullPathLen == 0)
return;
- UNICHAR *fullPathU = (UNICHAR *)calloc(fullPathLen + 2, sizeof (UNICHAR));
+ UNICHAR *fullPathU = (UNICHAR *)malloc((fullPathLen + 1) * sizeof (UNICHAR));
if (fullPathU == NULL)
{
okBox(0, "System message", "Not enough memory!");
@@ -649,8 +662,10 @@
return;
}
+ fullPathU[0] = 0;
+
#ifdef _WIN32
- MultiByteToWideChar(CP_UTF8, 0, fullPathUTF8, -1, fullPathU, fullPathLen);
+ MultiByteToWideChar(CP_UTF8, 0, fullPathUTF8, -1, fullPathU, fullPathLen+1);
#else
strcpy(fullPathU, fullPathUTF8);
#endif
--- a/src/ft2_mouse.c
+++ b/src/ft2_mouse.c
@@ -301,7 +301,7 @@
textBox_t *t = textBoxes;
for (i = 0; i < NUM_TEXTBOXES; i++, t++)
{
- if (ui.sysReqShown && i > 0)
+ if (ui.sysReqShown && i != 0) // Sys. Req can only have one (special) text box
continue;
if (!t->visible)
@@ -313,7 +313,10 @@
if (my >= t->y && my < t->y+t->h && mx >= t->x && mx < t->x+t->w)
{
mouse.mouseOverTextBox = true;
- setTextEditMouse();
+
+ if (mouseShape != MOUSE_IDLE_TEXT_EDIT)
+ setTextEditMouse();
+
return;
}
}
--- a/src/ft2_structs.h
+++ b/src/ft2_structs.h
@@ -11,9 +11,8 @@
typedef struct editor_t
{
- UNICHAR binaryPathU[PATH_MAX + 2];
- UNICHAR *tmpFilenameU, *tmpInstrFilenameU; // used by saving/loading threads
- UNICHAR *configFileLocation, *audioDevConfigFileLocation, *midiConfigFileLocation;
+ UNICHAR *binaryPathU, *tmpFilenameU, *tmpInstrFilenameU; // used by saving/loading threads
+ UNICHAR *configFileLocationU, *audioDevConfigFileLocationU, *midiConfigFileLocationU;
volatile bool mainLoopOngoing;
volatile bool busy, scopeThreadMutex, programRunning, wavIsRendering, wavReachedEndFlag;
--- a/src/ft2_sysreqs.c
+++ b/src/ft2_sysreqs.c
@@ -299,8 +299,11 @@
{
if (inputEvent.key.keysym.sym == SDLK_ESCAPE)
{
- returnVal = 0;
- ui.sysReqShown = false;
+ if (!inputEvent.key.repeat) // don't let previously held-down ESC immediately close the box
+ {
+ returnVal = 0;
+ ui.sysReqShown = false;
+ }
}
else if (inputEvent.key.keysym.sym == SDLK_RETURN)
{
--- a/src/ft2_textboxes.c
+++ b/src/ft2_textboxes.c
@@ -52,7 +52,7 @@
// ------ DISK OP. TEXTBOXES ------
// x, y, w, h, tx,ty, maxc, rmb, cmc
- { 31, 158, 134, 12, 2, 1, PATH_MAX-1, false, true },
+ { 31, 158, 134, 12, 2, 1, PATH_MAX, false, true },
// ------ CONFIG TEXTBOXES ------
// x, y, w, h, tx,ty, maxc, rmb, cmc
--- a/src/ft2_unicode.c
+++ b/src/ft2_unicode.c
@@ -57,7 +57,7 @@
return NULL;
}
- char *x = (char *)malloc((reqSize + 2) * sizeof (char));
+ char *x = (char *)malloc((reqSize + 1) * sizeof (char));
if (x == NULL)
{
free(w);
@@ -64,8 +64,7 @@
return NULL;
}
- x[reqSize+0] = '\0';
- x[reqSize+1] = '\0';
+ x[reqSize] = '\0';
retVal = WideCharToMultiByte(CP_UTF8, 0, w, srcLen, x, reqSize, 0, 0);
free(w);
@@ -148,7 +147,7 @@
return NULL;
}
- char *x = (char *)calloc(reqSize + 1, sizeof (char));
+ char *x = (char *)malloc((reqSize + 1) * sizeof (char));
if (x == NULL)
{
free(w);
@@ -216,7 +215,7 @@
{
const int8_t ch = (const int8_t)x[i];
if (ch < 32 && ch != 0 && ch != -124 && ch != -108 &&
- ch != -122 && ch != -114 && ch != -103 && ch != -113)
+ ch != -122 && ch != -114 && ch != -103 && ch != -113)
{
x[i] = ' '; // character not allowed, turn it into space
}
@@ -244,7 +243,7 @@
size_t outLen = srcLen * 2; // should be sufficient
- char *outBuf = (char *)calloc(outLen + 2, sizeof (char));
+ char *outBuf = (char *)malloc((outLen + 1) * sizeof (char));
if (outBuf == NULL)
return NULL;
@@ -266,6 +265,8 @@
return NULL;
}
+ outBuf[outLen] = '\0';
+
return outBuf;
}
@@ -290,7 +291,7 @@
size_t outLen = srcLen * 2; // should be sufficient
- char *outBuf = (char *)calloc(outLen + 1, sizeof (char));
+ char *outBuf = (char *)malloc((outLen + 1) * sizeof (char));
if (outBuf == NULL)
return NULL;
@@ -312,6 +313,8 @@
return NULL;
}
+ outBuf[outLen] = '\0';
+
if (removeIllegalChars)
{
// remove illegal characters (only allow certain nordic ones)
@@ -319,7 +322,7 @@
{
const int8_t ch = (const int8_t)outBuf[i];
if (ch < 32 && ch != 0 && ch != -124 && ch != -108 &&
- ch != -122 && ch != -114 && ch != -103 && ch != -113)
+ ch != -122 && ch != -114 && ch != -103 && ch != -113)
{
outBuf[i] = ' '; // character not allowed, turn it into space
}
--- a/src/ft2_video.c
+++ b/src/ft2_video.c
@@ -46,7 +46,7 @@
video_t video; // globalized
static bool songIsModified;
-static char wndTitle[128 + PATH_MAX];
+static char wndTitle[256];
static uint64_t timeNext64, timeNext64Frac;
static sprite_t sprites[SPRITE_NUM];
@@ -845,10 +845,14 @@
char *songTitle = getCurrSongFilename();
if (songTitle != NULL)
{
+ char songTitleTrunc[128];
+ strncpy(songTitleTrunc, songTitle, sizeof (songTitleTrunc)-1);
+ songTitleTrunc[sizeof (songTitleTrunc)-1] = '\0';
+
if (song.isModified)
- sprintf(wndTitle, "Fasttracker II clone v%s - \"%s\" (unsaved)", PROG_VER_STR, songTitle);
+ sprintf(wndTitle, "Fasttracker II clone v%s - \"%s\" (unsaved)", PROG_VER_STR, songTitleTrunc);
else
- sprintf(wndTitle, "Fasttracker II clone v%s - \"%s\"", PROG_VER_STR, songTitle);
+ sprintf(wndTitle, "Fasttracker II clone v%s - \"%s\"", PROG_VER_STR, songTitleTrunc);
}
else
{
--- a/src/helpdata/FT2.HLP
+++ b/src/helpdata/FT2.HLP
@@ -923,10 +923,6 @@
and you need to press a key or click the mouse to abort the render when you want
it to.
>@X010
->@C001Mouse / keyboard:
->
->@C002- Linux: The mouse cursor graphics can be glitchy at times...
->@X010
>@C001Video:
>@C002
>@X010- Fullscreen mode can be unbearably slow on a Raspberry Pi (even on RPi 4)
--- a/src/helpdata/ft2_help_data.h
+++ b/src/helpdata/ft2_help_data.h
@@ -3,9 +3,9 @@
#include <stdint.h>
-#define HELP_DATA_LEN 27486
+#define HELP_DATA_LEN 27385
-const uint8_t helpData[27486] =
+const uint8_t helpData[27385] =
{
0x4C,0x3B,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
@@ -2258,46 +2258,38 @@
0x74,0x6F,0x20,0x61,0x62,0x6F,0x72,0x74,0x20,0x74,0x68,0x65,
0x20,0x72,0x65,0x6E,0x64,0x65,0x72,0x20,0x77,0x68,0x65,0x6E,
0x20,0x79,0x6F,0x75,0x20,0x77,0x61,0x6E,0x74,0x06,0x69,0x74,
- 0x20,0x74,0x6F,0x2E,0x06,0x3E,0x40,0x58,0x30,0x31,0x30,0x17,
- 0x3E,0x40,0x43,0x30,0x30,0x31,0x4D,0x6F,0x75,0x73,0x65,0x20,
- 0x2F,0x20,0x6B,0x65,0x79,0x62,0x6F,0x61,0x72,0x64,0x3A,0x01,
- 0x3E,0x43,0x3E,0x40,0x43,0x30,0x30,0x32,0x2D,0x20,0x4C,0x69,
- 0x6E,0x75,0x78,0x3A,0x20,0x54,0x68,0x65,0x20,0x6D,0x6F,0x75,
- 0x73,0x65,0x20,0x63,0x75,0x72,0x73,0x6F,0x72,0x20,0x67,0x72,
- 0x61,0x70,0x68,0x69,0x63,0x73,0x20,0x63,0x61,0x6E,0x20,0x62,
- 0x65,0x20,0x67,0x6C,0x69,0x74,0x63,0x68,0x79,0x20,0x61,0x74,
- 0x20,0x74,0x69,0x6D,0x65,0x73,0x2E,0x2E,0x2E,0x06,0x3E,0x40,
- 0x58,0x30,0x31,0x30,0x0C,0x3E,0x40,0x43,0x30,0x30,0x31,0x56,
- 0x69,0x64,0x65,0x6F,0x3A,0x06,0x3E,0x40,0x43,0x30,0x30,0x32,
- 0x50,0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x46,0x75,0x6C,
- 0x6C,0x73,0x63,0x72,0x65,0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,
- 0x20,0x63,0x61,0x6E,0x20,0x62,0x65,0x20,0x75,0x6E,0x62,0x65,
- 0x61,0x72,0x61,0x62,0x6C,0x79,0x20,0x73,0x6C,0x6F,0x77,0x20,
- 0x6F,0x6E,0x20,0x61,0x20,0x52,0x61,0x73,0x70,0x62,0x65,0x72,
- 0x72,0x79,0x20,0x50,0x69,0x20,0x28,0x65,0x76,0x65,0x6E,0x20,
- 0x6F,0x6E,0x20,0x52,0x50,0x69,0x20,0x34,0x29,0x01,0x3E,0x52,
- 0x3E,0x40,0x58,0x30,0x31,0x30,0x2D,0x20,0x4E,0x6F,0x74,0x20,
- 0x61,0x20,0x62,0x75,0x67,0x2C,0x20,0x62,0x75,0x74,0x20,0x69,
- 0x66,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,
- 0x6F,0x72,0x27,0x73,0x20,0x72,0x65,0x66,0x72,0x65,0x73,0x68,
- 0x20,0x72,0x61,0x74,0x65,0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,
- 0x20,0x73,0x65,0x74,0x20,0x74,0x6F,0x20,0x36,0x30,0x48,0x7A,
- 0x20,0x28,0x6F,0x72,0x20,0x35,0x39,0x48,0x7A,0x29,0x4F,0x3E,
- 0x40,0x58,0x30,0x32,0x31,0x79,0x6F,0x75,0x20,0x6D,0x61,0x79,
- 0x20,0x65,0x78,0x70,0x65,0x72,0x69,0x65,0x6E,0x63,0x65,0x20,
- 0x76,0x69,0x73,0x75,0x61,0x6C,0x20,0x73,0x74,0x75,0x74,0x74,
- 0x65,0x72,0x69,0x6E,0x67,0x20,0x62,0x65,0x63,0x61,0x75,0x73,
- 0x65,0x20,0x56,0x53,0x79,0x6E,0x63,0x20,0x77,0x69,0x6C,0x6C,
- 0x20,0x6E,0x6F,0x74,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,
- 0x20,0x74,0x68,0x65,0x6E,0x2E,0x51,0x49,0x20,0x68,0x69,0x67,
- 0x68,0x6C,0x79,0x20,0x72,0x65,0x63,0x6F,0x6D,0x6D,0x65,0x6E,
- 0x64,0x20,0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x20,0x79,0x6F,
- 0x75,0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x20,0x61,
- 0x74,0x20,0x36,0x30,0x48,0x7A,0x20,0x69,0x66,0x20,0x79,0x6F,
- 0x75,0x27,0x72,0x65,0x20,0x61,0x20,0x68,0x61,0x72,0x64,0x63,
- 0x6F,0x72,0x65,0x20,0x75,0x73,0x65,0x72,0x20,0x6F,0x66,0x20,
- 0x74,0x68,0x69,0x73,0x08,0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,
- 0x2E,0x00,0x03,0x45,0x4E,0x44
+ 0x20,0x74,0x6F,0x2E,0x06,0x3E,0x40,0x58,0x30,0x31,0x30,0x0C,
+ 0x3E,0x40,0x43,0x30,0x30,0x31,0x56,0x69,0x64,0x65,0x6F,0x3A,
+ 0x06,0x3E,0x40,0x43,0x30,0x30,0x32,0x50,0x3E,0x40,0x58,0x30,
+ 0x31,0x30,0x2D,0x20,0x46,0x75,0x6C,0x6C,0x73,0x63,0x72,0x65,
+ 0x65,0x6E,0x20,0x6D,0x6F,0x64,0x65,0x20,0x63,0x61,0x6E,0x20,
+ 0x62,0x65,0x20,0x75,0x6E,0x62,0x65,0x61,0x72,0x61,0x62,0x6C,
+ 0x79,0x20,0x73,0x6C,0x6F,0x77,0x20,0x6F,0x6E,0x20,0x61,0x20,
+ 0x52,0x61,0x73,0x70,0x62,0x65,0x72,0x72,0x79,0x20,0x50,0x69,
+ 0x20,0x28,0x65,0x76,0x65,0x6E,0x20,0x6F,0x6E,0x20,0x52,0x50,
+ 0x69,0x20,0x34,0x29,0x01,0x3E,0x52,0x3E,0x40,0x58,0x30,0x31,
+ 0x30,0x2D,0x20,0x4E,0x6F,0x74,0x20,0x61,0x20,0x62,0x75,0x67,
+ 0x2C,0x20,0x62,0x75,0x74,0x20,0x69,0x66,0x20,0x79,0x6F,0x75,
+ 0x72,0x20,0x6D,0x6F,0x6E,0x69,0x74,0x6F,0x72,0x27,0x73,0x20,
+ 0x72,0x65,0x66,0x72,0x65,0x73,0x68,0x20,0x72,0x61,0x74,0x65,
+ 0x20,0x69,0x73,0x20,0x6E,0x6F,0x74,0x20,0x73,0x65,0x74,0x20,
+ 0x74,0x6F,0x20,0x36,0x30,0x48,0x7A,0x20,0x28,0x6F,0x72,0x20,
+ 0x35,0x39,0x48,0x7A,0x29,0x4F,0x3E,0x40,0x58,0x30,0x32,0x31,
+ 0x79,0x6F,0x75,0x20,0x6D,0x61,0x79,0x20,0x65,0x78,0x70,0x65,
+ 0x72,0x69,0x65,0x6E,0x63,0x65,0x20,0x76,0x69,0x73,0x75,0x61,
+ 0x6C,0x20,0x73,0x74,0x75,0x74,0x74,0x65,0x72,0x69,0x6E,0x67,
+ 0x20,0x62,0x65,0x63,0x61,0x75,0x73,0x65,0x20,0x56,0x53,0x79,
+ 0x6E,0x63,0x20,0x77,0x69,0x6C,0x6C,0x20,0x6E,0x6F,0x74,0x20,
+ 0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x74,0x68,0x65,0x6E,
+ 0x2E,0x51,0x49,0x20,0x68,0x69,0x67,0x68,0x6C,0x79,0x20,0x72,
+ 0x65,0x63,0x6F,0x6D,0x6D,0x65,0x6E,0x64,0x20,0x72,0x75,0x6E,
+ 0x6E,0x69,0x6E,0x67,0x20,0x79,0x6F,0x75,0x72,0x20,0x6D,0x6F,
+ 0x6E,0x69,0x74,0x6F,0x72,0x20,0x61,0x74,0x20,0x36,0x30,0x48,
+ 0x7A,0x20,0x69,0x66,0x20,0x79,0x6F,0x75,0x27,0x72,0x65,0x20,
+ 0x61,0x20,0x68,0x61,0x72,0x64,0x63,0x6F,0x72,0x65,0x20,0x75,
+ 0x73,0x65,0x72,0x20,0x6F,0x66,0x20,0x74,0x68,0x69,0x73,0x08,
+ 0x70,0x72,0x6F,0x67,0x72,0x61,0x6D,0x2E,0x00,0x03,0x45,0x4E,
+ 0x44
};
#endif