/**
* 920 Text Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 920 Text Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 920 Text Editor. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jecelyin.editor;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;
import com.jecelyin.util.FileUtil;
import com.jecelyin.util.JecLog;
import com.jecelyin.util.LinuxShell;
import com.stericson.RootTools.RootTools;
import org.mozilla.charsetdetector.CharsetDetector;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import jecelyin.android.compat.TextViewBase;
import jecelyin.android.v2.text.SpannableStringBuilder;
public class AsyncReadFile
{
private JecEditor mJecEditor;
public static final int RESULT_OK = 0;
public static final int RESULT_FAIL = 1;
private ProgressDialog mProgressDialog;
private int mSelStart = 0;
private int mSelEnd = 0;
private ReadHandler mReadHandler;
private String mEncoding = "";
class AsyncResult
{
public String path;
public String encoding;
public int linebreak;
public String errorMsg;
public SpannableStringBuilder data;
}
public AsyncReadFile(final JecEditor mJecEditor, final String path, final String encoding, final int lineBreak, int selStart, int selEnd)
{
JecEditor.isLoading = true;
// mJecEditor.text_content.requestFocus();
this.mJecEditor = mJecEditor;
mSelStart = selStart > 0 ? selStart : 0;
mSelEnd = selEnd > 0 ? selEnd : 0;
mReadHandler = new ReadHandler(AsyncReadFile.this);
showProgress();
mEncoding = encoding;
Thread thread = new Thread(new Runnable() {
@Override
public void run()
{
int what = RESULT_OK;
AsyncResult result = new AsyncResult();
try
{
String fileString = path;
File file = new File(fileString);
fileString = file.getAbsolutePath();
String tempFile = JecEditor.TEMP_PATH + "/"+file.getName()+".tmp";
//Log.d(TAG, "write:"+file.canWrite()+" rooted:"+isRoot+" access:"+RootTools.isAccessGiven());
boolean root = false;
if(!file.canWrite() && EditorSettings.TRY_ROOT && RootTools.isAccessGiven())
{
//RootTools.sendShell("busybox cp " + LinuxShell.getCmdPath(fileString) + " " + tempFile, 1000);
RootTools.copyFile(LinuxShell.getCmdPath(fileString), tempFile, true, true);
RootTools.sendShell("busybox chmod 777 " + tempFile, 1000);
fileString = tempFile;
file = new File(fileString);
root = true;
}
if(file.isFile())
{
SpannableStringBuilder mData = readFile(file, lineBreak);
if(root)
{
LinuxShell.execute("rm -rf " + tempFile);
}
what = RESULT_OK;
result.data = mData;
} else {
what = RESULT_FAIL;
result.errorMsg = AsyncReadFile.this.mJecEditor.getString(R.string.can_not_open_file);
}
}catch (FileNotFoundException e){
e.printStackTrace();
String errorMsg = e.getMessage();
if(errorMsg.contains("Permission denied")){
EditorSettings.setBoolean("get_root", true);
errorMsg = mJecEditor.getString(R.string.try_root);
try
{
RootTools.sendShell("busybox ls " + path, 1000);
} catch (Exception e1)
{
e1.printStackTrace();
}
}
what = RESULT_FAIL;
result.errorMsg = errorMsg;
}catch (Exception e)
{
e.printStackTrace();
final String errorMsg = e.getMessage();// R.string.exception;
what = RESULT_FAIL;
result.errorMsg = errorMsg;
}catch (OutOfMemoryError e)
{//内存不足
final String errorMsg = mJecEditor.getString(R.string.out_of_memory);
what = RESULT_FAIL;
result.errorMsg = errorMsg;
} finally {
result.path = path;
result.encoding = mEncoding;
result.linebreak = lineBreak;
Message msg = mReadHandler.obtainMessage(what, result);
msg.sendToTarget();
}
}
});
thread.start();
}
private void showProgress()
{
mProgressDialog = new ProgressDialog(mJecEditor);
mProgressDialog.setTitle(R.string.spinner_message);
mProgressDialog.setMessage(mJecEditor.getText(R.string.loading));
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(true);
mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog)
{
dismissProgress();
}
});
mProgressDialog.show();
}
public void dismissProgress()
{
if(mProgressDialog != null)
mProgressDialog.dismiss();
}
static class ReadHandler extends Handler
{
private AsyncReadFile mAsyncReadFile;
public ReadHandler(AsyncReadFile arf)
{
super();
mAsyncReadFile = arf;
}
@Override
public void handleMessage(Message msg)
{
AsyncResult rs = (AsyncResult) msg.obj;
mAsyncReadFile.dismissProgress();
if(msg.what == RESULT_OK) {
mAsyncReadFile.finish(rs.data, rs.path, rs.encoding, rs.linebreak);
} else {
JecEditor.isLoading = false;
JecLog.msg(rs.errorMsg);
}
}
};
private void finish(SpannableStringBuilder data, String path, String encoding, int lineBreak)
{
if(data == null)
{
JecEditor.isLoading = false;
return;
}
try
{
TextViewBase mEditText = mJecEditor.getEditText();
mEditText.setText(data);
mEditText.updateTextFinger();
int len = data.length();
if(mSelEnd >= len || mSelStart >= len)
mSelStart = mSelEnd = 0;
// scroll to topprivate
//mEditText.setSelection(0, 0);
mEditText.setSelection(mSelStart, mSelEnd);
mEditText.clearFocus();
// mJecEditor.text_content.invalidate();
mEditText.setEncoding(encoding);
mEditText.setLineBreak(lineBreak);
mEditText.setPath(path);
mJecEditor.onLoaded(mSelStart, mSelEnd);
}catch (OutOfMemoryError e)
{
Toast.makeText(mJecEditor, R.string.out_of_memory, Toast.LENGTH_LONG).show();
}catch (Exception e)
{
//Toast.makeText(mJecEditor, e.getMessage(), Toast.LENGTH_LONG).show();
JecLog.e(e.getMessage(), e);
}
}
private SpannableStringBuilder readFile(File file, int lineBreak) throws Exception
{
//检测编码
if(mEncoding==null || "".equals(mEncoding))
{
FileInputStream fis = new FileInputStream(file);
byte[] buff = new byte[64*1024];
int buf_len = fis.read(buff);
fis.close();
if(buf_len <= 0)
return null;
CharsetDetector cd = new CharsetDetector();
if(cd.isOK())
{
cd.handleData(buff, 0, buf_len);
cd.dataEnd();
mEncoding = cd.getCharset();
cd.destroy();
if ( mEncoding != null && mEncoding.length() > 0 )
{
if("GB18030".equals(mEncoding.toUpperCase()))
mEncoding = "GBK";
}else{
mEncoding = "utf-8";
}
}else{
mEncoding = "utf-8";
}
}
return FileUtil.readFile(file, mEncoding, lineBreak);
}
}