diff --git a/ChangeLog b/ChangeLog
index 553d0bc8..391a48b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2016-02-11
+ Added export to mobile command (SDL)
+ Added Desktop shortcut command (android)
+
2015-12-05
Implemented loading recent files via ALT+1 .. ALT+9
Fix potential editor crash with empty support widget
diff --git a/configure.ac b/configure.ac
index 9f887cd6..4369793a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ dnl This program is distributed under the terms of the GPL v2.0
dnl Download the GNU Public License (GPL) from www.gnu.org
dnl
-AC_INIT([smallbasic], [0.12.3])
+AC_INIT([smallbasic], [0.12.5])
AC_CONFIG_SRCDIR([configure.ac])
AC_CANONICAL_TARGET
diff --git a/ide/android/AndroidManifest.xml b/ide/android/AndroidManifest.xml
index 266a066b..e1b671ff 100644
--- a/ide/android/AndroidManifest.xml
+++ b/ide/android/AndroidManifest.xml
@@ -2,8 +2,8 @@
+ android:versionCode="19"
+ android:versionName="0.12.5">
@@ -64,5 +64,6 @@
+
diff --git a/ide/android/assets/main.bas b/ide/android/assets/main.bas
index ab7c2f53..284ee3e1 100644
--- a/ide/android/assets/main.bas
+++ b/ide/android/assets/main.bas
@@ -55,7 +55,7 @@ sub do_about()
print "(_ ._ _ _.|||_) /\ (_ |/ "
print "__)| | |(_||||_)/--\__)|\_"
print
- print "Version 0.12.3"
+ print "Version 0.12.5"
print
print "Copyright (c) 2002-2015 Chris Warren-Smith"
print "Copyright (c) 1999-2006 Nic Christopoulos" + chr(10)
diff --git a/src/platform/android/Makefile.am b/src/platform/android/Makefile.am
index c2423910..3f612be8 100644
--- a/src/platform/android/Makefile.am
+++ b/src/platform/android/Makefile.am
@@ -17,7 +17,7 @@ test: ant-build-test
(cd ../../../ide/android && \
adb -a logcat -c && \
adb -a shell am start net.sourceforge.smallbasic/net.sourceforge.smallbasic.MainActivity && \
- adb -a logcat)
+ adb -a logcat DEBUG:I smallbasic:I AndroidRuntime:E *:S)
clean-ant:
(cd ../../../ide/android && ant -quiet clean)
diff --git a/src/platform/android/jni/runtime.cpp b/src/platform/android/jni/runtime.cpp
index 5f4002cf..1795d9ef 100644
--- a/src/platform/android/jni/runtime.cpp
+++ b/src/platform/android/jni/runtime.cpp
@@ -89,6 +89,7 @@ void handleCommand(android_app *app, int32_t cmd) {
case APP_CMD_GAINED_FOCUS:
trace("gainedFocus");
runtime->setFocus(true);
+ runtime->redraw();
break;
case APP_CMD_LOST_FOCUS:
trace("lostFocus");
@@ -138,7 +139,7 @@ extern "C" JNIEXPORT void JNICALL Java_net_sourceforge_smallbasic_MainActivity_r
extern "C" JNIEXPORT void JNICALL Java_net_sourceforge_smallbasic_MainActivity_onResize
(JNIEnv *env, jclass jclazz, jint width, jint height) {
- if (runtime != NULL && runtime->isActive() && os_graphics) {
+ if (runtime != NULL && !runtime->isClosing() && runtime->isActive() && os_graphics) {
runtime->onResize(width, height);
}
}
@@ -176,6 +177,10 @@ Runtime::~Runtime() {
pthread_mutex_destroy(&_mutex);
}
+void Runtime::addShortcut(const char *path) {
+ setString("addShortcut", path);
+}
+
void Runtime::alert(const char *title, const char *message) {
logEntered();
@@ -200,8 +205,7 @@ void Runtime::alert(const char *title, bool longDuration) {
_app->activity->vm->AttachCurrentThread(&env, NULL);
jstring titleString = env->NewStringUTF(title);
jclass clazz = env->GetObjectClass(_app->activity->clazz);
- jmethodID method = env->GetMethodID(clazz, "showToast",
- "(Ljava/lang/String;Z)V");
+ jmethodID method = env->GetMethodID(clazz, "showToast", "(Ljava/lang/String;Z)V");
env->CallVoidMethod(_app->activity->clazz, method, titleString, longDuration);
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(titleString);
diff --git a/src/platform/android/jni/runtime.h b/src/platform/android/jni/runtime.h
index 6af9bd5b..ded3cb35 100644
--- a/src/platform/android/jni/runtime.h
+++ b/src/platform/android/jni/runtime.h
@@ -21,6 +21,7 @@ struct Runtime : public System {
Runtime(android_app *app);
virtual ~Runtime();
+ void addShortcut(const char *path);
void alert(const char *title, const char *message);
void alert(const char *title, bool longDuration=true);
int ask(const char *title, const char *prompt, bool cancel);
diff --git a/src/platform/android/src/net/sourceforge/smallbasic/MainActivity.java b/src/platform/android/src/net/sourceforge/smallbasic/MainActivity.java
index d9df0ee5..319cee7f 100644
--- a/src/platform/android/src/net/sourceforge/smallbasic/MainActivity.java
+++ b/src/platform/android/src/net/sourceforge/smallbasic/MainActivity.java
@@ -84,6 +84,23 @@ public class MainActivity extends NativeActivity {
public static native void onResize(int width, int height);
public static native void runFile(String fileName);
+ public void addShortcut(final String path) {
+ Intent shortcut = new Intent(getApplicationContext(), MainActivity.class);
+ shortcut.setAction(Intent.ACTION_MAIN);
+ shortcut.setData(Uri.parse("smallbasic://" + path));
+ Intent intent = new Intent();
+ int index = path.lastIndexOf('/');
+ String name = (index == -1) ? path : path.substring(index + 1);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcut);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
+ Intent.ShortcutIconResource.fromContext(getApplicationContext(),
+ R.drawable.ic_launcher));
+ intent.putExtra("duplicate", false);
+ intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
+ getApplicationContext().sendBroadcast(intent);
+ }
+
public int ask(final String title, final String prompt, final boolean cancel) {
final AskResult result = new AskResult();
final Activity activity = this;
diff --git a/src/platform/sdl/editor.cpp b/src/platform/sdl/editor.cpp
index 31f83dd7..d003a8b1 100644
--- a/src/platform/sdl/editor.cpp
+++ b/src/platform/sdl/editor.cpp
@@ -9,12 +9,16 @@
#include "config.h"
#include "common/sbapp.h"
+#include "common/fs_socket_client.h"
#include "ui/textedit.h"
#include "platform/sdl/runtime.h"
#include "platform/sdl/settings.h"
using namespace strlib;
+String g_exportAddr;
+String g_exportToken;
+
void onlineHelp(Runtime *runtime, TextEditInput *widget) {
char path[100];
const char *nodeId = widget->getNodeId();
@@ -60,6 +64,27 @@ void showRecentFiles(TextEditHelpWidget *helpWidget, String &loadPath) {
helpWidget->setText(fileList);
}
+void exportBuffer(AnsiWidget *out, const char *text, String &dest, String &token) {
+ char buffer[PATH_MAX];
+ dev_file_t f;
+ memset(&f, 0, sizeof(dev_file_t));
+
+ sprintf(f.name, "SOCL:%s\n", dest.c_str());
+ if (dest.indexOf(':', 0) != -1 && sockcl_open(&f)) {
+ sprintf(buffer, "# %s\n", token.c_str());
+ sockcl_write(&f, (byte *)buffer, strlen(buffer));
+ if (!sockcl_write(&f, (byte *)text, strlen(text))) {
+ sprintf(buffer, "Failed to write: %s", dest.c_str());
+ } else {
+ sprintf(buffer, "Exported file to %s", dest.c_str());
+ }
+ sockcl_close(&f);
+ } else {
+ sprintf(buffer, "Failed to open: %s", dest.c_str());
+ }
+ out->setStatus(buffer);
+}
+
void System::editSource(String &loadPath) {
logEntered();
@@ -73,6 +98,9 @@ void System::editSource(String &loadPath) {
TextEditInput *widget = editWidget;
String dirtyFile;
String cleanFile;
+ enum InputMode {
+ kInit, kExportAddr, kExportToken
+ } inputMode = kInit;
setupStatus(dirtyFile, cleanFile, loadPath);
_modifiedTime = getModifiedTime();
@@ -124,7 +152,6 @@ void System::editSource(String &loadPath) {
}
switch (event.key) {
- case SB_KEY_F(3):
case SB_KEY_F(8):
case SB_KEY_F(10):
case SB_KEY_F(11):
@@ -168,6 +195,22 @@ void System::editSource(String &loadPath) {
redraw = false;
onlineHelp((Runtime *)this, editWidget);
break;
+ case SB_KEY_F(4):
+ if (editWidget->getTextLength() && g_exportAddr.length() && g_exportToken.length()) {
+ exportBuffer(_output, editWidget->getText(), g_exportAddr, g_exportToken);
+ break;
+ }
+ // else fallthru to F3 handler
+ case SB_KEY_F(3):
+ if (editWidget->getTextLength()) {
+ saveFile(editWidget, loadPath);
+ _output->setStatus("Export to mobile SmallBASIC. Enter :");
+ widget = helpWidget;
+ helpWidget->createLineEdit(g_exportAddr);
+ helpWidget->show();
+ inputMode = kExportAddr;
+ }
+ break;
case SB_KEY_F(5):
saveFile(editWidget, loadPath);
_output->setStatus("Debug. F6=Step, F7=Continue, Esc=Close");
@@ -269,6 +312,25 @@ void System::editSource(String &loadPath) {
if (helpWidget->replaceMode()) {
_output->setStatus("Replace string with. Esc=Close");
dirty = editWidget->isDirty();
+ } else if (helpWidget->lineEditMode() && helpWidget->getTextLength()) {
+ switch (inputMode) {
+ case kExportAddr:
+ g_exportAddr = helpWidget->getText();
+ inputMode = kExportToken;
+ helpWidget->createLineEdit(g_exportToken);
+ _output->setStatus("Enter token. Esc=Close");
+ break;
+ case kExportToken:
+ g_exportToken = helpWidget->getText();
+ inputMode = kInit;
+ widget = editWidget;
+ exportBuffer(_output, editWidget->getText(), g_exportAddr, g_exportToken);
+ helpWidget->hide();
+ break;
+ default:
+ break;
+ }
+ redraw = true;
} else if (helpWidget->closeOnEnter() && helpWidget->isVisible()) {
if (helpWidget->replaceDoneMode()) {
_output->setStatus(dirtyFile);
diff --git a/src/platform/sdl/runtime.h b/src/platform/sdl/runtime.h
index 5d45b42b..030293e3 100644
--- a/src/platform/sdl/runtime.h
+++ b/src/platform/sdl/runtime.h
@@ -21,6 +21,7 @@ struct Runtime : public System {
Runtime(SDL_Window *window);
virtual ~Runtime();
+ void addShortcut(const char *) {}
void alert(const char *title, const char *message);
int ask(const char *title, const char *prompt, bool cancel);
void browseFile(const char *url);
diff --git a/src/ui/graphics.cpp b/src/ui/graphics.cpp
index 8fc55026..9ff2fc38 100644
--- a/src/ui/graphics.cpp
+++ b/src/ui/graphics.cpp
@@ -314,6 +314,11 @@ int Graphics::getPixel(Canvas *canvas, int posX, int posY) {
&& posY < canvas->_h - 1) {
pixel_t *line = canvas->getLine(posY);
result = line[posX];
+#if defined(PIXELFORMAT_RGBA8888)
+ uint8_t r,g,b;
+ GET_RGB2(result, r, g, b);
+ result = SET_RGB(r, g, b);
+#endif
}
return result;
}
diff --git a/src/ui/system.cpp b/src/ui/system.cpp
index d53b5437..af881048 100644
--- a/src/ui/system.cpp
+++ b/src/ui/system.cpp
@@ -41,7 +41,8 @@
#define MENU_DEBUG 18
#define MENU_OUTPUT 19
#define MENU_HELP 20
-#define MENU_SIZE 21
+#define MENU_SHORTCUT 21
+#define MENU_SIZE 22
#define MENU_COMPETION_0 (MENU_SIZE + 1)
#define MENU_COMPETION_1 (MENU_SIZE + 2)
#define MENU_COMPETION_2 (MENU_SIZE + 3)
@@ -342,6 +343,11 @@ void System::handleMenu(MAEvent &event) {
event.type = EVENT_TYPE_KEY_PRESSED;
event.key = SB_KEY_F(1);
break;
+ case MENU_SHORTCUT:
+ if (_activeFile.length() > 0) {
+ addShortcut(_activeFile.c_str());
+ }
+ break;
case MENU_COMPETION_0:
completeKeyword(0);
break;
@@ -631,22 +637,22 @@ void System::saveFile(TextEditInput *edit, strlib::String &path) {
void System::setBack() {
if (_userScreenId != -1) {
- // restore user screen
+ // return (back) from user screen, (view source)
_output->selectBackScreen(_userScreenId);
_output->selectFrontScreen(_userScreenId);
_userScreenId = -1;
- }
-
- // quit app when shell is active
- setExit(_mainBas);
-
- // follow history when available and not exiting
- if (!_mainBas) {
- // remove the current item
- _history.pop();
- if (_history.peek() != NULL) {
- _loadPath.empty();
- _loadPath.append(_history.peek());
+ } else {
+ // quit app when shell is active
+ setExit(_mainBas);
+
+ // follow history when available and not exiting
+ if (!_mainBas) {
+ // remove the current item
+ _history.pop();
+ if (_history.peek() != NULL) {
+ _loadPath.empty();
+ _loadPath.append(_history.peek());
+ }
}
}
}
@@ -865,6 +871,12 @@ void System::showMenu() {
items->add(new String(buffer));
_systemMenu[index++] = MENU_EDITMODE;
}
+#if !defined(_SDL)
+ if (!_mainBas && _activeFile.length() > 0) {
+ items->add(new String("Desktop Shortcut"));
+ _systemMenu[index++] = MENU_SHORTCUT;
+ }
+#endif
sprintf(buffer, "Audio [%s]", (opt_mute_audio ? "OFF" : "ON"));
items->add(new String(buffer));
_systemMenu[index++] = MENU_AUDIO;
diff --git a/src/ui/system.h b/src/ui/system.h
index 3bea273a..5210729e 100755
--- a/src/ui/system.h
+++ b/src/ui/system.h
@@ -53,6 +53,7 @@ struct System {
kHand, kArrow, kIBeam
};
+ virtual void addShortcut(const char *path) = 0;
virtual void alert(const char *title, const char *message) = 0;
virtual int ask(const char *title, const char *prompt, bool cancel=true) = 0;
virtual void debugStart(TextEditInput *edit, const char *file) = 0;
diff --git a/src/ui/textedit.cpp b/src/ui/textedit.cpp
index 5ed76699..3279dd85 100644
--- a/src/ui/textedit.cpp
+++ b/src/ui/textedit.cpp
@@ -108,6 +108,7 @@ const char *helpText =
"TAB indent line\n"
"F1,A-h keyword help\n"
"F2 online help\n"
+ "F3,F4 export\n"
"F5 debug\n"
"F9, C-r run\n";
@@ -1528,7 +1529,6 @@ bool TextEditHelpWidget::closeOnEnter() const {
bool TextEditHelpWidget::edit(int key, int screenWidth, int charWidth) {
bool result = false;
-
switch (_mode) {
case kSearch:
result = TextEditInput::edit(key, screenWidth, charWidth);
@@ -1558,6 +1558,11 @@ bool TextEditHelpWidget::edit(int key, int screenWidth, int charWidth) {
_editor->gotoLine(_buf._buffer);
}
break;
+ case kLineEdit:
+ if (key != SB_KEY_ENTER) {
+ result = TextEditInput::edit(key, screenWidth, charWidth);
+ }
+ break;
default:
switch (key) {
case STB_TEXTEDIT_K_LEFT:
@@ -1690,6 +1695,13 @@ void TextEditHelpWidget::createHelp() {
_buf.append(helpText, strlen(helpText));
}
+void TextEditHelpWidget::createLineEdit(const char *value) {
+ reset(kLineEdit);
+ if (value && value[0]) {
+ _buf.append(value, strlen(value));
+ }
+}
+
void TextEditHelpWidget::createKeywordIndex() {
char *keyword = _editor->getWordBeforeCursor();
reset(kHelpKeyword);
diff --git a/src/ui/textedit.h b/src/ui/textedit.h
index 29c01072..24955287 100644
--- a/src/ui/textedit.h
+++ b/src/ui/textedit.h
@@ -181,13 +181,15 @@ struct TextEditHelpWidget : public TextEditInput {
kReplace,
kReplaceDone,
kGotoLine,
- kMessage
+ kMessage,
+ kLineEdit
};
void clicked(int x, int y, bool pressed);
void createCompletionHelp();
void createGotoLine();
void createHelp();
+ void createLineEdit(const char *value);
void createKeywordIndex();
void createMessage() { reset(kMessage); }
void createOutline();
@@ -198,6 +200,7 @@ struct TextEditHelpWidget : public TextEditInput {
void resize(int w, int h) { _x = w - _width; _height = h; }
void reset(HelpMode mode);
bool closeOnEnter() const;
+ bool lineEditMode() const { return _mode == kLineEdit; }
bool messageMode() const { return _mode == kMessage; }
bool replaceMode() const { return _mode == kReplace; }
bool replaceDoneMode() const { return _mode == kReplaceDone; }