* Remove the KML folder from the KML URL.

* Add the state file name in the save toast.
This commit is contained in:
dgis 2020-07-31 00:04:12 +02:00
parent 588c5dc3df
commit c5d135d73f
9 changed files with 207 additions and 139 deletions

View file

@ -196,9 +196,23 @@ The Eric's Real scripts ("real*.kml" and "real*.bmp/png") are embedded in this a
TODO
- Android 11 new storage issues :-(
- Move the KML folder in the JSON settings embedded in the state file because Windows cannot open the state file with KML url longer than 256 byte.
* Need to set szEmuDirectory (and may be szRomDirectory for Emu48 only) in onFileNew() before NewDocument().
* If the JSON settings contains the KML folder, we need to set szEmuDirectory (and may be szRomDirectory for Emu48 only) in onFileOpen() before OpenDocument().
Else if NO JSON settings contains the KML folder, we can extract the variable szCurrentKml after OpenDocument().
If szCurrentKml is using the old format, we remove the KML folder part in the variable szCurrentKml and set this KML folder in the JSON setting.
Else if szCurrentKml does not contain the KML folder part, we should prompt the user to select the KML folder (It should solve the next issue).
* Need to change the variable szCurrentKml before saving (in onFileSave()/onFileSaveAs() before SaveDocument()).
* onViewScript should be change too!
- If the KML folder does not exist (like the first time), prompt the user to choose a new KML folder.
- ANR in NativeLib.buttonUp(), should make Win32::InvalidateRect() asynchronous (may be the cause of the lag and freeze).
- Add the name of the file in the toast "State saved".
- The clock seems unsynchronized sometimes.
- Bug: In Xiaomi mi A3 under Android10, the haptic feedback does not work (add an intensity setting).
- Somehow LEFT (Shift on the keyboard) + 7 activates the DIVIDE-key (z-Key)..., but with the NUM-Key it can make it work without problems...
I think it might have something to do with the "/" sign on the Shifted-7-key.
- The render pixels are very nice. A solution to obtain uniform pixel size could be a preset (a multiplier, auto) so the user could decide and upscale/downscale (Michael P).
- The clock seems unsynchronized sometimes (Michael P).
- Retain a key by right clicking if it is from a mouse.
- Add the possibility to load and save the flash in another file.
- Sometimes, the calculator seems to lag and finally freeze.
@ -209,7 +223,7 @@ TODO
BUILD
Emu48 for Android is built with Android Studio 3.5 (2019).
Emu48 for Android is built with Android Studio 4.0 (2020).
And to generate an installable APK file with a real Android device, it MUST be signed.
Either use Android Studio:

View file

@ -489,29 +489,37 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_getMacroState(JNIE
}
JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onFileNew(JNIEnv *env, jobject thisz, jstring kmlFilename) {
if (bDocumentAvail)
{
JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onFileNew(JNIEnv *env, jobject thisz, jstring kmlFilename, jstring kmlFolder) {
if (bDocumentAvail) {
SwitchToState(SM_INVALID);
if(bAutoSave) {
SaveDocument();
}
}
const char *filenameUTF8 = (*env)->GetStringUTFChars(env, kmlFilename , NULL) ;
const char *filenameUTF8 = (*env)->GetStringUTFChars(env, kmlFilename, NULL);
chooseCurrentKmlMode = ChooseKmlMode_FILE_NEW;
_tcscpy(szChosenCurrentKml, filenameUTF8);
(*env)->ReleaseStringUTFChars(env, kmlFilename, filenameUTF8);
TCHAR * fileScheme = _T("document:");
TCHAR * urlSchemeFound = _tcsstr(szChosenCurrentKml, fileScheme);
TCHAR * documentScheme = _T("document:");
TCHAR * urlSchemeFound = _tcsstr(szChosenCurrentKml, documentScheme);
if(urlSchemeFound) {
_tcscpy(szEmuDirectory, szChosenCurrentKml + _tcslen(fileScheme) * sizeof(TCHAR));
TCHAR * filename = _tcschr(szEmuDirectory, _T('|'));
if(filename) {
*filename = _T('\0');
}
_tcscpy(szRomDirectory, szEmuDirectory);
if(kmlFolder) {
const char *kmlFolderUTF8 = (*env)->GetStringUTFChars(env, kmlFolder, NULL);
// The folder URL is separated from the script filename and comes from the JSON settings in the state file.
_tcscpy(szEmuDirectory, kmlFolderUTF8);
_tcscpy(szRomDirectory, kmlFolderUTF8);
(*env)->ReleaseStringUTFChars(env, kmlFolder, kmlFolderUTF8);
} else {
// Keep the compatibility by allowing to put the KML folder combined with the KML script filename with a document: scheme.
_tcscpy(szEmuDirectory, szChosenCurrentKml + _tcslen(documentScheme) * sizeof(TCHAR));
TCHAR * filename = _tcschr(szEmuDirectory, _T('|'));
if(filename) {
*filename = _T('\0');
}
_tcscpy(szRomDirectory, szEmuDirectory);
}
} else {
_tcscpy(szEmuDirectory, "assets/calculators/");
_tcscpy(szRomDirectory, "assets/calculators/");
@ -535,26 +543,32 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onFileNew(JNIEnv *
}
return result;
}
JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onFileOpen(JNIEnv *env, jobject thisz, jstring stateFilename) {
if (bDocumentAvail)
{
JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onFileOpen(JNIEnv *env, jobject thisz, jstring stateFilename, jstring kmlFolder) {
if (bDocumentAvail) {
SwitchToState(SM_INVALID);
if(bAutoSave) {
SaveDocument();
}
}
const char *stateFilenameUTF8 = (*env)->GetStringUTFChars(env, stateFilename , NULL) ;
const char *stateFilenameUTF8 = (*env)->GetStringUTFChars(env, stateFilename, NULL);
_tcscpy(szBufferFilename, stateFilenameUTF8);
(*env)->ReleaseStringUTFChars(env, stateFilename, stateFilenameUTF8);
chooseCurrentKmlMode = ChooseKmlMode_FILE_OPEN;
if(kmlFolder) {
const char *kmlFolderUTF8 = (*env)->GetStringUTFChars(env, kmlFolder, NULL);
// The folder URL is separated from the script filename (not in the document: URL) and comes from the JSON settings in the state file.
_tcscpy(szEmuDirectory, kmlFolderUTF8);
_tcscpy(szRomDirectory, kmlFolderUTF8);
(*env)->ReleaseStringUTFChars(env, kmlFolder, kmlFolderUTF8);
}
chooseCurrentKmlMode = ChooseKmlMode_FILE_OPEN;
lastKMLFilename[0] = '\0';
BOOL result = OpenDocument(szBufferFilename);
if (result) {
if(hLcdDC && hLcdDC->selectedBitmap) {
hLcdDC->selectedBitmap->bitmapInfoHeader->biHeight = -abs(hLcdDC->selectedBitmap->bitmapInfoHeader->biHeight);
}
//MruAdd(szBufferFilename);
}
chooseCurrentKmlMode = ChooseKmlMode_UNKNOWN;
mainViewResizeCallback(nBackgroundW, nBackgroundH);
@ -562,7 +576,6 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onFileOpen(JNIEnv
if (pbyRom) SwitchToState(SM_RUN);
}
draw();
(*env)->ReleaseStringUTFChars(env, stateFilename, stateFilenameUTF8);
if(securityExceptionOccured) {
securityExceptionOccured = FALSE;
result = -2;
@ -694,6 +707,16 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onObjectLoad(JNIEn
return TRUE;
}
JNIEXPORT jstring JNICALL Java_org_emulator_calculator_NativeLib_getCurrentKml(JNIEnv *env, jobject thisz) {
jstring result = (*env)->NewStringUTF(env, szCurrentKml);
return result;
}
JNIEXPORT void JNICALL Java_org_emulator_calculator_NativeLib_setCurrentKml(JNIEnv *env, jobject thisz, jstring currentKml) {
const char *currentKmlUTF8 = (*env)->GetStringUTFChars(env, currentKml, NULL);
_tcscpy(szCurrentKml, currentKmlUTF8);
(*env)->ReleaseStringUTFChars(env, currentKml, currentKmlUTF8);
}
JNIEXPORT jobjectArray JNICALL Java_org_emulator_calculator_NativeLib_getObjectsToSave(JNIEnv *env, jobject thisz) {
return 0;
}
@ -849,55 +872,29 @@ JNIEXPORT void JNICALL Java_org_emulator_calculator_NativeLib_onViewReset(JNIEnv
SwitchToState(SM_RUN);
}
JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onViewScript(JNIEnv *env, jobject thisz, jstring kmlFilename) {
JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onViewScript(JNIEnv *env, jobject thisz, jstring kmlFilename, jstring kmlFolder) {
TCHAR szKmlFile[MAX_PATH];
// BOOL bKMLChanged,bSucc;
BYTE cType = cCurrentRomType;
SwitchToState(SM_INVALID);
// make a copy of the current KML script file name
_ASSERT(sizeof(szKmlFile) == sizeof(szCurrentKml));
lstrcpyn(szKmlFile,szCurrentKml,ARRAYSIZEOF(szKmlFile));
const char *filenameUTF8 = (*env)->GetStringUTFChars(env, kmlFilename , NULL) ;
_tcscpy(szCurrentKml, filenameUTF8);
(*env)->ReleaseStringUTFChars(env, kmlFilename, filenameUTF8);
// bKMLChanged = FALSE; // KML script not changed
BOOL bSucc = TRUE; // KML script successful loaded
const char *kmlFolderUTF8 = (*env)->GetStringUTFChars(env, kmlFolder, NULL);
if(kmlFolderUTF8) {
// The folder URL is separated from the script filename and comes from the JSON settings in the state file.
_tcscpy(szEmuDirectory, kmlFolderUTF8);
_tcscpy(szRomDirectory, kmlFolderUTF8);
(*env)->ReleaseStringUTFChars(env, kmlFolder, kmlFolderUTF8);
}
chooseCurrentKmlMode = ChooseKmlMode_CHANGE_KML;
chooseCurrentKmlMode = ChooseKmlMode_CHANGE_KML;
// do
// {
// if (!DisplayChooseKml(cType)) // quit with Cancel
// {
// if (!bKMLChanged) // KML script not changed
// break; // exit loop with current loaded KML script
//
// // restore KML script file name
// lstrcpyn(szCurrentKml,szKmlFile,ARRAYSIZEOF(szCurrentKml));
//
// // try to restore old KML script
// if ((bSucc = InitKML(szCurrentKml,FALSE)))
// break; // exit loop with success
//
// // restoring failed, save document
// if (IDCANCEL != SaveChanges(bAutoSave))
// break; // exit loop with no success
//
// _ASSERT(bSucc == FALSE); // for continuing loop
// }
// else // quit with Ok
// {
// bKMLChanged = TRUE; // KML script changed
bSucc = InitKML(szCurrentKml,FALSE);
// }
// }
// while (!bSucc); // retry if KML script is invalid
BOOL result = bSucc;
BOOL bSucc = InitKML(szCurrentKml,FALSE);
if(!bSucc) {
// restore KML script file name
@ -912,8 +909,7 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onViewScript(JNIEn
}
chooseCurrentKmlMode = ChooseKmlMode_UNKNOWN;
if (bSucc)
{
if (bSucc) {
if(hLcdDC && hLcdDC->selectedBitmap) {
hLcdDC->selectedBitmap->bitmapInfoHeader->biHeight = -abs(hLcdDC->selectedBitmap->bitmapInfoHeader->biHeight);
}
@ -928,14 +924,12 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onViewScript(JNIEn
Chipset.wRomCrc = wRomCrc; // update current ROM fingerprint
}
if (pbyRom) SwitchToState(SM_RUN); // continue emulation
}
else
{
} else {
ResetDocument(); // close document
SetWindowTitle(NULL);
}
return result;
return bSucc;
}
JNIEXPORT void JNICALL Java_org_emulator_calculator_NativeLib_onBackupSave(JNIEnv *env, jobject thisz) {

View file

@ -41,6 +41,8 @@ size_t assetsPrefixLength;
const TCHAR * contentScheme = _T("content://");
size_t contentSchemeLength;
const TCHAR * documentScheme = _T("document:");
TCHAR szFilePathTmp[MAX_PATH];
DWORD GetLastError(VOID) {
@ -80,8 +82,9 @@ DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer) {
return 0;
}
BOOL SetCurrentDirectory(LPCTSTR path)
{
BOOL SetCurrentDirectory(LPCTSTR path) {
// Set the current directory for the next calls to CreateFile() API with a relative path.
szCurrentContentDirectory = NULL;
szCurrentAssetDirectory = NULL;
@ -89,21 +92,22 @@ BOOL SetCurrentDirectory(LPCTSTR path)
return FALSE;
if(_tcsncmp(path, contentScheme, contentSchemeLength) == 0) {
// Set the current directory with an URL with the scheme "content://".
szCurrentContentDirectory = (LPTSTR) path;
return TRUE;
} else if(_tcsncmp(path, assetsPrefix, assetsPrefixLength) == 0) {
// Set the current directory with a path to target the Android asset folders (embedded in the app).
szCurrentAssetDirectory = (LPTSTR) (path + assetsPrefixLength * sizeof(TCHAR));
return TRUE;
} else {
} else
// Set the current directory using the file system "chdir" API. Deprecated, not supported by Android >= 10.
return (BOOL) chdir(path);
}
}
extern BOOL settingsPort2en;
extern BOOL settingsPort2wr;
HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, LPVOID hTemplateFile)
{
HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, LPVOID hTemplateFile) {
FILE_LOGD("CreateFile(lpFileName: \"%s\", dwDesiredAccess: 0x%08x)", lpFileName, dwShareMode);
BOOL forceNormalFile = FALSE;
securityExceptionOccured = FALSE;
@ -120,65 +124,68 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
TCHAR * urlContentSchemeFound = _tcsstr(lpFileName, contentScheme);
if(chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN || chooseCurrentKmlMode == ChooseKmlMode_CHANGE_KML) {
// When we open a new E48 state document
// Deal with the KML file and its containing folder
// A E48 state file can contain a path to the KML script.
if(foundDocumentScheme) {
// With a recorded "document:" scheme, extract the folder URL with content:// scheme
// document: is only for a KML file
_tcscpy(szEmuDirectory, lpFileName + _tcslen(documentScheme) * sizeof(TCHAR));
TCHAR * filename = _tcschr(szEmuDirectory, _T('|'));
if(filename) {
// When the state file is created or saved with this Android version,
// an URL like: document:content://<KMLFolderURL>|content://<KMLFileURL>
// is created and saved in the state file.
// Here we want to open a file (lpFileName) which contains the prefix "document:"
// So, we are loading a KML script.
// We extract the KML File URL with "content://" scheme (in the variable "filename"),
// and we extract the folder URL with "content://" scheme (in the variable "szEmuDirectory"/"szRomDirectory" and "szCurrentContentDirectory")
// which should contain the script and its dependencies like the includes, the images and the ROMs.
_tcscpy(szFilePathTmp, lpFileName + _tcslen(documentScheme) * sizeof(TCHAR));
TCHAR * filename = _tcschr(szFilePathTmp, _T('|'));
if(filename)
*filename = _T('\0');
if(szFilePathTmp[0]) {
// If szFilePathTmp is empty, this mean that the variable "szEmuDirectory", "szRomDirectory"
// and "szCurrentContentDirectory" are set before that method, using the JSON settings embedded in the state file.
_tcscpy(szEmuDirectory, szFilePathTmp);
#if EMUXX == 48
_tcscpy(szRomDirectory, szFilePathTmp);
#endif
SetCurrentDirectory(szFilePathTmp);
}
#if EMUXX == 48
_tcscpy(szRomDirectory, szEmuDirectory);
#endif
SetCurrentDirectory(szEmuDirectory);
} else {
TCHAR * fileExtension = _tcsrchr(lpFileName, _T('.'));
if (fileExtension &&
((fileExtension[1] == 'K' && fileExtension[2] == 'M' && fileExtension[3] == 'L') ||
(fileExtension[1] == 'k' && fileExtension[2] == 'm' && fileExtension[3] == 'l')
)) {
// And opening a KML file
if(lpFileName[0] == '/') {
// With a recorded standard file
_tcscpy(szEmuDirectory, lpFileName);
TCHAR * filename = _tcsrchr(szEmuDirectory, _T('/'));
if(filename) {
*filename = _T('\0');
}
TCHAR * fileExtension = _tcsrchr(lpFileName, _T('.'));
if (fileExtension &&
((fileExtension[1] == 'K' && fileExtension[2] == 'M' && fileExtension[3] == 'L') ||
(fileExtension[1] == 'k' && fileExtension[2] == 'm' && fileExtension[3] == 'l')
)) {
if(lpFileName[0] == '/') {
// We are loading a standard KML script from the folder inside the filesystem.
// We directly set the variable "szEmuDirectory"/"szRomDirectory" and "szCurrentAssetDirectory" with the KML folder
// which contain the script and its dependencies like the includes, the images and the ROMs.
// Deprecated, not supported by Android >= 10.
_tcscpy(szEmuDirectory, lpFileName);
TCHAR * filename = _tcsrchr(szEmuDirectory, _T('/'));
if(filename) {
*filename = _T('\0');
}
#if EMUXX == 48
_tcscpy(szRomDirectory, szEmuDirectory);
_tcscpy(szRomDirectory, szEmuDirectory);
#endif
SetCurrentDirectory(szEmuDirectory);
// } else if(foundDocumentScheme) {
// // With a recorded "document:" scheme, extract the folder URL with content:// scheme
// _tcscpy(szEmuDirectory, lpFileName + _tcslen(documentScheme) * sizeof(TCHAR));
// TCHAR * filename = _tcschr(szEmuDirectory, _T('|'));
// if(filename) {
// *filename = _T('\0');
// }
//#if EMUXX == 48
// _tcscpy(szRomDirectory, szEmuDirectory);
//#endif
// SetCurrentDirectory(szEmuDirectory);
} else {
_tcscpy(szEmuDirectory, "assets/calculators/");
SetCurrentDirectory(szEmuDirectory);
} else {
// We are loading a KML script from the embedded asset folder inside the Android App.
// We directly set the variable "szEmuDirectory"/"szRomDirectory" and "szCurrentAssetDirectory" with the KML folder
// which contain the script and its dependencies like the includes, the images and the ROMs.
_tcscpy(szEmuDirectory, "assets/calculators/");
#if EMUXX == 48
_tcscpy(szRomDirectory, "assets/calculators/");
_tcscpy(szRomDirectory, "assets/calculators/");
#endif
SetCurrentDirectory(szEmuDirectory);
}
}
}
SetCurrentDirectory(szEmuDirectory);
}
}
}
}
if(!forceNormalFile
&& (szCurrentAssetDirectory || _tcsncmp(lpFileName, assetsPrefix, assetsPrefixLength) == 0)
&& foundDocumentScheme == NULL
&& urlContentSchemeFound == NULL) {
// Asset file
// Loading a file from the Android asset folders (embedded in the app)
TCHAR szFileName[MAX_PATH];
AAsset * asset = NULL;
szFileName[0] = _T('\0');
@ -197,7 +204,10 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
return handle;
}
} else {
// Normal file
// Loading a "normal" file
// * either a file with the scheme "content://"
// * or a file with a simple name but within the current folder (szCurrentContentDirectory)
// * or a file with the scheme "file://". Deprecated not supported by Android >= 10.
BOOL useOpenFileFromContentResolver = FALSE;
int flags = O_RDWR;
int fd = -1;
@ -223,7 +233,7 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
}
if(urlContentSchemeFound) {
// Case of an absolute file with the scheme content://
// Case of an absolute file with the scheme "content://".
fd = openFileFromContentResolver(lpFileName, dwDesiredAccess);
useOpenFileFromContentResolver = TRUE;
if(fd < 0) {
@ -232,13 +242,14 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
securityExceptionOccured = TRUE;
}
} else if(szCurrentContentDirectory) {
// Case of a relative file to a folder with the scheme content://
// Case of a relative file to a folder with the scheme "content://".
fd = openFileInFolderFromContentResolver(lpFileName, szCurrentContentDirectory, dwDesiredAccess);
useOpenFileFromContentResolver = TRUE;
if(fd == -1) {
FILE_LOGD("CreateFile() openFileFromContentResolver() %d", errno);
}
} else {
// Case of an absolute file with the scheme "file://". Deprecated not supported by Android >= 10.
TCHAR * urlFileSchemeFound = _tcsstr(lpFileName, _T("file://"));
if(urlFileSchemeFound)
lpFileName = urlFileSchemeFound + 7;

View file

@ -18,6 +18,9 @@ import android.app.Activity;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NativeLib {
static {
@ -49,12 +52,14 @@ public class NativeLib {
public static native int getGlobalColor();
public static native int getMacroState();
public static native int onFileNew(String kmlFilename);
public static native int onFileOpen(String filename);
public static native int onFileNew(String kmlFilename, String kmlFolder);
public static native int onFileOpen(String filename, String kmlFolder);
public static native int onFileSave();
public static native int onFileSaveAs(String newFilename);
public static native int onFileClose();
public static native int onObjectLoad(String filename);
public static native String getCurrentKml();
public static native void setCurrentKml(String currentKml);
public static native String[] getObjectsToSave();
public static native int onObjectSave(String filename, boolean[] objectsToSaveItemChecked);
@ -62,7 +67,7 @@ public class NativeLib {
public static native void onStackCopy();
public static native void onStackPaste();
public static native void onViewReset();
public static native int onViewScript(String kmlFilename);
public static native int onViewScript(String kmlFilename, String kmlFolder);
public static native void onBackupSave();
public static native void onBackupRestore();
public static native void onBackupDelete();

View file

@ -49,10 +49,19 @@ public class Settings extends PreferenceDataStore {
protected final boolean debug = false;
private final SharedPreferences androidSettings;
// Defined the setting keys which are only defined at the application level.
private List<String> applicationSettingKeys = Arrays.asList("settings_kml_default", "settings_kml_folder", "lastDocument", "MRU");
// The settings only defined at the application level.
private final HashMap<String, Object> applicationSettings = new HashMap<>();
// The commonSettings are used when no calculator is loaded, and are the default settings of the embeddedStateSettings.
private final HashMap<String, Object> commonSettings = new HashMap<>();
// The embeddedStateSettings are saved in the calculator state file.
private final HashMap<String, Object> embeddedStateSettings = new HashMap<>();
private boolean isCommonSettings = true;
public interface OnOneKeyChangedListener {

View file

@ -438,7 +438,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}
class KMLScriptItem {
public String filename;
public String filename;
public String folder;
public String title;
public String model;
}
@ -450,6 +451,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
kmlScripts = new ArrayList<>();
if(kmlFolderUseDefault) {
// We use the default KML scripts and ROMs from the embedded asset folder inside the Android app.
AssetManager assetManager = getAssets();
String[] calculatorsAssetFilenames = new String[0];
try {
@ -483,7 +485,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
if (inGlobal) {
if (mLine.indexOf("End") == 0) {
KMLScriptItem newKMLScriptItem = new KMLScriptItem();
newKMLScriptItem.filename = calculatorFilename;
newKMLScriptItem.filename = calculatorFilename;
newKMLScriptItem.folder = null;
newKMLScriptItem.title = title;
newKMLScriptItem.model = model;
kmlScripts.add(newKMLScriptItem);
@ -516,7 +519,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}
}
} else {
Uri kmlFolderUri = Uri.parse(kmlFolderURL);
// We use the custom KML scripts and ROMs from a chosen folder.
Uri kmlFolderUri = Uri.parse(kmlFolderURL);
List<String> calculatorsAssetFilenames = new LinkedList<>();
DocumentFile kmlFolderDocumentFile = DocumentFile.fromTreeUri(this, kmlFolderUri);
@ -561,7 +565,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
if (inGlobal) {
if (mLine.indexOf("End") == 0) {
KMLScriptItem newKMLScriptItem = new KMLScriptItem();
newKMLScriptItem.filename = kmlFolderUseDefault ? calculatorFilename : "document:" + kmlFolderURL + "|" + calculatorFilename;
//newKMLScriptItem.filename = kmlFolderUseDefault ? calculatorFilename : "document:" + kmlFolderURL + "|" + calculatorFilename;
newKMLScriptItem.filename = "document:|" + calculatorFilename;
newKMLScriptItem.folder = kmlFolderURL;
newKMLScriptItem.title = title;
newKMLScriptItem.model = model;
kmlScripts.add(newKMLScriptItem);
@ -647,7 +653,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
ensureDocumentSaved(() -> showKMLPicker(false) );
}
private void newFileFromKML(String kmlScriptFilename) {
private void newFileFromKML(String kmlScriptFilename, String kmlScriptFolder) {
// Eventually, close the previous state file
NativeLib.onFileClose();
showCalculatorView(false);
@ -661,12 +667,15 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
updateFromPreferences(null, false);
// Create a new genuine state file
int result = NativeLib.onFileNew(kmlScriptFilename);
int result = NativeLib.onFileNew(kmlScriptFilename, kmlScriptFolder);
if(result > 0) {
showCalculatorView(true);
displayFilename("");
showKMLLog();
suggestToSaveNewFile();
// Note: kmlScriptFolder should be equal to kmlFolderURL!
// We keep the global settings_kml_folder distinct from embedded settings_kml_folder_embedded.
settings.putString("settings_kml_folder_embedded", kmlScriptFolder);
suggestToSaveNewFile();
} else
showKMLLogForce();
updateNavigationDrawerItems();
@ -942,9 +951,10 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
else
OnFileNew();
} else {
String kmlScriptFilename = kmlScriptsForCurrentModel.get(which).filename;
KMLScriptItem scriptItem = kmlScriptsForCurrentModel.get(which);
if(changeKML) {
int result = NativeLib.onViewScript(kmlScriptFilename);
// We only change the KML script here.
int result = NativeLib.onViewScript(scriptItem.filename, scriptItem.folder);
if(result > 0) {
displayKMLTitle();
showKMLLog();
@ -952,7 +962,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
showKMLLogForce();
updateNavigationDrawerItems();
} else
newFileFromKML(kmlScriptFilename);
// We create a new calculator with a specific KML script.
newFileFromKML(scriptItem.filename, scriptItem.folder);
}
}).show();
}
@ -1062,11 +1073,11 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
case INTENT_GETSAVEFILENAME: {
if(debug) Log.d(TAG, "onActivityResult INTENT_GETSAVEFILENAME " + url);
if (NativeLib.onFileSaveAs(url) != 0) {
showAlert(getString(R.string.message_state_saved));
settings.saveInStateFile(this, url);
saveLastDocument(url);
Utils.makeUriPersistable(this, data, uri);
displayFilename(url);
showAlert(String.format(Locale.US, getString(R.string.message_state_saved), getFilenameFromURL(url)));
if (fileSaveAsCallback != null)
fileSaveAsCallback.run();
}
@ -1187,14 +1198,36 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
settings.clearEmbeddedStateSettings();
settings.loadFromStateFile(this, url);
String kmlScriptFolder = settings.getString("settings_kml_folder_embedded", null);
// Update the Emu VM with the new settings
updateFromPreferences(null, false);
// Load the genuine state file
int result = NativeLib.onFileOpen(url);
int result = NativeLib.onFileOpen(url, kmlScriptFolder);
if(result > 0) {
setPort1Settings(NativeLib.getPort1Plugged(), NativeLib.getPort1Writable()); //TODO is it in the true state file or in settings?
if(kmlScriptFolder == null) {
// The KML folder is not in the JSON settings embedded in the state file,
// so, we need to extract it and change the variable szCurrentKml
String currentKml = NativeLib.getCurrentKml();
Pattern patternKMLDocumentURL = Pattern.compile("document:([^|]*)\\|(.+)");
Matcher m = patternKMLDocumentURL.matcher(currentKml);
if (m.find() && m.groupCount() == 2) {
kmlScriptFolder = m.group(1);
String kmlScriptFilename = m.group(2);
if(kmlScriptFolder != null && kmlScriptFolder.length() > 0) {
settings.putString("settings_kml_folder_embedded", kmlScriptFolder);
NativeLib.setCurrentKml("document:|" + kmlScriptFilename);
} else {
//TODO We should prompt the user to choose the KML folder?
// It should not happen here with custom KML folder because result should be 0!
}
}
// String kmlScriptFolder = NativeLib.getEmuDirectory();
// settings.putString("settings_kml_folder_embedded", kmlScriptFolder);
}
showCalculatorView(true);
displayFilename(url);
showKMLLog();
@ -1210,8 +1243,10 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
private void onFileSave() {
if (NativeLib.onFileSave() == 1) {
settings.saveInStateFile(this, NativeLib.getCurrentFilename());
showAlert(getString(R.string.message_state_saved));
String currentFilenameUrl = NativeLib.getCurrentFilename();
settings.saveInStateFile(this, currentFilenameUrl);
String currentFilename = getFilenameFromURL(currentFilenameUrl);
showAlert(String.format(Locale.US, getString(R.string.message_state_saved), currentFilename));
}
}

View file

@ -80,7 +80,7 @@
<string name="message_open_security_description">For security reason, you must select the folder where are the KML and ROM files and then, reopen this file!</string>
<string name="message_open_security_retry">Please, open again</string>
<string name="message_open_security_retry_description">I hope now you could open again the state file.</string>
<string name="message_state_saved">State saved</string>
<string name="message_state_saved">State saved in "%s".</string>
<string name="message_do_you_want_to_save">Do you want to save changes?\n(BACK to cancel)</string>
<string name="message_save_new_file">Do you want to save this new state file?\n(To avoid losing the state of the machine)</string>
<string name="message_yes">Yes</string>

View file

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:4.0.1'
// NOTE: Do not place your application dependencies here; they belong

View file

@ -1,6 +1,6 @@
#Wed Feb 26 12:01:15 CET 2020
#Mon Jun 01 16:14:55 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip