diff --git a/app/build.gradle b/app/build.gradle
index 809e6af677dd78be25cff49f0439807e3934eb59..c49b79bee6e80b7a58f52218711828a2e6eac54d 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,8 +11,8 @@ android {
         minSdkVersion 9
         targetSdkVersion 23
 
-        versionCode 151
-        versionName "6.4"
+        versionCode 169
+        versionName "6.5"
     }
 
     buildTypes {
@@ -38,9 +38,15 @@ android {
         compile 'com.android.support:appcompat-v7:23.4.0'
     }
 
+    lintOptions {
+        checkReleaseBuilds false
+    }
+
     android.applicationVariants.all { variant ->
+        def formattedDate = new Date().format('hh.mm')
+
         variant.outputs.all {
-            outputFileName = "./${variant.versionName}/${variant.versionCode}.apk"
+            outputFileName = "./${variant.versionName}/${variant.applicationId}_${variant.versionCode}_${formattedDate}.apk"
         }
     }
 
@@ -50,6 +56,5 @@ android {
     }
 }
 dependencies {
-    compile 'com.google.firebase:firebase-database:9.0.0'
-    compile 'com.squareup.okhttp3:okhttp:3.9.0'
+    compile 'com.squareup.okhttp3:okhttp:3.9.1'
 }
\ No newline at end of file
diff --git a/app/src/foss/java/ohi/andre/consolelauncher/FlavorUtils.java b/app/src/foss/java/ohi/andre/consolelauncher/FlavorUtils.java
deleted file mode 100755
index 7bdcdc9d670caab4f8f7fda51dadf38bfe8fa143..0000000000000000000000000000000000000000
--- a/app/src/foss/java/ohi/andre/consolelauncher/FlavorUtils.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package ohi.andre.consolelauncher;
-
-public class FlavorUtils {
-
-    public static void startANR () {
-
-    }
-	
-}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9b3584758be2d9b58194953fe89a5bd001f456ac..2370b0800c4464b1833727eca74ef0969930df16 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,11 +26,11 @@
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
-    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
 
     <permission
@@ -41,68 +41,77 @@
         android:protectionLevel="normal" />
 
     <!-- features -->
-    <uses-feature android:name="android.hardware.camera"
+    <uses-feature
+        android:name="android.hardware.camera"
         android:required="false" />
-    <uses-feature android:name="android.hardware.camera.flash"
+    <uses-feature
+        android:name="android.hardware.camera.flash"
         android:required="false" />
-    <uses-feature android:name="android.hardware.camera.autofocus"
+    <uses-feature
+        android:name="android.hardware.camera.autofocus"
         android:required="false" />
-    <uses-feature android:name="android.hardware.telephony"
+    <uses-feature
+        android:name="android.hardware.telephony"
         android:required="false" />
-    <uses-feature android:name="android.hardware.wifi"
+    <uses-feature
+        android:name="android.hardware.wifi"
         android:required="false" />
-    <uses-feature android:name="android.hardware.touchscreen"
+    <uses-feature
+        android:name="android.hardware.touchscreen"
         android:required="false" />
-    <uses-feature android:name="android.hardware.bluetooth"
+    <uses-feature
+        android:name="android.hardware.bluetooth"
+        android:required="false" />
+    <uses-feature
+        android:name="android.hardware.location.gps"
+        android:required="false" />
+    <uses-feature
+        android:name="android.hardware.location"
+        android:required="false" />
+    <uses-feature
+        android:name="android.hardware.location.network"
+        android:required="false" />
+    <uses-feature
+        android:name="android.hardware.audio.output"
         android:required="false" />
-    <uses-feature android:name="android.hardware.location.gps"
-        android:required="false"/>
-    <uses-feature android:name="android.hardware.location"
-        android:required="false"/>
-    <uses-feature android:name="android.hardware.location.network"
-        android:required="false"/>
-    <uses-feature android:name="android.hardware.audio.output"
-        android:required="false"/>
 
     <application
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
         android:theme="@style/Custom.Solid">
-
         <meta-data
             android:name="firebase_analytics_collection_deactivated"
             android:value="true" />
-        <meta-data android:name="firebase_crash_collection_enabled"
+        <meta-data
+            android:name="firebase_crash_collection_enabled"
             android:value="false" />
 
         <activity
             android:name=".LauncherActivity"
+            android:clearTaskOnLaunch="true"
             android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
-
+            android:enabled="true"
+            android:excludeFromRecents="true"
             android:launchMode="singleTask"
-            android:clearTaskOnLaunch="true"
-            android:stateNotNeeded="true"
             android:resumeWhilePausing="true"
+            android:stateNotNeeded="true"
             android:taskAffinity=""
-            android:enabled="true"
-            android:excludeFromRecents="true"
-
             android:windowSoftInputMode="stateAlwaysVisible|adjustResize">
-
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
                 <category android:name="android.intent.category.HOME" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.LAUNCHER_APP" />
             </intent-filter>
         </activity>
 
         <receiver
             android:name=".tuils.stuff.PolicyReceiver"
-            android:permission="android.permission.BIND_DEVICE_ADMIN"
-            android:description="@string/admin_permission">
+            android:description="@string/admin_permission"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
             <meta-data
                 android:name="android.app.device_admin"
                 android:resource="@xml/policy" />
@@ -117,26 +126,28 @@
             android:name=".managers.notifications.KeeperService"
             android:enabled="true"
             android:exported="false" />
-
-        <service android:name=".managers.music.MusicService"
+        <service
+            android:name=".managers.music.MusicService"
             android:enabled="true"
-            android:exported="true"/>
+            android:exported="true" />
 
         <activity
             android:name=".commands.tuixt.TuixtActivity"
-            android:theme="@style/Custom.Solid"
-            android:windowSoftInputMode="stateAlwaysVisible|adjustResize"
-            android:label="@string/tuixt_label"
-
             android:excludeFromRecents="true"
-            android:noHistory="true">
+            android:label="@string/tuixt_label"
+            android:noHistory="true"
+            android:theme="@style/Custom.Solid"
+            android:windowSoftInputMode="stateAlwaysVisible|adjustResize">
             <meta-data
                 android:name="android.support.PARENT_ACTIVITY"
                 android:value=".LauncherActivity" />
+
             <intent-filter>
-                <action android:name="android.intent.action.VIEW"/>
-                <action android:name="android.intent.action.EDIT"/>
-                <data android:mimeType="text/*"/>
+                <action android:name="android.intent.action.VIEW" />
+                <action android:name="android.intent.action.EDIT" />
+
+                <data android:mimeType="text/*" />
+
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             <intent-filter>
@@ -198,31 +209,29 @@
                     android:pathPattern=".*\\.xml"
                     android:scheme="file" />
             </intent-filter>
-
         </activity>
 
-        <service android:name=".managers.notifications.NotificationService"
+        <service
+            android:name=".managers.notifications.NotificationService"
             android:label="@string/notification_reader"
             android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
-
             <intent-filter>
                 <action android:name="android.service.notification.NotificationListenerService" />
             </intent-filter>
-
         </service>
-
-        <service android:name=".managers.notifications.NotificationMonitorService"/>
+        <service android:name=".managers.notifications.NotificationMonitorService" />
 
         <activity
             android:name=".tuils.stuff.FakeLauncherActivity"
             android:enabled="false">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
+
                 <category android:name="android.intent.category.HOME" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
-
+        <activity android:name=".tuils.ErrorActivity"></activity>
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java b/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
index b114ee48043a54f6330e1248c20496c0088305f3..a6a25a28b393b5562e7fb13a5d911ab46c8c4c2c 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
@@ -6,11 +6,13 @@ import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.content.ContextCompat;
+import android.support.v4.content.LocalBroadcastManager;
 import android.support.v7.app.AppCompatActivity;
 import android.view.ContextMenu;
 import android.view.KeyEvent;
@@ -41,20 +43,19 @@ import ohi.andre.consolelauncher.managers.xml.options.Notifications;
 import ohi.andre.consolelauncher.managers.xml.options.Theme;
 import ohi.andre.consolelauncher.managers.xml.options.Ui;
 import ohi.andre.consolelauncher.tuils.Assist;
-import ohi.andre.consolelauncher.tuils.InputOutputReceiver;
+import ohi.andre.consolelauncher.tuils.CustomExceptionHandler;
 import ohi.andre.consolelauncher.tuils.LongClickableSpan;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
+import ohi.andre.consolelauncher.tuils.PublicIOReceiver;
 import ohi.andre.consolelauncher.tuils.SimpleMutableEntry;
 import ohi.andre.consolelauncher.tuils.Tuils;
-import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
 import ohi.andre.consolelauncher.tuils.interfaces.Inputable;
 import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
 import ohi.andre.consolelauncher.tuils.interfaces.Reloadable;
-import ohi.andre.consolelauncher.tuils.interfaces.Suggester;
 
 public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
     private final String FIRSTACCESS_KEY = "x3";
-    private final String NEED_RESET_TIME = "t0";
 
     public static final int COMMAND_REQUEST_PERMISSION = 10;
     public static final int STARTING_PERMISSION = 11;
@@ -65,13 +66,15 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
     private UIManager ui;
     private MainManager main;
 
-    private InputOutputReceiver ioReceiver;
+    private PrivateIOReceiver privateIOReceiver;
+    private PublicIOReceiver publicIOReceiver;
 
     private boolean openKeyboardOnStart, canApplyTheme;
 
     private Runnable stopActivity = new Runnable() {
         @Override
         public void run() {
+            dispose();
             finish();
 
             Intent startMain = new Intent(Intent.ACTION_MAIN);
@@ -80,31 +83,6 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         }
     };
 
-    private CommandExecuter ex = new CommandExecuter() {
-
-        @Override
-        public void exec(String cmd, String aliasName) {
-            if(main != null) main.onCommand(cmd, aliasName);
-        }
-
-        @Override
-        public void exec(String input) {
-            exec(input, false);
-        }
-
-        @Override
-        public void exec(String input, boolean needWriteInput) {
-            if(ui != null && needWriteInput) ui.setOutput(input, TerminalManager.CATEGORY_INPUT);
-            if(main != null) main.onCommand(input, null);
-        }
-
-        @Override
-        public void exec(String input, Object obj) {
-            if(main != null) main.onCommand(input, obj);
-        }
-
-    };
-
     private Inputable in = new Inputable() {
 
         @Override
@@ -212,13 +190,6 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         }
     };
 
-    private Suggester sugg = new Suggester() {
-        @Override
-        public void requestUpdate() {
-            if(ui != null) ui.requestSuggestion(Tuils.EMPTYSTRING);
-        }
-    };
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -233,8 +204,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
                 ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
 
             ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, LauncherActivity.STARTING_PERMISSION);
-        }
-        else {
+        } else {
             canApplyTheme = true;
             finishOnCreate();
         }
@@ -242,39 +212,31 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
     private void finishOnCreate() {
 
-        RegexManager.create(this);
+        Thread.currentThread().setUncaughtExceptionHandler(new CustomExceptionHandler());
 
-        Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
-            @Override
-            public void uncaughtException(Thread t, Throwable e) {
-                Tuils.toFile(e);
-                Tuils.log(e);
-                System.exit(1);
-            }
-        });
+        XMLPrefsManager.loadCommons(this);
+        new RegexManager(LauncherActivity.this);
+        new TimeManager();
 
         IntentFilter filter = new IntentFilter();
-        filter.addAction(InputOutputReceiver.ACTION_CMD);
-        filter.addAction(InputOutputReceiver.ACTION_OUTPUT);
-        filter.addAction(InputOutputReceiver.ACTION_INPUT);
+        filter.addAction(PrivateIOReceiver.ACTION_INPUT);
+        filter.addAction(PrivateIOReceiver.ACTION_OUTPUT);
+        filter.addAction(PrivateIOReceiver.ACTION_REPLY);
 
-        ioReceiver = new InputOutputReceiver(ex, out, in);
-        getApplicationContext().registerReceiver(ioReceiver, filter);
+        privateIOReceiver = new PrivateIOReceiver(this, out, in);
+        LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(privateIOReceiver, filter);
 
-        try {
-            XMLPrefsManager.create(this);
-            new Thread() {
-                @Override
-                public void run() {
-                    super.run();
+        IntentFilter filter1 = new IntentFilter();
+        filter1.addAction(PublicIOReceiver.ACTION_CMD);
+        filter1.addAction(PublicIOReceiver.ACTION_OUTPUT);
 
-                    TimeManager.create();
-                }
-            }.start();
-        } catch (Exception e) {
-            Tuils.log(Tuils.getStackTrace(e));
-            Tuils.toFile(e);
-            return;
+        publicIOReceiver = new PublicIOReceiver();
+        getApplicationContext().registerReceiver(publicIOReceiver, filter1);
+
+        int requestedOrientation = XMLPrefsManager.getInt(Behavior.orientation);
+        if(requestedOrientation != 2 && requestedOrientation != -1) {
+            int orientation = getResources().getConfiguration().orientation;
+            if(orientation != requestedOrientation) setRequestedOrientation(requestedOrientation);
         }
 
         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !XMLPrefsManager.getBoolean(Ui.ignore_bar_color)) {
@@ -323,9 +285,9 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         boolean notifications = XMLPrefsManager.getBoolean(Notifications.show_notifications) || XMLPrefsManager.get(Notifications.show_notifications).equalsIgnoreCase("enabled");
         if(notifications) {
             try {
-                ComponentName thisComponent = new ComponentName(this, NotificationService.class);
+                ComponentName notificationComponent = new ComponentName(this, NotificationService.class);
                 PackageManager pm = getPackageManager();
-                pm.setComponentEnabledSetting(thisComponent, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+                pm.setComponentEnabledSetting(notificationComponent, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
 
                 if(!Tuils.hasNotificationAccess(this)) {
                     Intent i = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
@@ -339,12 +301,12 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
                 Intent monitor = new Intent(this, NotificationMonitorService.class);
                 startService(monitor);
 
-                Intent timeColorIntent = new Intent(this, NotificationService.class);
-                timeColorIntent.putExtra(Theme.time_color.label(), XMLPrefsManager.getColor(Theme.time_color));
-                startService(timeColorIntent);
+                Intent notificationIntent = new Intent(this, NotificationService.class);
+                notificationIntent.putExtra(Theme.time_color.label(), XMLPrefsManager.getColor(Theme.time_color));
+                startService(notificationIntent);
             } catch (NoClassDefFoundError er) {
-                Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                intent.putExtra(InputOutputReceiver.TEXT, getString(R.string.output_notification_error) + Tuils.SPACE + er.toString());
+                Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                intent.putExtra(PrivateIOReceiver.TEXT, getString(R.string.output_notification_error) + Tuils.SPACE + er.toString());
             }
         }
 
@@ -357,12 +319,13 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
         setContentView(R.layout.base_view);
 
+        main = new MainManager(this);
+
         ViewGroup mainView = (ViewGroup) findViewById(R.id.mainview);
-        main = new MainManager(this, in, out, sugg, ex);
-        ui = new UIManager(this, mainView, ex, main.getMainPack(), canApplyTheme);
+        ui = new UIManager(this, mainView, main.getMainPack(), canApplyTheme, main.executer());
+
         main.setRedirectionListener(ui.buildRedirectionListener());
-        main.setHintable(ui.getHintable());
-        main.setRooter(ui.getRooter());
+        ui.pack = main.getMainPack();
 
         in.in(Tuils.EMPTYSTRING);
         ui.focusTerminal();
@@ -380,13 +343,6 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
             ui.setInput("tutorial");
         }
 
-        boolean needResetTime = preferences.getBoolean(NEED_RESET_TIME, true);
-        if(needResetTime) {
-            editor.putBoolean(NEED_RESET_TIME, false);
-
-            Behavior.time_format.parent().write(Behavior.time_format, Behavior.time_format.defaultValue());
-        }
-
         editor.apply();
 
         System.gc();
@@ -403,7 +359,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
     protected void onRestart() {
         super.onRestart();
 
-        sugg.requestUpdate();
+        LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_UPDATE_SUGGESTIONS));
     }
 
     @Override
@@ -416,24 +372,52 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         }
     }
 
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
+    private boolean disposed = false;
+    private void dispose() {
+        if(disposed) return;
+
+        try {
+            LocalBroadcastManager.getInstance(this.getApplicationContext()).unregisterReceiver(privateIOReceiver);
+            getApplicationContext().unregisterReceiver(publicIOReceiver);
+        } catch (Exception e) {}
 
         try {
-            getApplicationContext().unregisterReceiver(ioReceiver);
             stopService(new Intent(this, NotificationMonitorService.class));
+        } catch (NoClassDefFoundError | Exception e) {
+            Tuils.log(e);
+        }
+
+        try {
             stopService(new Intent(this, KeeperService.class));
-        } catch (NoClassDefFoundError | Exception e) {}
+        } catch (NoClassDefFoundError | Exception e) {
+            Tuils.log(e);
+        }
+
+        try {
+            Intent notificationIntent = new Intent(this, NotificationService.class);
+            notificationIntent.putExtra(NotificationService.DESTROY, true);
+            startService(notificationIntent);
+        } catch (Exception e) {
+            Tuils.log(e);
+        }
 
         overridePendingTransition(0,0);
 
         if(main != null) main.destroy();
         if(ui != null) ui.dispose();
 
-        out.dispose();
+        XMLPrefsManager.dispose();
+        RegexManager.instance.dispose();
+        TimeManager.instance.dispose();
+
+        disposed = true;
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
 
-        System.exit(0);
+        dispose();
     }
 
     @Override
@@ -455,14 +439,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
     @Override
     public void reload() {
-        new Thread() {
-            @Override
-            public void run() {
-                super.run();
-
-                runOnUiThread(stopActivity);
-            }
-        }.start();
+        runOnUiThread(stopActivity);
     }
 
     @Override
@@ -498,7 +475,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
                 ContactManager.Contact contact = (ContactManager.Contact) suggestion.object;
                 contact.setSelectedNumber(item.getItemId());
 
-                in.in(suggestion.getText());
+                Tuils.sendInput(this, suggestion.getText());
 
                 return true;
             }
@@ -513,9 +490,9 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
         if(requestCode == TUIXT_REQUEST && resultCode != 0) {
             if(resultCode == TuixtActivity.BACK_PRESSED) {
-                out.onOutput(getString(R.string.tuixt_back_pressed));
+                Tuils.sendOutput(this, R.string.tuixt_back_pressed);
             } else {
-                out.onOutput(data.getStringExtra(TuixtActivity.ERROR_KEY));
+                Tuils.sendOutput(this, data.getStringExtra(TuixtActivity.ERROR_KEY));
             }
         }
     }
@@ -523,7 +500,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
     @Override
     public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
         if(permissions.length > 0 && permissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-            main.getMainPack().contacts.refreshContacts(this);
+            LocalBroadcastManager.getInstance(this.getApplicationContext()).sendBroadcast(new Intent(ContactManager.ACTION_REFRESH));
         }
 
         try {
@@ -531,7 +508,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
                 case COMMAND_REQUEST_PERMISSION:
                     if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                         MainPack info = main.getMainPack();
-                        main.onCommand(info.lastCommand, null);
+                        main.onCommand(info.lastCommand, null, false);
                     } else {
                         ui.setOutput(getString(R.string.output_nopermissions), TerminalManager.CATEGORY_OUTPUT);
                         main.sendPermissionNotGrantedWarning();
@@ -574,12 +551,18 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
 
-        String cmd = intent.getStringExtra(InputOutputReceiver.TEXT);
+        String cmd = intent.getStringExtra(PrivateIOReceiver.TEXT);
         if(cmd != null) {
-            Intent i = new Intent(InputOutputReceiver.ACTION_CMD);
-            i.putExtra(InputOutputReceiver.TEXT, cmd);
-            i.putExtra(InputOutputReceiver.SHOW_CONTENT, true);
-            sendBroadcast(i);
+            Intent i = new Intent(MainManager.ACTION_EXEC);
+            i.putExtra(MainManager.CMD_COUNT, MainManager.commandCount);
+            i.putExtra(MainManager.CMD, cmd);
+            i.putExtra(MainManager.NEED_WRITE_INPUT, true);
+            LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
         }
     }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+    }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/MainManager.java b/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
index 92c1908461c2dae26f9fb4edc32b5fc05e3df632..b51ee1b2c292a771875754b68dba7c3f6b3f360c 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
@@ -1,7 +1,11 @@
 package ohi.andre.consolelauncher;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Parcelable;
+import android.support.v4.content.LocalBroadcastManager;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
@@ -24,22 +28,21 @@ import ohi.andre.consolelauncher.managers.RssManager;
 import ohi.andre.consolelauncher.managers.TerminalManager;
 import ohi.andre.consolelauncher.managers.TimeManager;
 import ohi.andre.consolelauncher.managers.music.MusicManager2;
+import ohi.andre.consolelauncher.managers.music.MusicService;
+import ohi.andre.consolelauncher.managers.notifications.KeeperService;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Theme;
 import ohi.andre.consolelauncher.tuils.Compare;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
-import ohi.andre.consolelauncher.tuils.interfaces.Hintable;
-import ohi.andre.consolelauncher.tuils.interfaces.Inputable;
 import ohi.andre.consolelauncher.tuils.interfaces.OnRedirectionListener;
-import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
 import ohi.andre.consolelauncher.tuils.interfaces.Redirectator;
-import ohi.andre.consolelauncher.tuils.interfaces.Rooter;
-import ohi.andre.consolelauncher.tuils.interfaces.Suggester;
 import ohi.andre.consolelauncher.tuils.libsuperuser.Shell;
 import ohi.andre.consolelauncher.tuils.libsuperuser.ShellHolder;
+import okhttp3.Cache;
 import okhttp3.OkHttpClient;
 
 /*Copyright Francesco Andreuzzi
@@ -58,6 +61,9 @@ limitations under the License.*/
 
 public class MainManager {
 
+    public static String ACTION_EXEC = BuildConfig.APPLICATION_ID + ".main_exec";
+    public static String CMD = "cmd", NEED_WRITE_INPUT = "writeInput", ALIAS_NAME = "aliasName", PARCELABLE = "parcelable", CMD_COUNT = "cmdCount", MUSIC_SERVICE = "musicService";
+
     private RedirectCommand redirect;
     private Redirectator redirectator = new Redirectator() {
         @Override
@@ -101,9 +107,6 @@ public class MainManager {
 
     private Context mContext;
 
-    private Inputable in;
-    private Outputable out;
-
     private boolean showAliasValue;
     private boolean showAppHistory;
     private int aliasContentColor;
@@ -112,13 +115,22 @@ public class MainManager {
 
     public static Shell.Interactive interactive;
 
-    private Hintable hintable;
+    private AliasManager aliasManager;
+    private RssManager rssManager;
+    private AppsManager appsManager;
+    private ContactManager contactManager;
+    private MusicManager2 musicManager2;
+
+    private BroadcastReceiver receiver;
 
-    protected MainManager(LauncherActivity c, Inputable i, Outputable o, Suggester sugg, CommandExecuter executer) {
+    public static int commandCount = 0;
+
+    private boolean keeperServiceRunning;
+
+    protected MainManager(LauncherActivity c) {
         mContext = c;
 
-        in = i;
-        out = o;
+        keeperServiceRunning = XMLPrefsManager.getBoolean(Behavior.tui_notification);
 
         showAliasValue = XMLPrefsManager.getBoolean(Behavior.show_alias_content);
         showAppHistory = XMLPrefsManager.getBoolean(Behavior.show_launch_history);
@@ -128,55 +140,116 @@ public class MainManager {
 
         CommandGroup group = new CommandGroup(mContext, COMMANDS_PKG);
 
-        ContactManager cont = null;
         try {
-            cont = new ContactManager(mContext);
-        } catch (NullPointerException e) {}
-
-        MusicManager2 music = XMLPrefsManager.getBoolean(Behavior.enable_music) ? new MusicManager2(mContext) : null;
+            contactManager = new ContactManager(mContext);
+        } catch (NullPointerException e) {
+            Tuils.log(e);
+        }
 
-        AppsManager appsMgr = new AppsManager(c, sugg);
-        AliasManager aliasManager = new AliasManager(mContext);
+        appsManager = new AppsManager(c);
+        aliasManager = new AliasManager(mContext);
 
-        ShellHolder shellHolder = new ShellHolder(out);
+        ShellHolder shellHolder = new ShellHolder(mContext);
         interactive = shellHolder.build();
 
-        OkHttpClient client = new OkHttpClient();
-        RssManager rss = new RssManager(mContext, client);
+        OkHttpClient client = new OkHttpClient.Builder()
+                .cache(new Cache(mContext.getCacheDir(), 10*1024*1024))
+                .build();
+
+        rssManager = new RssManager(mContext, client);
+
+        musicManager2 = XMLPrefsManager.getBoolean(Behavior.enable_music) ? new MusicManager2(mContext) : null;
+
+        mainPack = new MainPack(mContext, group, aliasManager, appsManager, musicManager2, contactManager, redirectator, shellHolder, rssManager, client);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_EXEC);
+
+        receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getAction().equals(ACTION_EXEC)) {
+                    int cmdCount = intent.getIntExtra(CMD_COUNT, -1);
+                    if (cmdCount < commandCount) return;
+                    commandCount++;
+
+                    String cmd = intent.getStringExtra(CMD);
+                    if (cmd == null) cmd = intent.getStringExtra(PrivateIOReceiver.TEXT);
+
+                    if (cmd == null) {
+                        return;
+                    }
+
+                    String aliasName = intent.getStringExtra(ALIAS_NAME);
+                    boolean needWriteInput = intent.getBooleanExtra(NEED_WRITE_INPUT, false);
+                    Parcelable p = intent.getParcelableExtra(PARCELABLE);
+
+                    if(needWriteInput) {
+                        Intent i = new Intent(PrivateIOReceiver.ACTION_INPUT);
+                        i.putExtra(PrivateIOReceiver.TEXT, cmd);
+                        LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(i);
+                    }
+
+                    if(p != null) {
+                        onCommand(cmd, p, intent.getBooleanExtra(MainManager.MUSIC_SERVICE, false));
+                    } else {
+                        onCommand(cmd, aliasName, intent.getBooleanExtra(MainManager.MUSIC_SERVICE, false));
+                    }
+                }
+            }
+        };
+
+        LocalBroadcastManager.getInstance(mContext.getApplicationContext()).registerReceiver(receiver, filter);
+    }
 
-        mainPack = new MainPack(mContext, group, aliasManager, appsMgr, music, cont, c, executer, redirectator, shellHolder, rss, client);
+    private void updateServices(String cmd, boolean wasMusicService) {
+
+        if(keeperServiceRunning) {
+            Intent i = new Intent(mContext, KeeperService.class);
+            i.putExtra(KeeperService.CMD_KEY, cmd);
+            i.putExtra(KeeperService.PATH_KEY, mainPack.currentDirectory.getAbsolutePath());
+            mContext.startService(i);
+        }
+
+        if(wasMusicService) {
+            Intent i = new Intent(mContext, MusicService.class);
+            mContext.startService(i);
+        }
     }
 
-    public void onCommand(String input, Object obj) {
+    public void onCommand(String input, Object obj, boolean wasMusicService) {
         if(obj == null || !(obj instanceof AppsManager.LaunchInfo)) {
-            onCommand(input, null);
+            onCommand(input, null, wasMusicService);
             return;
         }
 
+        updateServices(input, wasMusicService);
+
         if(obj instanceof AppsManager.LaunchInfo && ((AppsManager.LaunchInfo) obj).publicLabel.equals(input)) {
             performLaunch((AppsManager.LaunchInfo) obj);
         } else {
-            onCommand(input, null);
+            onCommand(input, null, wasMusicService);
         }
     }
 
 //    command manager
-    public void onCommand(String input, String alias) {
-
+    public void onCommand(String input, String alias, boolean wasMusicService) {
         input = Tuils.removeUnncesarySpaces(input);
 
+        if(alias == null) updateServices(input, wasMusicService);
+
         if(redirect != null) {
             if(!redirect.isWaitingPermission()) {
                 redirect.afterObjects.add(input);
             }
             String output = redirect.onRedirect(mainPack);
-            out.onOutput(output);
+            Tuils.sendOutput(mContext, output);
 
             return;
         }
 
         if(alias != null && showAliasValue) {
-            out.onOutput(aliasContentColor, mainPack.aliasManager.formatLabel(alias, input));
+           Tuils.sendOutput(aliasContentColor, mContext, aliasManager.formatLabel(alias, input));
         }
 
         String[] cmds;
@@ -192,7 +265,7 @@ public class MainManager {
                 try {
                     r = trigger.trigger(mainPack, cmd);
                 } catch (Exception e) {
-                    out.onOutput(Tuils.getStackTrace(e));
+                    Tuils.sendOutput(mContext, Tuils.getStackTrace(e));
                     break;
                 }
                 if (r) {
@@ -203,7 +276,7 @@ public class MainManager {
     }
 
     public void onLongBack() {
-        in.in(Tuils.EMPTYSTRING);
+        Tuils.sendInput(mContext, Tuils.EMPTYSTRING);
     }
 
     public void sendPermissionNotGrantedWarning() {
@@ -217,6 +290,8 @@ public class MainManager {
     public void destroy() {
         mainPack.destroy();
 
+        LocalBroadcastManager.getInstance(mContext.getApplicationContext()).unregisterReceiver(receiver);
+
         new StoppableThread() {
             @Override
             public void run() {
@@ -237,12 +312,13 @@ public class MainManager {
         return mainPack;
     }
 
-    public void setHintable(Hintable hintable) {
-        this.hintable = hintable;
-    }
-
-    public void setRooter(Rooter rooter) {
-        this.mainPack.rooter = rooter;
+    public CommandExecuter executer() {
+        return new CommandExecuter() {
+            @Override
+            public void execute(String input, Object obj) {
+                onCommand(input, obj, false);
+            }
+        };
     }
 
 //
@@ -253,10 +329,9 @@ public class MainManager {
     Pattern pa = Pattern.compile("%a", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
     Pattern pp = Pattern.compile("%p", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
     Pattern pl = Pattern.compile("%l", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
-    Pattern pn = Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
 
     public boolean performLaunch(AppsManager.LaunchInfo i) {
-        Intent intent = mainPack.appsManager.getIntent(i);
+        Intent intent = appsManager.getIntent(i);
         if (intent == null) {
             return false;
         }
@@ -272,16 +347,17 @@ public class MainManager {
             a = pa.matcher(a).replaceAll(Matcher.quoteReplacement(intent.getComponent().getClassName()));
             a = pp.matcher(a).replaceAll(Matcher.quoteReplacement(intent.getComponent().getPackageName()));
             a = pl.matcher(a).replaceAll(Matcher.quoteReplacement(i.publicLabel));
-            a = pn.matcher(a).replaceAll(Matcher.quoteReplacement(Tuils.NEWLINE));
+            a = Tuils.patternNewline.matcher(a).replaceAll(Matcher.quoteReplacement(Tuils.NEWLINE));
 
             SpannableString text = new SpannableString(a);
             text.setSpan(new ForegroundColorSpan(outputColor), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-            CharSequence s = TimeManager.replace(text, timeColor);
+            CharSequence s = TimeManager.instance.replace(text, timeColor);
 
-            out.onOutput(s, TerminalManager.CATEGORY_OUTPUT);
+            Tuils.sendOutput(mContext, s, TerminalManager.CATEGORY_OUTPUT);
         }
 
         mContext.startActivity(intent);
+
         return true;
     }
 //
@@ -294,7 +370,7 @@ public class MainManager {
 
         @Override
         public boolean trigger(ExecutePack info, String input) {
-            String alias[] = mainPack.aliasManager.getAlias(input, true);
+            String alias[] = aliasManager.getAlias(input, true);
 
             String aliasValue = alias[0];
             if (alias[0] == null) {
@@ -304,9 +380,9 @@ public class MainManager {
             String aliasName = alias[1];
             String residual = alias[2];
 
-            aliasValue = mainPack.aliasManager.format(aliasValue, residual);
+            aliasValue = aliasManager.format(aliasValue, residual);
 
-            mainPack.executer.exec(aliasValue, aliasName);
+            onCommand(aliasValue, aliasName, false);
 
             return true;
         }
@@ -327,12 +403,12 @@ public class MainManager {
                 input = null;
             }
 
-            List<? extends Group> appGroups = AppsManager.groups;
+            List<? extends Group> appGroups = ((MainPack) info).appsManager.groups;
             if(appGroups != null) {
                 for(Group g : appGroups) {
                     if(name.equals(g.name())) {
                         if(input == null) {
-                            out.onOutput(AppsManager.AppUtils.printApps(AppsManager.AppUtils.labelList((List<AppsManager.LaunchInfo>) g.members(), false)));
+                            Tuils.sendOutput(mContext, AppsManager.AppUtils.printApps(AppsManager.AppUtils.labelList((List<AppsManager.LaunchInfo>) g.members(), false)));
                             return true;
                         } else {
                             return g.use(mainPack, input);
@@ -357,7 +433,8 @@ public class MainManager {
                     File f = new File(output.get(0));
                     if(f.exists()) {
                         mainPack.currentDirectory = f;
-                        if(hintable != null) hintable.updateHint();
+
+                        LocalBroadcastManager.getInstance(mContext.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_UPDATE_HINT));
                     }
                 }
             }
@@ -379,7 +456,7 @@ public class MainManager {
                 @Override
                 public void run() {
                     if(input.trim().equalsIgnoreCase("su")) {
-                        if(Shell.SU.available() && mainPack.rooter != null) mainPack.rooter.onRoot();
+                        if(Shell.SU.available()) LocalBroadcastManager.getInstance(mContext.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_ROOT));
                         interactive.addCommand("su");
 
                     } else if(input.contains("cd ")) {
@@ -399,7 +476,7 @@ public class MainManager {
 
         @Override
         public boolean trigger(ExecutePack info, String input) {
-            AppsManager.LaunchInfo i = mainPack.appsManager.findLaunchInfoWithLabel(input, AppsManager.SHOWN_APPS);
+            AppsManager.LaunchInfo i = appsManager.findLaunchInfoWithLabel(input, AppsManager.SHOWN_APPS);
             return i != null && performLaunch(i);
         }
     }
@@ -423,10 +500,10 @@ public class MainManager {
                         String output = command.exec(mContext.getResources(), info);
 
                         if(output != null) {
-                            out.onOutput(output);
+                            Tuils.sendOutput(mContext, output);
                         }
                     } catch (Exception e) {
-                        out.onOutput(Tuils.getStackTrace(e));
+                        Tuils.sendOutput(mContext, Tuils.getStackTrace(e));
                         Tuils.log(e);
                     }
                 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/UIManager.java b/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
index c620d4b938e7c749c5aa231594ba269948059105..be9db11bf94c8eb5e08b4eb25308b2a6a42b92ce 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
@@ -4,20 +4,24 @@ import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.Color;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.BatteryManager;
 import android.os.Build;
 import android.os.Handler;
+import android.support.v4.content.LocalBroadcastManager;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.DisplayMetrics;
+import android.util.Xml;
 import android.view.GestureDetector;
 import android.view.GestureDetector.OnDoubleTapListener;
 import android.view.Gravity;
@@ -34,6 +38,8 @@ import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -44,9 +50,11 @@ import java.util.regex.Pattern;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.RedirectCommand;
 import ohi.andre.consolelauncher.managers.MessagesManager;
+import ohi.andre.consolelauncher.managers.NotesManager;
 import ohi.andre.consolelauncher.managers.TerminalManager;
 import ohi.andre.consolelauncher.managers.TimeManager;
 import ohi.andre.consolelauncher.managers.suggestions.SuggestionRunnable;
+import ohi.andre.consolelauncher.managers.suggestions.SuggestionTextWatcher;
 import ohi.andre.consolelauncher.managers.suggestions.SuggestionsManager;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
@@ -59,27 +67,29 @@ import ohi.andre.consolelauncher.tuils.NetworkUtils;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
-import ohi.andre.consolelauncher.tuils.interfaces.Hintable;
 import ohi.andre.consolelauncher.tuils.interfaces.OnBatteryUpdate;
 import ohi.andre.consolelauncher.tuils.interfaces.OnRedirectionListener;
-import ohi.andre.consolelauncher.tuils.interfaces.Rooter;
 import ohi.andre.consolelauncher.tuils.interfaces.SuggestionViewDecorer;
 import ohi.andre.consolelauncher.tuils.stuff.PolicyReceiver;
 import ohi.andre.consolelauncher.tuils.stuff.TrashInterfaces;
 
 public class UIManager implements OnTouchListener {
 
+    public static String ACTION_UPDATE_SUGGESTIONS = BuildConfig.APPLICATION_ID + ".ui_update_suggestions", ACTION_UPDATE_HINT = BuildConfig.APPLICATION_ID + ".ui_update_hint",
+        ACTION_ROOT = BuildConfig.APPLICATION_ID + ".ui_root", ACTION_NOROOT = BuildConfig.APPLICATION_ID + ".ui_noroot",
+        ACTION_LOGTOFILE = BuildConfig.APPLICATION_ID + ".ui_log", ACTION_CLEAR = BuildConfig.APPLICATION_ID + "ui_clear";
+
+    public static String
+            FILE_NAME = "fileName";
+
     private enum Label {
         ram,
         device,
         time,
         battery,
         storage,
-        network;
-
-        static Label last() {
-            return network;
-        }
+        network,
+        notes;
     }
 
     private final int RAM_DELAY = 3000;
@@ -88,43 +98,57 @@ public class UIManager implements OnTouchListener {
 
     protected Context mContext;
 
+    private Handler handler;
+
     private DevicePolicyManager policy;
     private ComponentName component;
     private GestureDetector det;
-    private MainPack info;
 
     private InputMethodManager imm;
-    private CommandExecuter trigger;
     private TerminalManager mTerminalAdapter;
 
     int mediumPercentage, lowPercentage;
     String batteryFormat;
-//    boolean batteryCharging;
 
-    private String multipleCmdSeparator;
+//    never access this directly, use getLabelView
+    private TextView[] labelViews = new TextView[Label.values().length];
+
+    private float[] labelIndexes = new float[labelViews.length];
+    private int[] labelSizes = new int[labelViews.length];
+    private CharSequence[] labelTexts = new CharSequence[labelViews.length];
+
+    private TextView getLabelView(Label l) {
+        return labelViews[(int) labelIndexes[l.ordinal()]];
+    }
+
+    private NotesManager notesManager;
+    private NotesRunnable notesRunnable;
+    private class NotesRunnable implements Runnable {
+
+        int updateTime = 2000;
 
-    private OnNewInputListener inputListener = new OnNewInputListener() {
         @Override
-        public void onNewInput(String input, Object obj) {
-            if(suggestionsView != null) {
-                suggestionsView.removeAllViews();
-            }
+        public void run() {
+            if(notesManager != null) {
+                int i = Label.notes.ordinal();
 
-            trigger.exec(input, obj);
+                if(notesManager.hasChanged) {
+                    labelTexts[i] = Tuils.span(mContext, labelSizes[i], notesManager.getNotes());
+                    UIManager.this.update(labelIndexes[i]);
+                }
+
+                handler.postDelayed(this, updateTime);
+            }
         }
     };
 
-    private TextView[] labelViews = new TextView[Label.last().ordinal() + 1];
-    private int[] labelSizes = new int[Label.last().ordinal() + 1];
-    private CharSequence[] labelTexts = new CharSequence[Label.last().ordinal() + 1];
-    private float[] labelIndexes = new float[Label.last().ordinal() + 1];
-
-    private OnBatteryUpdate batteryUpdate = new OnBatteryUpdate() {
+    private BatteryUpdate batteryUpdate;
+    private class BatteryUpdate implements OnBatteryUpdate {
 
 //        %(charging:not charging)
 
-        final Pattern optionalCharging = Pattern.compile("%\\(([^\\/]*)\\/([^)]*)\\)", Pattern.CASE_INSENSITIVE);
-        final Pattern newline = Pattern.compile("%n", Pattern.LITERAL | Pattern.CASE_INSENSITIVE);
+//        final Pattern optionalCharging = Pattern.compile("%\\(([^\\/]*)\\/([^)]*)\\)", Pattern.CASE_INSENSITIVE);
+        Pattern optionalCharging;
         final Pattern value = Pattern.compile("%v", Pattern.LITERAL | Pattern.CASE_INSENSITIVE);
 
         boolean manyStatus, loaded;
@@ -144,6 +168,10 @@ public class UIManager implements OnTouchListener {
                     int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
                     charging = plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
                 }
+
+                String optionalSeparator = "\\" + XMLPrefsManager.get(Behavior.optional_values_separator);
+                String optional = "%\\(([^" + optionalSeparator + "]*)" + optionalSeparator + "([^)]*)\\)";
+                optionalCharging = Pattern.compile(optional, Pattern.CASE_INSENSITIVE);
             }
 
             if(p == -1) p = last;
@@ -178,7 +206,7 @@ public class UIManager implements OnTouchListener {
             }
 
             cp = value.matcher(cp).replaceAll(String.valueOf(percentage));
-            cp = newline.matcher(cp).replaceAll(Tuils.NEWLINE);
+            cp = Tuils.patternNewline.matcher(cp).replaceAll(Tuils.NEWLINE);
 
             int i = Label.battery.ordinal();
 
@@ -199,7 +227,8 @@ public class UIManager implements OnTouchListener {
         }
     };
 
-    private Runnable storageRunnable = new Runnable() {
+    private StorageRunnable storageRunnable;
+    private class StorageRunnable implements Runnable {
 
         private final String INT_AV = "%iav";
         private final String INT_TOT = "%itot";
@@ -247,7 +276,7 @@ public class UIManager implements OnTouchListener {
                 storagePatterns.add(Pattern.compile(EXT_TOT + "kb", Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
                 storagePatterns.add(Pattern.compile(EXT_TOT + "b", Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
 
-                storagePatterns.add(Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
+                storagePatterns.add(Tuils.patternNewline);
 
                 storagePatterns.add(Pattern.compile(INT_AV, Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
                 storagePatterns.add(Pattern.compile(INT_TOT, Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
@@ -299,11 +328,12 @@ public class UIManager implements OnTouchListener {
 
             labelTexts[i] = Tuils.span(mContext, copy, color, labelSizes[i]);
             update(labelIndexes[i]);
-            labelViews[(int) labelIndexes[i]].postDelayed(this, STORAGE_DELAY);
+            handler.postDelayed(this, STORAGE_DELAY);
         }
     };
 
-    private Runnable timeRunnable = new Runnable() {
+    private TimeRunnable timeRunnable;
+    private class TimeRunnable implements Runnable {
 
         boolean active;
         int color;
@@ -317,17 +347,17 @@ public class UIManager implements OnTouchListener {
 
             int i = Label.time.ordinal();
 
-            labelTexts[i] = TimeManager.replace(mContext, labelSizes[i], "%t0", color);
+            labelTexts[i] = TimeManager.instance.replace(mContext, labelSizes[i], "%t0", color);
             update(labelIndexes[i]);
-            labelViews[(int) labelIndexes[i]].postDelayed(this, TIME_DELAY);
+            handler.postDelayed(this, TIME_DELAY);
         }
     };
 
     private ActivityManager.MemoryInfo memory;
     private ActivityManager activityManager;
 
-    private Runnable ramRunnable = new Runnable() {
-
+    private RamRunnable ramRunnable;
+    private class RamRunnable implements Runnable {
         private final String AV = "%av";
         private final String TOT = "%tot";
 
@@ -360,7 +390,7 @@ public class UIManager implements OnTouchListener {
                 ramPatterns.add(Pattern.compile(TOT + "kb", Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
                 ramPatterns.add(Pattern.compile(TOT + "b", Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
 
-                ramPatterns.add(Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL));
+                ramPatterns.add(Tuils.patternNewline);
             }
 
             String copy = ramFormat;
@@ -387,12 +417,12 @@ public class UIManager implements OnTouchListener {
 
             labelTexts[i] = Tuils.span(mContext, copy, color, labelSizes[i]);
             update(labelIndexes[i]);
-            labelViews[(int) labelIndexes[i]].postDelayed(this, RAM_DELAY);
+            handler.postDelayed(this, RAM_DELAY);
         }
     };
 
-    private Runnable networkRunnable = new Runnable() {
-
+    private Runnable networkRunnable;
+    private class NetworkRunnable implements Runnable {
 //        %() -> wifi
 //        %[] -> data
 //        %{} -> bluetooth
@@ -424,16 +454,17 @@ public class UIManager implements OnTouchListener {
         final Pattern b2 = Pattern.compile("%b2", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
         final Pattern b3 = Pattern.compile("%b3", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
         final Pattern b4 = Pattern.compile("%b4", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
-        final Pattern nl = Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
         final Pattern ip4 = Pattern.compile("%ip4", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
         final Pattern ip6 = Pattern.compile("%ip6", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
         final Pattern dt = Pattern.compile("%dt", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
 
-        final Pattern optionalWifi = Pattern.compile("%\\(([^/]*)/([^)]*)\\)", Pattern.CASE_INSENSITIVE);
-        final Pattern optionalData = Pattern.compile("%\\[([^/]*)/([^\\]]*)\\]", Pattern.CASE_INSENSITIVE);
-        final Pattern optionalBluetooth = Pattern.compile("%\\{([^/]*)/([^}]*)\\}", Pattern.CASE_INSENSITIVE);
+//        final Pattern optionalWifi = Pattern.compile("%\\(([^/]*)/([^)]*)\\)", Pattern.CASE_INSENSITIVE);
+//        final Pattern optionalData = Pattern.compile("%\\[([^/]*)/([^\\]]*)\\]", Pattern.CASE_INSENSITIVE);
+//        final Pattern optionalBluetooth = Pattern.compile("%\\{([^/]*)/([^}]*)\\}", Pattern.CASE_INSENSITIVE);
 
-        String format;
+        Pattern optionalWifi, optionalData, optionalBluetooth;
+
+        String format, optionalValueSeparator;
         int color;
 
         WifiManager wifiManager;
@@ -461,6 +492,16 @@ public class UIManager implements OnTouchListener {
                 wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 
+                optionalValueSeparator = "\\" + XMLPrefsManager.get(Behavior.optional_values_separator);
+
+                String wifiRegex = "%\\(([^" + optionalValueSeparator + "]*)" + optionalValueSeparator + "([^)]*)\\)";
+                String dataRegex = "%\\[([^" + optionalValueSeparator + "]*)" + optionalValueSeparator + "([^\\]]*)\\]";
+                String bluetoothRegex = "%\\{([^" + optionalValueSeparator + "]*)" + optionalValueSeparator + "([^}]*)\\}";
+
+                optionalWifi = Pattern.compile(wifiRegex, Pattern.CASE_INSENSITIVE);
+                optionalBluetooth = Pattern.compile(bluetoothRegex, Pattern.CASE_INSENSITIVE);
+                optionalData = Pattern.compile(dataRegex, Pattern.CASE_INSENSITIVE);
+
                 try {
                     cmClass = Class.forName(connectivityManager.getClass().getName());
                     method = cmClass.getDeclaredMethod("getMobileDataEnabled");
@@ -524,13 +565,13 @@ public class UIManager implements OnTouchListener {
             copy = ip4.matcher(copy).replaceAll(NetworkUtils.getIPAddress(true));
             copy = ip6.matcher(copy).replaceAll(NetworkUtils.getIPAddress(false));
             copy = dt.matcher(copy).replaceAll(mobileType);
-            copy = nl.matcher(copy).replaceAll(Tuils.NEWLINE);
+            copy = Tuils.patternNewline.matcher(copy).replaceAll(Tuils.NEWLINE);
 
             int i = Label.network.ordinal();
 
             labelTexts[i] = Tuils.span(mContext, copy, color, labelSizes[i]);
             update(labelIndexes[i]);
-            labelViews[i].postDelayed(this, updateTime);
+            handler.postDelayed(this, updateTime);
         }
 
         private String apply(int depth, String s, boolean[] on, Pattern... ps) {
@@ -576,7 +617,7 @@ public class UIManager implements OnTouchListener {
 
             return s;
         }
-    };
+    }
 
     private void update(float line) {
         int base = (int) line;
@@ -598,213 +639,82 @@ public class UIManager implements OnTouchListener {
             }
         }
 
-        labelViews[base].setText(sequence);
+        if(sequence.length() == 0) labelViews[base].setVisibility(View.GONE);
+        else {
+            labelViews[base].setVisibility(View.VISIBLE);
+            labelViews[base].setText(sequence);
+        }
     }
 
-    private boolean showSuggestions;
-    private LinearLayout suggestionsView;
-    private SuggestionViewDecorer suggestionViewDecorer;
-    private SuggestionRunnable suggestionRunnable;
-    private LinearLayout.LayoutParams suggestionViewParams;
     private SuggestionsManager suggestionsManager;
-//    private boolean navigatingWithSpace = false;
 
     private TextView terminalView;
-    private Thread lastSuggestionThread;
-    private Handler handler = new Handler();
-    private Runnable removeAllSuggestions = new Runnable() {
-        @Override
-        public void run() {
-            suggestionsView.removeAllViews();
-        }
-    };
 
     private String doubleTapCmd;
     private boolean lockOnDbTap;
 
-    protected TextWatcher textWatcher = new TextWatcher() {
+    private BroadcastReceiver receiver;
 
-        @Override
-        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-        }
-
-        @Override
-        public void onTextChanged(CharSequence s, int st, int b, int c) {
-            requestSuggestion(s.toString());
-        }
-
-        @Override
-        public void afterTextChanged(Editable s) {}
-    };
-
-    private View.OnClickListener clickListener = new View.OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            SuggestionsManager.Suggestion suggestion = (SuggestionsManager.Suggestion) v.getTag(R.id.suggestion_id);
-            boolean execOnClick = suggestion.exec;
-
-            String text = suggestion.getText();
-            String input = mTerminalAdapter.getInput();
-
-            if(suggestion.type == SuggestionsManager.Suggestion.TYPE_PERMANENT) {
-                mTerminalAdapter.setInput(input + text);
-            } else {
-                boolean addSpace = suggestion.type != SuggestionsManager.Suggestion.TYPE_FILE && suggestion.type != SuggestionsManager.Suggestion.TYPE_COLOR;
-
-                if(multipleCmdSeparator.length() > 0) {
-                    String[] split = input.split(multipleCmdSeparator);
-                    if(split.length == 0) return;
-                    if(split.length == 1) mTerminalAdapter.setInput(text + (addSpace ? Tuils.SPACE : Tuils.EMPTYSTRING), suggestion.object);
-                    else {
-                        split[split.length - 1] = Tuils.EMPTYSTRING;
-
-                        String beforeInputs = Tuils.EMPTYSTRING;
-                        for(int count = 0; count < split.length - 1; count++) {
-                            beforeInputs = beforeInputs + split[count] + multipleCmdSeparator;
-                        }
-
-                        mTerminalAdapter.setInput(beforeInputs + text + (addSpace ? Tuils.SPACE : Tuils.EMPTYSTRING), suggestion.object);
-                    }
-                } else {
-                    mTerminalAdapter.setInput(text + (addSpace ? Tuils.SPACE : Tuils.EMPTYSTRING), suggestion.object);
-                }
-            }
+    public MainPack pack;
 
-            if (execOnClick) {
-                mTerminalAdapter.simulateEnter();
-            } else {
-                mTerminalAdapter.focusInputEnd();
-            }
-        }
-    };
+    protected UIManager(final Context context, final ViewGroup rootView, MainPack mainPack, boolean canApplyTheme, CommandExecuter executer) {
 
-    public void requestSuggestion(final String input) {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_UPDATE_SUGGESTIONS);
+        filter.addAction(ACTION_UPDATE_HINT);
+        filter.addAction(ACTION_ROOT);
+        filter.addAction(ACTION_NOROOT);
+//        filter.addAction(ACTION_CLEAR_SUGGESTIONS);
+        filter.addAction(ACTION_LOGTOFILE);
+        filter.addAction(ACTION_CLEAR);
 
-        if (suggestionsView == null || suggestionsManager == null || !showSuggestions) {
-            return;
-        }
-
-        if (suggestionViewParams == null) {
-            suggestionViewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-            suggestionViewParams.setMargins(15, 0, 15, 0);
-            suggestionViewParams.gravity = Gravity.CENTER_VERTICAL;
-        }
-
-        if(suggestionRunnable == null) {
-            suggestionRunnable = new SuggestionRunnable(suggestionsView, suggestionViewParams, (HorizontalScrollView) suggestionsView.getParent());
-        }
-
-        if (lastSuggestionThread != null) {
-            lastSuggestionThread.interrupt();
-            suggestionRunnable.interrupt();
-            if(handler != null) {
-                handler.removeCallbacks(suggestionRunnable);
-            }
-        }
-
-        lastSuggestionThread = new StoppableThread() {
+        receiver = new BroadcastReceiver() {
             @Override
-            public void run() {
-                super.run();
-
-                String before, lastWord;
-                String lastInput;
-                if(multipleCmdSeparator.length() > 0) {
-                    String[] split = input.split(multipleCmdSeparator);
-                    if(split.length == 0) lastInput = input;
-                    else lastInput = split[split.length - 1];
-                } else {
-                    lastInput = input;
-                }
-
-                int lastSpace = lastInput.lastIndexOf(Tuils.SPACE);
-                if(lastSpace == -1) {
-                    before = Tuils.EMPTYSTRING;
-                    lastWord = lastInput;
-                } else {
-                    before = lastInput.substring(0,lastSpace);
-                    lastWord = lastInput.substring(lastSpace + 1,lastInput.length());
-                }
-
-
-                final SuggestionsManager.Suggestion[] suggestions;
-                try {
-                    suggestions = suggestionsManager.getSuggestions(info, before, lastWord);
-                } catch (Exception e) {
-                    Tuils.log(e);
-                    Tuils.toFile(e);
-                    return;
-                }
-
-                if(suggestions.length == 0) {
-                    ((Activity) mContext).runOnUiThread(removeAllSuggestions);
-                    return;
-                }
-
-                if (Thread.interrupted()) {
-                    suggestionRunnable.interrupt();
-                    return;
-                }
-
-                final TextView[] existingViews = new TextView[suggestionsView.getChildCount()];
-                for (int count = 0; count < existingViews.length; count++) {
-                    existingViews[count] = (TextView) suggestionsView.getChildAt(count);
-                }
-
-                if (Thread.interrupted()) {
-                    suggestionRunnable.interrupt();
-                    return;
-                }
-
-                int n = suggestions.length - existingViews.length;
-                TextView[] toAdd = null;
-                TextView[] toRecycle = null;
-                if (n == 0) {
-                    toRecycle = existingViews;
-                    toAdd = null;
-                } else if (n > 0) {
-                    toRecycle = existingViews;
-                    toAdd = new TextView[n];
-                    for (int count = 0; count < toAdd.length; count++) {
-                        toAdd[count] = suggestionViewDecorer.getSuggestionView(mContext);
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+
+                if(action.equals(ACTION_UPDATE_SUGGESTIONS)) {
+                    if(suggestionsManager != null) suggestionsManager.requestSuggestion(Tuils.EMPTYSTRING);
+                } else if(action.equals(ACTION_UPDATE_HINT)) {
+                    mTerminalAdapter.setDefaultHint();
+                } else if(action.equals(ACTION_ROOT)) {
+                    mTerminalAdapter.onRoot();
+                } else if(action.equals(ACTION_NOROOT)) {
+                    mTerminalAdapter.onStandard();
+//                } else if(action.equals(ACTION_CLEAR_SUGGESTIONS)) {
+//                    if(suggestionsManager != null) suggestionsManager.clear();
+                } else if(action.equals(ACTION_LOGTOFILE)) {
+                    String fileName = intent.getStringExtra(FILE_NAME);
+                    if(fileName == null || fileName.contains(File.separator)) return;
+
+                    File file = new File(Tuils.getFolder(), fileName);
+                    if(file.exists()) file.delete();
+
+                    try {
+                        file.createNewFile();
+
+                        FileOutputStream fos = new FileOutputStream(file);
+                        fos.write(mTerminalAdapter.getTerminalText().getBytes());
+
+                        Tuils.sendOutput(context, "Logged to " + file.getAbsolutePath());
+                    } catch (Exception e) {
+                        Tuils.sendOutput(Color.RED, context, e.toString());
                     }
-                } else if (n < 0) {
-                    toAdd = null;
-                    toRecycle = new TextView[suggestions.length];
-                    System.arraycopy(existingViews, 0, toRecycle, 0, toRecycle.length);
+                } else if(action.equals(ACTION_CLEAR)) {
+                    mTerminalAdapter.clear();
+                    if(suggestionsManager != null) suggestionsManager.requestSuggestion(Tuils.EMPTYSTRING);
                 }
-
-                if (Thread.interrupted()) {
-                    suggestionRunnable.interrupt();
-                    return;
-                }
-
-                suggestionRunnable.setN(n);
-                suggestionRunnable.setSuggestions(suggestions);
-                suggestionRunnable.setToAdd(toAdd);
-                suggestionRunnable.setToRecycle(toRecycle);
-                suggestionRunnable.reset();
-                ((Activity) mContext).runOnUiThread(suggestionRunnable);
             }
         };
 
-        try {
-            lastSuggestionThread.start();
-        } catch (InternalError e) {}
-    }
-
-    protected UIManager(final Context context, final ViewGroup rootView, final CommandExecuter tri, MainPack mainPack, boolean canApplyTheme) {
+        LocalBroadcastManager.getInstance(context.getApplicationContext()).registerReceiver(receiver, filter);
 
         policy = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
         component = new ComponentName(context, PolicyReceiver.class);
 
-        multipleCmdSeparator = XMLPrefsManager.get(Behavior.multiple_cmd_separator);
-//        selectFirstSuggestionEnter = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Behavior.enter_first_suggestion);
-
         mContext = context;
-        this.info = mainPack;
 
-        trigger = tri;
+        handler = new Handler();
 
         imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
 
@@ -838,6 +748,7 @@ public class UIManager implements OnTouchListener {
         labelSizes[Label.battery.ordinal()] = XMLPrefsManager.getInt(Ui.battery_size);
         labelSizes[Label.storage.ordinal()] = XMLPrefsManager.getInt(Ui.storage_size);
         labelSizes[Label.network.ordinal()] = XMLPrefsManager.getInt(Ui.network_size);
+        labelSizes[Label.notes.ordinal()] = XMLPrefsManager.getInt(Ui.notes_size);
 
         DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
         rootView.setPadding(Tuils.mmToPx(metrics, leftMM), Tuils.mmToPx(metrics, topMM), Tuils.mmToPx(metrics, rightMM), Tuils.mmToPx(metrics, bottomMM));
@@ -848,35 +759,41 @@ public class UIManager implements OnTouchListener {
                 (TextView) rootView.findViewById(R.id.tv2),
                 (TextView) rootView.findViewById(R.id.tv3),
                 (TextView) rootView.findViewById(R.id.tv4),
-                (TextView) rootView.findViewById(R.id.tv5)
+                (TextView) rootView.findViewById(R.id.tv5),
+                (TextView) rootView.findViewById(R.id.tv6)
         };
 
-        boolean showRam = XMLPrefsManager.getBoolean(Ui.show_ram);
-        boolean showStorage = XMLPrefsManager.getBoolean(Ui.show_storage_info);
-        boolean showDevice = XMLPrefsManager.getBoolean(Ui.show_device_name);
-        boolean showTime = XMLPrefsManager.getBoolean(Ui.show_time);
-        boolean showBattery = XMLPrefsManager.getBoolean(Ui.show_battery);
-        boolean showNetwork = XMLPrefsManager.getBoolean(Ui.show_network_info);
-
-        float rIndex = showRam ? XMLPrefsManager.getFloat(Ui.ram_index) : Integer.MAX_VALUE;
-        float dIndex = showDevice ? XMLPrefsManager.getFloat(Ui.device_index) : Integer.MAX_VALUE;
-        float bIndex = showBattery ? XMLPrefsManager.getFloat(Ui.battery_index) : Integer.MAX_VALUE;
-        float tIndex = showTime ? XMLPrefsManager.getFloat(Ui.time_index) : Integer.MAX_VALUE;
-        float sIndex = showStorage ? XMLPrefsManager.getFloat(Ui.storage_index) : Integer.MAX_VALUE;
-        float nIndex = showNetwork ? XMLPrefsManager.getFloat(Ui.network_index) : Integer.MAX_VALUE;
-
-        int[] pos = {
+        boolean[] show = new boolean[Label.values().length];
+        show[Label.notes.ordinal()] = XMLPrefsManager.getBoolean(Ui.show_notes);
+        show[Label.ram.ordinal()] = XMLPrefsManager.getBoolean(Ui.show_ram);
+        show[Label.device.ordinal()] = XMLPrefsManager.getBoolean(Ui.show_device_name);
+        show[Label.time.ordinal()] = XMLPrefsManager.getBoolean(Ui.show_time);
+        show[Label.battery.ordinal()] = XMLPrefsManager.getBoolean(Ui.show_battery);
+        show[Label.network.ordinal()] = XMLPrefsManager.getBoolean(Ui.show_network_info);
+        show[Label.storage.ordinal()] = XMLPrefsManager.getBoolean(Ui.show_storage_info);
+
+        float[] indexes = new float[Label.values().length];
+        indexes[Label.notes.ordinal()] = show[Label.notes.ordinal()] ? XMLPrefsManager.getFloat(Ui.notes_index) : Integer.MAX_VALUE;
+        indexes[Label.ram.ordinal()] = show[Label.ram.ordinal()] ? XMLPrefsManager.getFloat(Ui.ram_index) : Integer.MAX_VALUE;
+        indexes[Label.device.ordinal()] = show[Label.device.ordinal()] ? XMLPrefsManager.getFloat(Ui.device_index) : Integer.MAX_VALUE;
+        indexes[Label.time.ordinal()] = show[Label.time.ordinal()] ? XMLPrefsManager.getFloat(Ui.time_index) : Integer.MAX_VALUE;
+        indexes[Label.battery.ordinal()] = show[Label.battery.ordinal()] ? XMLPrefsManager.getFloat(Ui.battery_index) : Integer.MAX_VALUE;
+        indexes[Label.network.ordinal()] = show[Label.network.ordinal()] ? XMLPrefsManager.getFloat(Ui.network_index) : Integer.MAX_VALUE;
+        indexes[Label.storage.ordinal()] = show[Label.storage.ordinal()] ? XMLPrefsManager.getFloat(Ui.storage_index) : Integer.MAX_VALUE;
+
+        int[] alignment = {
                 XMLPrefsManager.getInt(Ui.status_line0_alignment),
                 XMLPrefsManager.getInt(Ui.status_line1_alignment),
                 XMLPrefsManager.getInt(Ui.status_line2_alignment),
                 XMLPrefsManager.getInt(Ui.status_line3_alignment),
                 XMLPrefsManager.getInt(Ui.status_line4_alignment),
-                XMLPrefsManager.getInt(Ui.status_line5_alignment)
+                XMLPrefsManager.getInt(Ui.status_line5_alignment),
+                XMLPrefsManager.getInt(Ui.status_line6_alignment)
         };
 
-        AllowEqualsSequence sequence = new AllowEqualsSequence(new float[] {rIndex, dIndex, bIndex, tIndex, sIndex, nIndex},
-                new Object[] {Label.ram, Label.device, Label.battery, Label.time, Label.storage, Label.network});
+        AllowEqualsSequence sequence = new AllowEqualsSequence(indexes, Label.values());
 
+        int effectiveCount = 0;
         for(int count = 0; count < labelViews.length; count++) {
             Object[] os = sequence.get(count);
 
@@ -893,28 +810,32 @@ public class UIManager implements OnTouchListener {
             if(count >= sequence.getMinKey() && count <= sequence.getMaxKey() && os.length > 0) {
                 labelViews[count].setTypeface(Tuils.getTypeface(context));
 
+                int ec = effectiveCount++;
+
 //                -1 = left     0 = center     1 = right
-                int p = pos[count];
+                int p = alignment[ec];
                 if(p >= 0) labelViews[count].setGravity(p == 0 ? Gravity.CENTER_HORIZONTAL : Gravity.RIGHT);
             } else {
                 labelViews[count].setVisibility(View.GONE);
             }
         }
 
-        if (showRam) {
+        if (show[Label.ram.ordinal()]) {
+            ramRunnable = new RamRunnable();
+
             memory = new ActivityManager.MemoryInfo();
             activityManager = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);
-            labelViews[Label.ram.ordinal()].post(ramRunnable);
+            handler.post(ramRunnable);
         }
 
-        if(showStorage) {
-            labelViews[Label.storage.ordinal()].post(storageRunnable);
+        if(show[Label.storage.ordinal()]) {
+            storageRunnable = new StorageRunnable();
+            handler.post(storageRunnable);
         }
 
-        if (showDevice) {
+        if (show[Label.device.ordinal()]) {
             Pattern USERNAME = Pattern.compile("%u", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
             Pattern DV = Pattern.compile("%d", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
-            Pattern NEWLINE = Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
 
             String deviceFormat = XMLPrefsManager.get(Behavior.device_format);
 
@@ -926,17 +847,20 @@ public class UIManager implements OnTouchListener {
 
             deviceFormat = USERNAME.matcher(deviceFormat).replaceAll(Matcher.quoteReplacement(username != null ? username : "null"));
             deviceFormat = DV.matcher(deviceFormat).replaceAll(Matcher.quoteReplacement(deviceName));
-            deviceFormat = NEWLINE.matcher(deviceFormat).replaceAll(Matcher.quoteReplacement(Tuils.NEWLINE));
+            deviceFormat = Tuils.patternNewline.matcher(deviceFormat).replaceAll(Matcher.quoteReplacement(Tuils.NEWLINE));
 
             labelTexts[Label.device.ordinal()] = Tuils.span(mContext, deviceFormat, XMLPrefsManager.getColor(Theme.device_color), XMLPrefsManager.getInt(Ui.device_size));
             update(labelIndexes[Label.device.ordinal()]);
         }
 
-        if(showTime) {
-            labelViews[Label.time.ordinal()].post(timeRunnable);
+        if(show[Label.time.ordinal()]) {
+            timeRunnable = new TimeRunnable();
+            handler.post(timeRunnable);
         }
 
-        if(showBattery) {
+        if(show[Label.battery.ordinal()]) {
+            batteryUpdate = new BatteryUpdate();
+
             mediumPercentage = XMLPrefsManager.getInt(Behavior.battery_medium);
             lowPercentage = XMLPrefsManager.getInt(Behavior.battery_low);
 
@@ -944,10 +868,16 @@ public class UIManager implements OnTouchListener {
         } else {
             batteryUpdate = null;
         }
-//        batt, ram, ...
 
-        if(showNetwork) {
-            labelViews[Label.network.ordinal()].post(networkRunnable);
+        if(show[Label.network.ordinal()]) {
+            networkRunnable = new NetworkRunnable();
+            handler.post(networkRunnable);
+        }
+
+        notesManager = new NotesManager(context, labelViews[(int) labelIndexes[Label.notes.ordinal()]]);
+        if(show[Label.notes.ordinal()]) {
+            notesRunnable = new NotesRunnable();
+            handler.post(notesRunnable);
         }
 
         final boolean inputBottom = XMLPrefsManager.getBoolean(Ui.input_bottom);
@@ -989,9 +919,9 @@ public class UIManager implements OnTouchListener {
             pasteView = (ImageButton) inputOutputView.findViewById(R.id.paste_view);
         }
 
-        if (XMLPrefsManager.getBoolean(Suggestions.show_suggestions)) {
-            showSuggestions = true;
+        mTerminalAdapter = new TerminalManager(terminalView, inputView, prefixView, submitView, backView, nextView, deleteView, pasteView, context, mainPack, executer);
 
+        if (XMLPrefsManager.getBoolean(Suggestions.show_suggestions)) {
             HorizontalScrollView sv = (HorizontalScrollView) rootView.findViewById(R.id.suggestions_container);
             sv.setFocusable(false);
             sv.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@@ -1003,41 +933,13 @@ public class UIManager implements OnTouchListener {
                 }
             });
 
-            suggestionsView = (LinearLayout) rootView.findViewById(R.id.suggestions_group);
-
-            inputView.addTextChangedListener(textWatcher);
-
-            suggestionsManager = new SuggestionsManager();
-
-            this.suggestionViewDecorer = new SuggestionViewDecorer() {
-
-                final int PADDING = 15;
-
-                @Override
-                public TextView getSuggestionView(Context context) {
-                    TextView textView = new TextView(mContext);
-                    textView.setOnClickListener(clickListener);
+            LinearLayout suggestionsView = (LinearLayout) rootView.findViewById(R.id.suggestions_group);
 
-                    textView.setFocusable(false);
-                    textView.setLongClickable(false);
-                    textView.setClickable(true);
+            suggestionsManager = new SuggestionsManager(suggestionsView, mainPack, mTerminalAdapter);
 
-                    textView.setTypeface(Tuils.getTypeface(context));
-                    textView.setTextSize(XMLPrefsManager.getInt(Suggestions.suggestions_size));
-
-                    textView.setPadding(PADDING, PADDING, PADDING, PADDING);
-
-                    textView.setLines(1);
-                    textView.setMaxLines(1);
-
-                    return textView;
-                }
-            };
+            inputView.addTextChangedListener(new SuggestionTextWatcher(suggestionsManager));
         } else {
-            showSuggestions = false;
             rootView.findViewById(R.id.suggestions_group).setVisibility(View.GONE);
-            this.textWatcher = null;
-            this.clickListener = null;
         }
 
         lockOnDbTap = XMLPrefsManager.getBoolean(Behavior.double_tap_lock);
@@ -1048,9 +950,6 @@ public class UIManager implements OnTouchListener {
             det = null;
         } else initDetector();
 
-        mTerminalAdapter = new TerminalManager(terminalView, inputView, prefixView, submitView, backView, nextView, deleteView, pasteView, context, mainPack);
-        mTerminalAdapter.setInputListener(inputListener);
-
         if(XMLPrefsManager.getBoolean(Behavior.show_hints)) {
             MessagesManager messagesManager = new MessagesManager(context,
                     new MessagesManager.Message(R.string.hint_alias),
@@ -1069,8 +968,7 @@ public class UIManager implements OnTouchListener {
                     new MessagesManager.Message(R.string.hint_tutorial),
                     new MessagesManager.Message(R.string.hint_twitter),
                     new MessagesManager.Message(R.string.hint_wallpaper),
-                    new MessagesManager.Message(R.string.hint_musicdisable),
-                    new MessagesManager.Message(R.string.hint_excludenotification)
+                    new MessagesManager.Message( R.string.hint_excludenotification)
             );
 
             mTerminalAdapter.setMessagesManager(messagesManager);
@@ -1078,7 +976,17 @@ public class UIManager implements OnTouchListener {
     }
 
     public void dispose() {
-        if(handler != null) handler.removeCallbacksAndMessages(null);
+        if(handler != null) {
+            handler.removeCallbacksAndMessages(null);
+            handler = null;
+        }
+
+        if(suggestionsManager != null) suggestionsManager.dispose();
+        if(notesManager != null) notesManager.dispose(mContext);
+        LocalBroadcastManager.getInstance(mContext.getApplicationContext()).unregisterReceiver(receiver);
+        Tuils.unregisterBatteryReceiver(mContext);
+
+        Tuils.cancelFont();
     }
 
     public void openKeyboard() {
@@ -1120,17 +1028,11 @@ public class UIManager implements OnTouchListener {
     }
 
     public void disableSuggestions() {
-        if(suggestionsView != null) {
-            showSuggestions = false;
-            suggestionsView.setVisibility(View.GONE);
-        }
+        if(suggestionsManager != null) suggestionsManager.hide();
     }
 
     public void enableSuggestions() {
-        if(suggestionsView != null) {
-            showSuggestions = true;
-            suggestionsView.setVisibility(View.VISIBLE);
-        }
+        if(suggestionsManager != null) suggestionsManager.show();
     }
 
     public void onBackPressed() {
@@ -1141,19 +1043,6 @@ public class UIManager implements OnTouchListener {
         mTerminalAdapter.requestInputFocus();
     }
 
-    public Hintable getHintable() {
-        return new Hintable() {
-            @Override
-            public void updateHint() {
-                mTerminalAdapter.setDefaultHint();
-            }
-        };
-    }
-
-    public Rooter getRooter() {
-        return mTerminalAdapter.getRooter();
-    }
-
     //	 init detector for double tap
     private void initDetector() {
         det = new GestureDetector(mContext, TrashInterfaces.trashGestureListener);
@@ -1247,28 +1136,5 @@ public class UIManager implements OnTouchListener {
         };
     }
 
-//    public interface SuggestionNavigator {
-//        boolean isNavigating();
-//        void onEnter();
-//    }
-
-    public interface OnNewInputListener {
-        void onNewInput(String input, Object obj);
-    }
-
-//    public class PowerConnectionReceiver extends BroadcastReceiver {
-//        @Override
-//        public void onReceive(Context context, Intent intent) {
-//            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
-//            boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
-//
-//            if(isCharging) {
-//                battery.postDelayed(batteryChargingRunnable, BATTERY_CHARGING_DELAY);
-//            } else {
-//                battery.removeCallbacks(batteryChargingRunnable);
-//            }
-//        }
-//    }
-
 }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/Command.java b/app/src/main/java/ohi/andre/consolelauncher/commands/Command.java
index 340dbff78a2971ca36544e97965fcb033cfbf446..a579982e1eec9fd3c8b5c6097905b7b3118f71d6 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/Command.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/Command.java
@@ -33,12 +33,12 @@ public class Command {
 
             int[] args = param.args();
             if(args == null || mArgs[0] instanceof String) {
-                if(((String) mArgs[0]).length() == 0) cmd.onNotArgEnough(info, 0);
+                if(((String) mArgs[0]).length() == 0) return cmd.onNotArgEnough(info, 0);
                 else return resources.getString(R.string.output_invalid_param) + Tuils.SPACE + mArgs[0];
             }
 
             if(indexNotFound != -1) {
-                param.onArgNotFound(info, indexNotFound);
+                return param.onArgNotFound(info, indexNotFound);
             }
 
             if(pCmd.defaultParamReference() != null) {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java
index 4130ecdcbb15be2a3dadb6f47b1985712a7cf0d4..b3b61d2fe92dc5744b6b71374fc428e6c0d17c97 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java
@@ -9,7 +9,6 @@ public interface CommandAbstraction {
     int CONTACTNUMBER = 13;
     int TEXTLIST = 14;
     int SONG = 15;
-    int FILE_LIST = 16;
     int COMMAND = 17;
     int PARAM = 18;
     int BOOLEAN = 19;
@@ -24,6 +23,7 @@ public interface CommandAbstraction {
     int APP_GROUP = 28;
     int APP_INSIDE_GROUP = 29;
     int LONG = 30;
+    int BOUND_REPLY_APP = 31;
 
     String exec(ExecutePack pack) throws Exception;
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandGroup.java b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandGroup.java
index e00fc3d1901370800900be190fe4f91b61cf3e3e..82093b1540c8f913c679abff620d410596855143 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandGroup.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandGroup.java
@@ -50,7 +50,7 @@ public class CommandGroup {
 
     public CommandAbstraction getCommandByName(String name) {
         for(CommandAbstraction c : commands) {
-            if(c.getClass().getName().endsWith(Tuils.DOT.concat(name))) {
+            if(c.getClass().getSimpleName().equals(name)) {
                 return c;
             }
         }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java
index 68b2e27bdd6cc3842b9c35160443a2b7e131ebd6..fef452e3eb41987f70d9e16338a01ac9abb485c1 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java
@@ -17,9 +17,10 @@ import ohi.andre.consolelauncher.managers.ContactManager;
 import ohi.andre.consolelauncher.managers.FileManager;
 import ohi.andre.consolelauncher.managers.FileManager.DirInfo;
 import ohi.andre.consolelauncher.managers.RssManager;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.music.MusicManager2;
 import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
+import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Apps;
 import ohi.andre.consolelauncher.managers.xml.options.Notifications;
 import ohi.andre.consolelauncher.managers.xml.options.Rss;
@@ -32,7 +33,7 @@ public class CommandTuils {
     private static FileManager.SpecificExtensionFileFilter extensionFileFilter = new FileManager.SpecificExtensionFileFilter();
     private static FileManager.SpecificNameFileFilter nameFileFilter = new FileManager.SpecificNameFileFilter();
 
-    public static List<XMLPrefsManager.XMLPrefsSave> xmlPrefsEntrys;
+    public static List<XMLPrefsSave> xmlPrefsEntrys;
     public static List<String> xmlPrefsFiles;
 
     //	parse a command
@@ -146,13 +147,6 @@ public class CommandTuils {
             if(pack.player == null) return null;
 
             return song(input, pack.player);
-        } else if (type == CommandAbstraction.FILE_LIST && info instanceof MainPack) {
-            MainPack pack = (MainPack) info;
-
-            if (suggestion)
-                return file(input, pack.currentDirectory);
-            else
-                return fileList(input, pack.currentDirectory);
         } else if (type == CommandAbstraction.COMMAND) {
             return command(input, info.commandGroup);
         } else if(type == CommandAbstraction.BOOLEAN) {
@@ -169,9 +163,7 @@ public class CommandTuils {
             return defaultApp(input, ((MainPack) info).appsManager);
         } else if(type == CommandAbstraction.ALL_PACKAGES) {
             return allPackages(input, ((MainPack) info).appsManager);
-        } else if(type == CommandAbstraction.NO_SPACE_STRING) {
-            return noSpaceString(input);
-        } else if(type == CommandAbstraction.APP_GROUP) {
+        } else if(type == CommandAbstraction.NO_SPACE_STRING || type == CommandAbstraction.APP_GROUP || type == CommandAbstraction.BOUND_REPLY_APP) {
             return noSpaceString(input);
         } else if(type == CommandAbstraction.APP_INSIDE_GROUP) {
             return activityName(input, ((MainPack) info).appsManager);
@@ -182,7 +174,6 @@ public class CommandTuils {
         return null;
     }
 
-
 //	args extractors {
 
     private static ArgInfo numberLong(String input) {
@@ -227,7 +218,7 @@ public class CommandTuils {
             notUsed = null;
         }
 
-        Object result = used.toLowerCase().equals("true");
+        Object result = Boolean.parseBoolean(used);
         return new ArgInfo(result, notUsed, used.length() > 0, used.length() > 0 ? 1 : 0);
     }
 
@@ -256,19 +247,44 @@ public class CommandTuils {
     }
 
     private static ArgInfo command(String string, CommandGroup active) {
+        ArgInfo i = noSpaceString(string);
+        string = (String) i.arg;
+
         CommandAbstraction abstraction = null;
         try {
             abstraction = active.getCommandByName(string);
-        } catch (Exception e) {}
+        } catch (Exception e) {
+            Tuils.log(e);
+            Tuils.toFile(e);
+        }
 
-        return new ArgInfo(abstraction, null, abstraction != null, 1);
+        return new ArgInfo(abstraction, i.residualString, abstraction != null, 1);
     }
 
     @SuppressWarnings("unchecked")
     private static ArgInfo file(String input, File cd) {
+        input = input.trim();
+        if(input.startsWith("\"") || input.startsWith("'") && input.substring(1, input.length()).contains("\"")) {
+            String afterFirst = input.substring(1, input.length());
+
+            int endIndex = afterFirst.indexOf("\"");
+            if(endIndex == -1) endIndex = afterFirst.indexOf("'");
+
+            if(endIndex != -1) {
+                String file = afterFirst.substring(0, endIndex);
+                String residual = afterFirst.substring(endIndex + 1, afterFirst.length());
+
+                File f;
+                if(afterFirst.startsWith("/")) /*absolute*/ f = new File(file);
+                else f = new File(cd, file);
+
+                return new ArgInfo(f, residual, true, 1);
+            }
+        }
+
         List<String> strings = (List<String>) CommandTuils.textList(input).arg;
 
-        String toVerify = "";
+        String toVerify = Tuils.EMPTYSTRING;
         for (int count = 0; count < strings.size(); count++) {
             toVerify = toVerify.concat(strings.get(count));
 
@@ -281,47 +297,45 @@ public class CommandTuils {
                 return new ArgInfo(info.file, residual, true, 1);
             }
 
-            toVerify = toVerify.concat(" ");
+            toVerify = toVerify.concat(Tuils.SPACE);
         }
 
         return new ArgInfo(null, input, false, 0);
     }
 
-    @SuppressWarnings("unchecked")
-    private static ArgInfo fileList(String input, File cd) {
-        List<File> files = new ArrayList<>();
-        List<String> strings = (List<String>) CommandTuils.textList(input).arg;
-
-        String toVerify = "";
-        for (int count = 0; count < strings.size(); count++) {
-            String s = strings.get(count);
-
-            toVerify = toVerify.concat(s);
-
-            DirInfo dir = CommandTuils.getFile(toVerify, cd);
-            if (dir.notFound == null) {
-                files.add(dir.file);
-
-                toVerify = "";
-                continue;
-            }
-
-            List<File> tempFiles = CommandTuils.attemptWildcard(dir);
-            if (tempFiles != null) {
-                files.addAll(tempFiles);
-
-                toVerify = Tuils.EMPTYSTRING;
-                continue;
-            }
-
-            toVerify = toVerify.concat(Tuils.SPACE);
-        }
-
-        if (toVerify.length() > 0)
-            return new ArgInfo(null, null, false, 0);
-
-        return new ArgInfo(files, null, files.size() > 0, files.size());
-    }
+//    @SuppressWarnings("unchecked")
+//    private static ArgInfo fileList(String input, File cd) {
+//        List<File> files = new ArrayList<>();
+//        List<String> strings = (List<String>) CommandTuils.textList(input).arg;
+//
+//        String toVerify = Tuils.EMPTYSTRING;
+//        for (int count = 0; count < strings.size(); count++) {
+//            String s = strings.get(count);
+//
+//            toVerify = toVerify.concat(s);
+//
+//            DirInfo dir = CommandTuils.getFile(toVerify, cd);
+//            if (dir.notFound == null) {
+//                files.add(dir.file);
+//
+//                toVerify = Tuils.EMPTYSTRING;
+//                continue;
+//            }
+//
+//            List<File> tempFiles = CommandTuils.attemptWildcard(dir);
+//            if (tempFiles != null) {
+//                files.addAll(tempFiles);
+//
+//                toVerify = Tuils.EMPTYSTRING;
+//                continue;
+//            }
+//
+//            toVerify = toVerify.concat(Tuils.SPACE);
+//        }
+//
+//        if (toVerify.length() > 0) return new ArgInfo(null, null, false, 0);
+//        return new ArgInfo(files, null, files.size() > 0, files.size());
+//    }
 
     private static DirInfo getFile(String path, File cd) {
         return FileManager.cd(cd, path);
@@ -370,10 +384,7 @@ public class CommandTuils {
         String param = input.substring(0, indexOfFirstSpace).trim();
         if(!param.startsWith("-")) param = "-".concat(param);
 
-        Tuils.log(param);
-
         SimpleMutableEntry<Boolean, Param> sm = cmd.getParam(pack, param);
-        Tuils.log(sm.getKey(), sm.getValue());
         Param p = sm.getValue();
         boolean df = sm.getKey();
 
@@ -438,7 +449,7 @@ public class CommandTuils {
         }
 
         String candidate = index == -1 ? input : input.substring(0,index);
-        for(XMLPrefsManager.XMLPrefsSave xs : xmlPrefsEntrys) {
+        for(XMLPrefsSave xs : xmlPrefsEntrys) {
             if(xs.is(candidate)) {
                 return new ArgInfo(xs, index == -1 ? null : input.substring(index + 1,input.length()), true, 1);
             }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandsPreferences.java b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandsPreferences.java
index ef73e1dda2f955b44fad88993a6cd621cb3540c3..667ed8630284098d4e5d621808cc9c4f8344103d 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandsPreferences.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandsPreferences.java
@@ -3,6 +3,7 @@ package ohi.andre.consolelauncher.commands;
 import java.util.HashMap;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Cmd;
 
 /**
@@ -11,19 +12,42 @@ import ohi.andre.consolelauncher.managers.xml.options.Cmd;
 
 public class CommandsPreferences {
 
+    public static final String PRIORITY_SUFFIX = "_priority";
+
     private HashMap<String, String> preferenceHashMap;
 
     public CommandsPreferences() {
         preferenceHashMap = new HashMap<>();
 
-        for(XMLPrefsManager.XMLPrefsSave save : Cmd.values()) {
+        for(XMLPrefsSave save : Cmd.values()) {
             preferenceHashMap.put(save.label(), XMLPrefsManager.get(save));
         }
     }
 
-    public String get(XMLPrefsManager.XMLPrefsSave save) {
-        String v = preferenceHashMap.get(save.label());
+    public String get(String s) {
+        String v = preferenceHashMap.get(s);
+        if(v == null) return XMLPrefsManager.get(XMLPrefsManager.XMLPrefsRoot.CMD, s);
+        return v;
+    }
+
+    public String get(XMLPrefsSave save) {
+        String v = get(save.label());
         if(v == null || v.length() == 0) v = save.defaultValue();
         return v;
     }
+
+    public int userSetPriority(CommandAbstraction c) {
+        try {
+            String p = get(c.getClass().getSimpleName() + PRIORITY_SUFFIX);
+            return Integer.parseInt(p);
+        } catch (Exception e) {
+            return Integer.MAX_VALUE;
+        }
+    }
+
+    public int getPriority(CommandAbstraction c) {
+        int priority = userSetPriority(c);
+        if(priority == Integer.MAX_VALUE) return c.priority();
+        return priority;
+    }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/ExecutePack.java b/app/src/main/java/ohi/andre/consolelauncher/commands/ExecutePack.java
index 27ae035d77b5bdd925226e7a4b0249ff526f6558..e28d9ad650b9aa6152619398400e00b7768c3e68 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/ExecutePack.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/ExecutePack.java
@@ -5,7 +5,7 @@ import android.content.Context;
 import java.util.ArrayList;
 
 import ohi.andre.consolelauncher.managers.AppsManager;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 @SuppressWarnings("deprecation")
 public abstract class ExecutePack {
@@ -51,8 +51,8 @@ public abstract class ExecutePack {
         return (ArrayList) get();
     }
 
-    public XMLPrefsManager.XMLPrefsSave getPrefsSave() {
-        return (XMLPrefsManager.XMLPrefsSave) get();
+    public XMLPrefsSave getPrefsSave() {
+        return (XMLPrefsSave) get();
     }
 
     public AppsManager.LaunchInfo getLaunchInfo() {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/MainPack.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/MainPack.java
index 31881a6d567e08a532fd6b4aff26c934c293e4be..9d254e1431c2c1b84d440c914deea6c0ff97ae1d 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/MainPack.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/MainPack.java
@@ -20,10 +20,7 @@ import ohi.andre.consolelauncher.managers.flashlight.TorchManager;
 import ohi.andre.consolelauncher.managers.music.MusicManager2;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
-import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
 import ohi.andre.consolelauncher.tuils.interfaces.Redirectator;
-import ohi.andre.consolelauncher.tuils.interfaces.Reloadable;
-import ohi.andre.consolelauncher.tuils.interfaces.Rooter;
 import ohi.andre.consolelauncher.tuils.libsuperuser.ShellHolder;
 import okhttp3.OkHttpClient;
 
@@ -39,11 +36,6 @@ public class MainPack extends ExecutePack {
     //	resources references
     public Resources res;
 
-    //	flashlight
-//    public boolean isFlashOn = false, canUseFlash = false;
-//    public Camera camera;
-//    public Camera.Parameters parameters;
-
     //	internet
     public WifiManager wifi;
 
@@ -62,16 +54,8 @@ public class MainPack extends ExecutePack {
     public AliasManager aliasManager;
     public AppsManager appsManager;
 
-    //	reload field
-    public Reloadable reloadable;
-
-    public Rooter rooter;
-
     public CommandsPreferences cmdPrefs;
 
-    //	execute a command
-    public CommandExecuter executer;
-
     public LocationManager locationManager;
 
     public String lastCommand;
@@ -85,7 +69,7 @@ public class MainPack extends ExecutePack {
     public OkHttpClient client;
 
     public MainPack(Context context, CommandGroup commandGroup, AliasManager alMgr, AppsManager appmgr, MusicManager2 p,
-                    ContactManager c, Reloadable r, CommandExecuter executeCommand, Redirectator redirectator, ShellHolder shellHolder, RssManager rssManager, OkHttpClient client) {
+                    ContactManager c, Redirectator redirectator, ShellHolder shellHolder, RssManager rssManager, OkHttpClient client) {
         super(commandGroup);
 
         this.currentDirectory = XMLPrefsManager.get(File.class, Behavior.home_path);
@@ -98,52 +82,20 @@ public class MainPack extends ExecutePack {
 
         this.res = context.getResources();
 
-        this.executer = executeCommand;
-
         this.context = context;
 
         this.aliasManager = alMgr;
         this.appsManager = appmgr;
 
-//        this.canUseFlash = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
-
         this.cmdPrefs = new CommandsPreferences();
 
         this.player = p;
         this.contacts = c;
 
-        this.reloadable = r;
-
         this.redirectator = redirectator;
     }
 
-//    public void initCamera() {
-//        try {
-//            this.camera = Camera.open();
-//            this.parameters = this.camera.getParameters();
-//            List<Camera.Size> sizes = this.parameters.getSupportedPreviewSizes();
-//            if(sizes != null && sizes.size() > 0) {
-//                this.parameters.setPreviewSize(sizes.get(0).width, sizes.get(0).height);
-//            }
-//        } catch (Exception e) {
-//            this.camera = null;
-//            this.parameters = null;
-//        }
-//    }
-
     public void dispose() {
-//        if (this.camera == null || this.isFlashOn)
-//            return;
-//
-//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-//            flash.detachSurfaceTexture(null);
-//        }
-
-//        this.camera.stopPreview();
-//        this.camera.release();
-//        this.camera = null;
-//        this.parameters = null;
-
         TorchManager mgr = TorchManager.getInstance();
         if(mgr.isOn()) mgr.turnOff();
     }
@@ -152,5 +104,6 @@ public class MainPack extends ExecutePack {
         if(player != null) player.destroy();
         appsManager.onDestroy();
         if(rssManager != null) rssManager.dispose();
+        contacts.destroy(context);
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/airplane.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/airplane.java
index 56cd940c006cc9bb0ea0130b4e341113a20f1e64..686f1f62a4a89cdf16f5bf7f2561fc485aacbcba 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/airplane.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/airplane.java
@@ -6,6 +6,7 @@ import android.os.Build;
 import android.provider.Settings;
 
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.APICommand;
@@ -13,7 +14,7 @@ import ohi.andre.consolelauncher.commands.specific.APICommand;
 /**
  * Created by andre on 03/12/15.
  */
-public class airplane extends APICommand {
+public class airplane implements APICommand, CommandAbstraction {
 
     @Override
     public String exec(ExecutePack pack) {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/apps.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/apps.java
index 03d6fe7e4d14f671216c4048ec6cb638116f0bb9..15a8830caf0e5e32665e6e1ec562523c8357fb12 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/apps.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/apps.java
@@ -14,7 +14,7 @@ import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.ParamCommand;
 import ohi.andre.consolelauncher.managers.AppsManager;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Apps;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
@@ -131,7 +131,7 @@ public class apps extends ParamCommand {
                 }
 
                 try {
-                    XMLPrefsManager.XMLPrefsSave save = Apps.valueOf("default_app_n" + index);
+                    XMLPrefsSave save = Apps.valueOf("default_app_n" + index);
                     save.parent().write(save, marker);
                     return null;
                 } catch (Exception e) {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/bluetooth.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/bluetooth.java
index 073f0cec0e210d9ca217d7ebbe2799d842a14715..47cd31ec74908ddf9f6a9c3593935376d6a1f999 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/bluetooth.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/bluetooth.java
@@ -6,20 +6,23 @@ import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
-import ohi.andre.consolelauncher.tuils.Tuils;
 
 public class bluetooth implements CommandAbstraction {
 
     @Override
     public String exec(ExecutePack pack) {
         MainPack info = (MainPack) pack;
+
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+
+        if(adapter == null) return info.context.getString(R.string.output_bluetooth_unavailable);
+
         if(adapter.isEnabled()) {
             adapter.disable();
-            return info.context.getString(R.string.output_bluetooth) + Tuils.SPACE + "false";
+            return info.context.getString(R.string.output_bluetooth) + " false";
         } else {
             adapter.enable();
-            return info.context.getString(R.string.output_bluetooth) + Tuils.SPACE + "true";
+            return info.context.getString(R.string.output_bluetooth) + " true";
         }
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/clear.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/clear.java
index e5c9790bf541750b87c5efc57db3e9ce983ae303..36a91ebd172a55c5f522ea42d40bf2605acc0c5c 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/clear.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/clear.java
@@ -1,6 +1,10 @@
 package ohi.andre.consolelauncher.commands.main.raw;
 
+import android.content.Intent;
+import android.support.v4.content.LocalBroadcastManager;
+
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.UIManager;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 
@@ -9,11 +13,10 @@ import ohi.andre.consolelauncher.commands.ExecutePack;
  */
 public class clear implements CommandAbstraction {
 
-    public static final String CLEAR = "#clear#";
-
     @Override
     public String exec(ExecutePack info) throws Exception {
-        return CLEAR;
+        LocalBroadcastManager.getInstance(info.context.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_CLEAR));
+        return null;
     }
 
     @Override
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java
index 7e62b136e9bd28f101a809e1049d3b82ad80e995..284c4d4e0ecd0ae4bddc8b02ed7bcc1c6ae335c5 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java
@@ -13,6 +13,7 @@ import ohi.andre.consolelauncher.managers.AppsManager;
 import ohi.andre.consolelauncher.managers.RssManager;
 import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Apps;
 import ohi.andre.consolelauncher.managers.xml.options.Notifications;
 import ohi.andre.consolelauncher.tuils.Tuils;
@@ -33,7 +34,7 @@ public class config extends ParamCommand {
 
             @Override
             public String exec(ExecutePack pack) {
-                XMLPrefsManager.XMLPrefsSave save = pack.getPrefsSave();
+                XMLPrefsSave save = pack.getPrefsSave();
                 save.parent().write(save, pack.getString());
 
                 if(save.label().startsWith("default_app_n")) {
@@ -56,7 +57,7 @@ public class config extends ParamCommand {
 
             @Override
             public String exec(ExecutePack pack) {
-                XMLPrefsManager.XMLPrefsSave save = pack.getPrefsSave();
+                XMLPrefsSave save = pack.getPrefsSave();
 
                 return "Type:" + Tuils.SPACE + save.type() + Tuils.NEWLINE
                         + "Default:" + Tuils.SPACE + save.defaultValue() + Tuils.NEWLINE
@@ -89,7 +90,7 @@ public class config extends ParamCommand {
 
             @Override
             public String exec(ExecutePack pack) {
-                XMLPrefsManager.XMLPrefsSave save = pack.getPrefsSave();
+                XMLPrefsSave save = pack.getPrefsSave();
                 save.parent().write(save, XMLPrefsManager.get(save) + pack.getString());
 
                 return null;
@@ -109,7 +110,7 @@ public class config extends ParamCommand {
 
             @Override
             public String exec(ExecutePack pack) {
-                XMLPrefsManager.XMLPrefsSave save = pack.getPrefsSave();
+                XMLPrefsSave save = pack.getPrefsSave();
                 String s = XMLPrefsManager.get(String.class, save);
                 if(s.length() == 0) return "\"\"";
                 return s;
@@ -165,16 +166,16 @@ public class config extends ParamCommand {
 
                 for(XMLPrefsManager.XMLPrefsRoot element : XMLPrefsManager.XMLPrefsRoot.values()) {
                     ss.add(element.path);
-                    for(XMLPrefsManager.XMLPrefsSave save : element.copy) {
+                    for(XMLPrefsSave save : element.copy) {
                         ss.add(Tuils.DOUBLE_SPACE + save.label());
                     }
                 }
                 ss.add(AppsManager.PATH);
-                for(XMLPrefsManager.XMLPrefsSave save : Apps.values()) {
+                for(XMLPrefsSave save : Apps.values()) {
                     ss.add(Tuils.DOUBLE_SPACE + save.label());
                 }
                 ss.add(NotificationManager.PATH);
-                for(XMLPrefsManager.XMLPrefsSave save : Notifications.values()) {
+                for(XMLPrefsSave save : Notifications.values()) {
                     ss.add(Tuils.DOUBLE_SPACE + save.label());
                 }
 
@@ -194,7 +195,7 @@ public class config extends ParamCommand {
 
             @Override
             public String exec(ExecutePack pack) {
-                XMLPrefsManager.XMLPrefsSave save = pack.getPrefsSave();
+                XMLPrefsSave save = pack.getPrefsSave();
                 save.parent().write(save, save.defaultValue());
                 return null;
             }
@@ -211,28 +212,25 @@ public class config extends ParamCommand {
 
                 if(!file.getName().endsWith(".xml")) {
 //                    is font
-                    File font = new File(Tuils.getFolder(), Tuils.FONT_PATH);
-                    if(font.exists()) {
-                        File[] files = font.listFiles();
-                        if(files.length > 0) Tuils.insertOld(files[0]);
-                        Tuils.deleteContent(font);
-                    } else {
-                        font.mkdir();
+                    if(Tuils.fontPath != null) {
+                        File font = new File(Tuils.fontPath);
+                        if (font.exists()) {
+                            File[] files = font.listFiles();
+                            if (files.length > 0) Tuils.insertOld(files[0]);
+                            Tuils.deleteContent(font);
+                        } else {
+                            font.mkdir();
+                        }
                     }
-
-                    File dest = new File(font, file.getName());
-                    file.renameTo(dest);
-
-                    return "Path: " + dest.getAbsolutePath();
                 } else {
                     File old = new File(Tuils.getFolder(), file.getName());
                     Tuils.insertOld(old);
+                }
 
-                    File dest = new File(Tuils.getFolder(), file.getName());
-                    file.renameTo(dest);
+                File dest = new File(Tuils.getFolder(), file.getName());
+                file.renameTo(dest);
 
-                    return "Path: " + dest.getAbsolutePath();
-                }
+                return "Path: " + dest.getAbsolutePath();
             }
         },
         tutorial {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/ctrlc.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/ctrlc.java
index ea26d99842c4ed6676a997721a91356bdc444160..31bba35cb5c253edc4bdfff0f535f180f2bb5b23 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/ctrlc.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/ctrlc.java
@@ -1,10 +1,18 @@
 package ohi.andre.consolelauncher.commands.main.raw;
 
+import android.content.Intent;
+import android.support.v4.content.LocalBroadcastManager;
+
+import java.io.File;
+
 import ohi.andre.consolelauncher.MainManager;
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.UIManager;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
+import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
 
 /**
@@ -25,10 +33,13 @@ public class ctrlc implements CommandAbstraction {
                 MainManager.interactive = null;
 
                 MainManager.interactive = ((MainPack) pack).shellHolder.build();
+
+                ((MainPack) pack).currentDirectory = XMLPrefsManager.get(File.class, Behavior.home_path);
+                LocalBroadcastManager.getInstance(pack.context.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_UPDATE_HINT));
             }
         }.start();
 
-        ((MainPack) pack).rooter.onStandard();
+        LocalBroadcastManager.getInstance(pack.context.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_NOROOT));
 
         return null;
     }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/data.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/data.java
index 52fbc65191bcd19dc1cf2eecb73120d64446dfa2..0043a4bd37205bcac0345ce82ddc89458e5140d3 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/data.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/data.java
@@ -10,12 +10,13 @@ import android.os.Build;
 import java.lang.reflect.Field;
 
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.APICommand;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
-public class data extends APICommand {
+public class data implements APICommand, CommandAbstraction {
 
     @Override
     public String exec(ExecutePack pack) {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/help.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/help.java
index aac066c6b11330716ec7635bbef19482f3708078..f8f3791d78959b4eb838919d1f0cd870b4b3b0a5 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/help.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/help.java
@@ -19,7 +19,7 @@ public class help implements CommandAbstraction {
         MainPack info = (MainPack) pack;
         CommandAbstraction cmd = info.get(CommandAbstraction.class);
         int res = cmd == null ? R.string.output_commandnotfound : cmd.helpRes();
-        return info.res.getString(res);
+        return "Priority: " + info.cmdPrefs.getPriority(cmd) + Tuils.NEWLINE + info.res.getString(res);
     }
 
     @Override
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/location.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/location.java
index a848ec4f3c5dc7a48ae53e8af07c5f6518ca54c3..8e17404a802353ef006cce6d97f35fce2db3c21e 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/location.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/location.java
@@ -14,6 +14,7 @@ import android.support.v4.app.ActivityCompat;
 
 import ohi.andre.consolelauncher.LauncherActivity;
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.APICommand;
@@ -23,7 +24,7 @@ import ohi.andre.consolelauncher.tuils.Tuils;
  * Created by francescoandreuzzi on 10/05/2017.
  */
 
-public class location extends APICommand {
+public class location implements APICommand, CommandAbstraction {
 
     @Override
     public String exec(final ExecutePack pack) throws Exception {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/music.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/music.java
index 077e65b2d5d6465ceabae7795cab9810b41fbbc3..8d959d6ce96abdb8c7b427115d919595f6f2d321 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/music.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/music.java
@@ -107,6 +107,7 @@ public class music extends ParamCommand {
 
                 MusicManager2 m = ((MainPack) pack).player;
                 Song song = m.get(m.getSongIndex());
+                if(song == null) return pack.context.getString(R.string.output_songnotfound);
 
                 builder.append("Name: " + song.getTitle()).append(Tuils.NEWLINE);
                 if(song.getID() == -1) builder.append("Path: " + song.getPath()).append(Tuils.NEWLINE);
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/notes.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/notes.java
new file mode 100644
index 0000000000000000000000000000000000000000..44e598b16ad6ad0406b0c873682f4589fe23f636
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/notes.java
@@ -0,0 +1,168 @@
+package ohi.andre.consolelauncher.commands.main.raw;
+
+import android.content.Intent;
+import android.support.v4.content.LocalBroadcastManager;
+
+import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
+import ohi.andre.consolelauncher.commands.ExecutePack;
+import ohi.andre.consolelauncher.commands.main.MainPack;
+import ohi.andre.consolelauncher.commands.specific.ParamCommand;
+import ohi.andre.consolelauncher.managers.NotesManager;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+/**
+ * Created by francescoandreuzzi on 12/02/2018.
+ */
+
+public class notes extends ParamCommand {
+
+    private enum Param implements ohi.andre.consolelauncher.commands.main.Param {
+
+        add {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.PLAIN_TEXT};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent i = new Intent(NotesManager.ACTION_ADD);
+                i.putExtra(NotesManager.TEXT, pack.getString());
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(i);
+                return null;
+            }
+        },
+        rm {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.PLAIN_TEXT};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent i = new Intent(NotesManager.ACTION_RM);
+                i.putExtra(NotesManager.TEXT, pack.getString());
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(i);
+                return null;
+            }
+        },
+        ls {
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent i = new Intent(NotesManager.ACTION_LS);
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(i);
+                return null;
+            }
+        },
+        clear {
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent i = new Intent(NotesManager.ACTION_CLEAR);
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(i);
+                return null;
+            }
+        },
+        lock {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.PLAIN_TEXT};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent i = new Intent(NotesManager.ACTION_LOCK);
+                i.putExtra(NotesManager.TEXT, pack.getString());
+                i.putExtra(NotesManager.LOCK, true);
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(i);
+                return null;
+            }
+        },
+        unlock {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.PLAIN_TEXT};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent i = new Intent(NotesManager.ACTION_LOCK);
+                i.putExtra(NotesManager.TEXT, pack.getString());
+                i.putExtra(NotesManager.LOCK, false);
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(i);
+                return null;
+            }
+        };
+
+        @Override
+        public int[] args() {
+            return new int[0];
+        }
+
+        static Param get(String p) {
+            p = p.toLowerCase();
+            Param[] ps = values();
+            for (Param p1 : ps)
+                if (p.endsWith(p1.label()))
+                    return p1;
+            return null;
+        }
+
+        static String[] labels() {
+            Param[] ps = values();
+            String[] ss = new String[ps.length];
+
+            for(int count = 0; count < ps.length; count++) {
+                ss[count] = ps[count].label();
+            }
+
+            return ss;
+        }
+
+        @Override
+        public String label() {
+            return Tuils.MINUS + name();
+        }
+
+        @Override
+        public String onArgNotFound(ExecutePack pack, int index) {
+            return pack.context.getString(R.string.help_notes);
+        }
+
+        @Override
+        public String onNotArgEnough(ExecutePack pack, int n) {
+            return pack.context.getString(R.string.help_notes);
+        }
+    }
+
+    @Override
+    protected ohi.andre.consolelauncher.commands.main.Param paramForString(MainPack pack, String param) {
+        return Param.get(param);
+    }
+
+    @Override
+    protected String doThings(ExecutePack pack) {
+        return null;
+    }
+
+    @Override
+    public String[] params() {
+        return Param.labels();
+    }
+
+    @Override
+    public int priority() {
+        return 4;
+    }
+
+    @Override
+    public int helpRes() {
+        return R.string.help_notes;
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/regex.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/regex.java
index b14de39344c2bbd14b2c48d558b1d09b031f3d05..9f8559095564926ed327f99076661f159c7e9202 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/regex.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/regex.java
@@ -19,7 +19,7 @@ public class regex extends ParamCommand {
         add {
             @Override
             public String exec(ExecutePack pack) {
-                String output = RegexManager.add(pack.getInt(), pack.getString());
+                String output = RegexManager.instance.add(pack.getInt(), pack.getString());
                 if(output == null) return null;
                 if(output.length() == 0) return pack.context.getString(R.string.id_already);
                 else return output;
@@ -33,7 +33,7 @@ public class regex extends ParamCommand {
         rm {
             @Override
             public String exec(ExecutePack pack) {
-                String output = RegexManager.rm(pack.getInt());
+                String output = RegexManager.instance.rm(pack.getInt());
                 if(output == null) return null;
                 if(output.length() == 0) return pack.context.getString(R.string.id_notfound);
                 return output;
@@ -47,7 +47,7 @@ public class regex extends ParamCommand {
         get {
             @Override
             public String exec(ExecutePack pack) {
-                RegexManager.Regex r = RegexManager.get(pack.getInt());
+                RegexManager.Regex r = RegexManager.instance.get(pack.getInt());
                 if(r == null) return pack.context.getString(R.string.id_notfound);
 
                 return r.regex != null ? r.regex.pattern() : r.literalPattern;
@@ -61,7 +61,7 @@ public class regex extends ParamCommand {
         test {
             @Override
             public String exec(ExecutePack pack) {
-                CharSequence s = RegexManager.test(pack.getInt(), pack.getString());
+                CharSequence s = RegexManager.instance.test(pack.getInt(), pack.getString());
                 if(s.length() == 0) return pack.context.getString(R.string.id_notfound);
 
                 Tuils.sendOutput(pack.context, s);
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/reply.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/reply.java
new file mode 100644
index 0000000000000000000000000000000000000000..dce2b5c66e02bbae317dc5ce170d9e08a8b75eef
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/reply.java
@@ -0,0 +1,163 @@
+package ohi.andre.consolelauncher.commands.main.raw;
+
+import android.content.Intent;
+import android.os.Build;
+import android.support.v4.content.LocalBroadcastManager;
+
+import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
+import ohi.andre.consolelauncher.commands.ExecutePack;
+import ohi.andre.consolelauncher.commands.main.MainPack;
+import ohi.andre.consolelauncher.commands.specific.APICommand;
+import ohi.andre.consolelauncher.commands.specific.ParamCommand;
+import ohi.andre.consolelauncher.managers.notifications.reply.ReplyManager;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+/**
+ * Created by francescoandreuzzi on 05/11/2017.
+ */
+
+public class reply extends ParamCommand implements APICommand {
+
+    private enum Param implements ohi.andre.consolelauncher.commands.main.Param {
+
+        to {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.BOUND_REPLY_APP, CommandAbstraction.PLAIN_TEXT};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent intent = new Intent(ReplyManager.ACTION);
+
+                intent.putExtra(ReplyManager.ID, pack.getString());
+                intent.putExtra(ReplyManager.WHAT, pack.getString());
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(intent);
+                return null;
+            }
+        },
+        bind {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.VISIBLE_PACKAGE};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                String output = ReplyManager.bind(pack.getLaunchInfo().componentName.getPackageName());
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(new Intent(ReplyManager.ACTION_UPDATE));
+                return output;
+            }
+        },
+        check {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.BOUND_REPLY_APP};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent intent = new Intent(ReplyManager.ACTION);
+                intent.putExtra(ReplyManager.ID, pack.getString());
+
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(intent);
+                return null;
+            }
+        },
+        unbind {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.VISIBLE_PACKAGE};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                String output = ReplyManager.unbind(pack.getLaunchInfo().componentName.getPackageName());
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(new Intent(ReplyManager.ACTION_UPDATE));
+
+                if(output != null && output.length() == 0) return pack.context.getString(R.string.reply_app_not_found) + pack.getLaunchInfo().componentName.getPackageName();
+                return output;
+            }
+        },
+        ls {
+            @Override
+            public int[] args() {
+                return new int[0];
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent intent = new Intent(ReplyManager.ACTION_LS);
+                LocalBroadcastManager.getInstance(pack.context).sendBroadcast(intent);
+                return null;
+            }
+        };
+
+        static Param get(String p) {
+            p = p.toLowerCase();
+            Param[] ps = values();
+            for (Param p1 : ps)
+                if (p.endsWith(p1.label()))
+                    return p1;
+            return null;
+        }
+
+        static String[] labels() {
+            Param[] ps = values();
+            String[] ss = new String[ps.length];
+
+            for (int count = 0; count < ps.length; count++) {
+                ss[count] = ps[count].label();
+            }
+
+            return ss;
+        }
+
+        @Override
+        public String label() {
+            return Tuils.MINUS + name();
+        }
+
+        @Override
+        public String onNotArgEnough(ExecutePack pack, int n) {
+            return pack.context.getString(R.string.help_reply);
+        }
+
+        @Override
+        public String onArgNotFound(ExecutePack pack, int index) {
+            return pack.context.getString(R.string.help_reply);
+        }
+    }
+
+    @Override
+    public String[] params() {
+        return Param.labels();
+    }
+
+    @Override
+    protected Param paramForString(MainPack pack, String param) {
+        return Param.get(param);
+    }
+
+    @Override
+    protected String doThings(ExecutePack pack) {
+        return null;
+    }
+
+    @Override
+    public int priority() {
+        return 4;
+    }
+
+    @Override
+    public int helpRes() {
+        return R.string.help_reply;
+    }
+
+    @Override
+    public boolean willWorkOn(int api) {
+        return api >= Build.VERSION_CODES.KITKAT_WATCH;
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java
index b88c5b976e8f8ba0d6be52e882f4f5ac37a112d6..f27403f5e2f129bdfa26f913ca33f415bad23ef8 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java
@@ -4,13 +4,15 @@ import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
+import ohi.andre.consolelauncher.tuils.interfaces.Reloadable;
 
 public class restart implements CommandAbstraction {
 
     @Override
     public String exec(ExecutePack pack) {
         MainPack info = (MainPack) pack;
-        info.reloadable.reload();
+        ((Reloadable) info.context).reload();
+
         return pack.context.getString(R.string.restarting);
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/rss.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/rss.java
index 67e88a89a2cfc19b999c86521781a69b251de9ba..d003528627df4ac04bd8aa168ba6d89e0fc047fe 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/rss.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/rss.java
@@ -190,7 +190,7 @@ public class rss extends ParamCommand {
                 if(value == null) return pack.context.getString(R.string.rss_never_checked);
 
                 try {
-                    return TimeManager.replace(XMLPrefsManager.get(Rss.rss_time_format), Long.parseLong(value),
+                    return TimeManager.instance.replace(XMLPrefsManager.get(Rss.rss_time_format), Long.parseLong(value),
                             Integer.MAX_VALUE).toString();
                 } catch (Exception e) {
                     Tuils.log(e);
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/search.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/search.java
index 6cef05805081eb699b4a6178fd357d7dfc322cd8..ee4eaaec10ac1cb8fd15f7135821bf3639b623dd 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/search.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/search.java
@@ -11,7 +11,7 @@ import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.ParamCommand;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Cmd;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
@@ -116,7 +116,7 @@ public class search extends ParamCommand {
     }
 
     @Override
-    public XMLPrefsManager.XMLPrefsSave defaultParamReference() {
+    public XMLPrefsSave defaultParamReference() {
         return Cmd.default_search;
     }
 
diff --git a/app/src/playstore/java/ohi/andre/consolelauncher/commands/main/raw/theme.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/theme.java
similarity index 70%
rename from app/src/playstore/java/ohi/andre/consolelauncher/commands/main/raw/theme.java
rename to app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/theme.java
index de9a3fa7c8ed8a56747d60019c3c9fe20903df78..efb70c1a319b6ada03928c35b9ae30525aee0772 100644
--- a/app/src/playstore/java/ohi/andre/consolelauncher/commands/main/raw/theme.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/theme.java
@@ -1,13 +1,10 @@
 package ohi.andre.consolelauncher.commands.main.raw;
 
-import java.io.File;
-
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.ParamCommand;
-import ohi.andre.consolelauncher.managers.ThemesManager;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
 /**
@@ -26,50 +23,47 @@ public class theme extends ParamCommand {
 
             @Override
             public String exec(ExecutePack pack) {
-                String theme = pack.getString();
-                ThemesManager.apply(pack.context, theme);
-                return null;
+                return "themes are not working at the moment, the new website will be ready soon";
             }
         },
         view {
             @Override
             public String exec(ExecutePack pack) {
-                pack.context.startActivity(Tuils.webPage("http://tui-launcher.surge.sh/"));
-                return null;
+                return "themes are not working at the moment, the new website will be ready soon";
             }
         },
         create {
             @Override
             public String exec(ExecutePack pack) {
-                pack.context.startActivity(Tuils.webPage("http://tui-launcher.surge.sh/create"));
-                return null;
+                return "themes are not working at the moment, the new website will be ready soon";
             }
         },
         ls {
             @Override
             public String exec(ExecutePack pack) {
-                ThemesManager.ls(pack.context);
-                return null;
+                return "themes are not working at the moment, the new website will be ready soon";
             }
         },
         old {
             @Override
             public String exec(ExecutePack pack) {
-                File theme = Tuils.getOld("theme.xml");
-                File suggestions = Tuils.getOld("suggestions.xml");
-
-                if(theme == null || suggestions == null) return pack.context.getString(R.string.theme_old_not_found);
-
-                File themeDest = new File(Tuils.getFolder(), "theme.xml");
-                File suggestionsDest = new File(Tuils.getFolder(), "suggestions.xml");
-
-                if(themeDest.exists()) themeDest.delete();
-                if(suggestionsDest.exists()) suggestionsDest.delete();
-
-                theme.renameTo(themeDest);
-                suggestions.renameTo(suggestionsDest);
-
-                return pack.context.getString(R.string.theme_reverted);
+//                File theme = Tuils.getOld("theme.xml");
+//                File suggestions = Tuils.getOld("suggestions.xml");
+//
+//                if(theme == null || suggestions == null) return pack.context.getString(R.string.theme_old_not_found);
+//
+//                File themeDest = new File(Tuils.getFolder(), "theme.xml");
+//                File suggestionsDest = new File(Tuils.getFolder(), "suggestions.xml");
+//
+//                if(themeDest.exists()) themeDest.delete();
+//                if(suggestionsDest.exists()) suggestionsDest.delete();
+//
+//                theme.renameTo(themeDest);
+//                suggestions.renameTo(suggestionsDest);
+//
+//                return pack.context.getString(R.string.theme_reverted);
+
+                return "themes are not working at the moment, the new website will be ready soon";
             }
         },
         tutorial {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/time.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/time.java
index 01620f8ad6e03d189c802c2627f34d4eb5be360b..d0cae4f5a78ef1a0c9a21e2c5aafc7259fe1f049 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/time.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/time.java
@@ -12,7 +12,7 @@ public class time implements CommandAbstraction {
     @Override
     public String exec(ExecutePack pack) {
         int index = pack.getInt();
-        return TimeManager.replace("%t" + index).toString();
+        return TimeManager.instance.replace("%t" + index).toString();
     }
 
     @Override
@@ -37,6 +37,6 @@ public class time implements CommandAbstraction {
 
     @Override
     public String onNotArgEnough(ExecutePack info, int nArgs) {
-        return TimeManager.replace("%t0").toString();
+        return TimeManager.instance.replace("%t0").toString();
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tui.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tui.java
index 3ed9d11e19e4930a1b248c7b1c85e671a14b83f7..45f0e4860833dd2ddd07fc351819696875324ca0 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tui.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tui.java
@@ -5,12 +5,19 @@ import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.support.v4.content.LocalBroadcastManager;
+
+import java.io.File;
 
 import ohi.andre.consolelauncher.BuildConfig;
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.UIManager;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
+import ohi.andre.consolelauncher.commands.CommandsPreferences;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.specific.ParamCommand;
+import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.stuff.PolicyReceiver;
 
@@ -42,7 +49,51 @@ public class tui extends ParamCommand {
             @Override
             public String exec(ExecutePack pack) {
                 MainPack info = (MainPack) pack;
-                return info.res.getString(R.string.version_label) + Tuils.SPACE + BuildConfig.VERSION_NAME + Tuils.NEWLINE + Tuils.NEWLINE + info.res.getString(R.string.output_about);
+                return "Version:" + Tuils.SPACE + BuildConfig.VERSION_NAME + " (code: " + BuildConfig.VERSION_CODE + ")" +
+                        (BuildConfig.DEBUG ? Tuils.NEWLINE + BuildConfig.BUILD_TYPE : Tuils.EMPTYSTRING) +
+                        Tuils.NEWLINE + Tuils.NEWLINE + info.res.getString(R.string.output_about);
+            }
+        },
+        log {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.PLAIN_TEXT};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                Intent i = new Intent(UIManager.ACTION_LOGTOFILE);
+                i.putExtra(UIManager.FILE_NAME, pack.getString());
+                LocalBroadcastManager.getInstance(pack.context.getApplicationContext()).sendBroadcast(i);
+
+                return null;
+            }
+
+            @Override
+            public String onNotArgEnough(ExecutePack pack, int n) {
+                return pack.context.getString(R.string.help_tui);
+            }
+        },
+        priority {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.COMMAND, CommandAbstraction.INT};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                File file = new File(Tuils.getFolder(), "cmd.xml");
+                return XMLPrefsManager.set(file, pack.get().getClass().getSimpleName() + CommandsPreferences.PRIORITY_SUFFIX, new String[] {XMLPrefsManager.VALUE_ATTRIBUTE}, new String[] {String.valueOf(pack.getInt())});
+            }
+
+            @Override
+            public String onNotArgEnough(ExecutePack pack, int n) {
+                return pack.context.getString(R.string.help_tui);
+            }
+
+            @Override
+            public String onArgNotFound(ExecutePack pack, int index) {
+                return pack.context.getString(R.string.output_invalidarg);
             }
         },
         telegram {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/vibrate.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/vibrate.java
index f98c6baae9b0b2c8ce05d493c43740ef22997f76..47c92d2f946b6a6aa03a191683e55e64b19041d4 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/vibrate.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/vibrate.java
@@ -17,7 +17,7 @@ public class vibrate implements CommandAbstraction {
 
     @Override
     public String exec(ExecutePack pack) throws Exception {
-        String text = pack.getString().trim();
+        String text = pack.getString();
         Context context = ((MainPack) pack).context;
 
         char separator = Tuils.firstNonDigit(text);
@@ -42,7 +42,6 @@ public class vibrate implements CommandAbstraction {
                 }
             }
 
-            text = text.trim();
             String[] split = text.split(separator + Tuils.EMPTYSTRING);
             long pattern[] = new long[split.length];
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/specific/APICommand.java b/app/src/main/java/ohi/andre/consolelauncher/commands/specific/APICommand.java
index eead85e44d7090dc5450f51149d2d4e3f9c60d1c..f671c49d3d786c0b6f1f57810a33319900ce2a10 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/specific/APICommand.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/specific/APICommand.java
@@ -1,12 +1,10 @@
 package ohi.andre.consolelauncher.commands.specific;
 
-import ohi.andre.consolelauncher.commands.CommandAbstraction;
-
 /**
  * Created by francescoandreuzzi on 01/08/2017.
  */
 
-public abstract class APICommand implements CommandAbstraction {
+public interface APICommand {
 
-    public abstract boolean willWorkOn(int api);
+    boolean willWorkOn(int api);
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java b/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java
index 606a498133fc183fafd4aa5adc5aa725f08b56f1..8c24c506dbb38fa2791193d0ef55b75f0f19585a 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java
@@ -5,7 +5,7 @@ import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.main.Param;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.tuils.SimpleMutableEntry;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
@@ -67,7 +67,7 @@ public abstract class ParamCommand implements CommandAbstraction {
     public abstract String[] params();
     protected abstract Param paramForString(MainPack pack, String param);
     protected abstract String doThings(ExecutePack pack);
-    public XMLPrefsManager.XMLPrefsSave defaultParamReference() {
+    public XMLPrefsSave defaultParamReference() {
         return null;
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java b/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java
index 4fe6aa3a68d6e144a25f7510590870e154215075..293867e44055cda3e345cc7ade91f191635bcccf 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java
@@ -79,7 +79,7 @@ public class TuixtActivity extends Activity {
         CommandGroup group = new CommandGroup(this, "ohi.andre.consolelauncher.commands.tuixt.raw");
 
         try {
-            XMLPrefsManager.create(this);
+            XMLPrefsManager.loadCommons(this);
         } catch (Exception e) {
             finish();
         }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/AliasManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/AliasManager.java
index cc9cb28838e4c8ce2d3746671a7d2029b91a60f6..27dbdcc78107065136b194ec4da30cf8c64bc5c5 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/AliasManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/AliasManager.java
@@ -11,10 +11,8 @@ import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.InputStreamReader;
-import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -22,31 +20,34 @@ import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.tuils.Tuils;
-import ohi.andre.consolelauncher.tuils.interfaces.Reloadable;
 
-public class AliasManager implements Reloadable {
+public class AliasManager {
 
     public static final String PATH = "alias.txt";
 
-    private List<Map.Entry<String, String>> aliases;
-    private String paramMarker, paramSeparator, aliasLabelFormat;
+    private List<Alias> aliases;
+    private String paramSeparator, aliasLabelFormat;
+    private boolean replaceAllMarkers;
 
     private Context context;
 
+    private Pattern parameterPattern;
+
     public AliasManager(Context c) {
         this.context = c;
 
-        reload();
-
-        paramMarker = Pattern.quote(XMLPrefsManager.get(Behavior.alias_param_marker));
+        parameterPattern = Pattern.compile(Pattern.quote(XMLPrefsManager.get(Behavior.alias_param_marker)));
         paramSeparator = Pattern.quote(XMLPrefsManager.get(Behavior.alias_param_separator));
         aliasLabelFormat = XMLPrefsManager.get(Behavior.alias_content_format);
+        replaceAllMarkers = XMLPrefsManager.getBoolean(Behavior.alias_replace_all_markers);
+
+        reload();
     }
 
     public String printAliases() {
         String output = Tuils.EMPTYSTRING;
-        for (Map.Entry<String, String> entry : aliases) {
-            output = output.concat(entry.getKey() + " --> " + entry.getValue() + Tuils.NEWLINE);
+        for (Alias a : aliases) {
+            output = output.concat(a.name + " --> " + a.value + Tuils.NEWLINE);
         }
 
         return output.trim();
@@ -57,31 +58,11 @@ public class AliasManager implements Reloadable {
 //    [2] = residualString
     public String[] getAlias(String alias, boolean supportSpaces) {
         if(supportSpaces) {
-
-//            String[] split = alias.split(Tuils.SPACE);
-//            String name = Tuils.EMPTYSTRING;
-//
-//            for(int count = 0; count < split.length; count++) {
-//                name += Tuils.SPACE + split[count];
-//                name = name.trim();
-//
-//                String a = aliases.get(name);
-//
-//                if(a != null) {
-//                    String residual = Tuils.EMPTYSTRING;
-//                    for(int c = count + 1; c < split.length; c++) {
-//                        residual += split[c] + Tuils.SPACE;
-//                    }
-//
-//                    return new String[] {a, name, residual.trim()};
-//                }
-//            }
-
             String args = Tuils.EMPTYSTRING;
 
             String aliasValue = null;
             while (true) {
-                aliasValue = getALiasFor(alias);
+                aliasValue = getALias(alias);
                 if(aliasValue != null) break;
                 else {
                     int index = alias.lastIndexOf(Tuils.SPACE);
@@ -95,7 +76,7 @@ public class AliasManager implements Reloadable {
 
             return new String[] {aliasValue, alias, args};
         } else {
-            return new String[] {getALiasFor(alias), alias, Tuils.EMPTYSTRING};
+            return new String[] {getALias(alias), alias, Tuils.EMPTYSTRING};
         }
     }
 
@@ -106,42 +87,42 @@ public class AliasManager implements Reloadable {
         String[] split = params.split(paramSeparator);
 
         for(String s : split) {
-            aliasValue = aliasValue.replaceFirst(paramMarker, s);
+            aliasValue = parameterPattern.matcher(aliasValue).replaceFirst(s);
         }
 
+        if(replaceAllMarkers) aliasValue = parameterPattern.matcher(aliasValue).replaceAll(split[0]);
+
         return aliasValue;
     }
 
-    private String getALiasFor(String name) {
-        for(Map.Entry<String, String> entry : aliases) {
-            if(name.equals(entry.getKey())) return entry.getValue();
+    private String getALias(String name) {
+        for(Alias a : aliases) {
+            if(name.equals(a.name)) return a.value;
         }
 
         return null;
     }
 
-    private void removeAliasFor(String name) {
+    private void removeAlias(String name) {
         for(int c = 0; c < aliases.size(); c++) {
-            Map.Entry e = aliases.get(c);
-            if(name.equals(e.getKey())) {
+            Alias a = aliases.get(c);
+            if(name.equals(a.name)) {
                 aliases.remove(c);
                 return;
             }
         }
     }
 
-    private final Pattern pn = Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
     private final Pattern pv = Pattern.compile("%v", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
     private final Pattern pa = Pattern.compile("%a", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
     public String formatLabel(String aliasName, String aliasValue) {
         String a = aliasLabelFormat;
-        a = pn.matcher(a).replaceAll(Matcher.quoteReplacement(Tuils.NEWLINE));
+        a = Tuils.patternNewline.matcher(a).replaceAll(Matcher.quoteReplacement(Tuils.NEWLINE));
         a = pv.matcher(a).replaceAll(Matcher.quoteReplacement(aliasValue));
         a = pa.matcher(a).replaceAll(Matcher.quoteReplacement(aliasName));
         return a;
     }
 
-    @Override
     public void reload() {
         if(aliases != null) aliases.clear();
         else aliases = new ArrayList<>();
@@ -179,10 +160,12 @@ public class AliasManager implements Reloadable {
                     Tuils.sendOutput(Color.RED, context,
                             context.getString(R.string.output_notaddingalias1) + Tuils.SPACE + name + Tuils.SPACE + context.getString(R.string.output_notaddingalias3));
                 } else {
-                    aliases.add(new AbstractMap.SimpleImmutableEntry<>(name, value));
+                    aliases.add(new Alias(name, value, parameterPattern));
                 }
             }
-        } catch (Exception e) {}
+        } catch (Exception e) {
+            Tuils.log(e);
+        }
     }
 
     public boolean add(String name, String value) {
@@ -193,7 +176,7 @@ public class AliasManager implements Reloadable {
             fos.write((Tuils.NEWLINE + name + "=" + value).getBytes());
             fos.close();
 
-            aliases.add(new AbstractMap.SimpleImmutableEntry<>(name, value));
+            aliases.add(new Alias(name, value, parameterPattern));
 
             return true;
         } catch (Exception e) {
@@ -222,7 +205,7 @@ public class AliasManager implements Reloadable {
             reader.close();
 
 
-            removeAliasFor(name);
+            removeAlias(name);
 
             return tempFile.renameTo(inputFile);
         } catch (Exception e) {
@@ -230,12 +213,34 @@ public class AliasManager implements Reloadable {
         }
     }
 
-    public List<String> getAliases() {
-        List<String> aliasKeys = new ArrayList<>(0);
-        if(aliases == null) return aliasKeys;
+    public List<Alias> getAliases(boolean excludeEmtpy) {
+        List<Alias> l = new ArrayList<>(aliases);
+        if(excludeEmtpy) {
+            for(int c = 0; c < l.size(); c++) {
+                if(l.get(c).name.length() == 0) {
+                    l.remove(c);
+                    break;
+                }
+            }
+        }
+
+        return l;
+    }
 
-        for(Map.Entry<String, String> entry : aliases) aliasKeys.add(entry.getKey());
+    public static class Alias {
+        public String name, value;
+        public boolean isParametrized;
 
-        return aliasKeys;
+        public Alias(String name, String value, Pattern parameterPattern) {
+            this.name = name;
+            this.value = value;
+
+            isParametrized = parameterPattern.matcher(value).find();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return (obj instanceof Alias && ((Alias) obj).name.equals(name)) || obj.equals(name);
+        }
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
index 8a8c5dbf667ce22ee826ebb496e9e432d63beff4..bab0869b883c6a974abf96e11ce39b50a563eaf3 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
@@ -13,12 +13,16 @@ import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.Color;
 import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.support.annotation.NonNull;
+import android.support.v4.content.LocalBroadcastManager;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -32,8 +36,12 @@ import java.util.regex.Pattern;
 
 import ohi.andre.consolelauncher.MainManager;
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.UIManager;
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsList;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Apps;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Theme;
@@ -41,14 +49,13 @@ import ohi.andre.consolelauncher.managers.xml.options.Ui;
 import ohi.andre.consolelauncher.tuils.Compare;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
-import ohi.andre.consolelauncher.tuils.interfaces.Suggester;
 
 import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.VALUE_ATTRIBUTE;
 import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.resetFile;
 import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.set;
 import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.writeTo;
 
-public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
+public class AppsManager implements XMLPrefsElement {
 
     public static final int SHOWN_APPS = 10;
     public static final int HIDDEN_APPS = 11;
@@ -57,10 +64,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
     private final String NAME = "APPS";
     private File file;
 
-    private final String SHOW_ATTRIBUTE = "show";
-    private final String APPS_ATTRIBUTE = "apps";
-    private final String BGCOLOR_ATTRIBUTE = "bgColor";
-    private final String FORECOLOR_ATTRIBUTE = "foreColor";
+    private final String SHOW_ATTRIBUTE = "show", APPS_ATTRIBUTE = "apps", BGCOLOR_ATTRIBUTE = "bgColor", FORECOLOR_ATTRIBUTE = "foreColor";
     private static final String APPS_SEPARATOR = ";";
 
     private Context context;
@@ -72,13 +76,13 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
     private SharedPreferences preferences;
     private SharedPreferences.Editor editor;
 
-    public static XMLPrefsManager.XmlPrefsElement instance = null;
+    public static XMLPrefsElement instance = null;
 
-    private XMLPrefsManager.XMLPrefsList defaultApps;
+    private XMLPrefsList prefsList;
 
-    public static List<Group> groups;
+    public List<Group> groups;
 
-    private Pattern pp, pl, pn;
+    private Pattern pp, pl;
     private String appInstalledFormat, appUninstalledFormat;
     int appInstalledColor, appUninstalledColor;
 
@@ -88,13 +92,13 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
     }
 
     @Override
-    public void write(XMLPrefsManager.XMLPrefsSave save, String value) {
+    public void write(XMLPrefsSave save, String value) {
         set(new File(Tuils.getFolder(), PATH), save.label(), new String[] {VALUE_ATTRIBUTE}, new String[] {value});
     }
 
     @Override
-    public XMLPrefsManager.XMLPrefsList getValues() {
-        return defaultApps;
+    public XMLPrefsList getValues() {
+        return prefsList;
     }
 
     private BroadcastReceiver appsBroadcast = new BroadcastReceiver() {
@@ -111,7 +115,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         }
     };
 
-    public AppsManager(Context context, final Suggester s) {
+    public AppsManager(final Context context) {
         instance = this;
 
         this.context = context;
@@ -122,14 +126,12 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         if(appInstalledFormat != null || appUninstalledFormat != null) {
             pp = Pattern.compile("%p", Pattern.CASE_INSENSITIVE);
             pl = Pattern.compile("%l", Pattern.CASE_INSENSITIVE);
-            pn = Pattern.compile("%n", Pattern.CASE_INSENSITIVE);
 
             appInstalledColor = XMLPrefsManager.getColor(Theme.app_installed_color);
             appUninstalledColor = XMLPrefsManager.getColor(Theme.app_uninstalled_color);
         } else {
             pp = null;
             pl = null;
-            pn = null;
         }
 
         File root = Tuils.getFolder();
@@ -149,7 +151,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                 super.run();
 
                 fill();
-                s.requestUpdate();
+                LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_UPDATE_SUGGESTIONS));
             }
         }.start();
     }
@@ -170,7 +172,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         groups.clear();
 
         try {
-            defaultApps = new XMLPrefsManager.XMLPrefsList();
+            prefsList = new XMLPrefsList();
 
             if(file != null) {
                 if(!file.exists()) {
@@ -184,9 +186,12 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                         Tuils.sendXMLParseError(context, PATH);
                         return;
                     }
-                } catch (Exception e) {
+                } catch (SAXParseException e) {
                     Tuils.sendXMLParseError(context, PATH, e);
                     return;
+                } catch (Exception e) {
+                    Tuils.log(e);
+                    return;
                 }
 
                 Document d = (Document) o[0];
@@ -201,7 +206,12 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                     String nn = node.getNodeName();
                     int nodeIndex = Tuils.find(nn, (List) enums);
                     if (nodeIndex != -1) {
-                        defaultApps.add(nn, node.getAttributes().getNamedItem(VALUE_ATTRIBUTE).getNodeValue());
+//                        default_app...
+                        if(nn.startsWith("d")) {
+                            prefsList.add(nn, node.getAttributes().getNamedItem(VALUE_ATTRIBUTE).getNodeValue());
+                        } else {
+                            prefsList.add(nn, XMLPrefsManager.getStringAttribute((Element) node, VALUE_ATTRIBUTE));
+                        }
 
                         for (int en = 0; en < enums.size(); en++) {
                             if (enums.get(en).label().equals(nn)) {
@@ -238,12 +248,14 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                                         for(String s : split) {
                                             for(int c = 0; c < as.size(); c++) {
                                                 if(as.get(c).equals(s)) {
-                                                    g.add(as.remove(c));
+                                                    g.add(as.remove(c), false);
                                                     continue External;
                                                 }
                                             }
                                         }
 
+                                        g.sort();
+
                                         if(e.hasAttribute(BGCOLOR_ATTRIBUTE)) {
                                             String c = e.getAttribute(BGCOLOR_ATTRIBUTE);
                                             if(c.length() > 0) {
@@ -305,14 +317,14 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                 }
 
                 if (enums.size() > 0) {
-                    for (XMLPrefsManager.XMLPrefsSave s : enums) {
+                    for (XMLPrefsSave s : enums) {
                         String value = s.defaultValue();
 
                         Element em = d.createElement(s.label());
                         em.setAttribute(VALUE_ATTRIBUTE, value);
                         root.appendChild(em);
 
-                        defaultApps.add(s.label(), value);
+                        prefsList.add(s.label(), value);
                     }
                     writeTo(d, file);
                 }
@@ -353,8 +365,17 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             Tuils.toFile(e1);
         }
 
-        appsHolder = new AppsHolder(allApps, defaultApps);
+        appsHolder = new AppsHolder(allApps, prefsList);
         AppUtils.checkEquality(hiddenApps);
+
+        Group.sorting = XMLPrefsManager.getInt(Apps.app_groups_sorting);
+        for(Group g : groups) g.sort();
+        Collections.sort(groups, new Comparator<Group>() {
+            @Override
+            public int compare(Group o1, Group o2) {
+                return Tuils.alphabeticCompare(o1.getName(), o2.getName());
+            }
+        });
     }
 
     private List<LaunchInfo> createAppMap(PackageManager mgr) {
@@ -396,7 +417,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                     }
                 }
 
-                cp = pn.matcher(cp).replaceAll(Tuils.NEWLINE);
+                cp = Tuils.patternNewline.matcher(cp).replaceAll(Tuils.NEWLINE);
 
                 Tuils.sendOutput(appInstalledColor, context, cp);
             }
@@ -431,7 +452,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                     cp = pl.matcher(cp).replaceAll(packageName.substring(index + 1));
                 }
             }
-            cp = pn.matcher(cp).replaceAll(Tuils.NEWLINE);
+            cp = Tuils.patternNewline.matcher(cp).replaceAll(Tuils.NEWLINE);
 
             Tuils.sendOutput(appUninstalledColor, context, cp);
         }
@@ -456,7 +477,9 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         if(appList == null) return null;
 
         LaunchInfo i = AppUtils.findLaunchInfoWithLabel(appList, label);
-        if(i != null) return i;
+        if(i != null) {
+            return i;
+        }
 
         List<LaunchInfo> is = AppUtils.findLaunchInfosWithPackage(label, appList);
         if(is == null || is.size() == 0) return null;
@@ -486,11 +509,10 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             }
         }.start();
 
-        Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.setComponent(info.componentName);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-        return intent;
+       return new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_LAUNCHER)
+                .setComponent(info.componentName)
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
     }
 
     public String hideActivity(LaunchInfo info) {
@@ -587,7 +609,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         XMLPrefsManager.writeTo(d, file);
 
         int index = Tuils.find(group, groups);
-        if(index != -1) groups.get(index).add(app);
+        if(index != -1) groups.get(index).add(app, true);
 
         return null;
     }
@@ -843,7 +865,39 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
     }
 
     public static class Group implements MainManager.Group {
-        List<LaunchInfo> apps;
+
+        public static final int ALPHABETIC_UP_DOWN = 0;
+        public static final int ALPHABETIC_DOWN_UP = 1;
+        public static final int TIME_UP_DOWN = 2;
+        public static final int TIME_DOWN_UP = 3;
+        public static final int MOSTUSED_UP_DOWN = 4;
+        public static final int MOSTUSED_DOWN_UP = 5;
+
+        public static int sorting;
+
+        public static Comparator<GroupLaunchInfo> comparator = new Comparator<GroupLaunchInfo>() {
+            @Override
+            public int compare(GroupLaunchInfo o1, GroupLaunchInfo o2) {
+                switch (sorting) {
+                    case ALPHABETIC_UP_DOWN:
+                        return Tuils.alphabeticCompare(o1.publicLabel, o2.publicLabel);
+                    case ALPHABETIC_DOWN_UP:
+                        return Tuils.alphabeticCompare(o2.publicLabel, o1.publicLabel);
+                    case TIME_UP_DOWN:
+                        return o1.initialIndex - o2.initialIndex;
+                    case TIME_DOWN_UP:
+                        return o2.initialIndex - o1.initialIndex;
+                    case MOSTUSED_UP_DOWN:
+                        return o2.launchedTimes - o1.launchedTimes;
+                    case MOSTUSED_DOWN_UP:
+                        return o1.launchedTimes - o2.launchedTimes;
+                }
+
+                return 0;
+            }
+        };
+
+        List<GroupLaunchInfo> apps;
 
         int bgColor = Integer.MAX_VALUE;
         int foreColor = Integer.MAX_VALUE;
@@ -855,21 +909,36 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             apps = new ArrayList<>();
         }
 
-        public void add(LaunchInfo info) {
-            apps.add(info);
+        public void add(LaunchInfo info, boolean sort) {
+            apps.add(new GroupLaunchInfo(info, apps.size()));
+
+            if(sort) sort();
         }
 
         public void remove(LaunchInfo info) {
-            apps.remove(info);
+            Iterator<GroupLaunchInfo> iterator = apps.iterator();
+            while (iterator.hasNext()) {
+                if(iterator.next().componentName.equals(info.componentName)) {
+                    iterator.remove();
+                    return;
+                }
+            }
         }
 
         public void remove(String app) {
-            List<LaunchInfo> cp = new ArrayList<>(apps);
-            for(LaunchInfo i : cp) {
-                if(i.componentName.getPackageName().equals(app)) apps.remove(i);
+            Iterator<GroupLaunchInfo> iterator = apps.iterator();
+            while (iterator.hasNext()) {
+                if(iterator.next().componentName.getPackageName().equals(app)) {
+                    iterator.remove();
+                    return;
+                }
             }
         }
 
+        public void sort() {
+            Collections.sort(apps, comparator);
+        }
+
         public boolean contains(LaunchInfo info) {
             return apps.contains(info);
         }
@@ -931,9 +1000,22 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             return false;
         }
 
+        private class GroupLaunchInfo extends LaunchInfo {
+
+            int initialIndex;
+
+            public GroupLaunchInfo(LaunchInfo info, int index) {
+                super(info.componentName.getPackageName(), info.componentName.getClassName(), info.publicLabel);
+                launchedTimes = info.launchedTimes;
+                unspacedLowercaseLabel = info.unspacedLowercaseLabel;
+
+                this.initialIndex = index;
+            }
+        }
+
     }
 
-    public static class LaunchInfo implements Compare.Stringable {
+    public static class LaunchInfo implements Compare.Stringable, Parcelable {
 
         private static final String COMPONENT_SEPARATOR = "-";
 
@@ -948,6 +1030,25 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             this.unspacedLowercaseLabel = Tuils.removeSpaces(this.publicLabel).toLowerCase();
         }
 
+        protected LaunchInfo(Parcel in) {
+            componentName = in.readParcelable(ComponentName.class.getClassLoader());
+            publicLabel = in.readString();
+            unspacedLowercaseLabel = in.readString();
+            launchedTimes = in.readInt();
+        }
+
+        public static final Creator<LaunchInfo> CREATOR = new Creator<LaunchInfo>() {
+            @Override
+            public LaunchInfo createFromParcel(Parcel in) {
+                return new LaunchInfo(in);
+            }
+
+            @Override
+            public LaunchInfo[] newArray(int size) {
+                return new LaunchInfo[size];
+            }
+        };
+
         public boolean isInside(String apps) {
             String[] split = apps.split(AppsManager.APPS_SEPARATOR);
             for(String s : split) {
@@ -1016,6 +1117,19 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         public String getString() {
             return publicLabel;
         }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeParcelable(componentName, flags);
+            dest.writeString(publicLabel);
+            dest.writeString(unspacedLowercaseLabel);
+            dest.writeInt(launchedTimes);
+        }
     }
 
     private class AppsHolder {
@@ -1023,7 +1137,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         final int MOST_USED = 10, NULL = 11, USER_DEFINIED = 12;
 
         private List<LaunchInfo> infos;
-        private XMLPrefsManager.XMLPrefsList values;
+        private XMLPrefsList values;
 
         private SuggestedAppMgr suggestedAppMgr;
 
@@ -1031,11 +1145,11 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             private List<SuggestedApp> suggested;
             private int lastWriteable = -1;
 
-            public SuggestedAppMgr(XMLPrefsManager.XMLPrefsList values, List<LaunchInfo> apps) {
+            public SuggestedAppMgr(XMLPrefsList values, List<LaunchInfo> apps) {
                 suggested = new ArrayList<>();
 
                 final String PREFIX = "default_app_n";
-                for(int count = 0; count < Apps.values().length; count++) {
+                for(int count = 0; count < 5; count++) {
                     String vl = values.get(Apps.valueOf(PREFIX + (count + 1))).value;
 
                     if(vl.equals(Apps.NULL)) continue;
@@ -1218,7 +1332,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             }
         };
 
-        public AppsHolder(List<LaunchInfo> infos, XMLPrefsManager.XMLPrefsList values) {
+        public AppsHolder(List<LaunchInfo> infos, XMLPrefsList values) {
             this.infos = infos;
             this.values = values;
             update(true);
@@ -1283,7 +1397,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             return null;
         }
 
-        public static LaunchInfo findLaunchInfoWithLabel(List<LaunchInfo> appList, String label) {
+        public static LaunchInfo findLaunchInfoWithLabel(List<? extends LaunchInfo> appList, String label) {
             label = Tuils.removeSpaces(label);
             for(LaunchInfo i : appList) if(i.unspacedLowercaseLabel.equalsIgnoreCase(label)) return i;
             return null;
@@ -1314,7 +1428,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                         continue;
                     }
 
-                    if (info.publicLabel.toLowerCase().replace(Tuils.SPACE, Tuils.EMPTYSTRING).equals(info2.publicLabel.toLowerCase().replace(Tuils.SPACE, Tuils.EMPTYSTRING))) {
+                    if (Tuils.equalsIgnoreSpaceAndCase(info.publicLabel, info2.publicLabel)) {
 //                        there are two activities in the same app loadlabel gives the same result
                         if(info.componentName.getPackageName().equals(info2.componentName.getPackageName())) {
                             info.publicLabel = insertActivityName(info.publicLabel, info.componentName.getClassName());
@@ -1384,7 +1498,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             builder.append("launched_times: ").append(app.launchedTimes).append(Tuils.NEWLINE).append(Tuils.NEWLINE);
 
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
-                builder.append("Install: ").append(TimeManager.replace("%t0", info.firstInstallTime, Integer.MAX_VALUE)).append(Tuils.NEWLINE).append(Tuils.NEWLINE);
+                builder.append("Install: ").append(TimeManager.instance.replace("%t0", info.firstInstallTime, Integer.MAX_VALUE)).append(Tuils.NEWLINE).append(Tuils.NEWLINE);
             }
 
             ActivityInfo[] a = info.activities;
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java
index ea9b64c9147a43d9143123609702882126bbdde5..61866cc754cd5ad6733fda80c660252142d2d911 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java
@@ -2,7 +2,10 @@ package ohi.andre.consolelauncher.managers;
 
 import android.Manifest;
 import android.app.Activity;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.net.Uri;
@@ -10,11 +13,14 @@ import android.provider.ContactsContract;
 import android.support.annotation.NonNull;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.content.ContextCompat;
+import android.support.v4.content.LocalBroadcastManager;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
+import ohi.andre.consolelauncher.BuildConfig;
 import ohi.andre.consolelauncher.LauncherActivity;
 import ohi.andre.consolelauncher.tuils.Compare;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
@@ -22,15 +28,37 @@ import ohi.andre.consolelauncher.tuils.Tuils;
 
 public class ContactManager {
 
+    public static String ACTION_REFRESH = BuildConfig.APPLICATION_ID + ".refresh_contacts";
+
     private Context context;
     private List<Contact> contacts;
 
+    private BroadcastReceiver receiver;
+
     public ContactManager(Context context) {
         this.context = context;
 
         if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
             refreshContacts(context);
         }
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_REFRESH);
+
+        receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if(intent.getAction().equals(ACTION_REFRESH)) {
+                    refreshContacts(context);
+                }
+            }
+        };
+
+        LocalBroadcastManager.getInstance(context.getApplicationContext()).registerReceiver(receiver, filter);
+    }
+
+    public void destroy(Context context) {
+        LocalBroadcastManager.getInstance(context.getApplicationContext()).unregisterReceiver(receiver);
     }
 
     public void refreshContacts(final Context context) {
@@ -104,9 +132,10 @@ public class ContactManager {
                     phones.close();
                 }
 
-                List<Contact> cp = new ArrayList<>(contacts);
-                for(int count = 0; count < cp.size(); count++) {
-                    if(cp.get(count).numbers.size() == 0) contacts.remove(count--);
+                Iterator<Contact> iterator = contacts.iterator();
+                while(iterator.hasNext()) {
+                    Contact c = iterator.next();
+                    if(c.numbers.size() == 0) iterator.remove();
                 }
 
                 Collections.sort(contacts);
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/NotesManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/NotesManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..844bfb6724baafbbfa50159d85d5908f158184c1
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/NotesManager.java
@@ -0,0 +1,592 @@
+package ohi.andre.consolelauncher.managers;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.v4.content.LocalBroadcastManager;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.UnderlineSpan;
+import android.widget.TextView;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import ohi.andre.consolelauncher.BuildConfig;
+import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.options.Behavior;
+import ohi.andre.consolelauncher.managers.xml.options.Theme;
+import ohi.andre.consolelauncher.managers.xml.options.Ui;
+import ohi.andre.consolelauncher.tuils.LongClickableSpan;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.VALUE_ATTRIBUTE;
+import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.resetFile;
+
+/**
+ * Created by francescoandreuzzi on 12/02/2018.
+ */
+
+public class NotesManager {
+
+    public static final String ACTION_RM = BuildConfig.APPLICATION_ID + ".rm_note", ACTION_ADD = BuildConfig.APPLICATION_ID + ".add_note", ACTION_CLEAR = BuildConfig.APPLICATION_ID + ".clear_notes",
+            ACTION_LS = BuildConfig.APPLICATION_ID + ".ls_notes", ACTION_LOCK = BuildConfig.APPLICATION_ID + ".lock_notes", CREATION_TIME = "creationTime", TEXT = "text", LOCK = "lock";
+    private final String PATH = "notes.xml", NAME = "NOTES", NOTE_NODE = "note";
+
+    CharSequence oldNotes;
+    public boolean hasChanged;
+
+    Set<Class> classes;
+    List<Note> notes;
+
+    Pattern optionalPattern;
+    String footer, header, divider;
+    int color, lockedColor, timeColor;
+
+    boolean allowLink;
+    int linkColor;
+
+    BroadcastReceiver receiver;
+
+    PackageManager packageManager;
+
+//    noteview can't be changed too much, it may be shared
+    public NotesManager(Context context, TextView noteView) {
+        classes = new HashSet<>();
+        notes = new ArrayList<>();
+
+        packageManager = context.getPackageManager();
+
+        String optionalSeparator = "\\" + XMLPrefsManager.get(Behavior.optional_values_separator);
+        String optional = "%\\(([^" + optionalSeparator + "]*)" + optionalSeparator + "([^)]*)\\)";
+        optionalPattern = Pattern.compile(optional, Pattern.CASE_INSENSITIVE);
+
+        color = XMLPrefsManager.getColor(Theme.notes_color);
+        lockedColor = XMLPrefsManager.getColor(Theme.notes_locked_color);
+        timeColor = XMLPrefsManager.getColor(Theme.time_color);
+
+        footer = XMLPrefsManager.get(Ui.notes_footer);
+        header = XMLPrefsManager.get(Ui.notes_header);
+        divider = XMLPrefsManager.get(Ui.notes_divider);
+        divider = Tuils.patternNewline.matcher(divider).replaceAll(Tuils.NEWLINE);
+
+        allowLink = XMLPrefsManager.getBoolean(Behavior.notes_allow_link);
+        if(allowLink && noteView != null) {
+            noteView.setMovementMethod(new LinkMovementMethod());
+            linkColor = XMLPrefsManager.getColor(Theme.link_color);
+        }
+
+        Note.sorting = XMLPrefsManager.getInt(Behavior.notes_sorting);
+
+//        String[] split = footer.split(separator);
+//        if(split.length > 1) {
+//            footerActive = split[0];
+//            footerDisabled = split[1];
+//        } else if(split[0].length() < footer.length()) {
+//            footerActive = split[0];
+//            footerDisabled = Tuils.EMPTYSTRING;
+//        } else {
+//            footerActive = footer;
+//            footerDisabled = footer;
+//        }
+//
+//        split = header.split(separator);
+//        if(split.length > 1) {
+//            headerActive = split[0];
+//            headerDisabled = split[1];
+//        } else if(split[0].length() < header.length()) {
+//            headerActive = split[0];
+//            headerDisabled = Tuils.EMPTYSTRING;
+//        } else {
+//            headerActive = header;
+//            headerDisabled = header;
+//        }
+
+        load(context, true);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_ADD);
+        filter.addAction(ACTION_RM);
+        filter.addAction(ACTION_CLEAR);
+        filter.addAction(ACTION_LS);
+        filter.addAction(ACTION_LOCK);
+
+        receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if(intent.getAction().equals(ACTION_ADD)) {
+                    Tuils.log("add note");
+
+                    String text = intent.getStringExtra(TEXT);
+                    if(text == null) return;
+
+                    boolean lock = false;
+                    String[] split = text.split(Tuils.SPACE);
+                    int startAt = 0;
+
+                    String beforeSpace = split.length >= 2 ? split[0] : null;
+                    if(beforeSpace != null) {
+                        if((beforeSpace.equals("true") || beforeSpace.equals("false"))) {
+                            lock = Boolean.parseBoolean(beforeSpace);
+                            startAt++;
+                        }
+
+                        String[] ar = new String[split.length - startAt];
+                        System.arraycopy(split, startAt, ar, 0, ar.length);
+                        text = Tuils.toPlanString(ar, Tuils.SPACE);
+                    }
+
+                    addNote(context, text, lock);
+                } else if(intent.getAction().equals(ACTION_RM)) {
+                    String s = intent.getStringExtra(TEXT);
+                    if(s == null) return;
+
+                    rmNote(context, s);
+                } else if(intent.getAction().equals(ACTION_CLEAR)) {
+                    clearNotes(context);
+                } else if(intent.getAction().equals(ACTION_LS)) {
+                    lsNotes(context);
+                } else if(intent.getAction().equals(ACTION_LOCK)) {
+                    String text = intent.getStringExtra(TEXT);
+                    boolean lock = intent.getBooleanExtra(LOCK, false);
+
+                    lockNote(context, text, lock);
+                }
+            }
+        };
+
+        LocalBroadcastManager.getInstance(context.getApplicationContext()).registerReceiver(receiver, filter);
+    }
+
+    private void load(Context context, boolean loadClasses) {
+        if(loadClasses) classes.clear();
+        notes.clear();
+
+        File file = new File(Tuils.getFolder(), PATH);
+        if(!file.exists()) {
+            resetFile(file, NAME);
+        }
+
+        Object[] o;
+        try {
+            o = XMLPrefsManager.buildDocument(file, NAME);
+            if(o == null) {
+                Tuils.sendXMLParseError(context, PATH);
+                return;
+            }
+        } catch (SAXParseException e) {
+            Tuils.sendXMLParseError(context, PATH, e);
+            return;
+        } catch (Exception e) {
+            Tuils.log(e);
+            return;
+        }
+
+        Element root = (Element) o[1];
+
+        NodeList nodes = root.getElementsByTagName("*");
+
+        for (int count = 0; count < nodes.getLength(); count++) {
+            final Node node = nodes.item(count);
+
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                final Element e = (Element) node;
+                final String name = e.getNodeName();
+
+                if(name.equals(NOTE_NODE)) {
+                    long time = XMLPrefsManager.getLongAttribute(e, CREATION_TIME);
+                    String text = XMLPrefsManager.getStringAttribute(e, XMLPrefsManager.VALUE_ATTRIBUTE);
+                    boolean lock = XMLPrefsManager.getBooleanAttribute(e, LOCK);
+
+                    notes.add(new Note(time, text, lock));
+                } else if(loadClasses) {
+                    int id;
+                    try {
+                        id = Integer.parseInt(name);
+                    } catch (Exception ex) {
+                        continue;
+                    }
+
+                    int color;
+                    try {
+                        color = Color.parseColor(XMLPrefsManager.getStringAttribute(e, VALUE_ATTRIBUTE));
+                    } catch (Exception ex) {
+                        continue;
+                    }
+
+                    classes.add(new Class(id, color));
+                }
+            }
+        }
+
+        Collections.sort(notes);
+
+        invalidateNotes();
+    }
+
+    Pattern colorPattern = Pattern.compile("(\\d+|#[\\da-zA-Z]{6,8})\\(([^)]*)\\)");
+    Pattern countPattern = Pattern.compile("%c", Pattern.CASE_INSENSITIVE);
+    Pattern lockPattern = Pattern.compile("%l", Pattern.CASE_INSENSITIVE);
+    Pattern rowPattern = Pattern.compile("%r", Pattern.CASE_INSENSITIVE);
+    Pattern uriPattern = Pattern.compile("([^#\\s]+:[^\\s]+|www\\.[^\\s]*)");
+
+    private void invalidateNotes() {
+        String header = this.header;
+        Matcher mh = optionalPattern.matcher(header);
+        while(mh.find()) {
+            header = header.replace(mh.group(0), mh.groupCount() == 2 ? mh.group(notes.size() > 0 ? 1 : 2) : Tuils.EMPTYSTRING);
+        }
+
+        if(header.length() > 0) {
+            String h = countPattern.matcher(header).replaceAll(String.valueOf(notes.size()));
+            h = Tuils.patternNewline.matcher(h).replaceAll(Tuils.NEWLINE);
+            oldNotes = Tuils.span(h, this.color);
+        } else {
+            oldNotes = Tuils.EMPTYSTRING;
+        }
+
+        CharSequence ns = Tuils.EMPTYSTRING;
+        for(int j = 0; j < notes.size(); j++) {
+            Note n = notes.get(j);
+
+            CharSequence t = n.text;
+            t = lockPattern.matcher(t).replaceAll(String.valueOf(n.lock));
+            t = rowPattern.matcher(t).replaceAll(String.valueOf(j + 1));
+            t = countPattern.matcher(t).replaceAll(String.valueOf(notes.size()));
+
+            t = Tuils.span(t, n.lock ? lockedColor : this.color);
+
+            t = TimeManager.instance.replace(t, n.creationTime, timeColor);
+
+            if(allowLink) {
+                Matcher m = uriPattern.matcher(t);
+                while(m.find()) {
+                    String g = m.group();
+
+//                    www.
+                    if(g.startsWith("w")) {
+                        g = "http://" + g;
+                    }
+
+                    Uri u = Uri.parse(g);
+                    if(u == null) continue;
+
+                    SpannableString sp = new SpannableString(m.group());
+                    sp.setSpan(new LongClickableSpan(u), 0, sp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    sp.setSpan(new UnderlineSpan(), 0, sp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    sp.setSpan(new ForegroundColorSpan(linkColor), 0, sp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+                    t = TextUtils.replace(t, new String[] {m.group()}, new CharSequence[] {sp});
+                }
+            }
+
+            ns = TextUtils.concat(ns, t, j != notes.size() - 1 ? divider : Tuils.EMPTYSTRING);
+        }
+
+        oldNotes = TextUtils.concat(oldNotes, ns);
+
+        String footer = this.footer;
+        Matcher mf = optionalPattern.matcher(footer);
+        while(mf.find()) {
+            footer = footer.replace(mf.group(0), mf.groupCount() == 2 ? mf.group(notes.size() > 0 ? 1 : 2) : Tuils.EMPTYSTRING);
+        }
+
+        if(footer.length() > 0) {
+            String h = countPattern.matcher(footer).replaceAll(String.valueOf(notes.size()));
+            h = Tuils.patternNewline.matcher(h).replaceAll(Tuils.NEWLINE);
+            oldNotes = TextUtils.concat(oldNotes, Tuils.span(h, this.color));
+        } else {}
+
+        Matcher m = colorPattern.matcher(oldNotes);
+        while(m.find()) {
+            String match = m.group();
+            String idColor = m.group(1);
+            CharSequence t = m.group(2);
+
+            int color;
+            if(idColor.startsWith("#")) {
+//                    color
+                try {
+                    color = Color.parseColor(idColor);
+                } catch (Exception e) {
+                    color = Color.RED;
+                }
+            } else {
+//                    id
+                try {
+                    int id = Integer.parseInt(idColor);
+                    Class c = findClass(id);
+                    color = c.color;
+                } catch (Exception e) {
+                    color = Color.RED;
+                }
+            }
+
+            t = Tuils.span(t.toString(), color);
+            oldNotes = TextUtils.replace(oldNotes, new String[] {match}, new CharSequence[] {t});
+        }
+
+        hasChanged = true;
+    }
+
+    public CharSequence getNotes() {
+        hasChanged = false;
+        return oldNotes;
+    }
+
+    private void addNote(Context context, String s, boolean lock) {
+        Tuils.log("called");
+
+        long t = System.currentTimeMillis();
+
+        notes.add(new Note(t, s, lock));
+        Collections.sort(notes);
+
+        File file = new File(Tuils.getFolder(), PATH);
+        if(!file.exists()) {
+            resetFile(file, NAME);
+        }
+
+        String output = XMLPrefsManager.add(file, NOTE_NODE, new String[] {CREATION_TIME, VALUE_ATTRIBUTE, LOCK}, new String[] {String.valueOf(t), s, String.valueOf(lock)});
+        if(output != null) {
+            if(output.length() > 0) Tuils.sendOutput(Color.RED, context, output);
+            else Tuils.sendOutput(Color.RED, context, R.string.note_not_found);
+        }
+
+        invalidateNotes();
+    }
+
+    private void rmNote(Context context, String s) {
+        int index = findNote(s);
+        if(index == -1) {
+            Tuils.sendOutput(Color.RED, context, R.string.note_not_found);
+            return;
+        }
+
+        long time = notes.remove(index).creationTime;
+
+        File file = new File(Tuils.getFolder(), PATH);
+        if(!file.exists()) {
+            resetFile(file, NAME);
+        }
+
+        String output = XMLPrefsManager.removeNode(file, new String[] {CREATION_TIME}, new String[] {String.valueOf(time)});
+        if(output != null) {
+            if(output.length() > 0) Tuils.sendOutput(Color.RED, context, output);
+            else {
+                Tuils.sendOutput(Color.RED, context, R.string.note_not_found);
+            }
+        }
+
+        invalidateNotes();
+    }
+
+    private void clearNotes(Context context) {
+        Iterator<Note> iterator = notes.iterator();
+        while(iterator.hasNext()) {
+            Note n = iterator.next();
+            if(!n.lock) iterator.remove();
+        }
+
+        File file = new File(Tuils.getFolder(), PATH);
+        if(!file.exists()) resetFile(file, NAME);
+
+        String output = XMLPrefsManager.removeNode(file, new String[] {LOCK}, new String[] {String.valueOf(false)}, true, true);
+        if(output != null && output.length() > 0) Tuils.sendOutput(Color.RED, context, output);
+
+        invalidateNotes();
+    }
+
+    private void lsNotes(Context c) {
+        StringBuilder builder = new StringBuilder();
+
+        for(int j = 0; j < notes.size(); j++) {
+            Note n = notes.get(j);
+            builder.append(" - ").append(j + 1).append(n.lock ? " [locked]" : Tuils.EMPTYSTRING).append(" -> ").append(n.text).append(Tuils.NEWLINE);
+        }
+
+        Tuils.sendOutput(c, builder.toString().trim());
+    }
+
+    private void lockNote(Context context, String s, boolean lock) {
+        int index = findNote(s);
+        if(index == -1) {
+            Tuils.sendOutput(Color.RED, context, R.string.note_not_found);
+            return;
+        }
+
+        Note n = notes.get(index);
+        n.lock = lock;
+        Collections.sort(notes);
+
+        long time = n.creationTime;
+
+        File file = new File(Tuils.getFolder(), PATH);
+        if(!file.exists()) {
+            resetFile(file, NAME);
+        }
+
+        String output = XMLPrefsManager.set(file, NOTE_NODE, new String[] {CREATION_TIME}, new String[] {String.valueOf(time)}, new String[] {LOCK}, new String[] {String.valueOf(lock)}, true);
+        if(output != null && output.length() > 0) Tuils.sendOutput(Color.RED, context, output);
+
+        invalidateNotes();
+    }
+
+    private int findNote(String s) {
+        try {
+            int index = Integer.parseInt(s) - 1;
+            if(index < 0 || index >= notes.size()) return -1;
+            return index;
+        } catch (Exception e) {}
+
+        s = s.toLowerCase().trim();
+
+        CharSequence note;
+        int c = 0;
+        for(; c < notes.size(); c++) {
+            Note n = notes.get(c);
+
+            String text = n.text;
+
+            text = lockPattern.matcher(text).replaceAll(String.valueOf(n.lock));
+            text = rowPattern.matcher(text).replaceAll(String.valueOf(c + 1));
+            text = countPattern.matcher(text).replaceAll(String.valueOf(notes.size()));
+
+            note = text;
+
+            Matcher m = colorPattern.matcher(notes.get(c).text);
+            while(m.find()) {
+                String match = m.group();
+                String idColor = m.group(1);
+                CharSequence t = m.group(2);
+
+                int color;
+                if(idColor.startsWith("#")) {
+//                    color
+                    try {
+                        color = Color.parseColor(idColor);
+                    } catch (Exception e) {
+                        color = Color.RED;
+                    }
+                } else {
+//                    id
+                    try {
+                        int id = Integer.parseInt(idColor);
+                        Class cl = findClass(id);
+                        color = cl.color;
+                    } catch (Exception e) {
+                        color = Color.RED;
+                    }
+                }
+
+                t = Tuils.span(t.toString(), color);
+                note = TextUtils.replace(note, new String[] {match}, new CharSequence[] {t});
+            }
+
+            if(note.toString().toLowerCase().startsWith(s)) break;
+        }
+
+        if(c == notes.size()) {
+            return -1;
+        }
+        return c;
+    }
+
+    private Class findClass(int id) {
+        Iterator<Class> classIterator = classes.iterator();
+        while(classIterator.hasNext()) {
+            Class cl = classIterator.next();
+            if(cl.id == id) return cl;
+        }
+
+        return null;
+    }
+
+    public void dispose(Context context) {
+        LocalBroadcastManager.getInstance(context.getApplicationContext()).unregisterReceiver(receiver);
+    }
+
+    private class Class {
+        int id;
+        int color;
+
+        public Class(int id, int color) {
+            this.id = id;
+            this.color = color;
+        }
+    }
+
+    private static class Note implements Comparable<Note> {
+        private static final int SORTING_TIME_UPDOWN = 0;
+        private static final int SORTING_TIME_DOWNUP = 1;
+        private static final int SORTING_ALPHA_UPDOWN = 2;
+        private static final int SORTING_ALPHA_DOWNUP = 3;
+        private static final int SORTING_LOCK_BEFORE = 4;
+        private static final int SORTING_UNLOCK_BEFORE = 5;
+
+        long creationTime;
+        String text;
+        boolean lock;
+
+        public static int sorting = Integer.MAX_VALUE;
+
+        public Note(long time, String text, boolean lock) {
+            this.creationTime = time;
+            this.text = text;
+            this.lock = lock;
+        }
+
+        @Override
+        public int compareTo(@NonNull Note o) {
+            switch (sorting) {
+                case SORTING_TIME_UPDOWN:
+                    return (int) (creationTime - o.creationTime);
+                case SORTING_TIME_DOWNUP:
+                    return (int) (o.creationTime - creationTime);
+                case SORTING_ALPHA_UPDOWN:
+                    return Tuils.alphabeticCompare(text, o.text);
+                case SORTING_ALPHA_DOWNUP:
+                    return Tuils.alphabeticCompare(o.text, text);
+                case SORTING_LOCK_BEFORE:
+                    if(lock) {
+                        if(o.lock) return 0;
+                        return -1;
+                    } else {
+                        if(o.lock) return 1;
+                        return 0;
+                    }
+                case SORTING_UNLOCK_BEFORE:
+                    if(lock) {
+                        if(o.lock) return 0;
+                        return 1;
+                    } else {
+                        if(o.lock) return -1;
+                        return 0;
+                    }
+                default:
+                    return 1;
+            }
+        }
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/RegexManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/RegexManager.java
index fe018ea1eab6ae078d9aae53e9e8010fa2516e0a..33a6d5fedefa559f2f5cc23ac2059534aa66f27f 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/RegexManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/RegexManager.java
@@ -7,6 +7,7 @@ import android.text.SpannableString;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -27,18 +28,14 @@ import ohi.andre.consolelauncher.tuils.Tuils;
 
 public class RegexManager {
 
-    private static final String PATH = "regex.xml", ROOT = "REGEX";
-    private static final String REGEX_LABEL = "regex", ID_ATTRIBUTE = "id";
+    private final String PATH = "regex.xml", ROOT = "REGEX";
+    private final String REGEX_LABEL = "regex", ID_ATTRIBUTE = "id";
 
-    private static List<Regex> regexes;
+    private List<Regex> regexes;
 
-    private RegexManager() {}
-
-    private static boolean available = false;
-    public static void create(final Context context) {
-        if(available) return;
-        available = true;
+    public static RegexManager instance;
 
+    public RegexManager(final Context context) {
         if(regexes != null) regexes.clear();
         else regexes = new ArrayList<>();
 
@@ -68,9 +65,12 @@ public class RegexManager {
                             Tuils.sendXMLParseError(context, PATH);
                             return;
                         }
-                    } catch (Exception e) {
+                    } catch (SAXParseException e) {
                         Tuils.sendXMLParseError(context, PATH, e);
                         return;
+                    } catch (Exception e) {
+                        Tuils.log(e);
+                        return;
                     }
 
                     Element el = (Element) o[1];
@@ -104,16 +104,17 @@ public class RegexManager {
                         }
                     }
                 } catch (Exception e) {
-                    Tuils.sendXMLParseError(context, PATH, e);
+                    Tuils.log(e);
+                    Tuils.toFile(e);
                     return;
                 }
             }
         }.start();
-    }
 
-    public static Regex get(int id) {
-        if(!available) return null;
+        instance = this;
+    }
 
+    public Regex get(int id) {
         for(Regex r : regexes) {
             if(r.id == id) return r;
         }
@@ -121,7 +122,7 @@ public class RegexManager {
         return null;
     }
 
-    private static void rmFromList(int id) {
+    private void rmFromList(int id) {
         Iterator<Regex> iterator = regexes.iterator();
         while (iterator.hasNext()) {
             Regex r = iterator.next();
@@ -133,7 +134,7 @@ public class RegexManager {
 
 //    null: all good
 //    "": used id
-    public static String add(int id, String value) {
+    public String add(int id, String value) {
         for(int c = 0; c < regexes.size(); c++) {
             if(regexes.get(c).id == id) return Tuils.EMPTYSTRING;
         }
@@ -147,7 +148,7 @@ public class RegexManager {
 
 //    null: all good
 //    "": not found
-    public static String rm(int id) {
+    public String rm(int id) {
         try {
             File file = new File(Tuils.getFolder(), PATH);
 
@@ -189,7 +190,7 @@ public class RegexManager {
         }
     }
 
-    public static CharSequence test(int id, String test) {
+    public CharSequence test(int id, String test) {
         Regex regex = get(id);
         if(regex == null) return Tuils.EMPTYSTRING;
 
@@ -213,6 +214,15 @@ public class RegexManager {
         return s;
     }
 
+    public void dispose() {
+        if(regexes != null) {
+            regexes.clear();
+            regexes = null;
+        }
+
+        instance = null;
+    }
+
     public static class Regex {
         public Pattern regex;
         public String literalPattern;
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/RssManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/RssManager.java
index 7375d182f7aa22636e09ee802a7489b356b2610c..9b0b672d4930b3f8325d6b758ad7614cb5e849a2 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/RssManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/RssManager.java
@@ -5,12 +5,14 @@ import android.content.Intent;
 import android.graphics.Color;
 import android.net.ConnectivityManager;
 import android.os.Handler;
+import android.support.v4.content.LocalBroadcastManager;
 import android.text.TextUtils;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
 
 import java.io.BufferedInputStream;
 import java.io.File;
@@ -26,10 +28,13 @@ import java.util.regex.Pattern;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
+import ohi.andre.consolelauncher.MainManager;
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsList;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Theme;
-import ohi.andre.consolelauncher.tuils.InputOutputReceiver;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.html_escape.HtmlEscape;
@@ -46,7 +51,7 @@ import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.writeTo;
  * Created by francescoandreuzzi on 01/10/2017.
  */
 
-public class RssManager implements XMLPrefsManager.XmlPrefsElement {
+public class RssManager implements XMLPrefsElement {
 
 //    header:
 //    last-modified
@@ -64,18 +69,18 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
 
     public static final String RSS_LABEL = "rss", FORMAT_LABEL = "format", REGEX_CMD_LABEL = "regex";
 
-    private final String LAST_MODIFIED_FIELD = "Last-Modified", ETAG_FIELD = "ETag", IF_MODIFIED_SINCE_FIELD = "If-Modified-Since", IF_NONE_MATCH_FIELD = "If-None-Match", GET_LABEL = "GET";
+//    private final String LAST_MODIFIED_FIELD = "Last-Modified", ETAG_FIELD = "ETag", IF_MODIFIED_SINCE_FIELD = "If-Modified-Since", IF_NONE_MATCH_FIELD = "If-None-Match", GET_LABEL = "GET";
 
     private final String PUBDATE_CHILD = "pubDate", ENTRY_CHILD = "item", LINK_CHILD = "link", HREF_ATTRIBUTE = "href";
 
     private SimpleDateFormat defaultRSSDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
 
-    private static XMLPrefsManager.XMLPrefsList values;
+    private static XMLPrefsList values;
 
     public static final String PATH = "rss.xml";
     public static final String NAME = "RSS";
 
-    public static XMLPrefsManager.XmlPrefsElement instance = null;
+    public static XMLPrefsElement instance = null;
 
     @Override
     public String[] deleted() {
@@ -83,12 +88,12 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
     }
 
     @Override
-    public XMLPrefsManager.XMLPrefsList getValues() {
+    public XMLPrefsList getValues() {
         return values;
     }
 
     @Override
-    public void write(XMLPrefsManager.XMLPrefsSave save, String value) {
+    public void write(XMLPrefsSave save, String value) {
         set(new File(Tuils.getFolder(), PATH), save.label(), new String[] {VALUE_ATTRIBUTE}, new String[] {value});
     }
 
@@ -128,7 +133,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
 
         prepare();
 
-        values = new XMLPrefsManager.XMLPrefsList();
+        values = new XMLPrefsList();
 
         handler = new Handler();
         refresh();
@@ -160,9 +165,12 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                         Tuils.sendXMLParseError(context, PATH);
                         return;
                     }
-                } catch (Exception e) {
+                } catch (SAXParseException e) {
                     Tuils.sendXMLParseError(context, PATH, e);
                     return;
+                } catch (Exception e) {
+                    Tuils.log(e);
+                    return;
                 }
 
                 try {
@@ -249,7 +257,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                     }
 
                     if (enums.size() > 0) {
-                        for (XMLPrefsManager.XMLPrefsSave s : enums) {
+                        for (XMLPrefsSave s : enums) {
                             String value = s.defaultValue();
 
                             Element em = document.createElement(s.label());
@@ -319,7 +327,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                 for(CmdableRegex rg : cmdRegexes) {
                     try {
                         int id = Integer.parseInt(rg.literalPattern);
-                        rg.regex = RegexManager.get(id).regex;
+                        rg.regex = RegexManager.instance.get(id).regex;
                     } catch (Exception exc) {
                         try {
                             rg.regex = Pattern.compile(rg.literalPattern);
@@ -594,8 +602,6 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
         }
     };
 
-    final String quotes = "\"";
-
     private void updateRss(final Rss feed, final boolean firstTime) {
         updateRss(feed, firstTime, false);
     }
@@ -608,9 +614,8 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
         return true;
     }
 
-    private void updateRss(final Rss feed, final boolean firstTime, boolean force) {
+    private void updateRss(final Rss feed, final boolean firstTime, final boolean force) {
         if(!force && feed.wifiOnly && !connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) {
-
             feed.lastCheckedClient = System.currentTimeMillis();
             feed.updateFile(rssIndexFile);
 
@@ -623,6 +628,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                 super.run();
 
                 if(!Tuils.hasInternetAccess()) {
+                    if(force) Tuils.sendOutput(Color.RED, context, "No internet access");
                     return;
                 }
 
@@ -631,14 +637,14 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                             .url(feed.url)
                             .get();
 
-                    if(!firstTime && feed.lMod != null && feed.etag != null) {
-                        builder.addHeader(IF_MODIFIED_SINCE_FIELD, feed.lMod);
-                        builder.addHeader(IF_NONE_MATCH_FIELD, quotes + feed.etag + quotes);
-                    }
+//                    if(!firstTime && feed.lMod != null && feed.etag != null) {
+//                        builder.addHeader(IF_MODIFIED_SINCE_FIELD, feed.lMod);
+//                        builder.addHeader(IF_NONE_MATCH_FIELD, quotes + feed.etag + quotes);
+//                    }
 
                     Response response = client.newCall(builder.build()).execute();
 
-                    if(firstTime || response.code() != 304) {
+                    if(response.isSuccessful() && (firstTime || response.code() != 304)) {
                         ResponseBody body = response.body();
 
                         long bytes = 0;
@@ -662,7 +668,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                             c = kbPattern.matcher(c).replaceAll(String.valueOf(kb));
                             c = bPattern.matcher(c).replaceAll(String.valueOf(bytes));
 
-                            c = TimeManager.replace(c, timeColor);
+                            c = TimeManager.instance.replace(c, timeColor);
 
                             Tuils.sendOutput(downloadMessageColor, context, c);
                         }
@@ -672,9 +678,9 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                             return;
                         }
 
-                        feed.lMod = response.header(LAST_MODIFIED_FIELD);
-                        feed.etag = response.header(ETAG_FIELD);
-                        if(feed.etag != null) feed.etag = feed.etag.replaceAll("\"", Tuils.EMPTYSTRING);
+//                        feed.lMod = response.header(LAST_MODIFIED_FIELD);
+//                        feed.etag = response.header(ETAG_FIELD);
+//                        if(feed.etag != null) feed.etag = feed.etag.replaceAll("\"", Tuils.EMPTYSTRING);
 
                         response.close();
 
@@ -706,7 +712,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
         Document doc;
         try {
             doc = dBuilder.parse(rssFile);
-        } catch (Exception e) {
+        } catch (SAXParseException e) {
             Tuils.sendXMLParseError(context, PATH, e);
             return false;
         }
@@ -766,7 +772,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
             Tuils.sendOutput(Color.RED, context, context.getString(R.string.rss_invalid_date) + Tuils.SPACE + (dateTag));
         } else if(greatestTime != -1) {
             feed.lastShownItem = greatestTime;
-            feed.updateTime(rssIndexFile);
+            feed.updateLastShownItem(rssIndexFile);
         }
 
         return updated;
@@ -779,14 +785,12 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
     private final String OPEN_URL = "search -u ";
     private final String PERCENTAGE = "%";
 
-    private Pattern nl = Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
-
 //    called when a new element is detected, it could be triggered many times again in some milliseconds
     private void showItem(Rss feed, Element item, boolean userRequested) {
         if(item == null) return;
 
         String cp = feed.format != null ? feed.format : defaultFormat;
-        cp = nl.matcher(cp).replaceAll(Tuils.NEWLINE);
+        cp = Tuils.patternNewline.matcher(cp).replaceAll(Tuils.NEWLINE);
 
         CharSequence s = Tuils.span(cp, feed.color);
 
@@ -817,7 +821,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                         }
 
                         long timeLong = d.getTime();
-                        value = TimeManager.replace(timeFormat, timeLong, Integer.MAX_VALUE).toString();
+                        value = TimeManager.instance.replace(timeFormat, timeLong, Integer.MAX_VALUE).toString();
                     } else {
                         value = HtmlEscape.unescapeHtml(value);
 
@@ -871,10 +875,11 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
                         cmd = cmd.replaceAll(PERCENTAGE + c, rssMatcher.group(c));
                     }
 
-                    Intent intent = new Intent(InputOutputReceiver.ACTION_CMD);
-                    intent.putExtra(InputOutputReceiver.SHOW_CONTENT, false);
-                    intent.putExtra(InputOutputReceiver.TEXT, cmd);
-                    context.sendBroadcast(intent);
+                    Intent intent = new Intent(MainManager.ACTION_EXEC);
+                    intent.putExtra(MainManager.NEED_WRITE_INPUT, false);
+                    intent.putExtra(MainManager.CMD, cmd);
+                    intent.putExtra(MainManager.CMD_COUNT, MainManager.commandCount);
+                    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
                 }
             }
         }
@@ -904,7 +909,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
         public long updateTimeSeconds, lastCheckedClient, lastShownItem;
         public int id;
         public boolean show;
-        public String lMod, etag;
+//        public String lMod, etag;
 
         public String entryTag, dateTag;
 
@@ -915,8 +920,6 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
 
         public int color;
 
-        public long millisecondsLeft, lastUpdated;
-
         public boolean wifiOnly;
 
         public SimpleDateFormat timeFormat;
@@ -928,8 +931,6 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
         public Rss(String url, long updateTimeSeconds, long lastCheckedClient, long lastShownItem, int id, boolean show, String lMod, String etag, String format,
                    String includeIfMatches, String excludeIfMatches, int color, boolean wifiOnly, String timeFormat, String rootNode, String timeNode) {
             setAll(url, updateTimeSeconds, lastCheckedClient, lastShownItem, id, show, lMod, etag, format, includeIfMatches, excludeIfMatches, color, wifiOnly, timeFormat, rootNode, timeNode);
-
-            millisecondsLeft = updateTimeSeconds * 1000 - (System.currentTimeMillis() - lastCheckedClient);
         }
 
         public static Rss fromElement(Element t) {
@@ -993,8 +994,8 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
             this.lastCheckedClient = lastCheckedClient;
             this.id = id;
             this.show = show;
-            this.lMod = lMod;
-            this.etag = etag;
+//            this.lMod = lMod;
+//            this.etag = etag;
 
             this.format = format;
 
@@ -1017,20 +1018,13 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
         }
 
         public boolean needUpdate() {
-            millisecondsLeft -= System.currentTimeMillis() - lastUpdated;
-
-            lastUpdated = System.currentTimeMillis();
-
-            if(millisecondsLeft <= 0) {
-                millisecondsLeft = updateTimeSeconds * 1000;
-
-                return true;
-            }
-
-            return false;
+//            Tuils.log("lc", lastCheckedClient);
+//            Tuils.log(System.currentTimeMillis() - lastCheckedClient);
+//            Tuils.log("up", updateTimeSeconds * 1000);
+            return System.currentTimeMillis() - lastCheckedClient >= (updateTimeSeconds * 1000);
         }
 
-        public void updateTime(File rssFile) {
+        public void updateLastShownItem(File rssFile) {
             XMLPrefsManager.set(rssFile, RSS_LABEL, new String[] {ID_ATTRIBUTE}, new String[] {String.valueOf(id)}, new String[] {LAST_SHOWN_ITEM_ATTRIBUTE},
                     new String[] {String.valueOf(lastShownItem)}, false);
         }
@@ -1039,7 +1033,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
             if(includeIfMatches != null) {
                 try {
                     int id = Integer.parseInt(tempInclude);
-                    includeIfMatches = RegexManager.get(id).regex;
+                    includeIfMatches = RegexManager.instance.get(id).regex;
                 } catch (Exception exc) {
                     includeIfMatches = Pattern.compile(tempInclude);
                 }
@@ -1050,7 +1044,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
             if(excludeIfMatches != null) {
                 try {
                     int id = Integer.parseInt(tempExclude);
-                    excludeIfMatches = RegexManager.get(id).regex;
+                    excludeIfMatches = RegexManager.instance.get(id).regex;
                 } catch (Exception exc) {
                     includeIfMatches = Pattern.compile(tempExclude);
                 }
@@ -1059,7 +1053,7 @@ public class RssManager implements XMLPrefsManager.XmlPrefsElement {
 
         private void updateFile(File rssFile) {
             XMLPrefsManager.set(rssFile, RSS_LABEL, new String[] {ID_ATTRIBUTE}, new String[] {String.valueOf(id)},
-                    new String[] {LASTCHECKED_ATTRIBUTE, LASTMODIFIED_ATTRIBUTE, ETAG_ATTRIBUTE}, new String[] {String.valueOf(lastCheckedClient), lMod, etag},
+                    new String[] {LASTCHECKED_ATTRIBUTE/*, LASTMODIFIED_ATTRIBUTE, ETAG_ATTRIBUTE*/}, new String[] {String.valueOf(lastCheckedClient)/*, lMod, etag*/},
                     false);
         }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalManager.java
index ae96775d1a6927c274c9525abe5777d1a8ba2f16..f0386b9b87dd6cecdcc06b67b05b6d27c0864ea8 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalManager.java
@@ -2,7 +2,6 @@ package ohi.andre.consolelauncher.managers;
 
 import android.app.Activity;
 import android.content.Context;
-import android.content.Intent;
 import android.graphics.Color;
 import android.os.IBinder;
 import android.text.InputType;
@@ -24,19 +23,16 @@ import android.widget.TextView;
 import java.util.ArrayList;
 import java.util.List;
 
-import ohi.andre.consolelauncher.UIManager;
 import ohi.andre.consolelauncher.commands.main.MainPack;
-import ohi.andre.consolelauncher.commands.main.raw.clear;
-import ohi.andre.consolelauncher.managers.notifications.KeeperService;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Theme;
 import ohi.andre.consolelauncher.managers.xml.options.Ui;
-import ohi.andre.consolelauncher.tuils.InputOutputReceiver;
 import ohi.andre.consolelauncher.tuils.LongClickMovementMethod;
 import ohi.andre.consolelauncher.tuils.LongClickableSpan;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
 import ohi.andre.consolelauncher.tuils.Tuils;
-import ohi.andre.consolelauncher.tuils.interfaces.Rooter;
+import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
 
 /*Copyright Francesco Andreuzzi
 
@@ -87,9 +83,6 @@ public class TerminalManager {
         }
     };
 
-    private UIManager.OnNewInputListener mInputListener;
-//    private UIManager.SuggestionNavigator mSuggestionNavigator;
-
     private MainPack mainPack;
 
     private boolean defaultHint = true;
@@ -109,16 +102,19 @@ public class TerminalManager {
     private String inputFormat, outputFormat;
     private int inputColor, outputColor;
 
-    private boolean keeperServiceRunning, clickCommands, longClickCommands;
+    private boolean clickCommands, longClickCommands;
 
     private Context mContext;
 
+    private CommandExecuter executer;
+
     public TerminalManager(final TextView terminalView, EditText inputView, TextView prefixView, ImageButton submitView, final ImageButton backView, ImageButton nextView, ImageButton deleteView,
-                           ImageButton pasteView, final Context context, MainPack mainPack) {
+                           ImageButton pasteView, final Context context, MainPack mainPack, CommandExecuter executer) {
         if (terminalView == null || inputView == null || prefixView == null)
             throw new UnsupportedOperationException();
 
         this.mContext = context;
+        this.executer = executer;
 
         this.mainPack = mainPack;
 
@@ -140,8 +136,6 @@ public class TerminalManager {
 
         int ioSize = XMLPrefsManager.getInt(Ui.input_output_size);
 
-        keeperServiceRunning = XMLPrefsManager.getBoolean(Behavior.tui_notification);
-
         prefixView.setTypeface(Tuils.getTypeface(context));
         prefixView.setTextColor(XMLPrefsManager.getColor(Theme.input_color));
         prefixView.setTextSize(ioSize);
@@ -314,6 +308,7 @@ public class TerminalManager {
         CharSequence input = mInputView.getText();
 
         String cmd = input.toString().trim();
+
         Object obj = null;
         try {
             obj = ((Spannable) input).getSpans(0, input.length(), AppsManager.LaunchInfo.class)[0];
@@ -337,10 +332,23 @@ public class TerminalManager {
             howBack = -1;
         }
 
-//        I tried to use intents and ioreceiver.class instead, but it wasn't better
-        if (mInputListener != null) {
-            mInputListener.onNewInput(cmd, obj);
-        }
+//        DO NOT USE THE INTENT APPROACH
+//        apps are not launching properly, when one has been launched, an other attempt will show always the same
+//
+//        Intent intent = new Intent(MainManager.ACTION_EXEC);
+//        intent.putExtra(MainManager.CMD, cmd);
+//        intent.putExtra(MainManager.CMD_COUNT, MainManager.commandCount);
+//
+//        Parcelable p = null;
+//        if(obj instanceof Parcelable) p = (Parcelable) obj;
+//        intent.putExtra(MainManager.PARCELABLE, p);
+//
+//        LocalBroadcastManager.getInstance(mContext.getApplicationContext()).sendBroadcast(intent);
+
+        executer.execute(cmd, obj);
+
+//        because it will clear suggestions without refilling them, because "aftertextchanged" wont be called
+//        if(cmd.length() > 0) LocalBroadcastManager.getInstance(mContext.getApplicationContext()).sendBroadcast(new Intent(UIManager.ACTION_CLEAR_SUGGESTIONS));
 
         setupNewInput();
 
@@ -350,22 +358,12 @@ public class TerminalManager {
     public void setOutput(CharSequence output, int type) {
         if (output == null || output.length() == 0) return;
 
-        if(output.equals(clear.CLEAR)) {
-            clear();
-            return;
-        }
-
         writeToView(output, type);
     }
 
     public void setOutput(int color, CharSequence output) {
         if(output == null || output.length() == 0) return;
 
-        if(output.equals(clear.CLEAR)) {
-            clear();
-            return;
-        }
-
         if(color == Integer.MAX_VALUE) {
             color = XMLPrefsManager.getColor(Theme.output_color);
         }
@@ -377,6 +375,10 @@ public class TerminalManager {
         writeToView(s);
     }
 
+    public String getTerminalText() {
+        return mTerminalView.getText().toString();
+    }
+
     public void onBackPressed() {
         if(cmdList.size() > 0) {
 
@@ -412,13 +414,6 @@ public class TerminalManager {
     public static final String FORMAT_NEWLINE = "%n";
 
     private void writeToView(CharSequence text, int type) {
-        if(type == CATEGORY_INPUT && keeperServiceRunning) {
-            Intent i = new Intent(mContext, KeeperService.class);
-            i.putExtra(KeeperService.CMD_KEY, text.toString());
-            i.putExtra(KeeperService.PATH_KEY, mainPack.currentDirectory.getAbsolutePath());
-            mContext.startService(i);
-        }
-
         text = getFinalText(text, type);
         text = TextUtils.concat(Tuils.NEWLINE, text);
         writeToView(text);
@@ -443,10 +438,10 @@ public class TerminalManager {
                 boolean su = t.toString().startsWith("su ") || suMode;
 
                 SpannableString si = Tuils.span(inputFormat, inputColor);
-                if(clickCommands || longClickCommands) si.setSpan(new LongClickableSpan(clickCommands ? t.toString() : null, longClickCommands ? t.toString() : null, InputOutputReceiver.ACTION_INPUT), 0,
+                if(clickCommands || longClickCommands) si.setSpan(new LongClickableSpan(clickCommands ? t.toString() : null, longClickCommands ? t.toString() : null, PrivateIOReceiver.ACTION_INPUT), 0,
                         si.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
-                s = TimeManager.replace(si,XMLPrefsManager.getColor(Theme.time_color));
+                s = TimeManager.instance.replace(si,XMLPrefsManager.getColor(Theme.time_color));
                 s = TextUtils.replace(s,
                         new String[] {FORMAT_INPUT, FORMAT_PREFIX, FORMAT_NEWLINE, FORMAT_INPUT.toUpperCase(), FORMAT_PREFIX.toUpperCase(), FORMAT_NEWLINE.toUpperCase()},
                         new CharSequence[] {t, su ? suPrefix : prefix, Tuils.NEWLINE, t, su ? suPrefix : prefix, Tuils.NEWLINE});
@@ -515,14 +510,6 @@ public class TerminalManager {
         this.messagesManager = msg;
     }
 
-    public void setInputListener(UIManager.OnNewInputListener listener) {
-        this.mInputListener = listener;
-    }
-
-//    public void setSuggestionNavigator(UIManager.SuggestionNavigator navigator) {
-//        this.mSuggestionNavigator = navigator;
-//    }
-
     public void focusInputEnd() {
         mInputView.setSelection(getInput().length());
     }
@@ -554,30 +541,23 @@ public class TerminalManager {
         clearCmdsCount = 0;
     }
 
-    public Rooter getRooter() {
-        return new Rooter() {
+    public void onRoot() {
+        ((Activity) mContext).runOnUiThread(new Runnable() {
             @Override
-            public void onRoot() {
-                ((Activity) mContext).runOnUiThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        suMode = true;
-                        mPrefix.setText(suPrefix.endsWith(Tuils.SPACE) ? suPrefix : suPrefix + Tuils.SPACE);
-                    }
-                });
+            public void run() {
+                suMode = true;
+                mPrefix.setText(suPrefix.endsWith(Tuils.SPACE) ? suPrefix : suPrefix + Tuils.SPACE);
             }
+        });
+    }
 
+    public void onStandard() {
+        ((Activity) mContext).runOnUiThread(new Runnable() {
             @Override
-            public void onStandard() {
-                ((Activity) mContext).runOnUiThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        suMode = false;
-                        mPrefix.setText(prefix.endsWith(Tuils.SPACE) ? prefix : prefix + Tuils.SPACE);
-                    }
-                });
+            public void run() {
+                suMode = false;
+                mPrefix.setText(prefix.endsWith(Tuils.SPACE) ? prefix : prefix + Tuils.SPACE);
             }
-        };
+        });
     }
-
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/ThemeManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/ThemeManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..091bbbb9bd2e336bf15bfab26ae3cc4579d00e5c
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/ThemeManager.java
@@ -0,0 +1,18 @@
+package ohi.andre.consolelauncher.managers;
+
+import java.io.File;
+
+/**
+ * Created by francescoandreuzzi on 17/02/2018.
+ */
+
+public class ThemeManager {
+
+    public static void apply(String themeName) {
+
+    }
+
+    public static void apply(File zip) {
+        
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/TimeManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/TimeManager.java
index 22addaa110c2aa921426a7409e6eda8b812220d7..6caeb4fb5c67d05b37656ba475d91c17e76b312f 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/TimeManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/TimeManager.java
@@ -22,11 +22,13 @@ import ohi.andre.consolelauncher.tuils.Tuils;
 
 public class TimeManager {
 
-    static SimpleDateFormat[] dateFormatList;
+    SimpleDateFormat[] dateFormatList;
 
-    static Pattern extractor = Pattern.compile("%t([0-9]+)", Pattern.CASE_INSENSITIVE);
+    public static Pattern extractor = Pattern.compile("%t([0-9]+)", Pattern.CASE_INSENSITIVE);
 
-    public static void create() {
+    public static TimeManager instance;
+
+    public TimeManager() {
         final Pattern NEWLINE_PATTERN = Pattern.compile("%n");
 
         String format = XMLPrefsManager.get(Behavior.time_format);
@@ -43,32 +45,35 @@ public class TimeManager {
                 dateFormatList[c] = dateFormatList[0];
             }
         }
+
+        instance = this;
     }
 
-    private static SimpleDateFormat get(int index) {
+    private SimpleDateFormat get(int index) {
+        if(dateFormatList == null) return null;
         if(index < 0 || index >= dateFormatList.length) index = 0;
         if(index == 0 && dateFormatList.length == 0) return null;
 
         return dateFormatList[index];
     }
 
-    public static CharSequence replace(CharSequence cs) {
+    public CharSequence replace(CharSequence cs) {
         return replace(cs, -1, Integer.MAX_VALUE);
     }
 
-    public static CharSequence replace(CharSequence cs, int color) {
+    public CharSequence replace(CharSequence cs, int color) {
         return replace(cs, -1, color);
     }
 
-    public static CharSequence replace(CharSequence cs, long tm, int color) {
+    public CharSequence replace(CharSequence cs, long tm, int color) {
         return replace(null, Integer.MAX_VALUE, cs, tm, color);
     }
 
-    public static CharSequence replace(Context context, int size, CharSequence cs, int color) {
+    public CharSequence replace(Context context, int size, CharSequence cs, int color) {
         return replace(context, size, cs, -1, color);
     }
 
-    public static CharSequence replace(Context context, int size, CharSequence cs, long tm, int color) {
+    public CharSequence replace(Context context, int size, CharSequence cs, long tm, int color) {
         if(tm == -1) {
             tm = System.currentTimeMillis();
         }
@@ -113,4 +118,10 @@ public class TimeManager {
 
         return cs;
     }
+
+    public void dispose() {
+        dateFormatList = null;
+
+        instance = null;
+    }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight1.java b/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight1.java
index e2d1a10353bee82082d3031c6d5f3eea51c9295e..996418d0969a38576d126f1fb4632708aef16e4a 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight1.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight1.java
@@ -5,10 +5,11 @@ import android.content.Intent;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.os.Build;
+import android.support.v4.content.LocalBroadcastManager;
 
 import java.util.List;
 
-import ohi.andre.consolelauncher.tuils.InputOutputReceiver;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
 
 /**
  * Created by francescoandreuzzi on 20/08/2017.
@@ -46,9 +47,9 @@ public class Flashlight1 extends Flashlight {
                     } catch (Exception ex) {}
                 }
 
-                Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                intent.putExtra(InputOutputReceiver.TEXT, e.toString());
-                mContext.sendBroadcast(intent);
+                Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                intent.putExtra(PrivateIOReceiver.TEXT, e.toString());
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
             }
         }
     }
@@ -74,9 +75,9 @@ public class Flashlight1 extends Flashlight {
             try {
                 this.mCamera = Camera.open();
             } catch (Exception e) {
-                Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                intent.putExtra(InputOutputReceiver.TEXT, e.toString());
-                mContext.sendBroadcast(intent);
+                Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                intent.putExtra(PrivateIOReceiver.TEXT, e.toString());
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
                 return false;
             }
         }
@@ -95,9 +96,9 @@ public class Flashlight1 extends Flashlight {
             try {
                 mCamera.setParameters(mCameraParameters);
             } catch (RuntimeException e) {
-                Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                intent.putExtra(InputOutputReceiver.TEXT, e.toString());
-                mContext.sendBroadcast(intent);
+                Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                intent.putExtra(PrivateIOReceiver.TEXT, e.toString());
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
                 return false;
             }
         }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight2.java b/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight2.java
index 3a29eeddb0a8a6220660e3ed3e12de56b576a6a7..e2189472c9095da97cde7cd82048f387436f2c9c 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight2.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/flashlight/Flashlight2.java
@@ -24,8 +24,9 @@ import android.content.Intent;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
+import android.support.v4.content.LocalBroadcastManager;
 
-import ohi.andre.consolelauncher.tuils.InputOutputReceiver;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
 
 /**
  * Created by I327891 on 04-Feb-17.
@@ -51,18 +52,18 @@ public class Flashlight2 extends Flashlight {
             try {
                 this.mCameraIDList = mCameraManager.getCameraIdList();
             } catch (CameraAccessException e) {
-                Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                intent.putExtra(InputOutputReceiver.TEXT, e.toString());
-                mContext.sendBroadcast(intent);
+                Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                intent.putExtra(PrivateIOReceiver.TEXT, e.toString());
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
                 return;
             }
             try {
                 CameraCharacteristics mCameraParameters = mCameraManager.getCameraCharacteristics(this.mCameraIDList[0]);
                 this.flashSupported = mCameraParameters.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
             } catch (Exception e) {
-                Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                intent.putExtra(InputOutputReceiver.TEXT, e.toString());
-                mContext.sendBroadcast(intent);
+                Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                intent.putExtra(PrivateIOReceiver.TEXT, e.toString());
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
                 return;
             }
             if (this.flashSupported) {
@@ -70,9 +71,9 @@ public class Flashlight2 extends Flashlight {
                     mCameraManager.setTorchMode(this.mCameraIDList[0], true);
                     this.updateStatus(true);
                 } catch (CameraAccessException e) {
-                    Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                    intent.putExtra(InputOutputReceiver.TEXT, e.toString());
-                    mContext.sendBroadcast(intent);
+                    Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                    intent.putExtra(PrivateIOReceiver.TEXT, e.toString());
+                    LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
                 }
             }
         }
@@ -86,9 +87,9 @@ public class Flashlight2 extends Flashlight {
                 try {
                     mCameraManager.setTorchMode(mCameraIDList[0], false);
                 } catch (CameraAccessException e) {
-                    Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-                    intent.putExtra(InputOutputReceiver.TEXT, e.toString());
-                    mContext.sendBroadcast(intent);
+                    Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+                    intent.putExtra(PrivateIOReceiver.TEXT, e.toString());
+                    LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
                     return;
                 }
                 this.updateStatus(false);
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicManager2.java b/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicManager2.java
index 95bfdccb66ce080ca152bd95cb1895b5244709d2..977865bd6dd96d7a68b97ee4599dd2cf9b22801c 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicManager2.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicManager2.java
@@ -1,12 +1,16 @@
 package ohi.andre.consolelauncher.managers.music;
 
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.database.Cursor;
+import android.media.AudioManager;
 import android.net.Uri;
+import android.os.Build;
 import android.os.IBinder;
 import android.provider.MediaStore;
 import android.widget.MediaController;
@@ -46,10 +50,28 @@ public class MusicManager2 implements MediaController.MediaPlayerControl {
     int waitingMethod = 0;
     String savedParam;
 
+    BroadcastReceiver headsetBroadcast;
+
     public MusicManager2(Context c) {
         mContext = c;
         updateSongs();
 
+        headsetBroadcast = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent.getIntExtra("state", 0) == 0) pause();
+            }
+        };
+
+        String action;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            action = AudioManager.ACTION_HEADSET_PLUG;
+        } else {
+            action = Intent.ACTION_HEADSET_PLUG;
+        }
+
+        mContext.getApplicationContext().registerReceiver(headsetBroadcast, new IntentFilter(action));
+
         init();
     }
 
@@ -72,6 +94,12 @@ public class MusicManager2 implements MediaController.MediaPlayerControl {
             musicSrv = null;
         }
 
+        try {
+            mContext.getApplicationContext().unregisterReceiver(headsetBroadcast);
+        } catch (Exception e) {
+            Tuils.log(e);
+        }
+
         musicBound = false;
         playbackPaused = true;
         stopped = true;
@@ -107,7 +135,7 @@ public class MusicManager2 implements MediaController.MediaPlayerControl {
 
     @Override
     public void pause() {
-        if(musicSrv == null) return;
+        if(musicSrv == null || playbackPaused) return;
 
         playbackPaused=true;
         musicSrv.pausePlayer();
@@ -134,6 +162,8 @@ public class MusicManager2 implements MediaController.MediaPlayerControl {
     }
 
     public String lsSongs() {
+        if(songs.size() == 0) return "[]";
+
         List<String> ss = new ArrayList<>();
         for(Song s : songs) {
             ss.add(s.getTitle());
@@ -171,10 +201,16 @@ public class MusicManager2 implements MediaController.MediaPlayerControl {
                         musicCursor.close();
                     } else {
                         String path = XMLPrefsManager.get(Behavior.songs_folder);
-                        if(path.length() > 0) {
-                            File dir = new File(path);
-                            if(dir.isDirectory()) songs.addAll(Tuils.getSongsInFolder(dir));
+                        if(path.length() == 0) return;
+
+                        File file;
+                        if(path.startsWith(File.separator)) {
+                            file = new File(path);
+                        } else {
+                            file = new File(XMLPrefsManager.get(Behavior.home_path), path);
                         }
+
+                        if(file.exists() && file.isDirectory()) songs.addAll(Tuils.getSongsInFolder(file));
                     }
                 } catch (Exception e) {
                     Tuils.toFile(e);
@@ -196,13 +232,14 @@ public class MusicManager2 implements MediaController.MediaPlayerControl {
             musicSrv = binder.getService();
             musicSrv.setShuffle(XMLPrefsManager.getBoolean(Behavior.random_play));
 
-            if(songs == null || loader.isAlive()) {
+            if(loader.isAlive()) {
                 synchronized (songs) {
                     try {
                         songs.wait();
                     } catch (InterruptedException e) {}
                 }
             }
+
             musicSrv.setList(songs);
             musicBound = true;
 
@@ -287,6 +324,7 @@ public class MusicManager2 implements MediaController.MediaPlayerControl {
     }
 
     public Song get(int index) {
+        if(index < 0 || index >= songs.size()) return null;
         return songs.get(index);
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicService.java b/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicService.java
index 9c9eefbb33e98150911202239ff966d5e9e20626..0d79629ba22f431338c1c085af45b27c67c73cf3 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicService.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/music/MusicService.java
@@ -17,12 +17,14 @@ import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.RemoteInput;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.List;
-import java.util.Random;
 
 import ohi.andre.consolelauncher.LauncherActivity;
+import ohi.andre.consolelauncher.MainManager;
 import ohi.andre.consolelauncher.R;
-import ohi.andre.consolelauncher.tuils.InputOutputReceiver;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
+import ohi.andre.consolelauncher.tuils.PublicIOReceiver;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
 public class MusicService extends Service implements
@@ -35,16 +37,40 @@ public class MusicService extends Service implements
     private List<Song> songs;
     private int songPosn;
     private final IBinder musicBind = new MusicBinder();
-    private String songTitle="";
+    private String songTitle = Tuils.EMPTYSTRING;
     private boolean shuffle=false;
-    private Random rand;
+
+    private long lastNotificationChange;
+
+//    do not touch the song playback from here
 
     public void onCreate(){
         super.onCreate();
         songPosn=0;
-        rand=new Random();
         player = new MediaPlayer();
         initMusicPlayer();
+
+        lastNotificationChange = System.currentTimeMillis();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if(System.currentTimeMillis() - lastNotificationChange < 500 || songTitle == null || songTitle.length() == 0) return super.onStartCommand(intent, flags, startId);
+
+        lastNotificationChange = System.currentTimeMillis();
+        startForeground(NOTIFY_ID, buildNotification(this.getApplicationContext(), songTitle));
+
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    @Override
+    public void onPrepared(MediaPlayer mp) {
+        if(songTitle == null || songTitle.length() == 0) return;
+
+        lastNotificationChange = System.currentTimeMillis();
+
+        mp.start();
+        startForeground(NOTIFY_ID, buildNotification(this.getApplicationContext(), songTitle));
     }
 
     public void initMusicPlayer(){
@@ -55,8 +81,9 @@ public class MusicService extends Service implements
         player.setOnErrorListener(this);
     }
 
-    public void setList(List<Song> theSongs){
-        songs=theSongs;
+    public void setList(List<Song> theSongs) {
+        songs = theSongs;
+        if(shuffle) Collections.shuffle(songs);
     }
 
     public class MusicBinder extends Binder {
@@ -78,7 +105,10 @@ public class MusicService extends Service implements
     public String playSong(){
         try {
             player.reset();
-        } catch (Exception e) {}
+        } catch (Exception e) {
+//            no need to log this error, as this will occur everytime
+            Tuils.log(e);
+        }
 
         Song playSong = songs.get(songPosn);
 
@@ -111,7 +141,7 @@ public class MusicService extends Service implements
     }
 
     public void setSong(int songIndex){
-        songPosn=songIndex;
+        songPosn = songIndex;
     }
 
     @Override
@@ -128,12 +158,6 @@ public class MusicService extends Service implements
         return false;
     }
 
-    @Override
-    public void onPrepared(MediaPlayer mp) {
-        mp.start();
-        startForeground(NOTIFY_ID, buildNotification(this.getApplicationContext(), songTitle));
-    }
-
     public static Notification buildNotification(Context context, String songTitle) {
         Intent notIntent = new Intent(context, LauncherActivity.class);
         PendingIntent pendInt = PendingIntent.getActivity(context, 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
@@ -147,14 +171,14 @@ public class MusicService extends Service implements
                 .setContentTitle("Playing")
                 .setContentText(songTitle);
 
-        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             String label = "cmd";
-            RemoteInput remoteInput = new RemoteInput.Builder(InputOutputReceiver.TEXT)
+            RemoteInput remoteInput = new RemoteInput.Builder(PrivateIOReceiver.TEXT)
                     .setLabel(label)
                     .build();
 
-            Intent i = new Intent(InputOutputReceiver.ACTION_CMD);
-            i.putExtra(InputOutputReceiver.WAS_KEY, InputOutputReceiver.WAS_MUSIC_SERVICE);
+            Intent i = new Intent(PublicIOReceiver.ACTION_CMD);
+            i.putExtra(MainManager.MUSIC_SERVICE, true);
 
             NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, label,
                     PendingIntent.getBroadcast(context.getApplicationContext(), 10, i, PendingIntent.FLAG_UPDATE_CURRENT))
@@ -211,27 +235,29 @@ public class MusicService extends Service implements
     }
 
     public String playPrev(){
-        songPosn--;
-        if(songPosn<0) songPosn=songs.size()-1;
+        if(songs.size() == 0) return getString(R.string.no_songs);
+        songPosn = previous();
         return playSong();
     }
 
-    public String playNext(){
-        if(shuffle){
-            int newSong = songPosn;
-            while(newSong==songPosn){
-                newSong=rand.nextInt(songs.size());
-            }
-            songPosn=newSong;
-        }
-        else{
-            songPosn++;
-            if(songPosn>=songs.size()) songPosn=0;
-        }
-
+    public String playNext() {
+        if(songs.size() == 0) return getString(R.string.no_songs);
+        songPosn = next();
         return playSong();
     }
 
+    private int next() {
+        int pos = songPosn + 1;
+        if(pos == songs.size()) pos = 0;
+        return pos;
+    }
+
+    private int previous() {
+        int pos = songPosn - 1;
+        if(pos < 0) pos = songs.size() - 1;
+        return pos;
+    }
+
     public int getSongIndex() {
         return songPosn;
     }
@@ -239,6 +265,10 @@ public class MusicService extends Service implements
     @Override
     public void onDestroy() {
         super.onDestroy();
+
+        player.release();
+        songs.clear();
+
         stopForeground(true);
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/KeeperService.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/KeeperService.java
index 350a57da643c9611d86bf1c98ccc441d78343e9e..ea790262005ad292d66c95202462fa6e74443d43 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/KeeperService.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/KeeperService.java
@@ -6,6 +6,7 @@ import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
+import android.os.Environment;
 import android.os.IBinder;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.NotificationManagerCompat;
@@ -19,7 +20,8 @@ import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Theme;
 import ohi.andre.consolelauncher.managers.xml.options.Ui;
-import ohi.andre.consolelauncher.tuils.InputOutputReceiver;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
+import ohi.andre.consolelauncher.tuils.PublicIOReceiver;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
 import static ohi.andre.consolelauncher.managers.TerminalManager.FORMAT_INPUT;
@@ -48,6 +50,7 @@ public class KeeperService extends Service {
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         if(startId == 1 || startId == 0) {
+
             title = XMLPrefsManager.get(Behavior.tui_notification_title);
             subtitle = XMLPrefsManager.get(Behavior.tui_notification_subtitle);
             clickCmd = XMLPrefsManager.get(Behavior.tui_notification_click_cmd);
@@ -63,7 +66,7 @@ public class KeeperService extends Service {
             if(priority > 2) priority = 2;
             if(priority < -2) priority = -2;
 
-            String path = intent.getStringExtra(PATH_KEY);
+            String path = intent != null ? intent.getStringExtra(PATH_KEY) : Environment.getExternalStorageDirectory().getAbsolutePath();
 
             startForeground(ONGOING_NOTIFICATION_ID, buildNotification(getApplicationContext(), title, subtitle, Tuils.getHint(path),
                     clickCmd, showHome, lastCommands, upDown, priority));
@@ -80,7 +83,7 @@ public class KeeperService extends Service {
 
             if(lastCommands != null) updateCmds(intent.getStringExtra(CMD_KEY));
 
-            String path = intent.getStringExtra(PATH_KEY);
+            String path = intent != null ? intent.getStringExtra(PATH_KEY) : Environment.getExternalStorageDirectory().getAbsolutePath();
 
             NotificationManagerCompat.from(getApplicationContext()).notify(KeeperService.ONGOING_NOTIFICATION_ID,
                     KeeperService.buildNotification(getApplicationContext(), title, subtitle, Tuils.getHint(path),
@@ -115,7 +118,7 @@ public class KeeperService extends Service {
 
         SpannableString si = Tuils.span(inputFormat, inputColor);
 
-        CharSequence s = TimeManager.replace(si, timeColor);
+        CharSequence s = TimeManager.instance.replace(si, timeColor);
         s = TextUtils.replace(s,
                 new String[] {FORMAT_INPUT, FORMAT_PREFIX, FORMAT_NEWLINE, FORMAT_INPUT.toUpperCase(), FORMAT_PREFIX.toUpperCase(), FORMAT_NEWLINE.toUpperCase()},
                 new CharSequence[] {cmd, su ? suPrefix : prefix, Tuils.NEWLINE, cmd, su ? suPrefix : prefix, Tuils.NEWLINE});
@@ -130,11 +133,12 @@ public class KeeperService extends Service {
 
     @Override
     public boolean onUnbind(Intent intent) {
+        lastCommands = null;
+
         return true;
     }
 
-    private static Notification buildNotification(Context c, String title, String subtitle, String cmdLabel, String clickCmd, boolean showHome, CharSequence[] lastCommands, boolean upDown, int priority) {
-
+    public static Notification buildNotification(Context c, String title, String subtitle, String cmdLabel, String clickCmd, boolean showHome, CharSequence[] lastCommands, boolean upDown, int priority) {
         PendingIntent pendingIntent;
         if(showHome) {
             Intent startMain = new Intent(Intent.ACTION_MAIN);
@@ -142,7 +146,7 @@ public class KeeperService extends Service {
             startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
             if(clickCmd != null && clickCmd.length() > 0) {
-                startMain.putExtra(InputOutputReceiver.TEXT, clickCmd);
+                startMain.putExtra(PrivateIOReceiver.TEXT, clickCmd);
             }
 
             pendingIntent = PendingIntent.getActivity(
@@ -152,9 +156,8 @@ public class KeeperService extends Service {
                     PendingIntent.FLAG_CANCEL_CURRENT
             );
         } else if(clickCmd != null && clickCmd.length() > 0) {
-            Intent cmdIntent = new Intent(InputOutputReceiver.ACTION_CMD);
-            cmdIntent.putExtra(InputOutputReceiver.TEXT, clickCmd);
-            cmdIntent.putExtra(InputOutputReceiver.SHOW_CONTENT, true);
+            Intent cmdIntent = new Intent(PublicIOReceiver.ACTION_CMD);
+            cmdIntent.putExtra(PrivateIOReceiver.TEXT, clickCmd);
 
             pendingIntent = PendingIntent.getBroadcast(
                     c,
@@ -166,55 +169,89 @@ public class KeeperService extends Service {
             pendingIntent = null;
         }
 
-        NotificationCompat.Style style = null;
-        if(lastCommands != null && lastCommands[0] != null) {
-            NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
-
-            if(upDown) {
-                for (CharSequence lastCommand : lastCommands) {
-                    if (lastCommand == null) break;
-                    inboxStyle.addLine(lastCommand);
-                }
-            } else {
-                for(int j = lastCommands.length - 1; j >= 0; j--) {
-                    if(lastCommands[j] == null) continue;
-                    inboxStyle.addLine(lastCommands[j]);
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            NotificationCompat.Builder builder = new NotificationCompat.Builder(c)
+                    .setSmallIcon(R.mipmap.ic_launcher)
+                    .setTicker(c.getString(R.string.start_notification))
+                    .setWhen(System.currentTimeMillis())
+                    .setPriority(priority)
+                    .setContentTitle(title)
+                    .setContentIntent(pendingIntent);
+
+            NotificationCompat.Style style = null;
+            if(lastCommands != null && lastCommands[0] != null) {
+                NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
+
+                if(upDown) {
+                    for (CharSequence lastCommand : lastCommands) {
+                        if (lastCommand == null) break;
+                        inboxStyle.addLine(lastCommand);
+                    }
+                } else {
+                    for(int j = lastCommands.length - 1; j >= 0; j--) {
+                        if(lastCommands[j] == null) continue;
+                        inboxStyle.addLine(lastCommands[j]);
+                    }
                 }
-            }
 
-            style = inboxStyle;
-        }
+                style = inboxStyle;
+            }
 
-        NotificationCompat.Builder builder = new NotificationCompat.Builder(c)
-                .setSmallIcon(R.mipmap.ic_launcher)
-                .setTicker(c.getString(R.string.start_notification))
-                .setWhen(System.currentTimeMillis())
-                .setPriority(priority)
-                .setContentTitle(title)
-                .setContentIntent(pendingIntent);
-
-        if(style != null) builder.setStyle(style);
-        else {
-            builder.setContentTitle(title);
-            builder.setContentText(subtitle);
-        }
+            if(style != null) builder.setStyle(style);
+            else {
+                builder.setContentTitle(title);
+                builder.setContentText(subtitle);
+            }
 
-        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            RemoteInput remoteInput = new RemoteInput.Builder(InputOutputReceiver.TEXT)
+            RemoteInput remoteInput = new RemoteInput.Builder(PrivateIOReceiver.TEXT)
                     .setLabel(cmdLabel)
                     .build();
 
-            Intent i = new Intent(InputOutputReceiver.ACTION_CMD);
-            i.putExtra(InputOutputReceiver.WAS_KEY, InputOutputReceiver.WAS_KEEPER_SERVICE);
+            Intent i = new Intent(PublicIOReceiver.ACTION_CMD);
 
-            NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.mipmap.ic_launcher, cmdLabel,
+            NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.Builder(
+                    R.mipmap.ic_launcher,
+                    cmdLabel,
                     PendingIntent.getBroadcast(c.getApplicationContext(), 40, i, PendingIntent.FLAG_UPDATE_CURRENT))
-                    .addRemoteInput(remoteInput)
-                    .build();
+                        .addRemoteInput(remoteInput);
 
-            builder.addAction(action);
-        }
+            builder.addAction(actionBuilder.build());
+
+            return builder.build();
+        } else {
+            NotificationCompat.Builder builder = new NotificationCompat.Builder(c)
+                    .setSmallIcon(R.mipmap.ic_launcher)
+                    .setTicker(c.getString(R.string.start_notification))
+                    .setWhen(System.currentTimeMillis())
+                    .setPriority(priority)
+                    .setContentTitle(title)
+                    .setContentIntent(pendingIntent);
+
+            NotificationCompat.Style style = null;
+            if (lastCommands != null && lastCommands[0] != null) {
+                NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
+
+                if (upDown) {
+                    for (CharSequence lastCommand : lastCommands) {
+                        if (lastCommand == null) break;
+                        inboxStyle.addLine(lastCommand);
+                    }
+                } else {
+                    for (int j = lastCommands.length - 1; j >= 0; j--) {
+                        if (lastCommands[j] == null) continue;
+                        inboxStyle.addLine(lastCommands[j]);
+                    }
+                }
 
-        return builder.build();
+                style = inboxStyle;
+            }
+
+            if (style != null) builder.setStyle(style);
+            else {
+                builder.setContentTitle(title);
+                builder.setContentText(subtitle);
+            }
+            return builder.build();
+        }
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java
index 6b000632f25901de93d9e42b920271fe33a15623..d15412fa297fbb760d7a5d71163f92639b84acdc 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java
@@ -9,6 +9,7 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -20,6 +21,9 @@ import java.util.regex.Pattern;
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.managers.RegexManager;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsList;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Notifications;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
@@ -33,51 +37,49 @@ import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.writeTo;
  */
 
 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
-public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
+public class NotificationManager implements XMLPrefsElement {
 
     private static final String COLOR_ATTRIBUTE = "color", ENABLED_ATTRIBUTE = "enabled", ID_ATTRIBUTE = "id", FORMAT_ATTRIBUTE = "format", FILTER_ATTRIBUTE = "filter";
 
     public static final String PATH = "notifications.xml";
     private static final String NAME = "NOTIFICATIONS";
 
-    public static XMLPrefsManager.XmlPrefsElement instance = null;
-
-    public static boolean default_app_state;
-    public static String default_color;
+    public boolean default_app_state;
+    public String default_color;
 
     @Override
     public String[] deleted() {
-        return new String[] {"enabled", "default_color", "default_app_state"};
+        return new String[] {};
     }
 
     @Override
-    public XMLPrefsManager.XMLPrefsList getValues() {
+    public XMLPrefsList getValues() {
         return values;
     }
 
     @Override
-    public void write(XMLPrefsManager.XMLPrefsSave save, String value) {
+    public void write(XMLPrefsSave save, String value) {
         set(new File(Tuils.getFolder(), PATH), save.label(), new String[] {VALUE_ATTRIBUTE}, new String[] {value});
     }
 
-    private static XMLPrefsManager.XMLPrefsList values;
-    private static List<NotificatedApp> apps;
-    private static List<Pattern> filters;
-    private static List<XMLPrefsManager.IdValue> formats;
+    private XMLPrefsList values;
+    private List<NotificatedApp> apps;
+    private List<Pattern> filters;
+    private List<XMLPrefsManager.IdValue> formats;
 
-    private NotificationManager() {}
+    public static NotificationManager instance = null;
+    public static NotificationManager create(Context context) {
+        if(instance == null) return new NotificationManager(context);
+        else return instance;
+    }
 
-    public static void create(Context context) {
-
-        if(instance != null) {
-            return;
-        }
-        instance = new NotificationManager();
+    private NotificationManager(Context context) {
+        instance = this;
 
         apps = new ArrayList<>();
         filters = new ArrayList<>();
         formats = new ArrayList<>();
-        values = new XMLPrefsManager.XMLPrefsList();
+        values = new XMLPrefsList();
 
         try {
             File r = Tuils.getFolder();
@@ -98,9 +100,12 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
                     Tuils.sendXMLParseError(context, PATH);
                     return;
                 }
-            } catch (Exception e) {
+            } catch (SAXParseException e) {
                 Tuils.sendXMLParseError(context, PATH, e);
                 return;
+            } catch (Exception e) {
+                Tuils.log(e);
+                return;
             }
 
             Document d = (Document) o[0];
@@ -135,7 +140,7 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
                         if (regex == null) continue;
                         try {
                             int id = Integer.parseInt(regex);
-                            pattern = RegexManager.get(id).regex;
+                            pattern = RegexManager.instance.get(id).regex;
                         } catch (Exception exc) {
                             try {
                                 pattern = Pattern.compile(regex);
@@ -188,7 +193,7 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
             }
 
             if (enums.size() > 0) {
-                for (XMLPrefsManager.XMLPrefsSave s : enums) {
+                for (XMLPrefsSave s : enums) {
                     String value = s.defaultValue();
 
                     Element em = d.createElement(s.label());
@@ -224,6 +229,31 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
         default_color = XMLPrefsManager.get(Notifications.default_notification_color);
     }
 
+    public void dispose() {
+
+        if(values != null) {
+            values.list.clear();
+            values = null;
+        }
+
+        if(apps != null) {
+            apps.clear();
+            apps = null;
+        }
+
+        if(filters != null) {
+            filters.clear();
+            filters = null;
+        }
+
+        if(formats != null) {
+            formats.clear();
+            formats = null;
+        }
+
+        instance = null;
+    }
+
     public static String setState(String pkg, boolean state) {
         return XMLPrefsManager.set(new File(Tuils.getFolder(), PATH), pkg, new String[] {ENABLED_ATTRIBUTE}, new String[] {String.valueOf(state)});
     }
@@ -252,7 +282,7 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
         return XMLPrefsManager.removeNode(new File(Tuils.getFolder(), PATH), FORMAT_ATTRIBUTE, new String[] {ID_ATTRIBUTE}, new String[] {String.valueOf(id)});
     }
 
-    public static boolean match(String pkg, String text) {
+    public boolean match(String pkg, String text) {
 //        if(pkg.equals(BuildConfig.APPLICATION_ID)) return true;
 
         for(Pattern f : filters) {
@@ -263,11 +293,11 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
         return false;
     }
 
-    public static int apps() {
+    public int apps() {
         return apps.size();
     }
 
-    public static NotificatedApp getAppState(String pkg) {
+    public NotificatedApp getAppState(String pkg) {
         int index = Tuils.find(pkg, apps);
         if(index == -1) return null;
         return apps.get(index);
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java
index 0cf9fa8d2146bead1f03fce851c7e5c1d2aab6bf..85b7b0ea3d7f4166602527fe40355a15e5a4ab61 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java
@@ -31,6 +31,7 @@ import java.util.regex.Pattern;
 
 import ohi.andre.consolelauncher.managers.TerminalManager;
 import ohi.andre.consolelauncher.managers.TimeManager;
+import ohi.andre.consolelauncher.managers.notifications.reply.ReplyManager;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Notifications;
@@ -42,6 +43,8 @@ import ohi.andre.consolelauncher.tuils.Tuils;
 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
 public class NotificationService extends NotificationListenerService {
 
+    public static final String DESTROY = "destroy";
+
     private final int UPDATE_TIME = 2000;
     private final String LINES_LABEL = "Lines", ANDROID_LABEL_PREFIX = "android.", NULL_LABEL = "null";
 
@@ -50,7 +53,7 @@ public class NotificationService extends NotificationListenerService {
 
     String format;
     int timeColor, color, maxOptionalDepth;
-    boolean enabled, click, longClick;
+    boolean enabled, click, longClick, active;
 
     Queue<StatusBarNotification> queue;
 
@@ -58,188 +61,211 @@ public class NotificationService extends NotificationListenerService {
     final Pattern timePattern = Pattern.compile("^%t[0-9]*$");
 
     PackageManager manager;
+    ReplyManager replyManager;
+    NotificationManager notificationManager;
 
     private final Pattern formatPattern = Pattern.compile("%(?:\\[(\\d+)\\])?(?:\\[([^]]+)\\])?(?:(?:\\{)([a-zA-Z\\.\\:\\s]+)(?:\\})|([a-zA-Z\\.\\:]+))");
 
-    StoppableThread bgThread = new StoppableThread() {
-        @Override
-        public void run() {
-            super.run();
+    StoppableThread bgThread;
 
-            if(!enabled) return;
+    @Override
+    public void onCreate() {
+        super.onCreate();
 
-            while(true) {
-                if(queue != null) {
+        init();
+    }
 
-                    StatusBarNotification sbn;
-                    while ((sbn = queue.poll()) != null) {
+    private void init() {
+        try {
+            notificationManager = NotificationManager.create(this);
+            XMLPrefsManager.loadCommons(this);
+        } catch (Exception e) {
+            Tuils.log(e);
+            return;
+        }
 
-                        android.app.Notification notification = sbn.getNotification();
-                        if (notification == null) {
-                            continue;
-                        }
+        try {
+            replyManager = new ReplyManager(this);
+        } catch (VerifyError error) {
+            replyManager = null;
+        }
 
-                        String pack = sbn.getPackageName();
+        bgThread = new StoppableThread() {
+            @Override
+            public void run() {
+                super.run();
 
-                        String appName;
-                        try {
-                            appName = manager.getApplicationInfo(pack, 0).loadLabel(manager).toString();
-                        } catch (PackageManager.NameNotFoundException e) {
-                            appName = "null";
-                        }
+                if(!enabled) return;
 
-                        NotificationManager.NotificatedApp nApp = NotificationManager.getAppState(pack);
-                        if ((nApp != null && !nApp.enabled)) {
-                            continue;
-                        }
+                while(true) {
+                    if(isInterrupted()) return;
 
-                        if (nApp == null && !NotificationManager.default_app_state) {
-                            continue;
-                        }
+                    if(queue != null) {
 
-                        String f;
-                        if(nApp != null && nApp.format != null) f = nApp.format;
-                        else f = format;
+                        StatusBarNotification sbn;
+                        while ((sbn = queue.poll()) != null) {
 
-                        int textColor;
-                        if(nApp != null && nApp.color != null) textColor = Color.parseColor(nApp.color);
-                        else textColor = color;
+                            android.app.Notification notification = sbn.getNotification();
+                            if (notification == null) {
+                                continue;
+                            }
+
+                            String pack = sbn.getPackageName();
+
+                            String appName;
+                            try {
+                                appName = manager.getApplicationInfo(pack, 0).loadLabel(manager).toString();
+                            } catch (PackageManager.NameNotFoundException e) {
+                                appName = "null";
+                            }
+
+                            NotificationManager.NotificatedApp nApp = notificationManager.getAppState(pack);
+                            if ((nApp != null && !nApp.enabled)) {
+                                continue;
+                            }
+
+                            if (nApp == null && !notificationManager.default_app_state) {
+                                continue;
+                            }
+
+                            String f;
+                            if(nApp != null && nApp.format != null) f = nApp.format;
+                            else f = format;
 
-                        CharSequence s = Tuils.span(f, textColor);
+                            int textColor;
+                            if(nApp != null && nApp.color != null) textColor = Color.parseColor(nApp.color);
+                            else textColor = color;
 
-                        Bundle bundle = NotificationCompat.getExtras(notification);
+                            CharSequence s = Tuils.span(f, textColor);
 
-                        if(bundle != null) {
-                            Matcher m = formatPattern.matcher(s);
-                            String match;
-                            while(m.find()) {
-                                match = m.group(0);
-                                if (!match.startsWith(PKG) && !match.startsWith(APP) && !match.startsWith(NEWLINE) && !timePattern.matcher(match).matches()) {
-                                    String length = m.group(1);
-                                    String color = m.group(2);
-                                    String value = m.group(3);
+                            Bundle bundle = NotificationCompat.getExtras(notification);
 
-                                    if(value == null || value.length() == 0) value = m.group(4);
+                            if(bundle != null) {
+                                Matcher m = formatPattern.matcher(s);
+                                String match;
+                                while(m.find()) {
+                                    match = m.group(0);
+                                    if (!match.startsWith(PKG) && !match.startsWith(APP) && !match.startsWith(NEWLINE) && !timePattern.matcher(match).matches()) {
+                                        String length = m.group(1);
+                                        String color = m.group(2);
+                                        String value = m.group(3);
 
-                                    if(value != null) value = value.trim();
-                                    else continue;
+                                        if(value == null || value.length() == 0) value = m.group(4);
 
-                                    if(value.length() == 0) continue;
+                                        if(value != null) value = value.trim();
+                                        else continue;
 
-                                    if(value.equals("ttl")) value = "title";
-                                    else if(value.equals("txt")) value = "text";
+                                        if(value.length() == 0) continue;
 
-                                    String[] temp = value.split(":"), split;
-                                    if(value.endsWith(":")) {
-                                        split = new String[temp.length + 1];
-                                        System.arraycopy(temp, 0, split, 0, temp.length);
-                                        split[split.length - 1] = Tuils.EMPTYSTRING;
-                                    } else split = temp;
+                                        if(value.equals("ttl")) value = "title";
+                                        else if(value.equals("txt")) value = "text";
+
+                                        String[] temp = value.split(":"), split;
+//                                    this is an other way to do what I did in NotesManager for footer/header
+                                        if(value.endsWith(":")) {
+                                            split = new String[temp.length + 1];
+                                            System.arraycopy(temp, 0, split, 0, temp.length);
+                                            split[split.length - 1] = Tuils.EMPTYSTRING;
+                                        } else split = temp;
 
 //                                    because the last one is the default text, but only if there is more than one label
-                                    int stopAt = split.length;
-                                    if(stopAt > 1) stopAt--;
-
-                                    CharSequence text = null;
-                                    for(int j = 0; j < stopAt; j++) {
-                                        if(split[j].contains(LINES_LABEL)) {
-                                            CharSequence[] array = bundle.getCharSequenceArray(ANDROID_LABEL_PREFIX + split[j]);
-                                            if(array != null) {
-                                                for(CharSequence c : array) {
-                                                    if(text == null) text = c;
-                                                    else text = TextUtils.concat(text, Tuils.NEWLINE, c);
+                                        int stopAt = split.length;
+                                        if(stopAt > 1) stopAt--;
+
+                                        CharSequence text = null;
+                                        for(int j = 0; j < stopAt; j++) {
+                                            if(split[j].contains(LINES_LABEL)) {
+                                                CharSequence[] array = bundle.getCharSequenceArray(ANDROID_LABEL_PREFIX + split[j]);
+                                                if(array != null) {
+                                                    for(CharSequence c : array) {
+                                                        if(text == null) text = c;
+                                                        else text = TextUtils.concat(text, Tuils.NEWLINE, c);
+                                                    }
                                                 }
+                                            } else {
+                                                text = bundle.getCharSequence(ANDROID_LABEL_PREFIX + split[j]);
                                             }
-                                        } else {
-                                            text = bundle.getCharSequence(ANDROID_LABEL_PREFIX + split[j]);
+
+                                            if(text != null && text.length() > 0) break;
                                         }
 
-                                        if(text != null && text.length() > 0) break;
-                                    }
+                                        if(text == null || text.length() == 0) {
+                                            text = split.length == 1 ? NULL_LABEL : split[split.length - 1];
+                                        }
 
-                                    if(text == null || text.length() == 0) {
-                                        text = split.length == 1 ? NULL_LABEL : split[split.length - 1];
-                                    }
+                                        String stringed = text.toString().trim();
 
-                                    String stringed = text.toString().trim();
+                                        try {
+                                            int l = Integer.parseInt(length);
+                                            stringed = stringed.substring(0,l);
+                                        } catch (Exception e) {}
 
-                                    try {
-                                        int l = Integer.parseInt(length);
-                                        stringed = stringed.substring(0,l);
-                                    } catch (Exception e) {}
+                                        try {
+                                            text = Tuils.span(stringed, Color.parseColor(color));
+                                        } catch (Exception e) {
+                                            text = stringed;
+                                        }
 
-                                    try {
-                                        text = Tuils.span(stringed, Color.parseColor(color));
-                                    } catch (Exception e) {
-                                        text = stringed;
+                                        s = TextUtils.replace(s, new String[] {m.group(0)}, new CharSequence[] {text});
                                     }
-
-                                    s = TextUtils.replace(s, new String[] {m.group(0)}, new CharSequence[] {text});
                                 }
                             }
-                        }
 
-                        String text = s.toString();
+                            String text = s.toString();
 
-                        if(NotificationManager.match(pack, text)) continue;
+                            if(notificationManager.match(pack, text)) continue;
 
-                        int found = isInPastNotifications(pack, text);
+                            int found = isInPastNotifications(pack, text);
 //                        if(found == 0) {
 //                            Tuils.log("app " + pack, pastNotifications.get(pack).toString());
 //                        }
 
-                        if(found == 2) continue;
+                            if(found == 2) continue;
 
 //                        else
-                        Notification n = new Notification(System.currentTimeMillis(), text, pack, notification.contentIntent);
-
-                        if(found == 1) {
-                            List<Notification> ns = new ArrayList<>();
-                            ns.add(n);
-                            pastNotifications.put(pack, ns);
-                        } else if(found == 0) {
-                            pastNotifications.get(pack).add(n);
-                        }
+                            Notification n = new Notification(System.currentTimeMillis(), text, pack, notification.contentIntent);
+
+                            if(found == 1) {
+                                List<Notification> ns = new ArrayList<>();
+                                ns.add(n);
+                                pastNotifications.put(pack, ns);
+                            } else if(found == 0) {
+                                pastNotifications.get(pack).add(n);
+                            }
 
-                        s = TextUtils.replace(s, new String[]{PKG, APP, NEWLINE}, new CharSequence[]{pack, appName, Tuils.NEWLINE});
-                        String st = s.toString();
-                        while (st.contains(NEWLINE)) {
-                            s = TextUtils.replace(s,
-                                    new String[]{NEWLINE},
-                                    new CharSequence[]{Tuils.NEWLINE});
-                            st = s.toString();
-                        }
+                            s = TextUtils.replace(s, new String[]{PKG, APP, NEWLINE}, new CharSequence[]{pack, appName, Tuils.NEWLINE});
+                            String st = s.toString();
+                            while (st.contains(NEWLINE)) {
+                                s = TextUtils.replace(s,
+                                        new String[]{NEWLINE},
+                                        new CharSequence[]{Tuils.NEWLINE});
+                                st = s.toString();
+                            }
 
-                        try {
-                            s = TimeManager.replace(s, timeColor);
-                        } catch (Exception e) {
-                            Tuils.log(e);
-                        }
+                            try {
+                                s = TimeManager.instance.replace(s, timeColor);
+                            } catch (Exception e) {
+                                Tuils.log(e);
+                            }
 
-                        Tuils.sendOutput(NotificationService.this.getApplicationContext(), s, TerminalManager.CATEGORY_NOTIFICATION, click ? notification.contentIntent : null, longClick ? n : null);
+//                        Tuils.log("text", text);
+//                        Tuils.log("--------");
+
+                            Tuils.sendOutput(NotificationService.this.getApplicationContext(), s, TerminalManager.CATEGORY_NOTIFICATION, click ? notification.contentIntent : null, longClick ? n : null);
+
+                            if(replyManager != null) replyManager.onNotification(sbn, s);
+                        }
                     }
-                }
 
-                try {
-                    sleep(UPDATE_TIME);
-                } catch (InterruptedException e) {
-                    Tuils.log(e);
-                    return;
+                    try {
+                        sleep(UPDATE_TIME);
+                    } catch (InterruptedException e) {
+                        Tuils.log(e);
+                        return;
+                    }
                 }
             }
-        }
-    };
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-
-        try {
-            NotificationManager.create(this);
-            XMLPrefsManager.create(this);
-        } catch (Exception e) {
-            return;
-        }
+        };
 
         manager = getPackageManager();
         enabled = XMLPrefsManager.getBoolean(Notifications.show_notifications) || XMLPrefsManager.get(Notifications.show_notifications).equalsIgnoreCase("enabled");
@@ -274,28 +300,63 @@ public class NotificationService extends NotificationListenerService {
 
         queue = new ArrayBlockingQueue<>(5);
         bgThread.start();
+
+        active = true;
     }
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         if(intent != null) {
-            timeColor = intent.getIntExtra(Theme.time_color.label(), Color.parseColor(Theme.time_color.defaultValue()));
+            boolean destroy = intent.getBooleanExtra(DESTROY, false);
+            if(destroy) dispose();
+            else timeColor = intent.getIntExtra(Theme.time_color.label(), Color.parseColor(Theme.time_color.defaultValue()));
         } else {
             timeColor = Color.parseColor(Theme.time_color.defaultValue());
         }
 
+        if(!active) init();
+
         return START_STICKY;
     }
 
+    private void dispose() {
+        if(replyManager != null) {
+            replyManager.dispose(this);
+            replyManager = null;
+        }
+
+        if(notificationManager != null) {
+            notificationManager.dispose();
+            notificationManager = null;
+        }
+
+        bgThread.interrupt();
+        bgThread = null;
+
+        if(pastNotifications != null) {
+            pastNotifications.clear();
+            pastNotifications = null;
+        }
+
+        if(queue != null) {
+            queue.clear();
+            queue = null;
+        }
+
+        active = false;
+    }
+
     @Override
     public void onDestroy() {
         super.onDestroy();
-        if(handler != null) handler.removeCallbacksAndMessages(null);
+
+//        ondestroy won't ever be called
     }
 
     @Override
     public void onNotificationPosted(StatusBarNotification sbn) {
         if(!enabled) return;
+
         queue.offer(sbn);
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/BoundApp.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/BoundApp.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ad4dc3ebbf090b1bb6ea63328e23772454e7b20
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/BoundApp.java
@@ -0,0 +1,29 @@
+package ohi.andre.consolelauncher.managers.notifications.reply;
+
+import ohi.andre.consolelauncher.tuils.Compare;
+
+/**
+ * Created by francescoandreuzzi on 24/01/2018.
+ */
+
+public class BoundApp implements Compare.Stringable {
+
+    public int applicationId;
+    public String label, packageName;
+
+    public BoundApp(int applicationId, String packageName, String label) {
+        this.applicationId = applicationId;
+        this.packageName = packageName;
+        this.label = label;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return obj != null && obj instanceof BoundApp && applicationId == ((BoundApp) obj).applicationId;
+    }
+
+    @Override
+    public String getString() {
+        return label;
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/NotificationWear.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/NotificationWear.java
new file mode 100644
index 0000000000000000000000000000000000000000..80b57c99a8a89662cbfce054386ea1422e012d21
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/NotificationWear.java
@@ -0,0 +1,31 @@
+package ohi.andre.consolelauncher.managers.notifications.reply;
+
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.os.Bundle;
+
+/**
+ * Created by francescoandreuzzi on 24/01/2018.
+ */
+
+public class NotificationWear {
+
+    public BoundApp app;
+
+    public PendingIntent pendingIntent;
+    public RemoteInput[] remoteInputs;
+    public Bundle bundle;
+    public int id;
+
+    public CharSequence text;
+
+    @Override
+    public boolean equals(Object obj) {
+        try {
+            NotificationWear h = (NotificationWear) obj;
+            return h.app.packageName.equals(app.packageName);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/ReplyManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/ReplyManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f8d1ca7c67e5371496b838719cc61ca2a32a92f
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/reply/ReplyManager.java
@@ -0,0 +1,429 @@
+package ohi.andre.consolelauncher.managers.notifications.reply;
+
+import android.annotation.TargetApi;
+import android.app.Notification;
+import android.app.RemoteInput;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.service.notification.StatusBarNotification;
+import android.support.v4.content.LocalBroadcastManager;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import ohi.andre.consolelauncher.BuildConfig;
+import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsList;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
+import ohi.andre.consolelauncher.managers.xml.options.Reply;
+import ohi.andre.consolelauncher.tuils.PrivateIOReceiver;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.VALUE_ATTRIBUTE;
+import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.set;
+import static ohi.andre.consolelauncher.managers.xml.XMLPrefsManager.writeTo;
+
+/**
+ * Created by francescoandreuzzi on 17/01/2018.
+ */
+
+public class ReplyManager implements XMLPrefsElement {
+
+    public static final String PATH = "reply.xml", NAME = "REPLY", ACTION = BuildConfig.APPLICATION_ID + ".reply", ID = "id", WHAT = "what", ACTION_UPDATE = BuildConfig.APPLICATION_ID + ".update", ACTION_LS = BuildConfig.APPLICATION_ID + ".lsreplies";
+    private static final String ID_ATTRIBUTE = "id";
+
+    private Set<NotificationWear> notificationWears;
+    public static List<BoundApp> boundApps;
+
+    private BroadcastReceiver receiver;
+
+    public static ReplyManager instance;
+    private XMLPrefsList values;
+
+    private boolean enabled;
+
+    private Context context;
+
+    public static int nextUsableId;
+
+    public ReplyManager(Context context) {
+        enabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH;
+        if(!enabled) return;
+
+        notificationWears = new HashSet<>();
+        values = new XMLPrefsList();
+        this.context = context;
+
+        instance = this;
+
+        load(true);
+
+        enabled = Boolean.parseBoolean(values.get(Reply.reply_enabled).value);
+        if(!enabled) {
+            notificationWears = null;
+            boundApps = null;
+        } else {
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(ACTION);
+            filter.addAction(ACTION_UPDATE);
+            filter.addAction(ACTION_LS);
+
+            receiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if(intent.getAction().equals(ACTION)) {
+                        String app = intent.getStringExtra(ID);
+                        String what = intent.getStringExtra(WHAT);
+
+                        int id;
+                        try {
+                            id = Integer.parseInt(app);
+                        } catch (Exception e) {
+                            BoundApp bapp = findApp(app);
+                            if(bapp == null) {
+                                Tuils.sendOutput(context, context.getString(R.string.reply_app_not_found) + Tuils.SPACE + app);
+                                return;
+                            }
+
+                            id = bapp.applicationId;
+                        }
+
+                        if(what == null) {
+                            check(id);
+                        } else {
+                            if(id == -1) return;
+                            replyTo(ReplyManager.this.context, id, what);
+                        }
+                    } else if(intent.getAction().equals(ACTION_UPDATE)) {
+                        load(false);
+                    } else if(intent.getAction().equals(ACTION_LS)) {
+                        ls(context);
+                    }
+                }
+            };
+
+            LocalBroadcastManager.getInstance(context.getApplicationContext()).registerReceiver(receiver, filter);
+        }
+    }
+
+    private void load(boolean loadPrefs) {
+        if(boundApps != null) boundApps.clear();
+        else boundApps = new ArrayList<>();
+
+        List<Reply> enums = new ArrayList<>(Arrays.asList(Reply.values()));
+
+        File file = new File(Tuils.getFolder(), PATH);
+
+        Object[] o;
+        try {
+            o = XMLPrefsManager.buildDocument(file, NAME);
+            if(o == null) {
+                Tuils.sendXMLParseError(context, PATH);
+                return;
+            }
+        } catch (SAXParseException e) {
+            Tuils.sendXMLParseError(context, PATH, e);
+            return;
+        } catch (Exception e) {
+            Tuils.log(e);
+            return;
+        }
+
+        Document d = (Document) o[0];
+        Element root = (Element) o[1];
+
+        NodeList nodes = root.getElementsByTagName("*");
+
+        PackageManager mgr = context.getPackageManager();
+
+        try {
+            for (int count = 0; count < nodes.getLength(); count++) {
+                final Node node = nodes.item(count);
+                String nn = node.getNodeName();
+
+                if (Tuils.find(nn, enums) != -1) {
+                    if(loadPrefs) {
+                        values.add(nn, node.getAttributes().getNamedItem(VALUE_ATTRIBUTE).getNodeValue());
+
+                        for (int en = 0; en < enums.size(); en++) {
+                            if (enums.get(en).label().equals(nn)) {
+                                enums.remove(en);
+                                break;
+                            }
+                        }
+                    }
+                } else {
+                    int id = XMLPrefsManager.getIntAttribute((Element) node, ID_ATTRIBUTE);
+
+                    ApplicationInfo info;
+                    try {
+                        info = mgr.getApplicationInfo(nn, 0);
+                    } catch (Exception e) {
+                        Tuils.log(e);
+                        continue;
+                    }
+
+                    String label = info.loadLabel(mgr).toString();
+                    if (id != -1) boundApps.add(new BoundApp(id, nn, label));
+                }
+            }
+
+            if (loadPrefs && enums.size() > 0) {
+                for (XMLPrefsSave s : enums) {
+                    String value = s.defaultValue();
+
+                    Element em = d.createElement(s.label());
+                    em.setAttribute(VALUE_ATTRIBUTE, value);
+                    root.appendChild(em);
+
+                    values.add(s.label(), value);
+                }
+
+                writeTo(d, file);
+            }
+        } catch (Exception e) {
+            Tuils.log(e);
+        }
+
+        nextUsableId = nextUsableId();
+    }
+
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
+    public void onNotification(StatusBarNotification notification, CharSequence text) {
+        if(!enabled) return;
+
+        BoundApp app = findApp(notification.getPackageName());
+        if(app == null) return;
+
+        NotificationWear w = extractWearNotification(notification);
+        if(w == null) return;
+
+        NotificationWear old = findNotificationWear(app);
+
+        if(old != null && (w.pendingIntent == null || w.remoteInputs == null || w.remoteInputs.length == 0)) return;
+        if(old != null) notificationWears.remove(old);
+
+        w.text = text;
+        w.app = app;
+
+        notificationWears.add(w);
+    }
+
+    private void replyTo(Context context, int applicationId, String what) {
+        if(!enabled) return;
+
+        BoundApp app = findApp(applicationId);
+        if(app == null) {
+            Tuils.sendOutput(context, context.getString(R.string.reply_id_not_found) + Tuils.SPACE + applicationId);
+            return;
+        }
+
+        NotificationWear wear = findNotificationWear(applicationId);
+        if(wear != null) replyTo(context, wear, what);
+        else Tuils.sendOutput(context, R.string.reply_notification_not_found);
+    }
+
+    @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
+    private void replyTo(Context context, NotificationWear notificationWear, String what) {
+        RemoteInput[] remoteInputs = notificationWear.remoteInputs;
+
+        Bundle localBundle = notificationWear.bundle;
+
+        Intent i = new Intent(PrivateIOReceiver.ACTION_REPLY);
+        i.putExtra(PrivateIOReceiver.BUNDLE, localBundle);
+        i.putExtra(PrivateIOReceiver.REMOTE_INPUTS, remoteInputs);
+        i.putExtra(PrivateIOReceiver.TEXT, what);
+        i.putExtra(PrivateIOReceiver.PENDING_INTENT, notificationWear.pendingIntent);
+        i.putExtra(PrivateIOReceiver.ID, notificationWear.id);
+        i.putExtra(PrivateIOReceiver.CURRENT_ID, PrivateIOReceiver.currentId);
+
+        LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(i);
+    }
+
+    @TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
+    private NotificationWear extractWearNotification(StatusBarNotification statusBarNotification) {
+        NotificationWear notificationWear = new NotificationWear();
+
+        Notification.WearableExtender wearableExtender = new Notification.WearableExtender(statusBarNotification.getNotification());
+        for(Notification.Action action : wearableExtender.getActions()) {
+            RemoteInput[] rs = action.getRemoteInputs();
+            if(rs != null && rs.length > 0) {
+                notificationWear.remoteInputs = rs;
+//                Actually I assume that there's only one action
+                notificationWear.pendingIntent = action.actionIntent;
+                break;
+            }
+        }
+
+        notificationWear.bundle = statusBarNotification.getNotification().extras;
+        notificationWear.id = statusBarNotification.getId();
+
+        return notificationWear;
+    }
+
+    private BoundApp findApp(int applicationId) {
+        if(boundApps != null) {
+            for(BoundApp a : boundApps) {
+                if(a.applicationId == applicationId) return a;
+            }
+        }
+
+        return null;
+    }
+
+    private BoundApp findApp(String pkg) {
+        if(boundApps != null) {
+            for(BoundApp a : boundApps) {
+                if(a.packageName.equals(pkg)) return a;
+            }
+        }
+
+        return null;
+    }
+
+    private NotificationWear findNotificationWear(BoundApp bapp) {
+        for(NotificationWear h : notificationWears) {
+            if(h.app != null && h.app.packageName.equals(bapp.packageName)) return h;
+        }
+        return null;
+    }
+
+    private NotificationWear findNotificationWear(int id) {
+        for(NotificationWear h : notificationWears) {
+            if(h.app != null && h.app.applicationId == id) return h;
+        }
+        return null;
+    }
+
+    public void dispose(Context context) {
+        try {
+            LocalBroadcastManager.getInstance(context.getApplicationContext()).unregisterReceiver(receiver);
+        } catch (Exception e) {}
+
+        if(notificationWears != null) {
+            notificationWears.clear();
+            notificationWears = null;
+        }
+        if(boundApps != null) {
+            boundApps.clear();
+            boundApps = null;
+        }
+        if(values != null) {
+            values.list.clear();
+            values = null;
+        }
+
+        instance = null;
+    }
+
+    @Override
+    public XMLPrefsList getValues() {
+        return values;
+    }
+
+    @Override
+    public void write(XMLPrefsSave save, String value) {
+        set(new File(Tuils.getFolder(), PATH), save.label(), new String[] {VALUE_ATTRIBUTE}, new String[] {value});
+    }
+
+    @Override
+    public String[] deleted() {
+        return new String[0];
+    }
+
+    public void check(int id) {
+        if(!enabled) return;
+
+        BoundApp app = findApp(id);
+        if(app == null) {
+            Tuils.sendOutput(context, context.getString(R.string.reply_id_not_found) + Tuils.SPACE + id);
+            return;
+        }
+
+        NotificationWear wear = findNotificationWear(app);
+        if(wear == null) {
+            Tuils.sendOutput(context, R.string.reply_notification_not_found);
+            return;
+        }
+
+        Tuils.sendOutput(context, wear.text);
+    }
+
+    public static String bind(String pkg) {
+        return XMLPrefsManager.set(new File(Tuils.getFolder(), PATH), pkg, new String[] {ID_ATTRIBUTE}, new String[] {String.valueOf(nextUsableId)});
+    }
+
+    public static String unbind(String pkg) {
+        return XMLPrefsManager.removeNode(new File(Tuils.getFolder(), PATH), pkg);
+    }
+
+    private int nextUsableId() {
+        int nextUsableID = 0;
+        while (true) {
+            boolean shouldRestart = false;
+
+            for(BoundApp b : boundApps) {
+                if(b.applicationId == nextUsableID) {
+                    shouldRestart = true;
+                    break;
+                }
+            }
+
+            if(!shouldRestart) return nextUsableID;
+
+            nextUsableID++;
+        }
+    }
+
+    public void ls(Context c) {
+        if(!enabled) return;
+
+        StringBuilder builder = new StringBuilder();
+        if(instance != null) {
+            for(BoundApp a : boundApps) builder.append(a.packageName).append(" -> ").append(a.applicationId).append(Tuils.NEWLINE);
+        }
+        String s = builder.toString();
+        if(s.length() == 0) s = "[]";
+
+        Tuils.sendOutput(context, s);
+    }
+
+//    private static class NotificationHolder {
+//        BindedApp app;
+//
+//        List<RemoteInput> remoteInputs;
+//        Bundle bundle;
+//        PendingIntent pendingIntent;
+//
+//        public NotificationHolder(BindedApp app, List<RemoteInput> remoteInputs, Bundle bundle, PendingIntent pendingIntent) {
+//            this.app = app;
+//            this.remoteInputs = remoteInputs;
+//            this.bundle = bundle;
+//            this.pendingIntent = pendingIntent;
+//        }
+//
+//        @Override
+//        public boolean equals(Object obj) {
+//            NotificationHolder h = (NotificationHolder) obj;
+//            return h.app.equals(app);
+//        }
+//    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/RemoverRunnable.java b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/RemoverRunnable.java
new file mode 100644
index 0000000000000000000000000000000000000000..b24bb0e37653e5b770c22f92cf7861a08a87a7f5
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/RemoverRunnable.java
@@ -0,0 +1,33 @@
+package ohi.andre.consolelauncher.managers.suggestions;
+
+import android.widget.LinearLayout;
+
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+/**
+ * Created by francescoandreuzzi on 11/03/2018.
+ */
+
+public class RemoverRunnable implements Runnable {
+
+    public boolean stop = false, isGoingToRun = false;
+
+    public LinearLayout suggestionsView;
+
+    public RemoverRunnable(LinearLayout suggestionsView) {
+        this.suggestionsView = suggestionsView;
+    }
+
+    @Override
+    public void run() {
+        Tuils.log("run");
+
+        if(stop) {
+            stop = false;
+        } else suggestionsView.removeAllViews();
+
+        isGoingToRun = false;
+
+        Tuils.log("now childs", suggestionsView.getChildCount());
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionRunnable.java b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionRunnable.java
index a57965d414dba5b43d3d570fd37e96e0e01fc7bf..7e8f50b64fe47771830ece298243cd98a66e1555 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionRunnable.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionRunnable.java
@@ -24,7 +24,10 @@ import android.widget.HorizontalScrollView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import java.util.List;
+
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.managers.AppsManager;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Suggestions;
@@ -46,14 +49,17 @@ public class SuggestionRunnable implements Runnable {
     private TextView[] toRecycle;
     private TextView[] toAdd;
 
-    private SuggestionsManager.Suggestion[] suggestions;
+    private List<SuggestionsManager.Suggestion> suggestions;
 
     private boolean interrupted;
 
-    public SuggestionRunnable(ViewGroup suggestionsView, LinearLayout.LayoutParams suggestionViewParams, HorizontalScrollView parent) {
+    MainPack pack;
+
+    public SuggestionRunnable(MainPack pack, ViewGroup suggestionsView, LinearLayout.LayoutParams suggestionViewParams, HorizontalScrollView parent) {
         this.suggestionsView = suggestionsView;
         this.suggestionViewParams = suggestionViewParams;
         this.scrollView = parent;
+        this.pack = pack;
 
         reset();
     }
@@ -70,7 +76,7 @@ public class SuggestionRunnable implements Runnable {
         this.toAdd = toAdd;
     }
 
-    public void setSuggestions(SuggestionsManager.Suggestion[] suggestions) {
+    public void setSuggestions(List<SuggestionsManager.Suggestion> suggestions) {
         this.suggestions = suggestions;
     }
 
@@ -82,31 +88,47 @@ public class SuggestionRunnable implements Runnable {
             }
         }
 
-        if (interrupted) {
-            return;
-        }
+        int length = suggestions.size();
 
-        for (int count = 0; count < suggestions.length; count++) {
+        for (int count = 0; count < suggestions.size(); count++) {
             if (interrupted) {
                 return;
             }
 
-            String s = suggestions[count].text;
-            if (toRecycle != null && count < toRecycle.length) {
-                toRecycle[count].setTag(R.id.suggestion_id, suggestions[count]);
+            SuggestionsManager.Suggestion s = suggestions.get(count);
+
+            String text = s.shownText != null ? s.shownText : s.text;
+
+            TextView sggView = null;
+            if (count < toRecycle.length) {
+                sggView = toRecycle[count];
+            }
+            else {
+                int space = length - (count + 1);
+                if(space < toAdd.length) {
+                    sggView = toAdd[space];
+
+                    if(toAdd[space].getParent() == null) {
+                        suggestionsView.addView(toAdd[space], suggestionViewParams);
+                    }
+                }
+            }
+
+            if (sggView != null) {
+                sggView.setTag(R.id.suggestion_id, s);
 
-                toRecycle[count].setText(s);
+                sggView.setText(text);
 
 //                bg and fore
                 int bgColor = Integer.MAX_VALUE;
                 int foreColor = Integer.MAX_VALUE;
-                if(suggestions[count].type == SuggestionsManager.Suggestion.TYPE_APP) {
 
-                    Object o = suggestions[count].object;
+                if(s.type == SuggestionsManager.Suggestion.TYPE_APP || s.type == SuggestionsManager.Suggestion.TYPE_APPGP) {
+                    Object o = s.object;
                     if(o != null && o instanceof AppsManager.LaunchInfo) {
                         AppsManager.LaunchInfo i = (AppsManager.LaunchInfo) o;
 
-                        for(AppsManager.Group g : AppsManager.groups) {
+                        for(AppsManager.Group g : pack.appsManager.groups) {
                             if(g.contains(i)) {
                                 o = g;
                                 break;
@@ -120,71 +142,19 @@ public class SuggestionRunnable implements Runnable {
                     }
                 }
 
-                if(bgColor != Integer.MAX_VALUE) toRecycle[count].setBackgroundColor(bgColor);
-                else toRecycle[count].setBackgroundDrawable(getSuggestionBg(suggestions[count].type));
-                if(foreColor != Integer.MAX_VALUE) toRecycle[count].setTextColor(foreColor);
-                else toRecycle[count].setTextColor(getSuggestionTextColor(suggestions[count].type));
+                if(bgColor != Integer.MAX_VALUE) sggView.setBackgroundColor(bgColor);
+                else sggView.setBackgroundDrawable(getSuggestionBg(s.type));
+                if(foreColor != Integer.MAX_VALUE) sggView.setTextColor(foreColor);
+                else sggView.setTextColor(getSuggestionTextColor(s.type));
 //                end bg and fore
 
-                if(suggestions[count].type == SuggestionsManager.Suggestion.TYPE_CONTACT) {
-                    toRecycle[count].setLongClickable(true);
-                    ((Activity) toRecycle[count].getContext()).registerForContextMenu(toRecycle[count]);
+                if(s.type == SuggestionsManager.Suggestion.TYPE_CONTACT) {
+                    sggView.setLongClickable(true);
+                    ((Activity) sggView.getContext()).registerForContextMenu(sggView);
                 } else {
-                    ((Activity) toRecycle[count].getContext()).unregisterForContextMenu(toRecycle[count]);
+                    ((Activity) sggView.getContext()).unregisterForContextMenu(sggView);
                 }
 
-            } else {
-                int space = suggestions.length - (count + 1);
-                if (toAdd != null && space < toAdd.length) {
-                    toAdd[space].setTag(R.id.suggestion_id, suggestions[count]);
-
-                    toAdd[space].setText(s);
-
-//                    bg and fore
-                    int bgColor = Integer.MAX_VALUE;
-                    int foreColor = Integer.MAX_VALUE;
-                    if(suggestions[count].type == SuggestionsManager.Suggestion.TYPE_APP) {
-
-                        Object o = suggestions[count].object;
-                        if(o != null && o instanceof AppsManager.LaunchInfo) {
-                            AppsManager.LaunchInfo i = (AppsManager.LaunchInfo) o;
-
-                            for(AppsManager.Group g : AppsManager.groups) {
-                                if(g.contains(i)) {
-                                    o = g;
-                                    break;
-                                }
-                            }
-                        }
-
-                        if(o != null && o instanceof AppsManager.Group) {
-                            bgColor = ((AppsManager.Group) o).getBgColor();
-                            foreColor = ((AppsManager.Group) o).getForeColor();
-                        }
-                    }
-
-                    if(bgColor != Integer.MAX_VALUE) toAdd[space].setBackgroundColor(bgColor);
-                    else toAdd[space].setBackgroundDrawable(getSuggestionBg(suggestions[count].type));
-                    if(foreColor != Integer.MAX_VALUE) toAdd[space].setTextColor(foreColor);
-                    else {
-                        toAdd[space].setTextColor(getSuggestionTextColor(suggestions[count].type));
-                    }
-//                    end bg and fore
-
-                    if(toAdd[space].getParent() == null) {
-                        suggestionsView.addView(toAdd[space], suggestionViewParams);
-                    }
-
-                    if(suggestions[count].type == SuggestionsManager.Suggestion.TYPE_CONTACT) {
-                        toAdd[space].setLongClickable(true);
-                        ((Activity) toAdd[space].getContext()).registerForContextMenu(toAdd[space]);
-                    } else {
-                        ((Activity) toAdd[space].getContext()).unregisterForContextMenu(toAdd[space]);
-                    }
-                } else {
-//                    throw new UnsupportedOperationException("no views enough");
-                    break;
-                }
             }
         }
 
@@ -223,7 +193,7 @@ public class SuggestionRunnable implements Runnable {
             return new ColorDrawable(Color.TRANSPARENT);
         } else {
             switch (type) {
-                case SuggestionsManager.Suggestion.TYPE_APP:
+                case SuggestionsManager.Suggestion.TYPE_APP: case SuggestionsManager.Suggestion.TYPE_APPGP:
                     return new ColorDrawable(suggAppBg);
                 case SuggestionsManager.Suggestion.TYPE_ALIAS:
                     return new ColorDrawable(suggAliasBg);
@@ -231,7 +201,7 @@ public class SuggestionRunnable implements Runnable {
                     return new ColorDrawable(suggCmdBg);
                 case SuggestionsManager.Suggestion.TYPE_CONTACT:
                     return new ColorDrawable(suggContactBg);
-                case SuggestionsManager.Suggestion.TYPE_FILE:
+                case SuggestionsManager.Suggestion.TYPE_FILE: case SuggestionsManager.Suggestion.TYPE_CONFIGFILE:
                     return new ColorDrawable(suggFileBg);
                 case SuggestionsManager.Suggestion.TYPE_SONG:
                     return new ColorDrawable(suggSongBg);
@@ -257,7 +227,7 @@ public class SuggestionRunnable implements Runnable {
         int chosen;
 
         switch (type) {
-            case SuggestionsManager.Suggestion.TYPE_APP:
+            case SuggestionsManager.Suggestion.TYPE_APP: case SuggestionsManager.Suggestion.TYPE_APPGP:
                 chosen = suggAppText;
                 break;
             case SuggestionsManager.Suggestion.TYPE_ALIAS:
@@ -269,7 +239,7 @@ public class SuggestionRunnable implements Runnable {
             case SuggestionsManager.Suggestion.TYPE_CONTACT:
                 chosen = suggContactText;
                 break;
-            case SuggestionsManager.Suggestion.TYPE_FILE:
+            case SuggestionsManager.Suggestion.TYPE_FILE: case SuggestionsManager.Suggestion.TYPE_CONFIGFILE:
                 chosen = suggFileText;
                 break;
             case SuggestionsManager.Suggestion.TYPE_SONG:
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionTextWatcher.java b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionTextWatcher.java
new file mode 100644
index 0000000000000000000000000000000000000000..a59ad5c3d0682e529d1d3ee21e283505461054a3
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionTextWatcher.java
@@ -0,0 +1,29 @@
+package ohi.andre.consolelauncher.managers.suggestions;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+
+/**
+ * Created by francescoandreuzzi on 06/03/2018.
+ */
+
+public class SuggestionTextWatcher implements TextWatcher {
+
+    SuggestionsManager suggestionsManager;
+
+    public SuggestionTextWatcher(SuggestionsManager suggestionsManager) {
+        this.suggestionsManager = suggestionsManager;
+    }
+
+    @Override
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+    }
+
+    @Override
+    public void onTextChanged(CharSequence s, int st, int b, int c) {
+        suggestionsManager.requestSuggestion(s.toString());
+    }
+
+    @Override
+    public void afterTextChanged(Editable s) {}
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java
index 38b2450aea43b71ea971147c0e84acb3ba042915..d2a6fb82c644dd87caf11b0eb6ea4af230a80225 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java
@@ -1,11 +1,26 @@
 package ohi.andre.consolelauncher.managers.suggestions;
 
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Handler;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
+import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.Command;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.CommandTuils;
@@ -18,16 +33,24 @@ import ohi.andre.consolelauncher.managers.AppsManager;
 import ohi.andre.consolelauncher.managers.ContactManager;
 import ohi.andre.consolelauncher.managers.FileManager;
 import ohi.andre.consolelauncher.managers.RssManager;
+import ohi.andre.consolelauncher.managers.TerminalManager;
 import ohi.andre.consolelauncher.managers.music.Song;
 import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
+import ohi.andre.consolelauncher.managers.notifications.reply.BoundApp;
+import ohi.andre.consolelauncher.managers.notifications.reply.ReplyManager;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Apps;
+import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Notifications;
+import ohi.andre.consolelauncher.managers.xml.options.Reply;
 import ohi.andre.consolelauncher.managers.xml.options.Rss;
 import ohi.andre.consolelauncher.managers.xml.options.Suggestions;
 import ohi.andre.consolelauncher.tuils.Compare;
 import ohi.andre.consolelauncher.tuils.SimpleMutableEntry;
+import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
+import ohi.andre.consolelauncher.tuils.interfaces.SuggestionViewDecorer;
 
 import static ohi.andre.consolelauncher.commands.CommandTuils.xmlPrefsEntrys;
 import static ohi.andre.consolelauncher.commands.CommandTuils.xmlPrefsFiles;
@@ -37,24 +60,397 @@ import static ohi.andre.consolelauncher.commands.CommandTuils.xmlPrefsFiles;
  */
 public class SuggestionsManager {
 
-    private final int MIN_COMMAND_PRIORITY = 5;
+    public static final String SINGLE_QUOTE = "'", DOUBLE_QUOTES = "\"";
+    private final int MAX_RATE = 100, NO_RATE = -1, FIRST_INTERVAL = 6;
+
+    private boolean showAliasDefault, set = false, clickToLaunch, showAppsGpDefault, enabled;
+    private int minCmdPriority;
+
+    private String multipleCmdSeparator;
+
+    private boolean doubleSpaceFirstSuggestion;
+    private LinearLayout suggestionsView;
+    private SuggestionViewDecorer suggestionViewDecorer;
+    private SuggestionRunnable suggestionRunnable;
+    private LinearLayout.LayoutParams suggestionViewParams;
+    private SuggestionsManager.Suggestion lastFirst;
+
+    private TerminalManager mTerminalAdapter;
+
+    private View.OnClickListener clickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            SuggestionsManager.Suggestion suggestion = (SuggestionsManager.Suggestion) v.getTag(R.id.suggestion_id);
+            clickSuggestion(suggestion);
+        }
+    };
+
+    private MainPack pack;
+    private StoppableThread lastSuggestionThread;
+    private Handler handler = new Handler();
+
+    private RemoverRunnable removeAllSuggestions;
+
+    int[] indexes, counts;
+    Comparator<Suggestion> comparator = new Comparator<Suggestion>() {
+        @Override
+        public int compare(Suggestion o1, Suggestion o2) {
+            if(o1.type >= indexes.length || o2.type >= indexes.length) {
+                if(o1.type == o2.type) {
+                    return o2.rate - o1.rate;
+                } else return 0;
+            }
+
+            int i = indexes[o1.type] - indexes[o2.type];
+
+            if(i == 0) return o2.rate - o1.rate;
+            return i;
+        }
+    };
+
+    int[] noInputIndexes, noInputCounts;
+    Comparator<Suggestion> noInputComparator = new Comparator<Suggestion>() {
+        @Override
+        public int compare(Suggestion o1, Suggestion o2) {
+            if(o1.type >= indexes.length || o2.type >= indexes.length) {
+                if(o1.type == o2.type) {
+                    return o2.rate - o1.rate;
+                } else return 0;
+            }
+
+            int i = noInputIndexes[o1.type] - noInputIndexes[o2.type];
+
+            if(i == 0) return o2.rate - o1.rate;
+            return i;
+        }
+    };
+
+    Comparator<SimpleMutableEntry<Compare.Stringable, Integer>> stringableComparator = new Comparator<SimpleMutableEntry<Compare.Stringable, Integer>>() {
+        @Override
+        public int compare(SimpleMutableEntry<Compare.Stringable, Integer> o1, SimpleMutableEntry<Compare.Stringable, Integer> o2) {
+            return o2.getValue() - o1.getValue();
+        }
+    };
+
+    public SuggestionsManager(LinearLayout suggestionsView, MainPack mainPack, TerminalManager mTerminalAdapter) {
+        this.suggestionsView = suggestionsView;
+        this.pack = mainPack;
+        this.mTerminalAdapter = mTerminalAdapter;
+
+        this.removeAllSuggestions = new RemoverRunnable(suggestionsView);
+
+        doubleSpaceFirstSuggestion = XMLPrefsManager.getBoolean(Suggestions.double_space_click_first_suggestion);
+        SuggestionsManager.Suggestion.appendQuotesBeforeFile = XMLPrefsManager.getBoolean(Behavior.append_quote_before_file);
+        multipleCmdSeparator = XMLPrefsManager.get(Behavior.multiple_cmd_separator);
+
+        enabled = true;
+
+        suggestionViewDecorer = new SuggestionViewDecorer() {
+
+            final int PADDING = 15;
+
+            @Override
+            public TextView getSuggestionView(Context context) {
+                TextView textView = new TextView(context);
+                textView.setOnClickListener(clickListener);
+
+                textView.setFocusable(false);
+                textView.setLongClickable(false);
+                textView.setClickable(true);
+
+                textView.setTypeface(Tuils.getTypeface(context));
+                textView.setTextSize(XMLPrefsManager.getInt(Suggestions.suggestions_size));
+
+                textView.setPadding(PADDING, PADDING, PADDING, PADDING);
+
+                textView.setLines(1);
+                textView.setMaxLines(1);
+
+                return textView;
+            }
+        };
+
+        showAliasDefault = XMLPrefsManager.getBoolean(Suggestions.suggest_alias_default);
+        showAppsGpDefault = XMLPrefsManager.getBoolean(Suggestions.suggest_appgp_default);
+        set = true;
+        clickToLaunch = XMLPrefsManager.getBoolean(Suggestions.click_to_launch);
+
+        minCmdPriority = XMLPrefsManager.getInt(Suggestions.noinput_min_command_priority);
+
+        String s = XMLPrefsManager.get(Suggestions.suggestions_order);
+        Pattern orderPattern = Pattern.compile("(\\d+)\\((\\d+)\\)");
+        Matcher m = orderPattern.matcher(s);
+
+        indexes = new int[4];
+        counts = new int[4];
+
+        int index = 0;
+        while(m.find() && index < indexes.length) {
+            int type = Integer.parseInt(m.group(1));
+
+            if(type >= indexes.length) {
+                Tuils.sendOutput(Color.RED, pack.context, "Invalid suggestion type: " + type);
+
+                indexes = null;
+                counts = null;
+                comparator = null;
+
+                break;
+            }
+
+            int count = Integer.parseInt(m.group(2));
+
+            indexes[type] = index;
+            counts[type] = count;
+
+            index++;
+        }
+
+        s = XMLPrefsManager.get(Suggestions.noinput_suggestions_order);
+        orderPattern = Pattern.compile("(\\d+)\\((\\d+)\\)");
+        m = orderPattern.matcher(s);
+
+        noInputIndexes = new int[4];
+        noInputCounts = new int[4];
+
+        index = 0;
+        while(m.find() && index < noInputIndexes.length) {
+            int type = Integer.parseInt(m.group(1));
+
+            if(type >= noInputIndexes.length) {
+                Tuils.sendOutput(Color.RED, pack.context, "Invalid suggestion type: " + type);
+
+                noInputIndexes = null;
+                noInputCounts = null;
+                noInputComparator = null;
+
+                break;
+            }
+
+            int count = Integer.parseInt(m.group(2));
+
+            noInputIndexes[type] = index;
+            noInputCounts[type] = count;
+
+            index++;
+        }
+    }
+
+    private void stop() {
+        handler.removeCallbacksAndMessages(null);
+        if(lastSuggestionThread != null) lastSuggestionThread.interrupt();
+    }
+
+    public void dispose() {
+        stop();
+    }
+
+    public void clear() {
+        stop();
+        suggestionsView.removeAllViews();
+    }
+
+    public void hide() {
+        enabled = false;
+        suggestionsView.setVisibility(View.GONE);
+
+        stop();
+    }
+
+    public void show() {
+        enabled = true;
+        suggestionsView.setVisibility(View.VISIBLE);
+    }
+
+    public void clickSuggestion(SuggestionsManager.Suggestion suggestion) {
+        boolean execOnClick = suggestion.exec;
+
+        String text = suggestion.getText();
+        String input = mTerminalAdapter.getInput();
+
+        if(suggestion.type == SuggestionsManager.Suggestion.TYPE_PERMANENT) {
+            mTerminalAdapter.setInput(input + text);
+        } else {
+            boolean addSpace = suggestion.type != SuggestionsManager.Suggestion.TYPE_FILE && suggestion.type != SuggestionsManager.Suggestion.TYPE_COLOR;
+
+            if(multipleCmdSeparator.length() > 0) {
+//                try to understand if the user is using a multiple cmd
+                String[] split = input.split(multipleCmdSeparator);
+
+//                not using it
+                if(split.length == 1) mTerminalAdapter.setInput(text + (addSpace ? Tuils.SPACE : Tuils.EMPTYSTRING), suggestion.object);
+
+//                yes
+                else {
+                    split[split.length - 1] = Tuils.EMPTYSTRING;
+
+                    String beforeInputs = Tuils.EMPTYSTRING;
+                    for(int count = 0; count < split.length - 1; count++) {
+                        beforeInputs = beforeInputs + split[count] + multipleCmdSeparator;
+                    }
+
+                    mTerminalAdapter.setInput(beforeInputs + text + (addSpace ? Tuils.SPACE : Tuils.EMPTYSTRING), suggestion.object);
+                }
+            } else {
+                mTerminalAdapter.setInput(text + (addSpace ? Tuils.SPACE : Tuils.EMPTYSTRING), suggestion.object);
+            }
+        }
+
+        if (execOnClick) {
+            mTerminalAdapter.simulateEnter();
+        } else {
+            mTerminalAdapter.focusInputEnd();
+        }
+    }
 
-    private final int MAX_RATE = 100;
-    private final int NO_RATE = -1;
+    public void requestSuggestion(final String input) {
 
-    private final int FIRST_INTERVAL = 6;
+        Tuils.log("request sugg for", input);
 
-    private boolean showAliasDefault, set = false, clickToLaunch, showAppsGpDefault;
+        if (suggestionViewParams == null) {
+            suggestionViewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+            suggestionViewParams.setMargins(15, 0, 15, 0);
+            suggestionViewParams.gravity = Gravity.CENTER_VERTICAL;
+        }
 
-    public Suggestion[] getSuggestions(MainPack info, String beforeLastSpace , String lastWord) {
+        if(suggestionRunnable == null) {
+            suggestionRunnable = new SuggestionRunnable(pack, suggestionsView, suggestionViewParams, (HorizontalScrollView) suggestionsView.getParent());
+        }
 
-        if(!set) {
-            showAliasDefault = XMLPrefsManager.getBoolean(Suggestions.suggest_alias_default);
-            showAppsGpDefault = XMLPrefsManager.getBoolean(Suggestions.suggest_appgp_default);
-            set = true;
-            clickToLaunch = XMLPrefsManager.getBoolean(Suggestions.click_to_launch);
+        if (lastSuggestionThread != null) {
+            lastSuggestionThread.interrupt();
+            suggestionRunnable.interrupt();
+            if(handler != null) {
+                handler.removeCallbacks(suggestionRunnable);
+            }
+        }
+
+        try {
+            int l = input.length();
+            if (doubleSpaceFirstSuggestion && l > 0 && input.charAt(l - 1) == ' ') {
+                if (input.charAt(l - 2) == ' ') {
+//                    double space
+                    if(lastFirst == null && suggestionsView.getChildCount() > 0) {
+                        SuggestionsManager.Suggestion s = (SuggestionsManager.Suggestion) suggestionsView.getChildAt(0).getTag(R.id.suggestion_id);
+                        if(!input.trim().endsWith(s.getText())) lastFirst = s;
+                    }
+
+                    if(lastFirst != null) {
+                        SuggestionsManager.Suggestion s = lastFirst;
+                        mTerminalAdapter.setInput(0 == l - 2 ? Tuils.EMPTYSTRING : input.substring(0, l - 2));
+                        clickSuggestion(s);
+                        return;
+                    }
+                } else if (suggestionsView.getChildCount() > 0) {
+//                    single space
+                    lastFirst = (SuggestionsManager.Suggestion) suggestionsView.getChildAt(0).getTag(R.id.suggestion_id);
+                    if(lastFirst.getText().equals(input.trim())) {
+                        lastFirst = null;
+                    }
+                }
+            } else {
+                lastFirst = null;
+            }
+        } catch (Exception e) {
+//            this will trigger an error when there's a single space in the input field, but it's not a problem
         }
 
+        lastSuggestionThread = new StoppableThread() {
+            @Override
+            public void run() {
+
+                super.run();
+
+                String before, lastWord;
+                String lastInput;
+                if(multipleCmdSeparator.length() > 0) {
+                    String[] split = input.split(multipleCmdSeparator);
+                    if(split.length == 0) lastInput = input;
+                    else lastInput = split[split.length - 1];
+                } else {
+                    lastInput = input;
+                }
+
+                int lastSpace = lastInput.lastIndexOf(Tuils.SPACE);
+                if(lastSpace == -1) {
+                    before = Tuils.EMPTYSTRING;
+                    lastWord = lastInput;
+                } else {
+                    before = lastInput.substring(0,lastSpace);
+                    lastWord = lastInput.substring(lastSpace + 1,lastInput.length());
+                }
+
+                final List<SuggestionsManager.Suggestion> suggestions;
+                try {
+                    suggestions = getSuggestions(before, lastWord);
+                } catch (Exception e) {
+                    Tuils.log(e);
+                    Tuils.toFile(e);
+                    return;
+                }
+
+                if(suggestions.size() == 0) {
+                    ((Activity) pack.context).runOnUiThread(removeAllSuggestions);
+                    removeAllSuggestions.isGoingToRun = true;
+
+                    return;
+                } else if(removeAllSuggestions.isGoingToRun) removeAllSuggestions.stop = true;
+
+                if (Thread.interrupted()) {
+                    suggestionRunnable.interrupt();
+                    return;
+                }
+
+                final TextView[] existingViews = new TextView[suggestionsView.getChildCount()];
+                for (int count = 0; count < existingViews.length; count++) {
+                    existingViews[count] = (TextView) suggestionsView.getChildAt(count);
+                }
+
+                if (Thread.interrupted()) {
+                    suggestionRunnable.interrupt();
+                    return;
+                }
+
+                int n = suggestions.size() - existingViews.length;
+                TextView[] toAdd = null;
+                TextView[] toRecycle = null;
+                if (n == 0) {
+                    toRecycle = existingViews;
+                    toAdd = null;
+                } else if (n > 0) {
+                    toRecycle = existingViews;
+                    toAdd = new TextView[n];
+                    for (int count = 0; count < toAdd.length; count++) {
+                        toAdd[count] = suggestionViewDecorer.getSuggestionView(pack.context);
+                    }
+                } else if (n < 0) {
+                    toAdd = null;
+                    toRecycle = new TextView[suggestions.size()];
+                    System.arraycopy(existingViews, 0, toRecycle, 0, toRecycle.length);
+                }
+
+                if (Thread.interrupted()) {
+                    suggestionRunnable.interrupt();
+                    return;
+                }
+
+                suggestionRunnable.setN(n);
+                suggestionRunnable.setSuggestions(suggestions);
+                suggestionRunnable.setToAdd(toAdd);
+                suggestionRunnable.setToRecycle(toRecycle);
+                suggestionRunnable.reset();
+                ((Activity) pack.context).runOnUiThread(suggestionRunnable);
+            }
+        };
+
+        try {
+            lastSuggestionThread.start();
+        } catch (InternalError e) {}
+    }
+
+
+//    there's always a space between beforelastspace and lastword
+    public List<Suggestion> getSuggestions(String beforeLastSpace, String lastWord) {
         List<Suggestion> suggestionList = new ArrayList<>();
 
         beforeLastSpace  = beforeLastSpace .trim();
@@ -65,7 +461,7 @@ public class SuggestionsManager {
 //            lastword = 0 && beforeLastSpace  = 0
 
             if (beforeLastSpace .length() == 0) {
-                AppsManager.LaunchInfo[] apps = info.appsManager.getSuggestedApps();
+                AppsManager.LaunchInfo[] apps = pack.appsManager.getSuggestedApps();
                 if (apps != null) {
                     for(int count = 0; count < apps.length; count++) {
                         if(apps[count] == null) {
@@ -78,18 +474,18 @@ public class SuggestionsManager {
                     }
                 }
 
-                if(showAliasDefault) suggestAlias(info.aliasManager, suggestionList, lastWord);
-                if(showAppsGpDefault) suggestAppGroup(suggestionList, lastWord, beforeLastSpace );
+                suggestCommand(pack, suggestionList, null);
 
-                return suggestionList.toArray(new Suggestion[suggestionList.size()]);
+                if(showAliasDefault) suggestAlias(pack.aliasManager, suggestionList, lastWord);
+                if(showAppsGpDefault) suggestAppGroup(pack, suggestionList, lastWord, beforeLastSpace );
             }
 
-//            lastword == 0 && beforeLastSpace  > 0
+//            lastword == 0 && beforeLastSpace > 0
             else {
 //                check if this is a command
                 Command cmd = null;
                 try {
-                    cmd = CommandTuils.parse(beforeLastSpace , info, true);
+                    cmd = CommandTuils.parse(beforeLastSpace , pack, true);
                 } catch (Exception e) {}
 
                 if (cmd != null) {
@@ -100,20 +496,20 @@ public class SuggestionsManager {
 
                     if (cmd.mArgs != null && cmd.mArgs.length > 0 && cmd.cmd instanceof ParamCommand && cmd.nArgs >= 1 && cmd.mArgs[0] instanceof Param &&
                             ((Param) cmd.mArgs[0]).args().length + 1 == cmd.nArgs) {
-                        return new Suggestion[0];
+                        return suggestionList;
                     }
 
 //                    if( ( !(cmd.cmd instanceof ParamCommand) && cmd.nArgs == cmd.cmd.maxArgs() - 1 && cmd.indexNotFound == cmd.cmd.maxArgs() - 1) ||
 //                            (cmd.mArgs != null && cmd.mArgs.length > 0 && cmd.cmd instanceof ParamCommand && cmd.nArgs >= 1 && ((ParamCommand) cmd.cmd).argsForParam((String) cmd.mArgs[0]).length == cmd.nArgs
 //                                    && cmd.indexNotFound == ((ParamCommand) cmd.cmd).argsForParam((String) cmd.mArgs[0]).length)) {
 ////                        the last arg wasnt found
-//                        suggestArgs(info, cmd.cmd instanceof ParamCommand ? ((ParamCommand) cmd.cmd).argsForParam((String) cmd.mArgs[0])[cmd.nArgs - 1] : cmd.cmd.argType()[cmd.nArgs], suggestionList, lastWord, beforeLastSpace );
+//                        suggestArgs(pack, cmd.cmd instanceof ParamCommand ? ((ParamCommand) cmd.cmd).argsForParam((String) cmd.mArgs[0])[cmd.nArgs - 1] : cmd.cmd.argType()[cmd.nArgs], suggestionList, lastWord, beforeLastSpace );
 //                    }
 
                     if(cmd.cmd instanceof ParamCommand && (cmd.mArgs == null || cmd.mArgs.length == 0 || cmd.mArgs[0] instanceof String)) {
-                        suggestParams(info, suggestionList, (ParamCommand) cmd.cmd, beforeLastSpace , null);
+                        suggestParams(pack, suggestionList, (ParamCommand) cmd.cmd, beforeLastSpace , null);
                     }
-                    else suggestArgs(info, cmd.nextArg(), suggestionList, beforeLastSpace );
+                    else suggestArgs(pack, cmd.nextArg(), suggestionList, beforeLastSpace );
 
                 } else {
 
@@ -127,10 +523,10 @@ public class SuggestionsManager {
                     }
 
                     if(isShellCmd) {
-                        suggestFile(info, suggestionList, Tuils.EMPTYSTRING, beforeLastSpace );
+                        suggestFile(pack, suggestionList, Tuils.EMPTYSTRING, beforeLastSpace );
                     } else {
 //                        ==> app
-                        if(!suggestAppInsideGroup(suggestionList, Tuils.EMPTYSTRING, beforeLastSpace , false)) suggestApp(info, suggestionList, beforeLastSpace  + Tuils.SPACE, Tuils.EMPTYSTRING);
+                        if(!suggestAppInsideGroup(pack, suggestionList, Tuils.EMPTYSTRING, beforeLastSpace , false)) suggestApp(pack, suggestionList, beforeLastSpace  + Tuils.SPACE, Tuils.EMPTYSTRING);
                     }
 
                 }
@@ -144,7 +540,7 @@ public class SuggestionsManager {
 //                lastword > 0 && beforeLastSpace  > 0
                 Command cmd = null;
                 try {
-                    cmd = CommandTuils.parse(beforeLastSpace , info, true);
+                    cmd = CommandTuils.parse(beforeLastSpace , pack, true);
                 } catch (Exception e) {}
 
                 if (cmd != null) {
@@ -159,8 +555,8 @@ public class SuggestionsManager {
 //                    }
 
                     if(cmd.cmd instanceof ParamCommand && (cmd.mArgs == null || cmd.mArgs.length == 0 || cmd.mArgs[0] instanceof String)) {
-                        suggestParams(info, suggestionList, (ParamCommand) cmd.cmd, beforeLastSpace , lastWord);
-                    } else suggestArgs(info, cmd.nextArg(), suggestionList, lastWord, beforeLastSpace );
+                        suggestParams(pack, suggestionList, (ParamCommand) cmd.cmd, beforeLastSpace , lastWord);
+                    } else suggestArgs(pack, cmd.nextArg(), suggestionList, lastWord, beforeLastSpace );
                 } else {
 
                     String[] split = beforeLastSpace .replaceAll("['\"]", Tuils.EMPTYSTRING).split(Tuils.SPACE);
@@ -173,24 +569,28 @@ public class SuggestionsManager {
                     }
 
                     if(isShellCmd) {
-                        suggestFile(info, suggestionList, lastWord, beforeLastSpace );
+                        suggestFile(pack, suggestionList, lastWord, beforeLastSpace );
                     } else {
-                        if(!suggestAppInsideGroup(suggestionList, lastWord, beforeLastSpace , false)) suggestApp(info, suggestionList, beforeLastSpace  + Tuils.SPACE + lastWord, Tuils.EMPTYSTRING);
+                        if(!suggestAppInsideGroup(pack, suggestionList, lastWord, beforeLastSpace , false)) suggestApp(pack, suggestionList, beforeLastSpace  + Tuils.SPACE + lastWord, Tuils.EMPTYSTRING);
                     }
                 }
 
             } else {
 //                lastword > 0 && beforeLastSpace  = 0
-                suggestCommand(info, suggestionList, lastWord, beforeLastSpace );
-                suggestAlias(info.aliasManager, suggestionList, lastWord);
-                suggestApp(info, suggestionList, lastWord, Tuils.EMPTYSTRING);
-                suggestAppGroup(suggestionList, lastWord, beforeLastSpace );
+                suggestCommand(pack, suggestionList, lastWord, beforeLastSpace );
+                suggestAlias(pack.aliasManager, suggestionList, lastWord);
+                suggestApp(pack, suggestionList, lastWord, Tuils.EMPTYSTRING);
+                suggestAppGroup(pack, suggestionList, lastWord, beforeLastSpace );
             }
         }
 
-        Collections.sort(suggestionList);
-        Suggestion[] array = new Suggestion[suggestionList.size()];
-        return suggestionList.toArray(array);
+        Comparator<Suggestion> cmp;
+        if(lastWord.length() == 0 && beforeLastSpace.length() == 0) cmp = noInputComparator;
+        else cmp = comparator;
+
+        if(cmp != null) Collections.sort(suggestionList, cmp);
+
+        return suggestionList;
     }
 
     private boolean needsFileSuggestion(String cmd) {
@@ -205,8 +605,22 @@ public class SuggestionsManager {
     }
 
     private void suggestAlias(AliasManager aliasManager, List<Suggestion> suggestions, String lastWord) {
-        if(lastWord.length() == 0) for(String s : aliasManager.getAliases()) suggestions.add(new Suggestion(Tuils.EMPTYSTRING, s, clickToLaunch, NO_RATE, Suggestion.TYPE_ALIAS));
-        else for(String s : aliasManager.getAliases()) if(s.startsWith(lastWord)) suggestions.add(new Suggestion(Tuils.EMPTYSTRING, s, clickToLaunch, NO_RATE, Suggestion.TYPE_ALIAS));
+        int canInsert = counts[Suggestion.TYPE_ALIAS];
+
+        if(lastWord.length() == 0)
+            for(AliasManager.Alias a : aliasManager.getAliases(true)) {
+                if(canInsert == 0) return;
+                canInsert--;
+
+                suggestions.add(new Suggestion(Tuils.EMPTYSTRING, a.name, clickToLaunch && !a.isParametrized, NO_RATE, Suggestion.TYPE_ALIAS));
+            }
+        else for(AliasManager.Alias a : aliasManager.getAliases(true))
+            if(a.name.startsWith(lastWord)) {
+                if(canInsert == 0) return;
+                canInsert--;
+
+                suggestions.add(new Suggestion(Tuils.EMPTYSTRING, a.name, clickToLaunch && !a.isParametrized, NO_RATE, Suggestion.TYPE_ALIAS));
+            }
     }
 
     private void suggestParams(MainPack pack, List<Suggestion> suggestions, ParamCommand cmd, String beforeLastSpace , String lastWord) {
@@ -238,7 +652,6 @@ public class SuggestionsManager {
     private void suggestArgs(MainPack info, int type, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
         switch (type) {
             case CommandAbstraction.FILE:
-            case CommandAbstraction.FILE_LIST:
                 suggestFile(info, suggestions, afterLastSpace, beforeLastSpace );
                 break;
             case CommandAbstraction.VISIBLE_PACKAGE:
@@ -275,10 +688,13 @@ public class SuggestionsManager {
                 suggestAllPackages(info, suggestions, afterLastSpace, beforeLastSpace );
                 break;
             case CommandAbstraction.APP_GROUP:
-                suggestAppGroup(suggestions, afterLastSpace, beforeLastSpace );
+                suggestAppGroup(info, suggestions, afterLastSpace, beforeLastSpace );
                 break;
             case CommandAbstraction.APP_INSIDE_GROUP:
-                suggestAppInsideGroup(suggestions, afterLastSpace, beforeLastSpace , true);
+                suggestAppInsideGroup(info, suggestions, afterLastSpace, beforeLastSpace , true);
+                break;
+            case CommandAbstraction.BOUND_REPLY_APP:
+                suggestBoundReplyApp(suggestions, afterLastSpace, beforeLastSpace);
                 break;
         }
     }
@@ -292,45 +708,79 @@ public class SuggestionsManager {
         suggestions.add(new Suggestion(beforeLastSpace , "false", clickToLaunch, NO_RATE, Suggestion.TYPE_BOOLEAN));
     }
 
-    private void suggestFile(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
-        if(afterLastSpace == null || !afterLastSpace.endsWith(File.separator)) {
-            suggestions.add(new Suggestion(beforeLastSpace  + Tuils.SPACE + (afterLastSpace != null ? afterLastSpace : Tuils.EMPTYSTRING), File.separator, false, MAX_RATE, Suggestion.TYPE_FILE));
+    Pattern rmQuotes = Pattern.compile("[\"']");
+    private void suggestFile(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace) {
+        boolean noAfterLastSpace = afterLastSpace == null || afterLastSpace.length() == 0;
+        boolean afterLastSpaceNotEndsWithSeparator = noAfterLastSpace || !afterLastSpace.endsWith(File.separator);
+        if(noAfterLastSpace || afterLastSpaceNotEndsWithSeparator) {
+            suggestions.add(new Suggestion(beforeLastSpace, File.separator, false, MAX_RATE, Suggestion.TYPE_FILE, afterLastSpace));
         }
 
-        if (afterLastSpace == null || afterLastSpace.length() == 0) {
-            suggestFilesInDir(suggestions, info.currentDirectory, beforeLastSpace );
+        if(Suggestion.appendQuotesBeforeFile && !noAfterLastSpace && !afterLastSpace.endsWith(SINGLE_QUOTE) && !afterLastSpace.endsWith(DOUBLE_QUOTES))
+            suggestions.add(new Suggestion(beforeLastSpace, SINGLE_QUOTE, false, MAX_RATE, Suggestion.TYPE_FILE, afterLastSpace));
+
+        if (noAfterLastSpace) {
+            suggestFilesInDir(null, suggestions, info.currentDirectory, beforeLastSpace);
             return;
         }
 
-        if (!afterLastSpace.contains(File.separator) && afterLastSpace.length() > 0) {
-            suggestFilesInDir(suggestions, info.currentDirectory, afterLastSpace, beforeLastSpace );
-        } else if (afterLastSpace.length() > 0) {
-            if (afterLastSpace.endsWith(File.separator)) {
-                afterLastSpace = afterLastSpace.substring(0, afterLastSpace.length() - 1);
-                beforeLastSpace  = beforeLastSpace  + Tuils.SPACE + afterLastSpace + File.separator;
+        if (!afterLastSpace.contains(File.separator)) {
+            suggestFilesInDir(suggestions, info.currentDirectory, afterLastSpace, beforeLastSpace, null);
+        } else {
 
-                FileManager.DirInfo dirInfo = FileManager.cd(info.currentDirectory, afterLastSpace);
-                suggestFilesInDir(suggestions, dirInfo.file, beforeLastSpace );
-            } else {
-//                contains / but doesn't end with it
-                FileManager.DirInfo dirInfo = FileManager.cd(info.currentDirectory, afterLastSpace.substring(0,afterLastSpace.lastIndexOf(File.separator)));
+//            if it's ../../
+            if (!afterLastSpaceNotEndsWithSeparator) {
+                String total = beforeLastSpace + Tuils.SPACE + afterLastSpace;
+                int quotesCount = total.length() - total.replace(DOUBLE_QUOTES, Tuils.EMPTYSTRING).replace(SINGLE_QUOTE, Tuils.EMPTYSTRING).length();
+
+                if(quotesCount > 0) {
+                    int singleQIndex = total.lastIndexOf(SINGLE_QUOTE);
+                    int doubleQIndex = total.lastIndexOf(DOUBLE_QUOTES);
+
+                    int lastQuote = Math.max(singleQIndex, doubleQIndex);
+
+                    String file = total.substring(lastQuote + Math.abs(quotesCount % 2 - 2));
+                    FileManager.DirInfo dirInfo = FileManager.cd(info.currentDirectory, file);
+                    suggestFilesInDir(afterLastSpace, suggestions, dirInfo.file, beforeLastSpace);
+
+//                        original code, above the compact code
+//                    if(quotesCount % 2 == 1)
+//                        not odds quotes count -> the last quote opens the last file
+//                        String file = total.substring(lastQuote + 1);
+//                    else
+//                        odd quotes count -> after the space after the last quote it begins the new file
+//                        String file = total.substring(lastQuote + 2);
+                } else {
+//                    removes the /
+                    afterLastSpace = afterLastSpace.substring(0, afterLastSpace.length() - 1);
+                    FileManager.DirInfo dirInfo = FileManager.cd(info.currentDirectory, afterLastSpace);
+                    suggestFilesInDir(afterLastSpace + File.separator, suggestions, dirInfo.file, beforeLastSpace);
+                }
+            }
+//            if it's ../..
+            else {
+                String originalAfterLastSpace = afterLastSpace;
+                afterLastSpace = rmQuotes.matcher(afterLastSpace).replaceAll(Tuils.EMPTYSTRING);
 
                 int index = afterLastSpace.lastIndexOf(File.separator);
-                String hold = afterLastSpace.substring(0, index + 1);
-                afterLastSpace = afterLastSpace.substring(index + 1);
-                beforeLastSpace  = beforeLastSpace  + Tuils.SPACE + hold;
+                FileManager.DirInfo dirInfo = FileManager.cd(info.currentDirectory, afterLastSpace.substring(0,index));
+
+                int originalIndex = originalAfterLastSpace.lastIndexOf(File.separator);
 
-                suggestFilesInDir(suggestions, dirInfo.file, afterLastSpace, beforeLastSpace );
+                String alsals = originalAfterLastSpace.substring(0, originalIndex + 1);
+                String als = originalAfterLastSpace.substring(originalIndex + 1);
+//                beforeLastSpace  = beforeLastSpace + Tuils.SPACE + hold;
+
+                suggestFilesInDir(suggestions, dirInfo.file, als, beforeLastSpace, alsals);
             }
         }
     }
 
-    private void suggestFilesInDir(List<Suggestion> suggestions, File dir, String afterLastSpace, String beforeLastSpace ) {
-        if (dir == null || !dir.isDirectory())
-            return;
+    private void suggestFilesInDir(List<Suggestion> suggestions, File dir, String afterLastSeparator, String beforeLastSpace, String afterLastSpaceWithoutALS) {
+        if (dir == null || !dir.isDirectory()) return;
 
-        if (afterLastSpace == null || afterLastSpace.length() == 0) {
-            suggestFilesInDir(suggestions, dir, beforeLastSpace );
+        if (afterLastSeparator == null || afterLastSeparator.length() == 0) {
+            suggestFilesInDir(null, suggestions, dir, beforeLastSpace);
             return;
         }
 
@@ -339,12 +789,16 @@ public class SuggestionsManager {
             return;
         }
 
-        for(SimpleMutableEntry<String, Integer> s : Compare.matchesWithRate(files, afterLastSpace, false)) {
-            suggestions.add(new Suggestion(beforeLastSpace , s.getKey(), false, s.getValue(), Suggestion.TYPE_FILE));
+//        Tuils.log("bls", beforeLastSpace);
+//        Tuils.log("als", afterLastSeparator);
+//        Tuils.log("alsals", afterLastSpaceWithoutALS);
+
+        for(SimpleMutableEntry<String, Integer> s : Compare.matchesWithRate(files, rmQuotes.matcher(afterLastSeparator).replaceAll(Tuils.EMPTYSTRING), false)) {
+            suggestions.add(new Suggestion(beforeLastSpace , s.getKey(), false, s.getValue(), Suggestion.TYPE_FILE, afterLastSpaceWithoutALS));
         }
     }
 
-    private void suggestFilesInDir(List<Suggestion> suggestions, File dir, String beforeLastSpace ) {
+    private void suggestFilesInDir(String afterLastSpaceHolder, List<Suggestion> suggestions, File dir, String beforeLastSpace) {
         if (dir == null || !dir.isDirectory()) {
             return;
         }
@@ -356,7 +810,7 @@ public class SuggestionsManager {
             }
             Arrays.sort(files);
             for (String s : files) {
-                suggestions.add(new Suggestion(beforeLastSpace , s, false, NO_RATE, Suggestion.TYPE_FILE));
+                suggestions.add(new Suggestion(beforeLastSpace , s, false, NO_RATE, Suggestion.TYPE_FILE, afterLastSpaceHolder));
             }
         } catch (NullPointerException e) {}
     }
@@ -411,107 +865,86 @@ public class SuggestionsManager {
             String[] cmds = info.commandGroup.getCommandNames();
             if(cmds == null) return;
 
+            int canInsert = counts[Suggestion.TYPE_COMMAND];
             for (String s : cmds) {
-                if(Thread.currentThread().isInterrupted()) return;
+                if(canInsert == 0 || Thread.currentThread().isInterrupted()) return;
 
                 if(s.startsWith(afterLastSpace)) {
                     CommandAbstraction cmd = info.commandGroup.getCommandByName(s);
                     int[] args = cmd.argType();
                     boolean exec = args == null || args.length == 0;
                     suggestions.add(new Suggestion(beforeLastSpace , s, exec && clickToLaunch, MAX_RATE, Suggestion.TYPE_COMMAND));
+                    canInsert--;
                 }
             }
         }
     }
 
-    private void suggestColor(List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
-        if(afterLastSpace == null || afterLastSpace.length() == 0 || (afterLastSpace.length() == 1 && afterLastSpace.charAt(0) != '#')) {
-            suggestions.add(new Suggestion(beforeLastSpace , "#", false, MAX_RATE, Suggestion.TYPE_COLOR));
-        }
-    }
-
-    private void suggestCommand(MainPack info, List<Suggestion> suggestions, String beforeLastSpace ) {
-        String[] cmds = info.commandGroup.getCommandNames();
+    private void suggestCommand(MainPack info, List<Suggestion> suggestions, String beforeLastSpace) {
+        CommandAbstraction[] cmds = info.commandGroup.getCommands();
         if(cmds == null) return;
 
-        for (String s : cmds) {
-            if(Thread.currentThread().isInterrupted()) return;
+        int canInsert = noInputCounts[Suggestion.TYPE_COMMAND];
+        for (CommandAbstraction cmd : cmds) {
+            if(canInsert == 0 || Thread.currentThread().isInterrupted()) return;
 
-            CommandAbstraction cmd = info.commandGroup.getCommandByName(s);
-            if (cmd != null && cmd.priority() >= MIN_COMMAND_PRIORITY) {
+            if (info.cmdPrefs.getPriority(cmd) >= minCmdPriority) {
                 int[] args = cmd.argType();
                 boolean exec = args == null || args.length == 0;
-                suggestions.add(new Suggestion(beforeLastSpace , s, exec && clickToLaunch, cmd.priority(), Suggestion.TYPE_COMMAND));
+                suggestions.add(new Suggestion(beforeLastSpace , cmd.getClass().getSimpleName(), exec && clickToLaunch, info.cmdPrefs.getPriority(cmd), Suggestion.TYPE_COMMAND));
+                canInsert--;
             }
         }
     }
 
-    private void suggestApp(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace) {
-        List<AppsManager.LaunchInfo> apps = info.appsManager.shownApps();
-        if(apps == null) return;
-
-        if (afterLastSpace == null || afterLastSpace.length() == 0) {
-            for (AppsManager.LaunchInfo l : apps) {
-                suggestions.add(new Suggestion(beforeLastSpace , l.publicLabel, clickToLaunch, NO_RATE, Suggestion.TYPE_APP, l));
-            }
-        }
-        else {
-            List<SimpleMutableEntry<Compare.Stringable, Integer>> infos = Compare.matchesWithRate(apps, true, afterLastSpace);
-            for(SimpleMutableEntry<Compare.Stringable, Integer> i : infos) {
-                suggestions.add(new Suggestion(beforeLastSpace , i.getKey().getString(), clickToLaunch, i.getValue(), Suggestion.TYPE_APP, i.getKey()));
-            }
+    private void suggestColor(List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
+        if(afterLastSpace == null || afterLastSpace.length() == 0 || (afterLastSpace.length() == 1 && afterLastSpace.charAt(0) != '#')) {
+            suggestions.add(new Suggestion(beforeLastSpace , "#", false, MAX_RATE, Suggestion.TYPE_COLOR));
         }
     }
 
-    private void suggestHiddenApp(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace) {
-        List<AppsManager.LaunchInfo> apps = info.appsManager.hiddenApps();
-        if(apps == null) return;
+    private void suggestApp(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace) {
+        suggestApp(info.appsManager.shownApps(), suggestions, afterLastSpace, beforeLastSpace, true);
+    }
 
-        if (afterLastSpace == null || afterLastSpace.length() == 0) {
-            for (AppsManager.LaunchInfo a : apps) {
-                suggestions.add(new Suggestion(beforeLastSpace , a.publicLabel, false, NO_RATE, Suggestion.TYPE_APP));
-            }
-        }
-        else {
-            List<SimpleMutableEntry<Compare.Stringable, Integer>> infos = Compare.matchesWithRate(apps, true, afterLastSpace);
-            for(SimpleMutableEntry<Compare.Stringable, Integer> i : infos) {
-                suggestions.add(new Suggestion(beforeLastSpace , i.getKey().getString(), false, i.getValue(), Suggestion.TYPE_APP));
-            }
-        }
+    private void suggestHiddenApp(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace) {
+        suggestApp(info.appsManager.hiddenApps(), suggestions, afterLastSpace, beforeLastSpace, false);
     }
 
     private void suggestAllPackages(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
         List<AppsManager.LaunchInfo> apps = new ArrayList<>(info.appsManager.shownApps());
         apps.addAll(info.appsManager.hiddenApps());
-
-        if (afterLastSpace == null || afterLastSpace.length() == 0) {
-            for (AppsManager.LaunchInfo a : apps) {
-                suggestions.add(new Suggestion(beforeLastSpace , a.publicLabel, clickToLaunch, NO_RATE, Suggestion.TYPE_APP, a));
-            }
-        } else {
-            List<SimpleMutableEntry<Compare.Stringable, Integer>> infos = Compare.matchesWithRate(apps, true, afterLastSpace);
-            for(SimpleMutableEntry<Compare.Stringable, Integer> i : infos) {
-                suggestions.add(new Suggestion(beforeLastSpace , i.getKey().getString(), clickToLaunch, i.getValue(), Suggestion.TYPE_APP, i.getKey()));
-            }
-        }
+        suggestApp(apps, suggestions, afterLastSpace, beforeLastSpace, true);
     }
 
     private void suggestDefaultApp(MainPack info, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
         suggestions.add(new Suggestion(beforeLastSpace , "most_used", false, MAX_RATE, Suggestion.TYPE_PERMANENT));
         suggestions.add(new Suggestion(beforeLastSpace , "null", false, MAX_RATE, Suggestion.TYPE_PERMANENT));
 
-        List<AppsManager.LaunchInfo> apps = info.appsManager.shownApps();
+        suggestApp(info.appsManager.shownApps(), suggestions, afterLastSpace, beforeLastSpace, true);
+    }
+
+    private void suggestApp(List<AppsManager.LaunchInfo> apps, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace, boolean canClickToLaunch) {
         if(apps == null) return;
 
+        int canInsert = counts[Suggestion.TYPE_APP];
         if (afterLastSpace == null || afterLastSpace.length() == 0) {
-            for (AppsManager.LaunchInfo a : apps) {
-                suggestions.add(new Suggestion(beforeLastSpace , a.publicLabel, clickToLaunch, NO_RATE, Suggestion.TYPE_APP, a));
+            for (AppsManager.LaunchInfo l : apps) {
+                if(canInsert == 0) return;
+                canInsert--;
+
+                suggestions.add(new Suggestion(beforeLastSpace , l.publicLabel, canClickToLaunch && clickToLaunch, NO_RATE, Suggestion.TYPE_APP, l));
             }
         }
         else {
             List<SimpleMutableEntry<Compare.Stringable, Integer>> infos = Compare.matchesWithRate(apps, true, afterLastSpace);
+            Collections.sort(infos, stringableComparator);
+
             for(SimpleMutableEntry<Compare.Stringable, Integer> i : infos) {
-                suggestions.add(new Suggestion(beforeLastSpace , i.getKey().getString(), clickToLaunch, i.getValue(), Suggestion.TYPE_APP, i.getKey()));
+                if(canInsert == 0) return;
+                canInsert--;
+
+                suggestions.add(new Suggestion(beforeLastSpace , i.getKey().getString(), canClickToLaunch && clickToLaunch, i.getValue(), Suggestion.TYPE_APP, canClickToLaunch ? i.getKey() : null));
             }
         }
     }
@@ -525,16 +958,17 @@ public class SuggestionsManager {
             Collections.addAll(xmlPrefsEntrys, Apps.values());
             Collections.addAll(xmlPrefsEntrys, Notifications.values());
             Collections.addAll(xmlPrefsEntrys, Rss.values());
+            Collections.addAll(xmlPrefsEntrys, Reply.values());
         }
 
         if(afterLastSpace == null || afterLastSpace.length() == 0) {
-            for(XMLPrefsManager.XMLPrefsSave s : xmlPrefsEntrys) {
+            for(XMLPrefsSave s : xmlPrefsEntrys) {
                 Suggestion sg = new Suggestion(beforeLastSpace , s.label(), false, NO_RATE, Suggestion.TYPE_COMMAND);
                 suggestions.add(sg);
             }
         }
         else {
-            for (XMLPrefsManager.XMLPrefsSave s : xmlPrefsEntrys) {
+            for (XMLPrefsSave s : xmlPrefsEntrys) {
                 if(Thread.currentThread().isInterrupted()) return;
 
                 String label = s.label();
@@ -552,13 +986,14 @@ public class SuggestionsManager {
             for(XMLPrefsManager.XMLPrefsRoot element : XMLPrefsManager.XMLPrefsRoot.values())
                 xmlPrefsFiles.add(element.path);
             xmlPrefsFiles.add(AppsManager.PATH);
+            xmlPrefsFiles.add(ReplyManager.PATH);
             xmlPrefsFiles.add(NotificationManager.PATH);
             xmlPrefsFiles.add(RssManager.PATH);
         }
 
         if(afterLastSpace == null || afterLastSpace.length() == 0) {
             for(String s : xmlPrefsFiles) {
-                Suggestion sg = new Suggestion(beforeLastSpace , s, false, NO_RATE, Suggestion.TYPE_FILE);
+                Suggestion sg = new Suggestion(beforeLastSpace , s, false, NO_RATE, Suggestion.TYPE_CONFIGFILE, afterLastSpace);
                 suggestions.add(sg);
             }
         } else if(afterLastSpace.length() <= FIRST_INTERVAL) {
@@ -567,52 +1002,61 @@ public class SuggestionsManager {
                 if(Thread.currentThread().isInterrupted()) return;
 
                 if(s.startsWith(afterLastSpace)) {
-                    suggestions.add(new Suggestion(beforeLastSpace , s, false, MAX_RATE, Suggestion.TYPE_FILE));
+                    suggestions.add(new Suggestion(beforeLastSpace , s, false, MAX_RATE, Suggestion.TYPE_CONFIGFILE, afterLastSpace));
                 }
             }
         }
     }
 
-    private void suggestAppGroup(List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
-        List<AppsManager.Group> groups = AppsManager.groups;
+    private void suggestAppGroup(MainPack pack, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace ) {
+        List<AppsManager.Group> groups = pack.appsManager.groups;
 
+        int canInsert;
         if(afterLastSpace == null || afterLastSpace.length() == 0) {
+            canInsert = noInputCounts[Suggestion.TYPE_APPGP];
             for(AppsManager.Group g : groups) {
-                Suggestion sg = new Suggestion(beforeLastSpace , g.getName(), false, NO_RATE, Suggestion.TYPE_APP, g);
+                if(canInsert == 0) return;
+                canInsert--;
+
+                Suggestion sg = new Suggestion(beforeLastSpace , g.getName(), false, NO_RATE, Suggestion.TYPE_APPGP, g);
                 suggestions.add(sg);
             }
         }
         else {
+            canInsert = counts[Suggestion.TYPE_APPGP];
             for(AppsManager.Group g : groups) {
                 String label = g.getName();
                 int rate = Compare.matches(label, afterLastSpace, true);
                 if(rate != -1) {
-                    suggestions.add(new Suggestion(beforeLastSpace , label, false, rate, Suggestion.TYPE_APP, g));
+                    if(canInsert == 0) return;
+                    canInsert--;
+
+                    suggestions.add(new Suggestion(beforeLastSpace , label, false, rate, Suggestion.TYPE_APPGP, g));
                 }
             }
         }
     }
 
-    private boolean suggestAppInsideGroup(List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace , boolean keepGroupName) {
+    private boolean suggestAppInsideGroup(MainPack pack, List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace, boolean keepGroupName) {
         int index = -1;
 
         String app = Tuils.EMPTYSTRING;
 
-        if(!beforeLastSpace .contains(Tuils.SPACE)) {
-            index = Tuils.find(beforeLastSpace , AppsManager.groups);
+        if(!beforeLastSpace.contains(Tuils.SPACE)) {
+            index = Tuils.find(beforeLastSpace , pack.appsManager.groups);
             app = afterLastSpace;
             if(!keepGroupName) beforeLastSpace  = Tuils.EMPTYSTRING;
         } else {
-            String[] split = beforeLastSpace .split(Tuils.SPACE);
+            String[] split = beforeLastSpace.split(Tuils.SPACE);
             for(int count = 0; count < split.length; count++) {
-                index = Tuils.find(split[count], AppsManager.groups);
+                index = Tuils.find(split[count], pack.appsManager.groups);
                 if(index != -1) {
 
-                    beforeLastSpace  = Tuils.EMPTYSTRING;
+                    beforeLastSpace = Tuils.EMPTYSTRING;
                     for(int i = 0; (keepGroupName ? i <= count : i < count); i++) {
-                        beforeLastSpace  = beforeLastSpace  + split[i] + Tuils.SPACE;
+                        beforeLastSpace = beforeLastSpace + split[i] + Tuils.SPACE;
                     }
-                    beforeLastSpace  = beforeLastSpace .trim();
+                    beforeLastSpace = beforeLastSpace.trim();
 
                     count += 1;
                     for(; count < split.length; count++) {
@@ -628,7 +1072,7 @@ public class SuggestionsManager {
 
         if(index == -1) return false;
 
-        AppsManager.Group g = AppsManager.groups.get(index);
+        AppsManager.Group g = pack.appsManager.groups.get(index);
 
         List<? extends Compare.Stringable> apps = g.members();
         if(apps != null && apps.size() > 0) {
@@ -648,20 +1092,43 @@ public class SuggestionsManager {
         return true;
     }
 
-    public class Suggestion implements Comparable<Suggestion> {
+    private boolean suggestBoundReplyApp(List<Suggestion> suggestions, String afterLastSpace, String beforeLastSpace) {
+        List<BoundApp> apps = ReplyManager.boundApps;
+        if(apps == null || apps.size() == 0) return false;
+
+        if (afterLastSpace == null || afterLastSpace.length() == 0) {
+            for (BoundApp b : apps) {
+                suggestions.add(new Suggestion(beforeLastSpace, String.valueOf(b.applicationId), b.label, false, NO_RATE, Suggestion.TYPE_APP));
+            }
+        }
+        else {
+            List<SimpleMutableEntry<Compare.Stringable, Integer>> infos = Compare.matchesWithRate(apps, true, afterLastSpace);
+            for(SimpleMutableEntry<Compare.Stringable, Integer> i : infos) {
+                suggestions.add(new Suggestion(beforeLastSpace , String.valueOf(((BoundApp) i.getKey()).applicationId), i.getKey().getString(), false, i.getValue(), Suggestion.TYPE_APP));
+            }
+        }
+
+        return true;
+    }
+
+    public static class Suggestion {
 
-        public static final int TYPE_APP = 10;
-        public static final int TYPE_FILE = 11;
-        public static final int TYPE_ALIAS = 12;
-        public static final int TYPE_COMMAND = 13;
-        public static final int TYPE_SONG = 14;
-        public static final int TYPE_CONTACT = 15;
-        public static final int TYPE_BOOLEAN = 16;
-        public static final int TYPE_COLOR = 17;
-        public static final int TYPE_PERMANENT = 18;
+//        these suggestions will appear together
+        public static final int TYPE_APP = 0;
+        public static final int TYPE_ALIAS = 1;
+        public static final int TYPE_COMMAND = 2;
+        public static final int TYPE_APPGP = 3;
 
-        public String text;
-        public String textBefore;
+//        these suggestions will appear only in some special moments, ALONE
+        public static final int TYPE_FILE = 10;
+        public static final int TYPE_BOOLEAN = 11;
+        public static final int TYPE_SONG = 12;
+        public static final int TYPE_CONTACT = 13;
+        public static final int TYPE_COLOR = 14;
+        public static final int TYPE_PERMANENT = 15;
+        public static final int TYPE_CONFIGFILE = 16;
+
+        public String text, textBefore, shownText;
 
         public boolean exec;
         public int rate;
@@ -669,13 +1136,30 @@ public class SuggestionsManager {
 
         public Object object;
 
-        public Suggestion(String beforeLastSpace , String text, boolean exec, int rate, int type) {
+        public static boolean appendQuotesBeforeFile;
+
+        public Suggestion(String beforeLastSpace, String text, boolean exec, int rate, int type) {
             this(beforeLastSpace , text, exec, rate, type, null);
         }
 
-        public Suggestion(String beforeLastSpace , String text, boolean exec, int rate, int type, Object tag) {
-            this.textBefore = beforeLastSpace ;
+        public Suggestion(String beforeLastSpace, String text, boolean exec, int rate, int type, Object tag) {
+            this(beforeLastSpace , text, null, exec, rate, type, tag);
+        }
+
+        public Suggestion(String beforeLastSpace, String text, String shownText, boolean exec, int rate, int type) {
+            this(beforeLastSpace, text, shownText, exec, rate, type, null);
+        }
+
+        public Suggestion(String beforeLastSpace, String text, String shownText,  boolean exec, int rate, int type, Object tag) {
+//            Tuils.log("######");
+//            Tuils.log(Thread.currentThread().getStackTrace());
+//            Tuils.log("bf", beforeLastSpace);
+//            Tuils.log("lw", tag == null ? "null" : tag.toString());
+//            Tuils.log("txt", text);
+
+            this.textBefore = beforeLastSpace;
             this.text = text;
+            this.shownText = shownText;
 
             this.exec = exec;
             this.rate = rate;
@@ -693,22 +1177,35 @@ public class SuggestionsManager {
                 return textBefore + Tuils.SPACE + c.numbers.get(c.getSelectedNumber());
             } else if(type == Suggestion.TYPE_PERMANENT) {
                 return text;
+            } else if(type == Suggestion.TYPE_FILE) {
+                String lastWord = object == null ? null : (String) object;
+                if(lastWord == null) {
+                    lastWord = Tuils.EMPTYSTRING;
+                }
+
+                boolean textIsSpecial = (text.equals(File.separator) || text.equals(DOUBLE_QUOTES) || text.equals(SINGLE_QUOTE));
+                boolean appendLastWord = lastWord.endsWith(File.separator) || textIsSpecial;
+
+//                Tuils.log("-------------");
+//                Tuils.log("tspe", textIsSpecial);
+//                Tuils.log("tbe", textBefore.replaceAll(" ", "#"));
+//                Tuils.log("lw", lastWord);
+//                Tuils.log("txt", text);
+
+                return textBefore +
+                        Tuils.SPACE +
+                        (appendLastWord ? lastWord : Tuils.EMPTYSTRING) +
+                        (appendQuotesBeforeFile && !appendLastWord ? SINGLE_QUOTE : Tuils.EMPTYSTRING) +
+                        text;
             }
 
             if(textBefore == null || textBefore.length() == 0) {
                 return text;
-            } else if((text.startsWith(File.separator) || textBefore.endsWith(File.separator)) && type == TYPE_FILE) {
-                return textBefore + text;
             } else {
                 return textBefore + Tuils.SPACE + text;
             }
         }
 
-        @Override
-        public int compareTo(Suggestion another) {
-            return this.rate > another.rate? -1 : (this.rate == another.rate ? 0 : 1);
-        }
-
         @Override
         public String toString() {
             return text;
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/XMLPrefsManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/XMLPrefsManager.java
index b95ed48574fa42527090d473b94143fbec9e7d2b..0a76a826d3afbccd1d59e9034ab0e6a7970bfa56 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/XMLPrefsManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/XMLPrefsManager.java
@@ -7,6 +7,7 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -14,7 +15,6 @@ import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -26,6 +26,9 @@ import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
 import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsList;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Cmd;
 import ohi.andre.consolelauncher.managers.xml.options.Suggestions;
@@ -49,56 +52,42 @@ public class XMLPrefsManager {
         } catch (ParserConfigurationException e) {}
     }
 
-    public interface XMLPrefsSave {
-
-        String APP = "app", INTEGER = "int", BOOLEAN = "boolean", TEXT = "text", COLOR = "color";
-
-        String defaultValue();
-        String label();
-        String type();
-        String info();
-        XmlPrefsElement parent();
-        boolean is(String s);
-    }
-
-    public enum XMLPrefsRoot implements XmlPrefsElement {
+    public enum XMLPrefsRoot implements XMLPrefsElement {
 
         THEME("theme.xml", Theme.values()) {
             @Override
             public String[] deleted() {
-                return new String[] {"rss_color"};
+                return new String[] {"notes_unlocked_color"};
             }
         },
         CMD("cmd.xml", Cmd.values()) {
             @Override
             public String[] deleted() {
-                return new String[] {"time_format", "default_translatefrom", "default_translateto"};
+                return new String[] {};
             }
         },
         TOOLBAR("toolbar.xml", Toolbar.values()) {
             @Override
             public String[] deleted() {
-                return new String[] {"enabled"};
+                return new String[] {};
             }
         },
         UI("ui.xml", Ui.values()) {
             @Override
             public String[] deleted() {
-                return new String[] {"status_line0_alignment", "status_line1_alignment", "status_line2_alignment", "status_line3_alignment", "status_line4_alignment", "status_line5_alignment",
-                        "font_size", "show_timestamp_before_cmd", "linux_like", "show_username_ssninfo", "show_ssninfo", "show_path_ssninfo", "show_devicename_ssninfo", "show_alias_suggestions",
-                        "transparent_bars"};
+                return new String[] {};
             }
         },
         BEHAVIOR("behavior.xml", Behavior.values()) {
             @Override
             public String[] deleted() {
-                return new String[] {"double_tap_closes", "donation_message", "tui_notification_cmd_label", "autolower_firstchar", "long_click_vibrate", "long_click_vibrate_duration"};
+                return new String[] {};
             }
         },
         SUGGESTIONS("suggestions.xml", Suggestions.values()) {
             @Override
             public String[] deleted() {
-                return new String[] {"transparent", "enabled"};
+                return new String[] {};
             }
         };
 
@@ -130,76 +119,20 @@ public class XMLPrefsManager {
         }
     }
 
-    public interface XmlPrefsElement {
-        XMLPrefsList getValues();
-        void write(XMLPrefsSave save, String value);
-        String[] deleted();
-    }
-
-    public static class XMLPrefsEntry {
-
-        public String key, value;
-
-        public XMLPrefsEntry(String key, String value) {
-            this.key = key;
-            this.value = value;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if(obj instanceof XMLPrefsEntry) return this == obj;
-            else if(obj instanceof XMLPrefsSave) return this.key.equals(((XMLPrefsSave) obj).label());
-            return obj.equals(key);
-        }
-
-        @Override
-        public String toString() {
-            return key + " --> " + value;
-        }
-    }
-
-    public static class XMLPrefsList {
-
-        public List<XMLPrefsEntry> list = new ArrayList<>();
-
-        public void add(XMLPrefsEntry entry) {
-            list.add(entry);
-        }
-
-        public void add(String key, String value) {
-            list.add(new XMLPrefsEntry(key, value));
-        }
-
-        public XMLPrefsEntry get(Object o) {
-            if(o instanceof Integer) return at((Integer) o);
-
-            for(XMLPrefsEntry e : list) if(e.equals(o)) return e;
-            return null;
-        }
-
-        public XMLPrefsEntry at(int index) {
-            return list.get(index);
-        }
+    private XMLPrefsManager() {}
 
-        public int size() {
-            return list.size();
-        }
+    public static void dispose() {
+        commonsLoaded = false;
 
-        public List<String> values() {
-            List<String> vs = new ArrayList<>();
-            for(XMLPrefsEntry entry : list) vs.add(entry.key + "=" + entry.value);
-            return vs;
+        for(XMLPrefsRoot element : XMLPrefsRoot.values()) {
+            element.values.list.clear();
         }
     }
 
-    private XMLPrefsManager() {}
-
-    static boolean called = false;
-    public static void create(Context context) throws Exception {
-        boolean timeFound = false;
-
-        if(called) return;
-        called = true;
+    static boolean commonsLoaded = false;
+    public static void loadCommons(Context context) {
+        if(commonsLoaded) return;
+        commonsLoaded = true;
 
         File folder = Tuils.getFolder();
         if(folder == null) {
@@ -220,9 +153,12 @@ public class XMLPrefsManager {
                     Tuils.sendXMLParseError(context, element.path);
                     return;
                 }
-            } catch (Exception e) {
+            } catch (SAXParseException e) {
                 Tuils.sendXMLParseError(context, element.path, e);
                 continue;
+            } catch (Exception e) {
+                Tuils.log(e);
+                return;
             }
 
             Document d = (Document) o[0];
@@ -236,7 +172,9 @@ public class XMLPrefsManager {
 
             if(root == null) {
                 resetFile(file, element.name());
-                d = builder.parse(file);
+                try {
+                    d = builder.parse(file);
+                } catch (Exception e) {}
                 root = (Element) d.getElementsByTagName(element.name()).item(0);
             }
             NodeList nodes = root.getElementsByTagName("*");
@@ -244,150 +182,33 @@ public class XMLPrefsManager {
             for(int count = 0; count < nodes.getLength(); count++) {
                 Node node = nodes.item(count);
                 String nn = node.getNodeName();
-                String value = node.getAttributes().getNamedItem(VALUE_ATTRIBUTE).getNodeValue();
-
-//                remove this in a month?
-                if(!timeFound && nn.equals(Behavior.time_format.label()) && value.contains("%")) {
-                    timeFound = true;
-
-                    Pattern p = Pattern.compile("%(.{1})");
-                    Matcher m = p.matcher(value);
-                    while(m.find()) {
-                        char charc = m.group(1).charAt(0);
-
-                        String replaceWith = null;
-                        switch (charc) {
-                            case 'a':
-                                replaceWith = "EE";
-                                break;
-                            case 'A':
-                                replaceWith = "E";
-                                break;
-                            case 'b':
-                                replaceWith = "MM";
-                                break;
-                            case 'B':
-                                replaceWith = "M";
-                                break;
-                            case 'c':
-                                replaceWith = "EE MM dd HH:mm:ss yyyy";
-                                break;
-                            case 'C':
-                                break;
-                            case 'd':
-                                replaceWith = "dd";
-                                break;
-                            case 'D':
-                                replaceWith = "MM dd yyyy";
-                                break;
-                            case 'e':
-                                replaceWith = "dd";
-                                break;
-                            case 'F':
-                                replaceWith = "yyyy-MMM-dd";
-                                break;
-                            case 'g':
-                                break;
-                            case 'G':
-                                break;
-                            case 'h':
-                                replaceWith = "MMM";
-                                break;
-                            case 'H':
-                                replaceWith = "HH";
-                                break;
-                            case 'I':
-                                replaceWith = "hh";
-                                break;
-                            case 'j':
-                                replaceWith = "DDD";
-                                break;
-                            case 'k':
-                                replaceWith = "HH";
-                                break;
-                            case 'l':
-                                replaceWith = "hh";
-                                break;
-                            case 'm':
-                                replaceWith = "MM";
-                                break;
-                            case 'M':
-                                replaceWith = "mm";
-                                break;
-                            case 'n':
-                                break;
-                            case 'N':
-                                break;
-                            case 'p':
-                                replaceWith = "a";
-                                break;
-                            case 'P':
-                                break;
-                            case 'r':
-                                replaceWith = "KK:mm:ss a";
-                                break;
-                            case 'R':
-                                replaceWith = "HH:mm";
-                                break;
-                            case 's':
-                                break;
-                            case 'S':
-                                replaceWith = "s";
-                                break;
-                            case 't':
-                                break;
-                            case 'T':
-                                replaceWith = "HH:mm:ss";
-                                break;
-                            case 'u':
-                                replaceWith = "u";
-                                break;
-                            case 'U':
-                                replaceWith = "w";
-                                break;
-                            case 'V':
-                                break;
-                            case 'w':
-                                replaceWith = "u";
-                                break;
-                            case 'W':
-                                replaceWith = "w";
-                                break;
-                            case 'x':
-                                replaceWith = "MMM/dd/yyyy";
-                                break;
-                            case 'X':
-                                replaceWith = "HH:mm:ss";
-                                break;
-                            case 'y':
-                                replaceWith = "yy";
-                                break;
-                            case 'Y':
-                                replaceWith = "yyyy";
-                                break;
-                        }
-
-                        if(replaceWith != null) value = value.replaceAll(m.group(0), replaceWith);
-                    }
 
-                    ((Element) node).setAttribute(VALUE_ATTRIBUTE, value);
+                String value;
+                try {
+                    value = node.getAttributes().getNamedItem(VALUE_ATTRIBUTE).getNodeValue();
+                } catch (Exception e) {
+                    continue;
                 }
 
                 element.values.add(nn, value);
 
+                boolean check = false;
                 for(int en = 0; en < enums.size(); en++) {
                     if(enums.get(en).label().equals(nn)) {
                         enums.remove(en);
+                        check = true;
                         break;
-                    } else if(deleted != null) {
-                        int index = Tuils.find(nn, deleted);
-                        if(index != -1) {
-                            deleted[index] = null;
-                            Element e = (Element) node;
-                            root.removeChild(e);
-
-                            needToWrite = true;
-                        }
+                    }
+                }
+
+                if(!check && deleted != null) {
+                    int index = Tuils.find(nn, deleted);
+                    if(index != -1) {
+                        deleted[index] = null;
+                        Element e = (Element) node;
+                        root.removeChild(e);
+
+                        needToWrite = true;
                     }
                 }
             }
@@ -432,6 +253,81 @@ public class XMLPrefsManager {
         return Tuils.getDefaultValue(c);
     }
 
+    public static float getFloat(XMLPrefsSave prefsSave) {
+        return get(float.class, prefsSave);
+    }
+
+    public static double getDouble(XMLPrefsSave prefsSave) {
+        return get(double.class, prefsSave);
+    }
+
+    public static int getInt(XMLPrefsSave prefsSave) {
+        return get(int.class, prefsSave);
+    }
+
+    public static boolean getBoolean(XMLPrefsSave prefsSave) {
+        return get(boolean.class, prefsSave);
+    }
+
+    public static int getColor(XMLPrefsSave prefsSave) {
+        if(prefsSave.parent() == null) return Integer.MAX_VALUE;
+
+        try {
+            return (int) transform(prefsSave.parent().getValues().get(prefsSave).value, Color.class);
+        } catch (Exception e) {
+            String def = prefsSave.defaultValue();
+            if(def == null || def.length() == 0) {
+                return Integer.MAX_VALUE;
+            }
+
+            try {
+                return (int) transform(def, Color.class);
+            } catch (Exception e1) {
+                return Integer.MAX_VALUE;
+            }
+        }
+    }
+
+    public static String getString(XMLPrefsSave prefsSave) {
+        return get(prefsSave);
+    }
+
+    public static <T> T get(Class<T> c, XMLPrefsRoot root, String s) {
+        try {
+            return (T) transform(root.getValues().get(s).value, c);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static <T> T get(Class<T> c, XMLPrefsSave prefsSave) {
+        try {
+//            if(prefsSave.is(Notifications.show_notifications.label())) {
+//                Tuils.log("----------------");
+//                Tuils.log("label", prefsSave.label());
+//                Tuils.log("parent", prefsSave.parent().toString());
+//                Tuils.log("values tostring", prefsSave.parent().getValues().toString());
+//            }
+            return (T) transform(prefsSave.parent().getValues().get(prefsSave).value, c);
+        } catch (Exception e) {
+//            this will happen if the option is not found
+            try {
+                return (T) transform(prefsSave.defaultValue(), c);
+            } catch (Exception e1) {
+//                attempts to get a default value for the given type, as we say in italian, "the last beach"
+                return Tuils.getDefaultValue(c);
+            }
+        }
+    }
+
+    public static String get(XMLPrefsSave prefsSave) {
+        return get(String.class, prefsSave);
+    }
+
+    public static String get(XMLPrefsRoot root, String s) {
+        return get(String.class, root, s);
+    }
+
     static final Pattern p1 = Pattern.compile(">");
 //    static final Pattern p2 = Pattern.compile("</");
     static final Pattern p3 = Pattern.compile("\n\n");
@@ -450,6 +346,10 @@ public class XMLPrefsManager {
 //    [0] = document
 //    [1] = root
     public static Object[] buildDocument(File file, String rootName) throws Exception {
+        if(!file.exists()) {
+            resetFile(file, rootName);
+        }
+
         Document d;
         try {
             d = builder.parse(file);
@@ -457,12 +357,12 @@ public class XMLPrefsManager {
             Tuils.log(e);
 
             int nOfBytes = Tuils.nOfBytes(file);
-            Tuils.log("nof", nOfBytes);
             if(nOfBytes == 0 && rootName != null) {
                 XMLPrefsManager.resetFile(file, rootName);
                 d = builder.parse(file);
             } else return null;
         }
+
         Element r = d.getDocumentElement();
         return new Object[] {d, r};
     }
@@ -564,7 +464,7 @@ public class XMLPrefsManager {
                     if(n.getNodeType() == Node.ELEMENT_NODE) {
                         Element e = (Element) n;
 
-                        if(!checkAttributes(e, thatHasThose, forValues)) {
+                        if(!checkAttributes(e, thatHasThose, forValues, false)) {
                             continue Nodes;
                         }
 
@@ -637,6 +537,48 @@ public class XMLPrefsManager {
         }
     }
 
+    public static String removeNode(File file, String[] thatHasThose, String[] forValues) {
+        return removeNode(file, thatHasThose, forValues, false,false);
+    }
+
+    public static String removeNode(File file, String[] thatHasThose, String[] forValues, boolean alsoNotFound, boolean all) {
+        try {
+            Object[] o;
+            try {
+                o = buildDocument(file, null);
+                if(o == null) return Tuils.EMPTYSTRING;
+            } catch (Exception e) {
+                return e.toString();
+            }
+
+            Document d = (Document) o[0];
+            Element root = (Element) o[1];
+
+            NodeList list = root.getElementsByTagName("*");
+
+            boolean check = false;
+
+            for(int c = 0; c < list.getLength(); c++) {
+                Node n = list.item(c);
+
+                if(!(n instanceof Element)) continue;
+                Element e = (Element) n;
+
+                if(checkAttributes(e, thatHasThose, forValues, alsoNotFound)) {
+                    check = true;
+                    root.removeChild(n);
+                    if(!all) break;
+                }
+            }
+
+            writeTo(d, file);
+
+            return check ? null : Tuils.EMPTYSTRING;
+        } catch (Exception e) {
+            return e.toString();
+        }
+    }
+
     public static Node findNode(File file, String nodeName) {
         return findNode(file, nodeName, null, null);
     }
@@ -659,17 +601,40 @@ public class XMLPrefsManager {
         }
     }
 
-    public static Node findNode(Element root, String nodeName) {
-        return findNode(root, nodeName, null, null);
-    }
-
 //    useful only if you're looking for a single node
     public static Node findNode(Element root, String nodeName, String[] thatHasThose, String[] forValues) {
         NodeList nodes = root.getElementsByTagName(nodeName);
-        for(int j = 0; j < nodes.getLength(); j++) if(checkAttributes((Element) nodes.item(j), thatHasThose, forValues)) return nodes.item(j);
+        for(int j = 0; j < nodes.getLength(); j++) if(checkAttributes((Element) nodes.item(j), thatHasThose, forValues, false)) return nodes.item(j);
         return null;
     }
 
+    public static Node findNode(Element root, String nodeName) {
+        return findNode(root, nodeName, null, null);
+    }
+
+    public static List<Node> findNodes(Element root, String nodeName, String[] thatHasThose, String[] forValue) {
+        NodeList nodes = root.getElementsByTagName(nodeName != null ? nodeName : "*");
+
+        List<Node> nodeList = new ArrayList<>();
+
+        for(int c = 0; c < nodes.getLength(); c++) {
+            Node n = nodeList.get(c);
+
+            if(!(n instanceof Element)) continue;
+            Element e = (Element) n;
+
+            if(checkAttributes(e, thatHasThose, forValue, false)) {
+                nodeList.add(n);
+            }
+        }
+
+        return nodeList;
+    }
+
+    public static List<Node> findNodes(Element root, String[] thatHasThose, String[] forValue) {
+        return findNodes(root, null, thatHasThose, forValue);
+    }
+
     public static String attrValue(File file, String nodeName, String attrName) {
         return attrValue(file, nodeName, null, null, attrName);
     }
@@ -701,7 +666,7 @@ public class XMLPrefsManager {
                 Node node = nodes.item(count);
                 Element e = (Element) node;
 
-                if(!checkAttributes(e, thatHasThose, forValues)) continue;
+                if(!checkAttributes(e, thatHasThose, forValues, false)) continue;
 
                 String[] values = new String[attrNames.length];
                 for(int c = 0; c < attrNames.length; c++) values[count] = e.getAttribute(attrNames[c]);
@@ -713,75 +678,20 @@ public class XMLPrefsManager {
         return null;
     }
 
-    private static boolean checkAttributes(Element e, String[] thatHasThose, String[] forValues) {
+    private static boolean checkAttributes(Element e, String[] thatHasThose, String[] forValues, boolean alsoNotFound) {
         if(thatHasThose != null && forValues != null && thatHasThose.length == forValues.length) {
             for(int a = 0; a < thatHasThose.length; a++) {
-                if(!e.hasAttribute(thatHasThose[a])) return false;
+                if(!e.hasAttribute(thatHasThose[a])) return alsoNotFound;
                 if(!forValues[a].equals(e.getAttribute(thatHasThose[a]))) return false;
             }
         }
         return true;
     }
 
-    public static float getFloat(XMLPrefsManager.XMLPrefsSave prefsSave) {
-        return get(float.class, prefsSave);
-    }
-
-    public static double getDouble(XMLPrefsManager.XMLPrefsSave prefsSave) {
-        return get(double.class, prefsSave);
-    }
-
-    public static int getInt(XMLPrefsManager.XMLPrefsSave prefsSave) {
-        return get(int.class, prefsSave);
-    }
-
-    public static boolean getBoolean(XMLPrefsManager.XMLPrefsSave prefsSave) {
-        return get(boolean.class, prefsSave);
-    }
-
-    public static int getColor(XMLPrefsManager.XMLPrefsSave prefsSave) {
-        if(prefsSave.parent() == null) return Integer.MAX_VALUE;
-
-        try {
-            return (int) transform(prefsSave.parent().getValues().get(prefsSave).value, Color.class);
-        } catch (Exception e) {
-            String def = prefsSave.defaultValue();
-            if(def == null || def.length() == 0) {
-                return Integer.MAX_VALUE;
-            }
-
-            try {
-                return (int) transform(def, Color.class);
-            } catch (Exception e1) {
-                return Integer.MAX_VALUE;
-            }
-        }
-    }
-
-    public static String getString(XMLPrefsSave prefsSave) {
-        return get(prefsSave);
-    }
-
-    public static <T> T get(Class<T> c, XMLPrefsManager.XMLPrefsSave prefsSave) {
-        try {
-            return (T) transform(prefsSave.parent().getValues().get(prefsSave).value, c);
-        } catch (Exception e) {
-//            this will happen if the option is not found
-            try {
-                return (T) transform(prefsSave.defaultValue(), c);
-            } catch (Exception e1) {
-//                attempts to get a default value for the given type, as we say in italian, "the last beach"
-                return Tuils.getDefaultValue(c);
-            }
-        }
-    }
-
-    public static String get(XMLPrefsManager.XMLPrefsSave prefsSave) {
-        return get(String.class, prefsSave);
-    }
-
     public static boolean resetFile(File f, String name) {
         try {
+            if(f.exists()) f.delete();
+
             FileOutputStream stream = new FileOutputStream(f);
             stream.write(XML_DEFAULT.getBytes());
             stream.write(("<" + name + ">\n").getBytes());
@@ -800,12 +710,33 @@ public class XMLPrefsManager {
 
     public static long getLongAttribute(Element e, String attribute) {
         String value = getStringAttribute(e, attribute);
-        if(value == null) return -1;
-        return Long.parseLong(value);
+        try {
+            return Long.parseLong(value);
+        } catch (Exception ex) {
+            return -1;
+        }
     }
 
     public static boolean getBooleanAttribute(Element e, String attribute) {
-        return Boolean.parseBoolean(getStringAttribute(e, attribute));
+        String s = getStringAttribute(e, attribute);
+        return s != null && Boolean.parseBoolean(s);
+
+    }
+
+    public static int getIntAttribute(Element e, String attribute) {
+        try {
+            return Integer.parseInt(getStringAttribute(e, attribute));
+        } catch (Exception ex) {
+            return -1;
+        }
+    }
+
+    public static float getFloatAttribute(Element e, String attribute) {
+        try {
+            return Float.parseFloat(getStringAttribute(e, attribute));
+        } catch (Exception ex) {
+            return -1;
+        }
     }
 
     public static class IdValue {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsElement.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..124bd781daa6c4b5e65fdb9535b7de0edb1f36ce
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsElement.java
@@ -0,0 +1,11 @@
+package ohi.andre.consolelauncher.managers.xml.classes;
+
+/**
+ * Created by francescoandreuzzi on 06/03/2018.
+ */
+
+public interface XMLPrefsElement {
+    XMLPrefsList getValues();
+    void write(XMLPrefsSave save, String value);
+    String[] deleted();
+}
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsEntry.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..36432b29f127ad8a120d6233df58ee199d5e6327
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsEntry.java
@@ -0,0 +1,27 @@
+package ohi.andre.consolelauncher.managers.xml.classes;
+
+/**
+ * Created by francescoandreuzzi on 06/03/2018.
+ */
+
+public class XMLPrefsEntry {
+
+    public String key, value;
+
+    public XMLPrefsEntry(String key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if(obj instanceof XMLPrefsEntry) return this == obj;
+        else if(obj instanceof XMLPrefsSave) return this.key.equals(((XMLPrefsSave) obj).label());
+        return obj.equals(key);
+    }
+
+    @Override
+    public String toString() {
+        return key + " --> " + value;
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsList.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsList.java
new file mode 100644
index 0000000000000000000000000000000000000000..86472a16c8538ae1e6d47ce8869e2e31162b4ec3
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsList.java
@@ -0,0 +1,55 @@
+package ohi.andre.consolelauncher.managers.xml.classes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+/**
+ * Created by francescoandreuzzi on 06/03/2018.
+ */
+
+public class XMLPrefsList {
+
+    public List<XMLPrefsEntry> list = new ArrayList<>();
+
+    public void add(XMLPrefsEntry entry) {
+        list.add(entry);
+    }
+
+    public void add(String key, String value) {
+        list.add(new XMLPrefsEntry(key, value));
+    }
+
+    public XMLPrefsEntry get(Object o) {
+        if(o instanceof Integer) return at((Integer) o);
+
+        for(XMLPrefsEntry e : list) if(e.equals(o)) return e;
+        return null;
+    }
+
+    public XMLPrefsEntry at(int index) {
+        return list.get(index);
+    }
+
+    public int size() {
+        return list.size();
+    }
+
+    public List<String> values() {
+        List<String> vs = new ArrayList<>();
+        for(XMLPrefsEntry entry : list) vs.add(entry.key + "=" + entry.value);
+        return vs;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+
+        for(XMLPrefsEntry entry : list) {
+            builder.append(entry.key).append(" -> ").append(entry.value).append(Tuils.NEWLINE);
+        }
+
+        return builder.toString().trim();
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsSave.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsSave.java
new file mode 100644
index 0000000000000000000000000000000000000000..99fd5f4eff2173d89c2d804678dd7cb947eacb45
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/classes/XMLPrefsSave.java
@@ -0,0 +1,16 @@
+package ohi.andre.consolelauncher.managers.xml.classes;
+
+/**
+ * Created by francescoandreuzzi on 06/03/2018.
+ */
+
+public interface XMLPrefsSave {
+    String APP = "app", INTEGER = "int", BOOLEAN = "boolean", TEXT = "text", COLOR = "color";
+
+    String defaultValue();
+    String label();
+    String type();
+    String info();
+    XMLPrefsElement parent();
+    boolean is(String s);
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Apps.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Apps.java
index 5068a24dfeb8cbe994c1ea4595682b69ebf9b6e2..63f4b013bf1f8e4e02830af585dea24a1b2363dd 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Apps.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Apps.java
@@ -1,13 +1,14 @@
 package ohi.andre.consolelauncher.managers.xml.options;
 
 import ohi.andre.consolelauncher.managers.AppsManager;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Apps implements XMLPrefsManager.XMLPrefsSave {
+public enum Apps implements XMLPrefsSave {
 
     default_app_n1 {
         @Override
@@ -63,6 +64,22 @@ public enum Apps implements XMLPrefsManager.XMLPrefsSave {
         public String info() {
             return "The fifth default-suggested app";
         }
+    },
+    app_groups_sorting {
+        @Override
+        public String defaultValue() {
+            return "2";
+        }
+
+        @Override
+        public String info() {
+            return "0 = time up->down; 1 = time down->up; 2 = alphabetical up->down; 3 = alphabetical down->up; 4 = most used up->down; 5 = most used down->up";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.INTEGER;
+        }
     };
 
     public static final String MOST_USED = "most_used";
@@ -74,7 +91,7 @@ public enum Apps implements XMLPrefsManager.XMLPrefsSave {
     }
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return AppsManager.instance;
     }
 
@@ -85,6 +102,6 @@ public enum Apps implements XMLPrefsManager.XMLPrefsSave {
 
     @Override
     public String type() {
-        return XMLPrefsManager.XMLPrefsSave.APP;
+        return XMLPrefsSave.APP;
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Behavior.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Behavior.java
index a72ddfe7630485366d7dbbab9655ba5c69f7d640..86c781e7e68dfb0a705d7e556272a89746f75514 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Behavior.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Behavior.java
@@ -5,13 +5,15 @@ import android.os.Environment;
 import java.io.File;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
+public enum Behavior implements XMLPrefsSave {
 
     double_tap_lock {
         @Override
@@ -26,7 +28,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     double_tap_cmd {
@@ -42,7 +44,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     random_play {
@@ -58,7 +60,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     songs_folder {
@@ -74,7 +76,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     songs_from_mediastore {
@@ -90,7 +92,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     tui_notification {
@@ -106,7 +108,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     auto_show_keyboard {
@@ -122,7 +124,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     auto_scroll {
@@ -138,7 +140,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     show_hints {
@@ -154,7 +156,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     show_alias_content {
@@ -170,7 +172,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     show_launch_history {
@@ -186,7 +188,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     clear_after_cmds {
@@ -202,7 +204,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     clear_after_seconds {
@@ -218,7 +220,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     max_lines {
@@ -234,7 +236,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     time_format {
@@ -250,7 +252,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     time_format_separator {
@@ -266,7 +268,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     battery_medium {
@@ -282,7 +284,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     battery_low {
@@ -298,7 +300,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     device_format {
@@ -314,7 +316,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     ram_format {
@@ -330,7 +332,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     battery_format {
@@ -346,7 +348,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     storage_format {
@@ -362,7 +364,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     network_info_format {
@@ -378,7 +380,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     input_format {
@@ -394,7 +396,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     output_format {
@@ -410,7 +412,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     session_info_format {
@@ -426,7 +428,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     enable_app_launch {
@@ -442,7 +444,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     app_launch_format {
@@ -458,7 +460,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     alias_param_marker {
@@ -474,7 +476,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     alias_param_separator {
@@ -490,7 +492,23 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
+        }
+    },
+    alias_replace_all_markers {
+        @Override
+        public String defaultValue() {
+            return "true";
+        }
+
+        @Override
+        public String info() {
+            return "If true, if you pass a lower number of parameters to an alias, t-ui will use the first one to replace the others";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     multiple_cmd_separator {
@@ -506,7 +524,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     alias_content_format {
@@ -522,7 +540,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     external_storage_path {
@@ -544,7 +562,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     home_path {
@@ -560,7 +578,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     app_installed_format {
@@ -576,7 +594,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     app_uninstalled_format {
@@ -592,23 +610,23 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     enable_music {
         @Override
         public String defaultValue() {
-            return "true";
+            return "false";
         }
 
         @Override
         public String info() {
-            return "If false, t-ui won't try to load music from your device on startup";
+            return "If true, you will be able to use t-ui as a music player. Otherwise, the music command will try to communicate with the music player that your using";
         }
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     max_optional_depth {
@@ -624,7 +642,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     network_info_update_ms {
@@ -640,7 +658,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     tui_notification_title {
@@ -656,7 +674,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     tui_notification_subtitle {
@@ -672,7 +690,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     tui_notification_click_cmd {
@@ -688,7 +706,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     },
     tui_notification_click_showhome {
@@ -704,7 +722,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     tui_notification_lastcmds_size {
@@ -720,7 +738,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     tui_notification_lastcmds_updown {
@@ -736,7 +754,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     tui_notification_priority {
@@ -752,7 +770,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     long_click_vibration_duration {
@@ -768,7 +786,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     long_click_duration {
@@ -784,7 +802,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
     },
     click_commands {
@@ -800,7 +818,7 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     },
     long_click_commands {
@@ -816,12 +834,92 @@ public enum Behavior implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
+        }
+    },
+    append_quote_before_file {
+        @Override
+        public String defaultValue() {
+            return "false";
+        }
+
+        @Override
+        public String info() {
+            return "If true, t-ui will automatically append a quote before a file inserted clicking on a suggestion";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
+        }
+    },
+    optional_values_separator {
+        @Override
+        public String defaultValue() {
+            return "/";
+        }
+
+        @Override
+        public String info() {
+            return "The separator between two optional values (doesn\'t affect notification optional values)";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.TEXT;
+        }
+    },
+    notes_sorting {
+        @Override
+        public String defaultValue() {
+            return "0";
+        }
+
+        @Override
+        public String info() {
+            return "0 = time up->down; 1 = time down->up; 2 = alphabetical up->down; 3 = alphabetical down->up; 4 = locked before; 5 = unlocked before";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.INTEGER;
+        }
+    },
+    notes_allow_link {
+        @Override
+        public String defaultValue() {
+            return "true";
+        }
+
+        @Override
+        public String info() {
+            return "If false, adding links to notes will be disallowed (may slightly increase performance)";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
+        }
+    },
+    orientation {
+        @Override
+        public String defaultValue() {
+            return "2";
+        }
+
+        @Override
+        public String info() {
+            return "0 = landscape, 1 = portrait, 2 = sensor";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.INTEGER;
         }
     };
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return XMLPrefsManager.XMLPrefsRoot.BEHAVIOR;
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Cmd.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Cmd.java
index b5615bfa1e39b170bdfd7b93ef68fd346c55771e..84a02353deb5f27f8fc162e97fa008827653b907 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Cmd.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Cmd.java
@@ -1,12 +1,14 @@
 package ohi.andre.consolelauncher.managers.xml.options;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Cmd implements XMLPrefsManager.XMLPrefsSave {
+public enum Cmd implements XMLPrefsSave {
 
     default_search {
         @Override
@@ -21,12 +23,12 @@ public enum Cmd implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
     };
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return XMLPrefsManager.XMLPrefsRoot.CMD;
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Notifications.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Notifications.java
index 0a53ad0da6ac42352e66f15cd9c68746902943e2..6669087cd5ac7e02d6385896a1e2287e640a7e07 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Notifications.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Notifications.java
@@ -1,13 +1,14 @@
 package ohi.andre.consolelauncher.managers.xml.options;
 
 import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Notifications implements XMLPrefsManager.XMLPrefsSave {
+public enum Notifications implements XMLPrefsSave {
 
     show_notifications {
         @Override
@@ -39,7 +40,7 @@ public enum Notifications implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.COLOR;
+            return XMLPrefsSave.COLOR;
         }
 
         @Override
@@ -55,7 +56,7 @@ public enum Notifications implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -84,10 +85,58 @@ public enum Notifications implements XMLPrefsManager.XMLPrefsSave {
         public String info() {
             return "If true, you will be able to perform some quick operations long-clicking a notification";
         }
+    },
+    notification_popup_exclude_app {
+        @Override
+        public String defaultValue() {
+            return "true";
+        }
+
+        @Override
+        public String info() {
+            return "If false, the \"Exclude app\" option won\'t be shown in the long click popup menu";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
+        }
+    },
+    notification_popup_exclude_notification {
+        @Override
+        public String defaultValue() {
+            return "true";
+        }
+
+        @Override
+        public String info() {
+            return "If false, the \"Exclude notification\" option won\'t be shown in the long click popup menu";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
+        }
+    },
+    notification_popup_reply {
+        @Override
+        public String defaultValue() {
+            return "true";
+        }
+
+        @Override
+        public String info() {
+            return "If false, the \"Reply to the last notification\" option won\'t be shown in the long click popup menu";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
+        }
     };
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return NotificationManager.instance;
     }
 
@@ -103,6 +152,6 @@ public enum Notifications implements XMLPrefsManager.XMLPrefsSave {
 
     @Override
     public String type() {
-        return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+        return XMLPrefsSave.BOOLEAN;
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Reply.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Reply.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ea97f908c8f97e794e6dce184e321c565eaabb6
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Reply.java
@@ -0,0 +1,44 @@
+package ohi.andre.consolelauncher.managers.xml.options;
+
+import ohi.andre.consolelauncher.managers.notifications.reply.ReplyManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
+
+/**
+ * Created by francescoandreuzzi on 17/01/2018.
+ */
+
+public enum Reply implements XMLPrefsSave {
+
+    reply_enabled {
+        @Override
+        public String defaultValue() {
+            return "true";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
+        }
+
+        @Override
+        public String info() {
+            return "If false, notification reply will be disabled";
+        }
+    };
+
+    @Override
+    public XMLPrefsElement parent() {
+        return ReplyManager.instance;
+    }
+
+    @Override
+    public String label() {
+        return name();
+    }
+
+    @Override
+    public boolean is(String s) {
+        return name().equals(s);
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Rss.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Rss.java
index 7ed14cec19323772afa7c5831484ef5d93a8f8d4..81ee0109d4d0a9ca130995457b9074293bf4d5d8 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Rss.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Rss.java
@@ -1,13 +1,14 @@
 package ohi.andre.consolelauncher.managers.xml.options;
 
 import ohi.andre.consolelauncher.managers.RssManager;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 03/10/2017.
  */
 
-public enum Rss implements XMLPrefsManager.XMLPrefsSave {
+public enum Rss implements XMLPrefsSave {
 
     rss_default_color {
         @Override
@@ -17,7 +18,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.COLOR;
+            return XMLPrefsSave.COLOR;
         }
 
         @Override
@@ -33,7 +34,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -49,7 +50,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.COLOR;
+            return XMLPrefsSave.COLOR;
         }
 
         @Override
@@ -65,7 +66,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -81,7 +82,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -97,7 +98,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.COLOR;
+            return XMLPrefsSave.COLOR;
         }
 
         @Override
@@ -113,7 +114,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -129,7 +130,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.COLOR;
+            return XMLPrefsSave.COLOR;
         }
 
         @Override
@@ -145,7 +146,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.COLOR;
+            return XMLPrefsSave.COLOR;
         }
 
         @Override
@@ -162,7 +163,7 @@ public enum Rss implements XMLPrefsManager.XMLPrefsSave {
     ;
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return RssManager.instance;
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Suggestions.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Suggestions.java
index 3097d5937af8316b58e9db8bc90929fe13925c17..5f897d5c8d5bd2993407018cc49069db3d3a3c70 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Suggestions.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Suggestions.java
@@ -1,12 +1,14 @@
 package ohi.andre.consolelauncher.managers.xml.options;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
+public enum Suggestions implements XMLPrefsSave {
 
     show_suggestions {
         @Override
@@ -16,7 +18,7 @@ public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -32,7 +34,7 @@ public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -202,7 +204,7 @@ public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -218,7 +220,7 @@ public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -234,7 +236,7 @@ public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -250,17 +252,81 @@ public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
         public String info() {
             return "The text size of the suggestions";
         }
+    },
+    double_space_click_first_suggestion {
+        @Override
+        public String defaultValue() {
+            return "false";
+        }
+
+        @Override
+        public String type() {
+            return BOOLEAN;
+        }
+
+        @Override
+        public String info() {
+            return "If true, t-ui will simulate a click on the current first suggestion if you double-click the space bar";
+        }
+    },
+    noinput_suggestions_order {
+        @Override
+        public String defaultValue() {
+            return "0(5)1(5)2(5)3(3)";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.TEXT;
+        }
+
+        @Override
+        public String info() {
+            return "The order and the number of suggestions that appears on-screen when the input field is empty. 0=apps, 1=alias, 2=cmds, 3=app groups. Put between round brackets the maximum number of suggestions of the leading type";
+        }
+    },
+    suggestions_order {
+        @Override
+        public String defaultValue() {
+            return "0(5)1(5)2(5)3(3)";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.TEXT;
+        }
+
+        @Override
+        public String info() {
+            return "The order and the number of suggestions that appears on-screen. 0=apps, 1=alias, 2=cmds, 3=app groups. Put between round brackets the maximum number of suggestions of the leading type";
+        }
+    },
+    noinput_min_command_priority {
+        @Override
+        public String defaultValue() {
+            return "5";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.INTEGER;
+        }
+
+        @Override
+        public String info() {
+            return "The minimum priority of a command shown when the input field is empty";
+        }
     };
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return XMLPrefsManager.XMLPrefsRoot.SUGGESTIONS;
     }
 
@@ -276,6 +342,6 @@ public enum Suggestions implements XMLPrefsManager.XMLPrefsSave {
 
     @Override
     public String type() {
-        return XMLPrefsManager.XMLPrefsSave.COLOR;
+        return XMLPrefsSave.COLOR;
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Theme.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Theme.java
index b05c43088a3ae571abaf524fb9a8692f4c248bd3..f4ac326ff514f9eeb60042c3c84ca645da99c358 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Theme.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Theme.java
@@ -1,12 +1,14 @@
 package ohi.andre.consolelauncher.managers.xml.options;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Theme implements XMLPrefsManager.XMLPrefsSave {
+public enum Theme implements XMLPrefsSave {
 
     input_color {
         @Override
@@ -260,10 +262,43 @@ public enum Theme implements XMLPrefsManager.XMLPrefsSave {
         public String info() {
             return "The background color that will be used as marker";
         }
+    },
+    notes_color {
+        @Override
+        public String defaultValue() {
+            return "#8BC34A";
+        }
+
+        @Override
+        public String info() {
+            return "The default color of your notes";
+        }
+    },
+    notes_locked_color {
+        @Override
+        public String defaultValue() {
+            return "#3D5AFE";
+        }
+
+        @Override
+        public String info() {
+            return "The color of your locked notes";
+        }
+    },
+    link_color {
+        @Override
+        public String defaultValue() {
+            return "#0000EE";
+        }
+
+        @Override
+        public String info() {
+            return "The color of the links";
+        }
     };
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return XMLPrefsManager.XMLPrefsRoot.THEME;
     }
 
@@ -279,6 +314,6 @@ public enum Theme implements XMLPrefsManager.XMLPrefsSave {
 
     @Override
     public String type() {
-        return XMLPrefsManager.XMLPrefsSave.COLOR;
+        return XMLPrefsSave.COLOR;
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Toolbar.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Toolbar.java
index efc2ebde3d79173a7883cb2bca81c76e14766eeb..42e9cc5fee3e15a757d71b8d10bc8bdbfd243c2d 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Toolbar.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Toolbar.java
@@ -1,12 +1,14 @@
 package ohi.andre.consolelauncher.managers.xml.options;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Toolbar implements XMLPrefsManager.XMLPrefsSave {
+public enum Toolbar implements XMLPrefsSave {
 
     show_toolbar {
         @Override
@@ -21,12 +23,12 @@ public enum Toolbar implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
     };
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return XMLPrefsManager.XMLPrefsRoot.TOOLBAR;
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Ui.java b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Ui.java
index a0fe32ed9bbadd2c88d5031618bde780f826ecbf..4b54f1f38d67ccd44f62fcbcde44c8ebc0ef40aa 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Ui.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/xml/options/Ui.java
@@ -3,12 +3,14 @@ package ohi.andre.consolelauncher.managers.xml.options;
 import android.os.Build;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsElement;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 
 /**
  * Created by francescoandreuzzi on 24/09/2017.
  */
 
-public enum Ui implements XMLPrefsManager.XMLPrefsSave {
+public enum Ui implements XMLPrefsSave {
 
     show_enter_button {
         @Override
@@ -18,7 +20,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -34,7 +36,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -50,7 +52,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -66,7 +68,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -82,7 +84,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -98,7 +100,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -114,7 +116,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -130,7 +132,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -138,6 +140,22 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
             return "The network label font size";
         }
     },
+    notes_size {
+        @Override
+        public String defaultValue() {
+            return "13";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.INTEGER;
+        }
+
+        @Override
+        public String info() {
+            return "Notes size";
+        }
+    },
     input_output_size {
         @Override
         public String defaultValue() {
@@ -146,7 +164,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -162,7 +180,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -178,7 +196,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -194,7 +212,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -210,7 +228,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -226,7 +244,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -242,7 +260,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -250,6 +268,22 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
             return "If false, the time label will be hidden";
         }
     },
+    show_notes {
+        @Override
+        public String defaultValue() {
+            return "true";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.BOOLEAN;
+        }
+
+        @Override
+        public String info() {
+            return "If false, the notes label will be hidden";
+        }
+    },
     enable_battery_status {
         @Override
         public String defaultValue() {
@@ -258,7 +292,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -274,7 +308,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -290,7 +324,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -306,7 +340,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -322,7 +356,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -338,7 +372,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -354,7 +388,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -370,7 +404,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -386,7 +420,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -402,7 +436,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -418,7 +452,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -434,7 +468,23 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
+        }
+
+        @Override
+        public String info() {
+            return "This is used to order the labels on top of the screen";
+        }
+    },
+    notes_index {
+        @Override
+        public String defaultValue() {
+            return "6";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -450,12 +500,12 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
         public String info() {
-            return "The alignment of the first status line (<0 = left, =0 = center, >0 = right)";
+            return "The alignment of the 1st status line (<0 = left, =0 = center, >0 = right)";
         }
     },
     status_line1_alignment {
@@ -466,12 +516,12 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
         public String info() {
-            return "The alignment of the second status line (<0 = left, =0 = center, >0 = right)";
+            return "The alignment of the 2nd status line (<0 = left, =0 = center, >0 = right)";
         }
     },
     status_line2_alignment {
@@ -482,12 +532,12 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
         public String info() {
-            return "The alignment of the third status line (<0 = left, =0 = center, >0 = right)";
+            return "The alignment of the 3rd status line (<0 = left, =0 = center, >0 = right)";
         }
     },
     status_line3_alignment {
@@ -498,12 +548,12 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
         public String info() {
-            return "The alignment of the fourth status line (<0 = left, =0 = center, >0 = right)";
+            return "The alignment of the 4th status line (<0 = left, =0 = center, >0 = right)";
         }
     },
     status_line4_alignment {
@@ -514,12 +564,12 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
         public String info() {
-            return "The alignment of the fifth status line (<0 = left, =0 = center, >0 = right)";
+            return "The alignment of the 5th status line (<0 = left, =0 = center, >0 = right)";
         }
     },
     status_line5_alignment {
@@ -530,12 +580,28 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
+        }
+
+        @Override
+        public String info() {
+            return "The alignment of the 6th status line (<0 = left, =0 = center, >0 = right)";
+        }
+    },
+    status_line6_alignment {
+        @Override
+        public String defaultValue() {
+            return "0";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
         public String info() {
-            return "The alignment of the sixth status line (<0 = left, =0 = center, >0 = right)";
+            return "The alignment of the 7th status line (<0 = left, =0 = center, >0 = right)";
         }
     },
     input_prefix {
@@ -546,7 +612,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -562,7 +628,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.TEXT;
+            return XMLPrefsSave.TEXT;
         }
 
         @Override
@@ -578,7 +644,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -594,7 +660,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -610,7 +676,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -626,7 +692,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.INTEGER;
+            return XMLPrefsSave.INTEGER;
         }
 
         @Override
@@ -642,7 +708,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -658,7 +724,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -674,7 +740,7 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
@@ -690,17 +756,65 @@ public enum Ui implements XMLPrefsManager.XMLPrefsSave {
 
         @Override
         public String type() {
-            return XMLPrefsManager.XMLPrefsSave.BOOLEAN;
+            return XMLPrefsSave.BOOLEAN;
         }
 
         @Override
         public String info() {
             return "If true, when your input field is empty there will be a short line containing some information about the current session";
         }
+    },
+    notes_header {
+        @Override
+        public String defaultValue() {
+            return "%( --- Notes : %c ---%n/No notes)";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.TEXT;
+        }
+
+        @Override
+        public String info() {
+            return "The header above your notes";
+        }
+    },
+    notes_footer {
+        @Override
+        public String defaultValue() {
+            return "%(%n --- ----- ---/)";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.TEXT;
+        }
+
+        @Override
+        public String info() {
+            return "The footer below your notes";
+        }
+    },
+    notes_divider {
+        @Override
+        public String defaultValue() {
+            return "%n";
+        }
+
+        @Override
+        public String type() {
+            return XMLPrefsSave.TEXT;
+        }
+
+        @Override
+        public String info() {
+            return "The divider between two notes";
+        }
     };
 
     @Override
-    public XMLPrefsManager.XmlPrefsElement parent() {
+    public XMLPrefsElement parent() {
         return XMLPrefsManager.XMLPrefsRoot.UI;
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/Compare.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/Compare.java
index 4775c36afd729014b4c89ff634c0e4c722c1fd58..b07f86eb41d7c25362233372db14f698479157e8 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/Compare.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/Compare.java
@@ -29,7 +29,28 @@ public class Compare {
         return s;
     }
 
+//    private static String lastComparator = null;
+//    private static double averageTime;
+//    private static int n;
+
     public static int matches(String compared, String comparator, boolean allowSkip) {
+//        Tuils.log("-----------------");
+
+//        if(lastComparator != null && lastComparator.equals(comparator)) {}
+//        else {
+//            Tuils.log("#######################");
+//            Tuils.log("average for cmp: " + lastComparator);
+//            Tuils.log("average: " + averageTime + ", n: " + n);
+//            Tuils.log("#######################");
+//
+//            averageTime = 0;
+//            n = 0;
+//
+//            lastComparator = comparator;
+//        }
+
+//        long time = System.currentTimeMillis();
+
 //        Tuils.log("compared: " + compared + ", comparator: " + comparator);
 
         compared = removeAccents(compared).toLowerCase().trim();
@@ -50,30 +71,38 @@ public class Compare {
             }
         }
 
-        String unconsidered = unconsideredSymbols.matcher(compared).replaceAll(Tuils.EMPTYSTRING);
-        if(unconsidered.length() != compared.length()) {
-            s.add(new ComparePack(unconsidered, 0, 1));
-        }
+//        String unconsidered = unconsideredSymbols.matcher(compared).replaceAll(Tuils.EMPTYSTRING);
+//        if(unconsidered.length() != compared.length()) {
+//            s.add(new ComparePack(unconsidered, 0, 1));
+//        }
 
         s.add(new ComparePack(compared, 0, 1));
 
         float maxRate = -1;
+        int maxRateIndex = -1;
+
         Main:
         for(ComparePack cmp : s) {
 //            Tuils.log("s: " + cmp.s);
 
             int stop = Math.min(cmp.s.length(), comparator.length());
+//            Tuils.log("stop", stop);
             float minus = (float) (0.5 * (comparator.length() / 5));
 
-            float rate = cmp.coefficient() * -1;
-//            Tuils.log("initialRate: " + rate);
+            float rate = 0;
             for(int i = 0; i < stop; i++) {
                 char c1 = cmp.s.charAt(i);
                 char c2 = comparator.charAt(i);
 
+//                Tuils.log("index: " + i);
+
                 if(c1 == c2) {
+//                    Tuils.log("equals");
                     rate++;
-                } else {
+                }
+                else if(unconsideredSymbols.matcher(String.valueOf(c1)).find()) {}
+                else {
+//                    Tuils.log(c1 + " is not " + c2);
                     rate -= minus;
 
                     if(rate + (stop - 1 - i) < minRate) {
@@ -86,11 +115,22 @@ public class Compare {
 
             if(rate >= minRate) {
                 maxRate = Math.max(maxRate, rate);
+                maxRateIndex = cmp.index;
 //                Tuils.log("maxRate changed");
             }
         }
 
-        return Math.round(maxRate);
+//        int delay = (int) (System.currentTimeMillis() - time);
+//        Tuils.log("return", Math.round(maxRate));
+//        Tuils.log("time: " + delay);
+//        if(delay > 4) Tuils.log("!!!!!!!!!!!!!");
+//
+//        averageTime = (averageTime * n + delay) / (n + 1);
+//        n++;
+
+        int r = Math.round(maxRate);
+        if(r == comparator.length() && maxRateIndex == 0) return Integer.MAX_VALUE;
+        return r;
     }
 
     public static List<String> matches(List<String> compared, String comparator, boolean allowSkip) {
@@ -158,6 +198,7 @@ public class Compare {
 
     private static class ComparePack {
         String s;
+
         int index;
         int total;
 
@@ -166,10 +207,6 @@ public class Compare {
             this.index = index;
             this.total = total;
         }
-
-        public int coefficient() {
-            return index;
-        }
     }
 
     public interface Stringable {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/CustomExceptionHandler.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/CustomExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..1fe280ee063fbbc1fe49011e9d142e5f1c014769
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/CustomExceptionHandler.java
@@ -0,0 +1,21 @@
+package ohi.andre.consolelauncher.tuils;
+
+/**
+ * Created by francescoandreuzzi on 22/02/2018.
+ */
+
+public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {
+
+    private Thread.UncaughtExceptionHandler _defaultEH;
+
+    public CustomExceptionHandler(){
+        _defaultEH = Thread.getDefaultUncaughtExceptionHandler();
+    }
+
+    @Override
+    public void uncaughtException(Thread thread, final Throwable ex) {
+        Tuils.toFile(ex);
+        _defaultEH.uncaughtException(thread, ex);
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/InputOutputReceiver.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/InputOutputReceiver.java
deleted file mode 100644
index d3ca39177581a51f0404e2449c629d94a81c625e..0000000000000000000000000000000000000000
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/InputOutputReceiver.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package ohi.andre.consolelauncher.tuils;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.RemoteInput;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-
-import ohi.andre.consolelauncher.managers.TerminalManager;
-import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
-import ohi.andre.consolelauncher.tuils.interfaces.Inputable;
-import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
-
-/**
- * Created by francescoandreuzzi on 18/08/2017.
- */
-
-public class InputOutputReceiver extends BroadcastReceiver {
-
-//    this class handles incoming intent to
-//    process input
-//    show custom output
-
-    public static final int WAS_MUSIC_SERVICE = 10;
-    public static final int WAS_KEEPER_SERVICE = 11;
-
-    public static final String WAS_KEY = "was";
-
-    public static final String ACTION_OUTPUT = "ohi.andre.consolelauncher.action_output";
-//    this will set an input and click it
-    public static final String ACTION_CMD = "ohi.andre.consolelauncher.action_cmd";
-//    this will set an input and NOT click it
-    public static final String ACTION_INPUT = "ohi.andre.consolelauncher.action_input";
-    public static final String TEXT = "ohi.andre.consolelauncher.text";
-    public static final String TYPE = "ohi.andre.consolelauncher.type";
-    public static final String COLOR = "ohi.andre.consolelauncher.color";
-    public static final String ACTION = "ohi.andre.consolelauncher.action";
-    public static final String LONG_ACTION = "ohi.andre.consolelauncher.longaction";
-    public static final String SHOW_CONTENT = "ohi.andre.consolelauncher.show_content";
-
-    CommandExecuter executer;
-    Outputable outputable;
-    Inputable inputable;
-
-    public InputOutputReceiver(CommandExecuter executer, Outputable outputable, Inputable inputable) {
-        this.executer = executer;
-        this.outputable = outputable;
-        this.inputable = inputable;
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
-        if(remoteInput == null || remoteInput.size() == 0) {
-            CharSequence text = intent.getCharSequenceExtra(TEXT);
-            if(text == null) text = intent.getStringExtra(TEXT);
-            if(text == null) return;
-
-            if(intent.getAction().equals(ACTION_CMD)) {
-                executer.exec(text.toString(), intent.getBooleanExtra(SHOW_CONTENT, true));
-            } else if(intent.getAction().equals(ACTION_OUTPUT)) {
-                int color = intent.getIntExtra(COLOR, Integer.MAX_VALUE);
-
-                Object singleClickExtraObject, longClickExtraObject;
-
-                singleClickExtraObject = intent.getStringExtra(ACTION);
-                longClickExtraObject = intent.getStringExtra(LONG_ACTION);
-
-                if(singleClickExtraObject == null) singleClickExtraObject = intent.getParcelableExtra(ACTION);
-                if(longClickExtraObject == null) longClickExtraObject = intent.getParcelableExtra(LONG_ACTION);
-
-                if(singleClickExtraObject != null || longClickExtraObject != null) {
-                    text = new SpannableStringBuilder(text);
-                    ((SpannableStringBuilder) text).setSpan(new LongClickableSpan(singleClickExtraObject, longClickExtraObject), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-                }
-
-                if(color != Integer.MAX_VALUE) {
-                    outputable.onOutput(color, text);
-                } else {
-                    int type = intent.getIntExtra(TYPE, -1);
-                    if(type != -1) outputable.onOutput(text, type);
-                    else outputable.onOutput(text, TerminalManager.CATEGORY_OUTPUT);
-                }
-            } else if(intent.getAction().equals(ACTION_INPUT)) {
-                inputable.in(text.toString());
-            }
-        } else {
-            String cmd = remoteInput.getString(TEXT);
-            executer.exec(cmd, true);
-
-//            int was = intent.getIntExtra(WAS_KEY, 0);
-//            if(was == WAS_KEEPER_SERVICE) {
-//                NotificationManagerCompat.from(context).notify(KeeperService.ONGOING_NOTIFICATION_ID, KeeperService.buildNotification(context));
-//            } else if(was == WAS_MUSIC_SERVICE) {
-////                do nothing
-//            }
-        }
-    }
-}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/LongClickableSpan.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/LongClickableSpan.java
index 398db4ce7e68935b20e13a48a211c18900003173..47b0ea8e663bfcd491ce1cfdf62047c23ba8e72b 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/LongClickableSpan.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/LongClickableSpan.java
@@ -3,16 +3,22 @@ package ohi.andre.consolelauncher.tuils;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Color;
+import android.net.Uri;
 import android.os.Vibrator;
+import android.support.v4.content.LocalBroadcastManager;
 import android.text.TextPaint;
 import android.text.style.ClickableSpan;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.PopupMenu;
 
+import ohi.andre.consolelauncher.MainManager;
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
 import ohi.andre.consolelauncher.managers.notifications.NotificationService;
+import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.options.Notifications;
 
 /**
  * Created by francescoandreuzzi on 22/10/2017.
@@ -25,6 +31,9 @@ public class LongClickableSpan extends ClickableSpan {
     private Object clickO, longClickO;
     private String longIntentKey;
 
+    private static boolean set = false, showMenu;
+    private static boolean showExcludeApp, showExcludeNotification, showReply;
+
     public LongClickableSpan(Object clickAction, Object longClickAction) {
         this.clickO = clickAction;
         this.longClickO = longClickAction;
@@ -71,14 +80,29 @@ public class LongClickableSpan extends ClickableSpan {
         return execute(v, o, null);
     }
 
-    private static boolean execute(View v, Object o, String intentKey) {
+    private static boolean execute(final View v, Object o, String intentKey) {
         if(o == null) return false;
 
+        if(!set) {
+            set = true;
+
+            showExcludeApp = XMLPrefsManager.getBoolean(Notifications.notification_popup_exclude_app);
+            showExcludeNotification = XMLPrefsManager.getBoolean(Notifications.notification_popup_exclude_notification);
+            showReply = XMLPrefsManager.getBoolean(Notifications.notification_popup_reply);
+
+            showMenu = (showExcludeApp && showExcludeNotification) || (showExcludeApp && showReply) || (showExcludeNotification && showReply);
+        }
+
         if(o instanceof String) {
-            Intent intent = new Intent(intentKey != null ? intentKey : InputOutputReceiver.ACTION_CMD);
-            intent.putExtra(InputOutputReceiver.SHOW_CONTENT, false);
-            intent.putExtra(InputOutputReceiver.TEXT, (String) o);
-            v.getContext().sendBroadcast(intent);
+            Intent intent = new Intent(intentKey != null ? intentKey : MainManager.ACTION_EXEC);
+            intent.putExtra(PrivateIOReceiver.TEXT, (String) o);
+
+            if(intentKey == null || intentKey.equals(MainManager.ACTION_EXEC)) {
+                intent.putExtra(MainManager.NEED_WRITE_INPUT, false);
+                intent.putExtra(MainManager.CMD_COUNT, MainManager.commandCount);
+            }
+
+            LocalBroadcastManager.getInstance(v.getContext().getApplicationContext()).sendBroadcast(intent);
         } else if(o instanceof PendingIntent) {
             PendingIntent pi = (PendingIntent) o;
 
@@ -87,35 +111,64 @@ public class LongClickableSpan extends ClickableSpan {
             } catch (PendingIntent.CanceledException e) {
                 Tuils.log(e);
             }
+        } else if(o instanceof Uri) {
+            Intent i = new Intent(Intent.ACTION_VIEW, (Uri) o);
+            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            try {
+                v.getContext().startActivity(i);
+            } catch (Exception e) {
+                Tuils.sendOutput(Color.RED, v.getContext(), e.toString());
+            }
         } else if(o instanceof NotificationService.Notification) {
+            final NotificationService.Notification n = (NotificationService.Notification) o;
+
             if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
-                PopupMenu menu = new PopupMenu(v.getContext().getApplicationContext(), v);
-                menu.getMenuInflater().inflate(R.menu.notification_menu, menu.getMenu());
-
-                final NotificationService.Notification n = (NotificationService.Notification) o;
-
-                menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
-
-                    @Override
-                    public boolean onMenuItemClick(MenuItem item) {
-                        int id = item.getItemId();
-
-                        switch (id) {
-                            case R.id.exclude_app:
-                                NotificationManager.setState(n.pkg, false);
-                                break;
-                            case R.id.exclude_notification:
-                                NotificationManager.addFilter(n.text, -1);
-                                break;
-                            default:
-                                return false;
+                if(showMenu) {
+                    PopupMenu menu = new PopupMenu(v.getContext().getApplicationContext(), v);
+                    menu.getMenuInflater().inflate(R.menu.notification_menu, menu.getMenu());
+
+                    menu.getMenu().findItem(R.id.exclude_app).setVisible(showExcludeApp);
+                    menu.getMenu().findItem(R.id.exclude_notification).setVisible(showExcludeNotification);
+                    menu.getMenu().findItem(R.id.reply_notification).setVisible(showReply);
+
+                    menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+
+                        @Override
+                        public boolean onMenuItemClick(MenuItem item) {
+                            int id = item.getItemId();
+
+                            switch (id) {
+                                case R.id.exclude_app:
+                                    NotificationManager.setState(n.pkg, false);
+                                    break;
+                                case R.id.exclude_notification:
+                                    NotificationManager.addFilter(n.text, -1);
+                                    break;
+                                case R.id.reply_notification:
+                                    Intent intent = new Intent(PrivateIOReceiver.ACTION_INPUT);
+                                    intent.putExtra(PrivateIOReceiver.TEXT, "reply -to " + n.pkg + Tuils.SPACE);
+
+                                    LocalBroadcastManager.getInstance(v.getContext().getApplicationContext()).sendBroadcast(intent);
+                                default:
+                                    return false;
+                            }
+
+                            return true;
                         }
+                    });
 
-                        return true;
-                    }
-                });
+                    menu.show();
+                } else {
+                    if(showReply) {
+                        Intent intent = new Intent(PrivateIOReceiver.ACTION_INPUT);
+                        intent.putExtra(PrivateIOReceiver.TEXT, "reply -to " + n.pkg + Tuils.SPACE);
 
-                menu.show();
+                        LocalBroadcastManager.getInstance(v.getContext().getApplicationContext()).sendBroadcast(intent);
+                    }
+                    else if(showExcludeNotification) NotificationManager.addFilter(n.text, -1);
+                    else if(showExcludeApp) NotificationManager.setState(n.pkg, false);
+                }
             }
         }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/PrivateIOReceiver.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/PrivateIOReceiver.java
new file mode 100644
index 0000000000000000000000000000000000000000..33f4ef34daed8987c4747d1eccd96ec2ed930594
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/PrivateIOReceiver.java
@@ -0,0 +1,149 @@
+package ohi.andre.consolelauncher.tuils;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.support.v4.app.RemoteInput;
+import android.support.v4.content.LocalBroadcastManager;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+
+import ohi.andre.consolelauncher.BuildConfig;
+import ohi.andre.consolelauncher.MainManager;
+import ohi.andre.consolelauncher.managers.TerminalManager;
+import ohi.andre.consolelauncher.tuils.interfaces.Inputable;
+import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
+
+/**
+ * Created by francescoandreuzzi on 18/08/2017.
+ */
+
+public class PrivateIOReceiver extends BroadcastReceiver {
+
+//    this class handles incoming intent to
+//    process input
+//    show custom output
+
+    public static final String ACTION_OUTPUT = BuildConfig.APPLICATION_ID + ".action_output";
+    public static final String ACTION_INPUT = BuildConfig.APPLICATION_ID + ".action_input";
+    public static final String ACTION_REPLY = BuildConfig.APPLICATION_ID + ".action_reply";
+
+    public static final String TEXT = BuildConfig.APPLICATION_ID + ".text";
+    public static final String TYPE = BuildConfig.APPLICATION_ID + ".type";
+    public static final String COLOR = BuildConfig.APPLICATION_ID + ".color";
+    public static final String ACTION = BuildConfig.APPLICATION_ID + ".action";
+    public static final String LONG_ACTION = BuildConfig.APPLICATION_ID + ".longaction";
+    public static final String REMOTE_INPUTS = BuildConfig.APPLICATION_ID + ".remote_inputs";
+    public static final String BUNDLE = BuildConfig.APPLICATION_ID + ".bundle";
+    public static final String PENDING_INTENT = BuildConfig.APPLICATION_ID + ".pending_intent";
+    public static final String ID = BuildConfig.APPLICATION_ID + ".id";
+    public static final String CURRENT_ID = BuildConfig.APPLICATION_ID + ".current_id";
+
+    Outputable outputable;
+    Inputable inputable;
+
+    Activity activity;
+
+    public static int currentId = 0;
+
+    public PrivateIOReceiver(Activity activity, Outputable outputable, Inputable inputable) {
+        this.outputable = outputable;
+        this.inputable = inputable;
+        this.activity = activity;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+//        to avoid double onReceive calls
+        int cId = intent.getIntExtra(CURRENT_ID, -1);
+        if(cId != -1 && cId != currentId) return;
+        currentId++;
+
+        Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
+        if(remoteInput == null || remoteInput.size() == 0) {
+            CharSequence text = intent.getCharSequenceExtra(TEXT);
+            if(text == null) text = intent.getStringExtra(TEXT);
+            if(text == null) return;
+
+            if(intent.getAction().equals(ACTION_OUTPUT)) {
+                int color = intent.getIntExtra(COLOR, Integer.MAX_VALUE);
+
+                Object singleClickExtraObject, longClickExtraObject;
+
+                singleClickExtraObject = intent.getStringExtra(ACTION);
+                longClickExtraObject = intent.getStringExtra(LONG_ACTION);
+
+                if(singleClickExtraObject == null) singleClickExtraObject = intent.getParcelableExtra(ACTION);
+                if(longClickExtraObject == null) longClickExtraObject = intent.getParcelableExtra(LONG_ACTION);
+
+                if(singleClickExtraObject != null || longClickExtraObject != null) {
+                    text = new SpannableStringBuilder(text);
+                    ((SpannableStringBuilder) text).setSpan(new LongClickableSpan(singleClickExtraObject, longClickExtraObject), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+                }
+
+                if(color != Integer.MAX_VALUE) {
+                    outputable.onOutput(color, text);
+                } else {
+                    int type = intent.getIntExtra(TYPE, -1);
+                    if(type != -1) outputable.onOutput(text, type);
+                    else outputable.onOutput(text, TerminalManager.CATEGORY_OUTPUT);
+                }
+            }
+            else if(intent.getAction().equals(ACTION_INPUT)) {
+                inputable.in(text.toString());
+            } else if(intent.getAction().equals(ACTION_REPLY) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
+                Bundle b = intent.getBundleExtra(BUNDLE);
+                Parcelable[] ps = intent.getParcelableArrayExtra(REMOTE_INPUTS);
+                PendingIntent pi = intent.getParcelableExtra(PENDING_INTENT);
+                int id = intent.getIntExtra(ID, 0);
+
+                if(b == null) {
+                    Tuils.sendOutput(Color.RED, context, "The bundle is null");
+                    return;
+                }
+
+                if(ps == null || ps.length == 0) {
+                    Tuils.sendOutput(Color.RED, context, "No remote inputs");
+                    return;
+                }
+
+                if(pi == null) {
+                    Tuils.sendOutput(Color.RED, context, "The pending intent couldn\'t be found");
+                    return;
+                }
+
+                android.app.RemoteInput[] rms = new android.app.RemoteInput[ps.length];
+                for(int j = 0; j < rms.length; j++) {
+                    rms[j] = (android.app.RemoteInput) ps[j];
+                }
+
+                Intent localIntent = new Intent();
+                localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+                for(android.app.RemoteInput remoteIn : rms) {
+                    b.putCharSequence(remoteIn.getResultKey(), text);
+                }
+
+                android.app.RemoteInput.addResultsToIntent(rms, localIntent, b);
+                try {
+                    pi.send(context.getApplicationContext(), id, localIntent);
+                } catch (PendingIntent.CanceledException e) {
+                    Tuils.sendOutput(Color.RED, context, e.toString());
+                    Tuils.log(e);
+                }
+            }
+        } else {
+            String cmd = remoteInput.getString(TEXT);
+            Intent i = new Intent(MainManager.ACTION_EXEC);
+            i.putExtra(MainManager.CMD_COUNT, MainManager.commandCount);
+            i.putExtra(MainManager.CMD, cmd);
+            LocalBroadcastManager.getInstance(context.getApplicationContext()).sendBroadcast(i);
+        }
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/PublicIOReceiver.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/PublicIOReceiver.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea1bd63dc1d84e158d27590a18a816557bb564cf
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/PublicIOReceiver.java
@@ -0,0 +1,46 @@
+package ohi.andre.consolelauncher.tuils;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.RemoteInput;
+import android.support.v4.content.LocalBroadcastManager;
+
+import ohi.andre.consolelauncher.BuildConfig;
+import ohi.andre.consolelauncher.MainManager;
+
+/**
+ * Created by francescoandreuzzi on 04/02/2018.
+ */
+
+public class PublicIOReceiver extends BroadcastReceiver {
+
+    public static final String ACTION_OUTPUT = BuildConfig.APPLICATION_ID + ".action_public_output";
+    public static final String ACTION_CMD = BuildConfig.APPLICATION_ID + ".action_public_cmd";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action;
+        if(intent.getAction().equals(ACTION_CMD)) {
+            Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
+            if (remoteInput != null) {
+                String cmd = remoteInput.getString(PrivateIOReceiver.TEXT);
+                boolean wasMusic = remoteInput.getBoolean(MainManager.MUSIC_SERVICE) || intent.getBooleanExtra(MainManager.MUSIC_SERVICE, false);
+
+                intent.putExtra(MainManager.MUSIC_SERVICE, wasMusic);
+                intent.putExtra(MainManager.CMD, cmd);
+            } else {
+                return;
+            }
+
+            action = MainManager.ACTION_EXEC;
+
+            intent.putExtra(MainManager.CMD_COUNT, MainManager.commandCount);
+        } else if(intent.getAction().equals(ACTION_OUTPUT)) {
+            action = PrivateIOReceiver.ACTION_OUTPUT;
+        } else return;
+
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent.setAction(action));
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java
index bb15c8d835afaebb20106ea71a2c9892fd62e501..4b2197c61025083c55e434f40e09793efffb05b1 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java
@@ -18,7 +18,6 @@ import java.io.Serializable;
 import java.util.Map;
 
 public class SimpleMutableEntry<K, V> implements Map.Entry<K, V>, Serializable {
-    private static final long serialVersionUID = -8499721149061103585L;
 
     private final K key;
     private V value;
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java
index 6b1d83b54acc5bf267abea1bdb32361e5d1e118b..b5c82b9990f11919ead1a0c1042ea5288012b29a 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java
@@ -25,6 +25,7 @@ import android.os.Parcelable;
 import android.os.Process;
 import android.os.StatFs;
 import android.provider.Settings;
+import android.support.v4.content.LocalBroadcastManager;
 import android.telephony.TelephonyManager;
 import android.text.SpannableString;
 import android.text.Spanned;
@@ -41,6 +42,8 @@ import android.webkit.MimeTypeMap;
 import android.widget.EditText;
 import android.widget.TextView;
 
+import org.xml.sax.SAXParseException;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
@@ -51,6 +54,7 @@ import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.io.PrintWriter;
+import java.io.RandomAccessFile;
 import java.io.Reader;
 import java.io.StringWriter;
 import java.lang.reflect.Array;
@@ -59,6 +63,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.nio.channels.Channels;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
@@ -75,6 +80,7 @@ import ohi.andre.consolelauncher.managers.music.MusicManager2;
 import ohi.andre.consolelauncher.managers.music.Song;
 import ohi.andre.consolelauncher.managers.notifications.NotificationService;
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
+import ohi.andre.consolelauncher.managers.xml.classes.XMLPrefsSave;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
 import ohi.andre.consolelauncher.managers.xml.options.Ui;
 import ohi.andre.consolelauncher.tuils.interfaces.OnBatteryUpdate;
@@ -91,12 +97,15 @@ public class Tuils {
     private static final String TUI_FOLDER = "t-ui";
     public static final String MINUS = "-";
 
-    public static final String FONT_PATH = "font";
+    public static Pattern patternNewline = Pattern.compile("%n", Pattern.CASE_INSENSITIVE | Pattern.LITERAL);
+
     private static Typeface globalTypeface = null;
+    public static String fontPath = null;
+
     public static Typeface getTypeface(Context context) {
         if(globalTypeface == null) {
             try {
-                XMLPrefsManager.create(context);
+                XMLPrefsManager.loadCommons(context);
             } catch (Exception e) {
                 return null;
             }
@@ -106,13 +115,17 @@ public class Tuils {
             else {
                 File tui = Tuils.getFolder();
                 if(tui == null) {
-                    return systemFont ? Typeface.DEFAULT : Typeface.createFromAsset(context.getAssets(), "lucida_console.ttf");
+                    return Typeface.createFromAsset(context.getAssets(), "lucida_console.ttf");
                 }
 
+                Pattern p = Pattern.compile(".[ot]tf$");
+
                 File font = null;
                 for(File f : tui.listFiles()) {
-                    if(f.getName().startsWith(FONT_PATH)) {
+                    String name = f.getName();
+                    if(p.matcher(name).find()) {
                         font = f;
+                        fontPath = f.getAbsolutePath();
                         break;
                     }
                 }
@@ -132,6 +145,11 @@ public class Tuils {
         return globalTypeface;
     }
 
+    public static void cancelFont() {
+        globalTypeface = null;
+        fontPath = null;
+    }
+
     public static boolean notificationServiceIsRunning(Context context) {
         ComponentName collectorComponent = new ComponentName(context, NotificationService.class);
         ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
@@ -226,6 +244,10 @@ public class Tuils {
         }
     }
 
+    public static void unregisterBatteryReceiver(Context context) {
+        context.unregisterReceiver(batteryReceiver);
+    }
+
     private static OnBatteryUpdate batteryUpdate;
     private static BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
         @Override
@@ -444,15 +466,15 @@ public class Tuils {
         return round(result, 2);
     }
 
-    public static SpannableString span(String text, int color) {
+    public static SpannableString span(CharSequence text, int color) {
         return span(null, text, color, Integer.MAX_VALUE);
     }
 
-    public static SpannableString span(Context context, int size, String text) {
+    public static SpannableString span(Context context, int size, CharSequence text) {
         return span(context, text, Integer.MAX_VALUE, size);
     }
 
-    public static SpannableString span(Context context, String text, int color, int size) {
+    public static SpannableString span(Context context, CharSequence text, int color, int size) {
         SpannableString spannableString = new SpannableString(text);
         if(size != Integer.MAX_VALUE && context != null) spannableString.setSpan(new AbsoluteSizeSpan(convertSpToPixels(size, context)), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         if(color != Integer.MAX_VALUE) {
@@ -461,7 +483,7 @@ public class Tuils {
         return spannableString;
     }
 
-    public static SpannableString span(int bgColor, int foreColor, String text) {
+    public static SpannableString span(int bgColor, int foreColor, CharSequence text) {
         SpannableString spannableString = new SpannableString(text);
         spannableString.setSpan(new BackgroundColorSpan(bgColor), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
         spannableString.setSpan(new ForegroundColorSpan(foreColor), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -565,11 +587,11 @@ public class Tuils {
     }
 
     public static void sendOutput(int color, Context context, CharSequence s, int type) {
-        Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-        intent.putExtra(InputOutputReceiver.TEXT, s);
-        intent.putExtra(InputOutputReceiver.COLOR, color);
-        intent.putExtra(InputOutputReceiver.TYPE, type);
-        context.sendBroadcast(intent);
+        Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+        intent.putExtra(PrivateIOReceiver.TEXT, s);
+        intent.putExtra(PrivateIOReceiver.COLOR, color);
+        intent.putExtra(PrivateIOReceiver.TYPE, type);
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
     }
 
     public static void sendOutput(Context context, CharSequence s, int type, Object action) {
@@ -577,15 +599,15 @@ public class Tuils {
     }
 
     public static void sendOutput(int color, Context context, CharSequence s, int type, Object action) {
-        Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-        intent.putExtra(InputOutputReceiver.TEXT, s);
-        intent.putExtra(InputOutputReceiver.COLOR, color);
-        intent.putExtra(InputOutputReceiver.TYPE, type);
+        Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+        intent.putExtra(PrivateIOReceiver.TEXT, s);
+        intent.putExtra(PrivateIOReceiver.COLOR, color);
+        intent.putExtra(PrivateIOReceiver.TYPE, type);
 
-        if(action instanceof String) intent.putExtra(InputOutputReceiver.ACTION, (String) action);
-        else if(action instanceof Parcelable) intent.putExtra(InputOutputReceiver.ACTION, (Parcelable) action);
+        if(action instanceof String) intent.putExtra(PrivateIOReceiver.ACTION, (String) action);
+        else if(action instanceof Parcelable) intent.putExtra(PrivateIOReceiver.ACTION, (Parcelable) action);
 
-        context.sendBroadcast(intent);
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
     }
 
     public static void sendOutput(Context context, CharSequence s, int type, Object action, Object longAction) {
@@ -593,24 +615,24 @@ public class Tuils {
     }
 
     public static void sendOutput(int color, Context context, CharSequence s, int type, Object action, Object longAction) {
-        Intent intent = new Intent(InputOutputReceiver.ACTION_OUTPUT);
-        intent.putExtra(InputOutputReceiver.TEXT, s);
-        intent.putExtra(InputOutputReceiver.COLOR, color);
-        intent.putExtra(InputOutputReceiver.TYPE, type);
+        Intent intent = new Intent(PrivateIOReceiver.ACTION_OUTPUT);
+        intent.putExtra(PrivateIOReceiver.TEXT, s);
+        intent.putExtra(PrivateIOReceiver.COLOR, color);
+        intent.putExtra(PrivateIOReceiver.TYPE, type);
 
-        if(action instanceof String) intent.putExtra(InputOutputReceiver.ACTION, (String) action);
-        else if(action instanceof Parcelable) intent.putExtra(InputOutputReceiver.ACTION, (Parcelable) action);
+        if(action instanceof String) intent.putExtra(PrivateIOReceiver.ACTION, (String) action);
+        else if(action instanceof Parcelable) intent.putExtra(PrivateIOReceiver.ACTION, (Parcelable) action);
 
-        if(longAction instanceof String) intent.putExtra(InputOutputReceiver.LONG_ACTION, (String) longAction);
-        else if(longAction instanceof Parcelable) intent.putExtra(InputOutputReceiver.LONG_ACTION, (Parcelable) longAction);
+        if(longAction instanceof String) intent.putExtra(PrivateIOReceiver.LONG_ACTION, (String) longAction);
+        else if(longAction instanceof Parcelable) intent.putExtra(PrivateIOReceiver.LONG_ACTION, (Parcelable) longAction);
 
-        context.sendBroadcast(intent);
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
     }
 
     public static void sendInput(Context context, String text) {
-        Intent intent = new Intent(InputOutputReceiver.ACTION_INPUT);
-        intent.putExtra(InputOutputReceiver.TEXT, text);
-        context.sendBroadcast(intent);
+        Intent intent = new Intent(PrivateIOReceiver.ACTION_INPUT);
+        intent.putExtra(PrivateIOReceiver.TEXT, text);
+        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
     }
 
     public static final int TERA = 0;
@@ -701,15 +723,15 @@ public class Tuils {
 
             if(o == x) return count;
 
-            if (o instanceof XMLPrefsManager.XMLPrefsSave) {
+            if (o instanceof XMLPrefsSave) {
                 try {
-                    if (((XMLPrefsManager.XMLPrefsSave) o).is((String) x)) return count;
+                    if (((XMLPrefsSave) o).is((String) x)) return count;
                 } catch (Exception e) {}
             }
 
-            if (o instanceof String && x instanceof XMLPrefsManager.XMLPrefsSave) {
+            if (o instanceof String && x instanceof XMLPrefsSave) {
                 try {
-                    if (((XMLPrefsManager.XMLPrefsSave) x).is((String) o)) return count;
+                    if (((XMLPrefsSave) x).is((String) o)) return count;
                 } catch (Exception e) {}
             }
 
@@ -820,10 +842,11 @@ public class Tuils {
 
         if(o instanceof Throwable) {
             Log.e("andre", "", (Throwable) o);
-        } else if(o instanceof Object[]){
-            Log.e("andre", Arrays.toString((Object[]) o));
         } else {
-            Log.e("andre", String.valueOf(o));
+            String text;
+            if(o instanceof Object[]) text = Arrays.toString((Object[]) o);
+            else text = o.toString();
+            Log.e("andre", text);
         }
     }
 
@@ -835,6 +858,36 @@ public class Tuils {
         }
     }
 
+    public static void log(Object o, PrintStream to) {
+//        Log.e("andre", Arrays.toString(Thread.currentThread().getStackTrace()));
+
+        if(o instanceof Throwable) {
+            ((Throwable) o).printStackTrace(to);
+        } else {
+            String text;
+            if(o instanceof Object[]) text = Arrays.toString((Object[]) o);
+            else text = o.toString();
+
+            try {
+                to.write(text.getBytes());
+            } catch (IOException e) {
+                Tuils.log(e);
+            }
+        }
+    }
+
+    public static void log(Object o, Object o2, OutputStream to) {
+        try {
+            if(o instanceof Object[] && o2 instanceof Object[]){
+                to.write((Arrays.toString((Object[]) o) + " -- " + Arrays.toString((Object[]) o2)).getBytes());
+            } else {
+                to.write((String.valueOf(o) + " -- " + String.valueOf(o2)).getBytes());
+            }
+        } catch (Exception e) {
+            Tuils.log(e);
+        }
+    }
+
     public static boolean hasInternetAccess() {
         try {
             HttpURLConnection urlc = (HttpURLConnection) (new URL("http://clients3.google.com/generate_204").openConnection());
@@ -850,10 +903,15 @@ public class Tuils {
 
     public static void toFile(Throwable e) {
         try {
-            FileOutputStream out = new FileOutputStream(new File(Tuils.getFolder(), "crash.txt"), true);
-            out.write((Tuils.NEWLINE + Tuils.NEWLINE + new Date().toString() + Tuils.NEWLINE).getBytes());
-            e.printStackTrace(new PrintStream(out));
-            out.close();
+            RandomAccessFile f = new RandomAccessFile(new File(Tuils.getFolder(), "crash.txt"), "rw");
+            f.seek(0);
+            f.write((new Date().toString() + Tuils.NEWLINE + Tuils.NEWLINE).getBytes());
+            OutputStream is = Channels.newOutputStream(f.getChannel());
+            e.printStackTrace(new PrintStream(is));
+            f.write((Tuils.NEWLINE + Tuils.NEWLINE).getBytes());
+
+            is.close();
+            f.close();
         } catch (Exception e1) {}
     }
 
@@ -1084,13 +1142,13 @@ public class Tuils {
         return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
     }
 
-    private static final int FILEUPDATE_DELAY = 100;
+    private static final int FILEUPDATE_DELAY = 50;
     private static File folder = null;
     public static File getFolder() {
         if(folder != null) return folder;
 
         int elapsedTime = 0;
-        while (elapsedTime < 3500) {
+        while (elapsedTime < 3000) {
             File tuiFolder = Tuils.getTuiFolder();
             if(tuiFolder != null && ((tuiFolder.exists() && tuiFolder.isDirectory()) || tuiFolder.mkdir())) {
                 folder = tuiFolder;
@@ -1197,9 +1255,14 @@ public class Tuils {
         }
     }
 
-    public static void sendXMLParseError(Context context, String PATH, Exception e) {
-        Tuils.sendOutput(Color.RED, context, context.getString(R.string.output_xmlproblem1) + Tuils.SPACE + PATH + context.getString(R.string.output_xmlproblem2) +
-                Tuils.NEWLINE + context.getString(R.string.output_errorlabel) + e.toString());
+    public static void sendXMLParseError(Context context, String PATH, SAXParseException e) {
+        Tuils.sendOutput(
+                Color.RED,
+                context, context.getString(R.string.output_xmlproblem1) + Tuils.SPACE + PATH + context.getString(R.string.output_xmlproblem2) + Tuils.NEWLINE + context.getString(R.string.output_errorlabel) +
+                "File: " + e.getSystemId() + Tuils.NEWLINE +
+                "Message" + e.getMessage() + Tuils.NEWLINE +
+                "Line" + e.getLineNumber() + Tuils.NEWLINE +
+                "Column" + e.getColumnNumber());
     }
 
     public static void sendXMLParseError(Context context, String PATH) {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/broadcast/HeadsetBroadcast.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/broadcast/HeadsetBroadcast.java
deleted file mode 100755
index 634fa29a7ccbbae9ce6cbc8e42318d95ae9fce37..0000000000000000000000000000000000000000
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/broadcast/HeadsetBroadcast.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package ohi.andre.consolelauncher.tuils.broadcast;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Created by francescoandreuzzi on 24/01/16.
- */
-public class HeadsetBroadcast extends BroadcastReceiver {
-
-    Runnable headsetUnplugged;
-
-    public HeadsetBroadcast(Runnable r) {
-        super();
-
-        this.headsetUnplugged = r;
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (intent.getIntExtra("state", 0) != 1)
-            headsetUnplugged.run();
-    }
-}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java
old mode 100755
new mode 100644
index f6a0c80828c241365662a36bb293f019a49fdb98..4706d61d0f5efb3b1a692f48440168dc2eeda67d
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/CommandExecuter.java
@@ -1,12 +1,10 @@
 package ohi.andre.consolelauncher.tuils.interfaces;
 
 /**
- * Created by francescoandreuzzi on 25/01/16.
+ * Created by francescoandreuzzi on 03/03/2018.
  */
+
 public interface CommandExecuter {
 
-    void exec(String aliasValue, String aliasName);
-    void exec(String input);
-    void exec(String input, boolean needWriteInput);
-    void exec(String input, Object obj);
+    void execute(String input, Object obj);
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Hintable.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Hintable.java
deleted file mode 100644
index 0db778566bfbb6c4f8048383741b64db36503de8..0000000000000000000000000000000000000000
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Hintable.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package ohi.andre.consolelauncher.tuils.interfaces;
-
-/**
- * Created by francescoandreuzzi on 31/07/2017.
- */
-
-public interface Hintable {
-    void updateHint();
-}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Inputable.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Inputable.java
old mode 100755
new mode 100644
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Outputable.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Outputable.java
old mode 100755
new mode 100644
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Reloadable.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Reloadable.java
old mode 100755
new mode 100644
index b116e5ee56f41b05f099ba0c677ca89883b72a02..f483a36e33bc3583afdb74edd122fbe224bd53d1
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Reloadable.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Reloadable.java
@@ -1,6 +1,10 @@
 package ohi.andre.consolelauncher.tuils.interfaces;
 
+/**
+ * Created by francescoandreuzzi on 05/03/2018.
+ */
+
 public interface Reloadable {
-    void reload();
-}
 
+    public void reload();
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Rooter.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Rooter.java
deleted file mode 100644
index a104c5f64f5525a6e59d9fa269509f3b356f1fbf..0000000000000000000000000000000000000000
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Rooter.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package ohi.andre.consolelauncher.tuils.interfaces;
-
-/**
- * Created by francescoandreuzzi on 31/07/2017.
- */
-
-public interface Rooter {
-    void onRoot();
-    void onStandard();
-}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Suggester.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Suggester.java
deleted file mode 100644
index a972758871535a497de7d93798656767e7dfabd5..0000000000000000000000000000000000000000
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/interfaces/Suggester.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package ohi.andre.consolelauncher.tuils.interfaces;
-
-/**
- * Created by francescoandreuzzi on 24/07/2017.
- */
-
-public interface Suggester {
-
-    void requestUpdate();
-}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/libsuperuser/ShellHolder.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/libsuperuser/ShellHolder.java
index 215332861a39d2edd87517f6344a0a0404689f76..3a53bc70a25c8d814c9b7158c9696a1b0faeae28 100644
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/libsuperuser/ShellHolder.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/libsuperuser/ShellHolder.java
@@ -1,10 +1,12 @@
 package ohi.andre.consolelauncher.tuils.libsuperuser;
 
+import android.content.Context;
+
 import java.io.File;
 
 import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.xml.options.Behavior;
-import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
+import ohi.andre.consolelauncher.tuils.Tuils;
 
 /**
  * Created by francescoandreuzzi on 18/08/2017.
@@ -12,10 +14,10 @@ import ohi.andre.consolelauncher.tuils.interfaces.Outputable;
 
 public class ShellHolder {
 
-    private Outputable outputable;
+    private Context context;
 
-    public ShellHolder(Outputable outputable) {
-        this.outputable = outputable;
+    public ShellHolder(Context context) {
+        this.context = context;
     }
 
     public Shell.Interactive build() {
@@ -23,13 +25,13 @@ public class ShellHolder {
                 .setOnSTDOUTLineListener(new StreamGobbler.OnLineListener() {
                     @Override
                     public void onLine(String line) {
-                        outputable.onOutput(line);
+                        Tuils.sendOutput(context, line);
                     }
                 })
                 .setOnSTDERRLineListener(new StreamGobbler.OnLineListener() {
                     @Override
                     public void onLine(String line) {
-                        outputable.onOutput(line);
+                        Tuils.sendOutput(context, line);
                     }
                 })
                 .open();
diff --git a/app/src/main/res/layout/about_device_view.xml b/app/src/main/res/layout/about_device_view.xml
index feec5874d14c8d8512206cf9929d47bdb1e82625..32772dfb7ea31842b4dea74efe5ec0827c75f95d 100755
--- a/app/src/main/res/layout/about_device_view.xml
+++ b/app/src/main/res/layout/about_device_view.xml
@@ -28,4 +28,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
+    <TextView android:id="@+id/tv6"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
 </LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/menu/notification_menu.xml b/app/src/main/res/menu/notification_menu.xml
index 62cd80cb10dd7c4c55093abe83b770d6fc4030fb..d6c2782d54daa923873417d74600a56dbadbba76 100644
--- a/app/src/main/res/menu/notification_menu.xml
+++ b/app/src/main/res/menu/notification_menu.xml
@@ -2,4 +2,5 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/exclude_app" android:title="@string/exclude_app"/>
     <item android:id="@+id/exclude_notification" android:title="@string/exclude_notification"/>
+    <item android:id="@+id/reply_notification" android:title="@string/reply_notification"/>
 </menu>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9f9059a9d8b5561801c5f80d3582b6d0fa4931c2..57c1eb48c6bca6aa938379aba52ba7af0bc16f7a 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,22 +2,27 @@
 
     <!-- various text -->
     <string name="app_name">T-UI</string>
-    <string name="version_label">Version:</string>
     <string name="location_off">Turn on GPS or network location</string>
     <string name="share_label">Share</string>
     <string name="output_about">Francesco Andreuzzi (Italy)\n\t-> Programmer
-        \n\nLuke Winward (USA)\n\t-> Idea and design</string>
+        \n\nThanks to Luke Winward for his original idea</string>
     <string name="output_refresh">Refresh: apps, alias, music, contacts, rss feeds</string>
     <string name="output_rate">Thank you!</string>
     <string name="start_notification">T-UI started</string>
     <string name="tui_running">T-UI is running</string>
     <string name="anr">t-ui is having some issues. Please send to the developer your file crash.txt in the "t-ui" folder</string>
     <string name="admin_permission">Lock the screen on double tap</string>
-    <string name="translation_not_found">Translation not found</string>
+    <string name="reply_app_not_found">Couldn\'t find bound app:</string>
+    <string name="error">A fatal error occurred, check the file crash.txt inside your t-ui folder</string>
+
+    <!-- reply -->
+    <string name="reply_id_not_found">No bound app found with ID:</string>
+    <string name="reply_notification_not_found">No notification from this app</string>
 
     <!-- notifications menu -->
-    <string name="exclude_notification">Exclude this notification</string>
+    <string name="exclude_notification">Exclude notification</string>
     <string name="exclude_app">Exclude app</string>
+    <string name="reply_notification">Reply to the last notification</string>
     <string name="notification_service_not_running">The notification service is\'t running</string>
 
     <!-- regex -->
@@ -30,7 +35,7 @@
     <string name="theme_reverted">Reverted to the previous theme</string>
 
     <!-- files -->
-    <string name="output_error">An unknown error has occurred</string>
+    <string name="output_error">An unknown error occurred</string>
     <string name="output_isdirectory">This is a directory</string>
     <string name="output_filenotfound">File not found</string>
 
@@ -50,23 +55,22 @@
     <string name="tuinotfound_xmlprefs">Your xml preferences couldn\'t be loaded because your \"t-ui\" folder is not readable at the moment (you should try to use the command \"restart\")</string>
 
     <!-- hints -->
-    <string name="hint_donate">\nDo you like my work?\nIf yes, rate t-ui on Play Store (cmd: $ rate) or offer me a coffee (cmd: $ donate). Thank you!</string>
+    <string name="hint_donate">Do you like my work?\nIf yes, rate t-ui on Play Store (cmd: $ rate) or offer me a coffee (cmd: $ donate). Thank you!</string>
     <string name="hint_twitter">Did you know? t-ui is on Twitter. You can have a look with the cmd \"$ tui -twitter\"</string>
     <string name="hint_telegram">Did you know? There\'s a Telegram group with many enthusiastic users, where you can discuss, share and chat with the developer.\nJust use the cmd \"$ tui -telegram\"</string>
     <string name="hint_googlep">Did you know? Our official Google+ community is full of tips, experimental apks and discussions.\nYou can have a look with the cmd \"$ tui -googlep\"</string>
     <string name="hint_tutorial">Did you read the tutorial? If you don\'t remember how to view it, the cmd is \"$ tutorial\"</string>
     <string name="hint_theme">Did you know that you can easily switch your theme? Have a look at the cmd \"$ theme\"</string>
     <string name="hint_theme2">Did you know? You can create your custom theme and share it to other users. Have a look at the cmd \"$ theme -create\"</string>
-    <string name="hint_help">Are you having any doubts about a command? Just use the cmd \"$ help cmdName\"</string>
+    <string name="hint_help">Doubts about a command? Just use \"$ help cmdName\"</string>
     <string name="hint_music">Did you know? You can listen your music without launching other apps but t-ui. Have a look at the cmd \"$ music\"</string>
     <string name="hint_appgroups">Did you know? t-ui 6.4 introduced App Groups, a feature that let\'s you customize your app suggestions, creating different categories.\nYou can get more details with the cmd
         \"$ apps -tutorial\"</string>
     <string name="hint_notifications">Did you know? You can see your notifications directly from t-ui.\nIf you\'re interested, have a look at the tutorial: \"$ notifications -tutorial\"</string>
     <string name="hint_clear">Are you sick of clearing your screen? Have a look at the options \"clear_after_cmds\", \"clear_after_seconds\" and \"maxlines\"</string>
     <string name="hint_wallpaper">Do you want to use your wallpaper as t-ui background? Use the cmd: \"$ config -set system_wallpaper true\"</string>
-    <string name="hint_config">Are you having doubts about any config option? Use the cmd \"$ config -tutorial\" and look for that option inside the table</string>
-    <string name="hint_alias">Did you know that t-ui supports aliases? It also supports parameterized aliases.\nFor more info, use the cmd \"$ alias -tutorial\"</string>
-    <string name="hint_musicdisable">Do you want to make t-ui lighter? Use the cmd \"$ config -set enable_music false\" to disable the music player and save resources</string>
+    <string name="hint_config">Doubts about any config option? Use the cmd \"$ config -info\" and look for that option inside the table</string>
+    <string name="hint_alias">Did you know that t-ui supports aliases? It also supports parametrized aliases.\nFor more info, use the cmd \"$ alias -tutorial\"</string>
     <string name="hint_excludenotification">Did you know? You can exclude an unwanted notification long-clicking on it</string>
 
     <string name="hint_disable">You can disable this messages with the cmd \"$ config -set show_hints false\"</string>
@@ -98,10 +102,16 @@
     <string name="output_groupspace">Spaces are not allowed inside group names</string>
     <string name="output_notification_error">The notification service couldn\'t be started:</string>
 
-    <!-- rss -->
-    <string name="rss_not_found">Invalid ID: no RSS feed found</string>
+    <!-- note -->
+    <string name="note_not_found">Note not found</string>
+    <string name="row_used">This row is busy</string>
+
+    <!-- id -->
     <string name="id_already">This ID has already been used</string>
     <string name="id_notfound">Invalid ID</string>
+
+    <!-- rss -->
+    <string name="rss_not_found">Invalid ID: no RSS feed found</string>
     <string name="rss_never_checked">This RSS feed hasn\'t been checked yet</string>
     <string name="rss_invalid_timeformat">The time format couldn\'t be parsed</string>
     <string name="rss_invalid_date">Invalid publication date tag:</string>
@@ -134,13 +144,15 @@
     <string name="output_wifi">WiFi active:</string>
     <string name="output_data">Mobile Data active:</string>
     <string name="output_bluetooth">Bluetooth active:</string>
+    <string name="output_bluetooth_unavailable">Bluetooth is not available on this device</string>
     <string name="output_airplane">Airplane mode active:</string>
 
     <!-- music -->
     <string name="output_playing">Playing:</string>
     <string name="output_stopped">Player stopped</string>
     <string name="output_songnotfound">Song not found</string>
-    <string name="output_musicdisabled">enable_music is false!</string>
+    <string name="output_musicdisabled">enable_music is false</string>
+    <string name="no_songs">0 songs found</string>
 
     <!-- command/args -->
     <string name="output_commandnotfound">Command not found.\nTry to use \"$ help\" or \"$ tutorial\"</string>
@@ -227,15 +239,26 @@
         \n-select [song] -> play the selected song
         \n-info -> get info about the current song
         \n-seekto [seconds] -> seek to the selected part of the current song</string>
+    <string name="help_notes">-add [optional: lock {true/false}] [text] -> add a new note
+        \n-rm [row] OR [text] -> remove an existing note
+        \n-ls -> list all your notes
+        \n-clear -> remove all notes (except the locked ones)
+        \n-lock [id] OR [text] -> lock an existing note
+        \n-unlock [id] OR [text] -> unlock an existing note</string>
     <string name="help_rate">Leave a feedback on the Play Store page</string>
     <string name="help_refresh">Refresh apps, alias, music, contacts</string>
     <string name="help_regex">-add [ID] [regex] -> add a new regex with the given ID
         \n-rm [ID] -> remove the regex with the given ID
         \n-test [ID] [string] -> test the corresponding regex over the given string</string>
+    <string name="help_reply">-to [ID or packageName] [what] -> reply to the last notification from the application bound with the given ID
+        \n-bind [appName] -> bind the application
+        \n-unbind [appName] -> unbind the application
+        \n-ls -> show your bound applications
+        \n-check [ID or packageName] -> check the last notification from the application bound with the given ID</string>
     <string name="help_restart">Restart t-ui and load modified values</string>
     <string name="help_search">-gg [search this...] -> Google Search
         \n-ps [search this...] -> Google Play Store
-        \n-file [search this...] -> Files
+        \n-u [URL] -> open the URL
         \n-yt [search this...] -> YouTube
         \n-dd [search this...] -> DuckDuck Go
     </string>
@@ -255,12 +278,17 @@
         \n$ tuixt [textFile]
     </string>
     <string name="help_tui">-rm -> uninstall t-ui
-        \n-about -> show info about the developer and the current version</string>
+        \n-about -> show info about the developer and the current version
         \n-reset -> removes the t-ui folder and resets default settings (restart required)
+        \n-log [fileName] -> log the text on screen to the file
+        \n-priority [command] [int] -> set the priority of the selected command
         \n-twitter -> show t-ui Twitter page
         \n-googlep -> show the community on Google+
         \n-telegram -> open the official Telegram group
-        \n-folder -> print the path of the t-ui folder
+        \n-folder -> print the path of the t-ui folder</string>
+    <string name="help_tuinotes">-add [line] [text] -> add a new note at the specified line (the note will be appended if line is omitted)
+        \n-rm [line] -> remove the note at the specified line
+        \n-clear -> remove all the notes</string>
     <string name="help_tutorial">Open the tutorial page on GitHub</string>
     <string name="help_uninstall">Uninstall an application
         \n\nUsage:
@@ -269,7 +297,7 @@
     <string name="help_wifi">Toggle wifi</string>
     <string name="help_sms">Send an SMS.
         \n\nUsage:
-        \n$ sms [contactName] OR [number]
+        \n$ sms [contactName/number]
         \n$ [text]
     </string>
     <string name="help_vibrate">Make your device vibrate.
diff --git a/app/src/playstore/java/ohi/andre/consolelauncher/FlavorUtils.java b/app/src/playstore/java/ohi/andre/consolelauncher/FlavorUtils.java
deleted file mode 100755
index 62100c6f03bac7d7e1a4530bfb72f49810fa7d26..0000000000000000000000000000000000000000
--- a/app/src/playstore/java/ohi/andre/consolelauncher/FlavorUtils.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package ohi.andre.consolelauncher;
-
-import com.github.anrwatchdog.ANRError;
-import com.github.anrwatchdog.ANRWatchDog;
-
-import ohi.andre.consolelauncher.tuils.Tuils;
-
-public class FlavorUtils {
-
-    public static void startANR () {
-        new ANRWatchDog(5000)
-                .setANRListener(new ANRWatchDog.ANRListener() {
-                    @Override
-                    public void onAppNotResponding(ANRError anrError) {
-                        Tuils.log(anrError);
-                        Tuils.toFile(anrError);
-                    }
-                })
-                .setReportMainThreadOnly()
-                .start();
-    }
-}
diff --git a/app/src/playstore/java/ohi/andre/consolelauncher/managers/ThemesManager.java b/app/src/playstore/java/ohi/andre/consolelauncher/managers/ThemesManager.java
deleted file mode 100644
index 95a4ed5748f69e4bafc797cea65ab0cc11264f86..0000000000000000000000000000000000000000
--- a/app/src/playstore/java/ohi/andre/consolelauncher/managers/ThemesManager.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package ohi.andre.consolelauncher.managers;
-
-import android.content.Context;
-
-import com.google.firebase.database.DataSnapshot;
-import com.google.firebase.database.DatabaseError;
-import com.google.firebase.database.DatabaseReference;
-import com.google.firebase.database.FirebaseDatabase;
-import com.google.firebase.database.ValueEventListener;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import ohi.andre.consolelauncher.R;
-import ohi.andre.consolelauncher.managers.xml.XMLPrefsManager;
-import ohi.andre.consolelauncher.tuils.Tuils;
-
-/**
- * Created by francescoandreuzzi on 19/08/2017.
- */
-
-public class ThemesManager {
-
-    public static void apply(final Context context, final String name) {
-        final DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
-
-        reference.addListenerForSingleValueEvent(new ValueEventListener() {
-            @Override
-            public void onDataChange(DataSnapshot dataSnapshot) {
-
-                DataSnapshot theme = dataSnapshot.child("themes").child(name);
-                if(theme != null && theme.exists()) {
-
-                    File currentTheme = new File(Tuils.getFolder(), "theme.xml");
-                    File currentSuggestions = new File(Tuils.getFolder(), "suggestions.xml");
-
-                    String themePath = currentTheme.getAbsolutePath();
-                    String suggestionsPath = currentSuggestions.getAbsolutePath();
-
-                    Tuils.insertOld(currentTheme);
-                    Tuils.insertOld(currentSuggestions);
-
-                    Object o;
-
-                    String author = Tuils.EMPTYSTRING;
-                    if(theme.hasChild("author")) {
-                        o = theme.child("author").getValue();
-                        if(o != null) {
-                            author = o.toString();
-                        }
-                    }
-
-                    if(theme.hasChild("downloads")) {
-                        o = theme.child("downloads").getValue();
-                        if (o != null) {
-                            try {
-                                long downloads = Long.parseLong(o.toString());
-                                reference.child("themes").child(name).child("downloads").setValue(downloads + 1);
-                            } catch (Exception e) {
-                                Tuils.log(e);
-                            }
-                        }
-                    }
-
-                    theme = theme.child("files");
-                    if(theme == null || !theme.exists()) {
-                        Tuils.sendOutput(context, R.string.theme_invalid);
-                        return;
-                    }
-
-                    DataSnapshot t = theme.child("THEME");
-                    DataSnapshot s = theme.child("SUGGESTIONS");
-
-                    if(t == null || !t.exists() || s == null || !s.exists()) {
-                        Tuils.sendOutput(context, R.string.theme_invalid);
-                        return;
-                    }
-
-                    createFile(themePath, "THEME", t);
-                    createFile(suggestionsPath, "SUGGESTIONS", s);
-
-                    Tuils.sendOutput(context, "Applied theme " + name + (author.length() > 0 ? " by " + author : Tuils.EMPTYSTRING));
-                } else {
-                    Tuils.sendOutput(context, R.string.theme_not_found);
-                }
-            }
-
-            @Override
-            public void onCancelled(DatabaseError databaseError) {
-                Tuils.sendOutput(context, databaseError.getMessage());
-            }
-        });
-    }
-
-    public static void ls(final Context context) {
-        FirebaseDatabase.getInstance().getReference().addListenerForSingleValueEvent(new ValueEventListener() {
-
-            @Override
-            public void onDataChange(DataSnapshot dataSnapshot) {
-                List<String> strings = new ArrayList<>();
-
-                DataSnapshot themes = dataSnapshot.child("themes");
-                for(DataSnapshot s : themes.getChildren()) {
-                    String name = s.getKey();
-                    if(name.startsWith("custom_theme")) continue;
-
-                    strings.add(s.getKey());
-                }
-
-                Collections.sort(strings);
-                Tuils.addPrefix(strings, Tuils.DOUBLE_SPACE);
-                Tuils.insertHeaders(strings, false);
-
-                Tuils.sendOutput(context, Tuils.toPlanString(strings, Tuils.NEWLINE));
-            }
-
-            @Override
-            public void onCancelled(DatabaseError databaseError) {}
-        });
-    }
-
-    private static Pattern rgbaExtractor = Pattern.compile("rgba\\(([0-9]+),([0-9]+),([0-9]+),([0-9]+)\\)");
-
-    private static void createFile(String path, String r, DataSnapshot s) {
-        File file = new File(path);
-        XMLPrefsManager.resetFile(file, r);
-
-        try {
-            Object[] o;
-            try {
-                o = XMLPrefsManager.buildDocument(file, r);
-            } catch (Exception e) {
-                return;
-            }
-
-            if(o == null) return;
-
-            Document d = (Document) o[0];
-            Element root = (Element) o[1];
-
-            for(DataSnapshot ds : s.getChildren()) {
-                String value = ds.getValue().toString();
-                if(value.startsWith("rgba(")) value = rgbaToHex(value);
-
-                Element em = d.createElement(ds.getKey());
-                em.setAttribute(XMLPrefsManager.VALUE_ATTRIBUTE, value);
-                root.appendChild(em);
-            }
-
-            XMLPrefsManager.writeTo(d, file);
-
-        } catch (Exception e) {
-            Tuils.log(e);
-        }
-    }
-
-    private static String rgbaToHex(String value) {
-        StringBuilder builder = new StringBuilder();
-        builder.append("#");
-
-        Matcher matcher = rgbaExtractor.matcher(value);
-        if(matcher.find()) {
-            try {
-                String redString = matcher.group(1);
-                String greenString = matcher.group(2);
-                String blueString = matcher.group(3);
-                String alphaString = matcher.group(4);
-
-                int alpha = (int) (Float.parseFloat(alphaString) * 255);
-
-                String redHex = Integer.toHexString(Integer.parseInt(redString));
-                if(redHex.length() == 1) redHex = "0" + redHex;
-
-                String greenHex = Integer.toHexString(Integer.parseInt(greenString));
-                if(greenHex.length() == 1) greenHex = "0" + greenHex;
-
-                String blueHex = Integer.toHexString(Integer.parseInt(blueString));
-                if(blueHex.length() == 1) blueHex = "0" + blueHex;
-
-                String alphaHex = Integer.toHexString(alpha);
-                if(alphaHex.length() == 1) alphaHex = "0" + alphaHex;
-
-                builder.append(alphaHex).append(redHex).append(greenHex).append(blueHex);
-            } catch (Exception e) {
-                return null;
-            }
-        }
-
-        return builder.toString();
-    }
-}
diff --git a/build.gradle b/build.gradle
index baa3266cc6eec65f20ff5666a49fa581e8b440a3..f20d08008a17919f45484cf2ffa376406b16377f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ buildscript {
     }
 
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.3.3'
+        classpath 'com.android.tools.build:gradle:3.0.1'
         classpath 'com.google.gms:google-services:3.1.0'
     }
 }