summaryrefslogtreecommitdiff
path: root/src/fqterm/fqterm_scriptengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/fqterm/fqterm_scriptengine.cpp')
-rw-r--r--src/fqterm/fqterm_scriptengine.cpp488
1 files changed, 488 insertions, 0 deletions
diff --git a/src/fqterm/fqterm_scriptengine.cpp b/src/fqterm/fqterm_scriptengine.cpp
new file mode 100644
index 0000000..efab413
--- /dev/null
+++ b/src/fqterm/fqterm_scriptengine.cpp
@@ -0,0 +1,488 @@
+/***************************************************************************
+* fqterm, a terminal emulator for both BBS and *nix. *
+* Copyright (C) 2008 fqterm development group. *
+* *
+* This program 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 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program 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 this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. *
+***************************************************************************/
+
+
+
+#include "fqterm_scriptengine.h"
+#include "fqterm_window.h"
+#include "fqterm_screen.h"
+#include "fqterm_session.h"
+#include "fqterm_buffer.h"
+#include "common.h"
+#include "fqterm_path.h"
+
+#ifdef HAVE_PYTHON
+#include <Python.h>
+#endif
+
+#include <QString>
+#include <QDir>
+#include <QMessageBox>
+#include <QTime>
+#include <QTimer>
+#include <QFile>
+#include <QPoint>
+#include <QCursor>
+#include <QFileInfo>
+#include <QScriptContext>
+#include <QScriptContextInfo>
+namespace FQTerm {
+
+
+template <typename Tp>
+QScriptValue qScriptValueFromQObject(QScriptEngine *engine, Tp &qobject) {
+ return engine->newQObject(qobject);
+}
+
+template <typename Tp>
+void qScriptValueToQObject(const QScriptValue &value, Tp &qobject) {
+ qobject = qobject_cast<Tp>(value.toQObject());
+}
+
+template <typename Tp>
+int qScriptRegisterQObjectMetaType(
+ QScriptEngine *engine, const QScriptValue &prototype = QScriptValue()
+ ) {
+ return qScriptRegisterMetaType<Tp>(engine, qScriptValueFromQObject,
+ qScriptValueToQObject, prototype);
+}
+
+
+FQTermScriptEngine::FQTermScriptEngine(FQTermWindow* parent)
+: QObject(parent),
+ window_(parent),
+ engine_(NULL),
+ articleCopyThread_(NULL),
+ timerIDCount_(0) {
+ FQ_VERIFY(window_);
+ session_ = window_->getSession();
+ buffer_ = window_->getSession()->getBuffer();
+ screen_ = window_->getScreen();
+ articleCopyThread_ = new ArticleCopyThread(*session_, session_->getWaitCondition(), session_->getBufferLock());
+ FQ_VERIFY(connect(articleCopyThread_, SIGNAL(articleCopied(int, const QString)),
+ this, SLOT(articleCopied(int, const QString))));
+ engine_ = new QScriptEngine();
+ engine_->globalObject().setProperty(
+ "fq_session", engine_->newQObject(session_));
+ engine_->globalObject().setProperty(
+ "fq_window", engine_->newQObject(window_));
+ engine_->globalObject().setProperty(
+ "fq_buffer", engine_->newQObject(buffer_));
+ engine_->globalObject().setProperty(
+ "fq_screen", engine_->newQObject(screen_));
+ engine_->globalObject().setProperty(
+ "fqterm", engine_->newQObject(this));
+}
+
+FQTermScriptEngine::~FQTermScriptEngine() {
+ engine_->abortEvaluation();
+ delete engine_;
+}
+
+void FQTermScriptEngine::runScript( const QString& filename ) {
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ FQ_TRACE("script", 0) << "Unable to open the script file: " << filename;
+ QMessageBox::warning(window_, tr("FQTerm"),
+ tr("Unable to open the script file\n") + filename,
+ QMessageBox::Close);
+ return;
+ }
+
+ QString script = QString::fromUtf8(file.readAll());
+ QFileInfo fileInfo(filename);
+ QScriptValue result = engine_->evaluate(script, fileInfo.absoluteFilePath());
+ if (engine_->hasUncaughtException()) {
+ int line = engine_->uncaughtExceptionLineNumber();
+ FQ_TRACE("script", 0) << "uncaught exception at line " << line
+ << ":" << result.toString();
+ QMessageBox::warning(window_, tr("FQTerm"),
+ tr("uncaught exception at line ") + QString::number(line)
+ + ":\n" + result.toString(),
+ QMessageBox::Close);
+ }
+}
+
+void FQTermScriptEngine::stopScript() {
+ //all loops should be stopped here.
+ articleCopied_ = true;
+ engine_->abortEvaluation();
+}
+
+void FQTermScriptEngine::msgBox( const QString& msg ) {
+ QMessageBox::warning(window_, tr("FQTerm"),
+ msg,
+ QMessageBox::Close);
+}
+
+int FQTermScriptEngine::caretX() {
+ return buffer_->getCaretColumn();
+}
+
+int FQTermScriptEngine::caretY() {
+ return buffer_->getCaretRow();
+}
+
+int FQTermScriptEngine::columns() {
+ return buffer_->getNumColumns();
+}
+
+int FQTermScriptEngine::rows() {
+ return buffer_->getNumRows();
+}
+
+void FQTermScriptEngine::sendString(const QString& str) {
+ window_->writeRawString(str);
+}
+
+void FQTermScriptEngine::sendParsedString( const QString& str ){
+ window_->externInput(str);
+}
+
+QString FQTermScriptEngine::getText(int row) {
+ QString str;
+ if (row < rows())
+ buffer_->getTextLineInTerm(row)->getAllPlainText(str);
+ return str;
+}
+
+QString FQTermScriptEngine::getAttrText(int row) {
+ QString str;
+ if (row < rows())
+ buffer_->getTextLineInTerm(row)->getAllAnsiText(str);
+ return str;
+}
+
+bool FQTermScriptEngine::isConnected() {
+ return window_->isConnected();
+}
+
+void FQTermScriptEngine::disconnect() {
+ window_->disconnect();
+}
+
+void FQTermScriptEngine::reconnect() {
+ session_->reconnect();
+}
+
+//FIXME: UTF8 and HKSCS
+QString FQTermScriptEngine::getBBSCodec() {
+ return session_->param().serverEncodingID_ == 0 ? "GBK" : "Big5";
+}
+
+QString FQTermScriptEngine::getAddress() {
+ return session_->param().hostAddress_;
+}
+
+int FQTermScriptEngine::getPort() {
+ return session_->param().port_;
+}
+// connection protocol 0-telnet 1-SSH1 2-SSH2
+int FQTermScriptEngine::getProtocol() {
+ return session_->param().protocolType_;
+}
+
+QString FQTermScriptEngine::getReplyKey() {
+ return session_->param().replyKeyCombination_;
+}
+
+QString FQTermScriptEngine::getURL() {
+ return session_->getUrl();
+}
+
+QString FQTermScriptEngine::getIP() {
+ return session_->getIP();
+}
+
+void FQTermScriptEngine::previewImage(const QString& url) {
+ window_->getHttpHelper(url, true);
+}
+
+void FQTermScriptEngine::sleep(int ms) {
+ int originInterval = engine_->processEventsInterval();
+ engine_->setProcessEventsInterval(1);
+ QString busy_wait = "var start = new Date().getTime();\n"
+ "while(true) {if(new Date().getTime() - start > " + QString("%1").arg(ms) + ") break;}\n";
+ engine_->evaluate(busy_wait);
+ engine_->setProcessEventsInterval(originInterval);
+}
+
+//TODO: flags
+void FQTermScriptEngine::articleCopied(int state, const QString content) {
+ if (state == DAE_FINISH) {
+ articleCopied_ = true;
+ articleText_ = content;
+ } else /*if (state == DAE_TIMEOUT)*/ {
+ articleCopied_ = true;
+ articleText_ = "";
+ }
+}
+
+QString FQTermScriptEngine::copyArticle() {
+ articleCopied_ = false;
+ articleText_ = "";
+ articleCopyThread_->wait();
+ articleCopyThread_->start();
+ while(!articleCopied_) {
+ sleep(200);
+ }
+ return articleText_;
+}
+
+void FQTermScriptEngine::finalizeScript() {
+ engine_->setProcessEventsInterval(-1);
+ stopScript();
+ setParent(NULL);
+ //TODO: safe?
+ deleteLater();
+}
+
+void FQTermScriptEngine::writeFile( const QString& filename, const QString& str ) {
+ QFile file(filename);
+ file.open(QIODevice::WriteOnly);
+ file.write(U2U8(str));
+ file.close();
+}
+
+QString FQTermScriptEngine::readFile( const QString& filename ) {
+ QFile file(filename);
+ file.open(QIODevice::ReadOnly);
+ QString str = U82U(file.readAll());
+ file.close();
+ return str;
+}
+
+void FQTermScriptEngine::appendFile( const QString& filename, const QString& str ) {
+ QFile file(filename);
+ file.open(QIODevice::WriteOnly | QIODevice::Append);
+ file.write(U2U8(str));
+ file.close();
+}
+
+QStringList FQTermScriptEngine::readFolder( const QString& path ) {
+ return QDir(path).entryList(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot | QDir::Readable);
+}
+
+QString FQTermScriptEngine::platform() {
+#if defined(WIN32)
+ return "Win";
+#elif defined(__unix__) && !defined(__APPLE__)
+ return "Linux";
+#else
+ return "Mac";
+#endif
+}
+
+bool FQTermScriptEngine::makePath( const QString& path ){
+ return QDir().mkpath(path);
+}
+
+QString FQTermScriptEngine::newLine() {
+ return OS_NEW_LINE;
+}
+
+void FQTermScriptEngine::openUrl(const QString & url) {
+ window_->openUrlImpl(url);
+}
+
+QString FQTermScriptEngine::getSelect(bool color_copy) {
+ return buffer_->getTextSelected(
+ session_->param().isRectSelect_,
+ color_copy,
+ window_->parseString((const char*)session_->param().escapeString_.toLatin1()));
+}
+
+QList<int> FQTermScriptEngine::mapToChar(int screenX, int screenY) {
+ QPoint charP(screen_->mapToChar(QPoint(screenX, screenY)));
+ QList<int> result;
+ result << charP.x() << charP.y() - screen_->getBufferStart();
+ return result;
+}
+
+int FQTermScriptEngine::charX(int screen_x) {
+ return screen_->mapToChar(QPoint(screen_x, 0)).x();
+}
+
+int FQTermScriptEngine::charY(int screen_y) {
+ return screen_->mapToChar(QPoint(0, screen_y)).y() - screen_->getBufferStart();
+}
+
+QString FQTermScriptEngine::getTextAt( int row, int column, int len ) {
+ if (column < 0 || column >= columns() ||
+ row < 0 || row >= rows())
+ return "";
+ if (column + len > columns() || len < 0) {
+ len = columns() - column;
+ }
+ QString result;
+ buffer_->getTextLineInTerm(row)->getPlainText(column, column + len, result);
+ return result;
+}
+
+QString FQTermScriptEngine::getAttrTextAt( int row, int column, int len ) {
+ if (column < 0 || column >= columns() ||
+ row < 0 || row >= rows())
+ return "";
+ if (column + len > columns() || len < 0) {
+ len = columns() - column;
+ }
+ QString result;
+ buffer_->getTextLineInTerm(row)->getAnsiText(column, column + len, result);
+ return result;
+}
+
+QString FQTermScriptEngine::getFullTextAt(int row, int column, int len) {
+ return getTextAt(row, buffer_->getTextLineInTerm(row)->getCellBegin(column), len);
+}
+
+QString FQTermScriptEngine::getFullAttrText(int row, int column, int len) {
+ return getAttrTextAt(row, buffer_->getTextLineInTerm(row)->getCellBegin(column), len);
+}
+
+int FQTermScriptEngine::mouseSX() {
+ return screen_->mapFromGlobal(QCursor::pos()).x();
+}
+
+int FQTermScriptEngine::mouseSY() {
+ return screen_->mapFromGlobal(QCursor::pos()).y();
+}
+
+int FQTermScriptEngine::screenX( int char_x ){
+ return screen_->mapToPixel(QPoint(char_x, 0)).x();
+}
+
+int FQTermScriptEngine::screenY( int char_y ){
+ return screen_->mapToPixel(QPoint(0, char_y + screen_->getBufferStart())).y();
+}
+
+bool FQTermScriptEngine::scriptCallback( const QString& func, const QScriptValueList& args ) {
+ QScriptValue f = engine_->globalObject().property("fqterm").property(func);
+ if (f.isFunction()) {
+ QScriptValue res = f.call(QScriptValue(), args);
+ if (!engine_->hasUncaughtException() && res.isBool()) {
+ return res.toBool();
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
+bool FQTermScriptEngine::importFile( const QString& filename ) {
+ QFileInfo fileInfo(filename);
+ if (!fileInfo.isAbsolute()) {
+ //first search current running path.
+ if (engine_->currentContext() && engine_->currentContext()->parentContext()) {
+ QString runningFile = QScriptContextInfo(engine_->currentContext()->parentContext()).fileName();
+ if (!runningFile.isEmpty()) {
+ QFileInfo current(runningFile);
+ fileInfo = QFileInfo(current.absolutePath() + '/' + filename);
+ }
+ }
+ //then look in script folder.
+ if (!fileInfo.exists()) {
+ fileInfo = QFileInfo(getPath(RESOURCE) + "script/" + filename);
+ }
+ }
+ if (!fileInfo.exists()) {
+ return false;
+ }
+ fileInfo.makeAbsolute();
+ runScript(fileInfo.absoluteFilePath());
+ return true;
+}
+
+int FQTermScriptEngine::setInterval(int ms, const QScriptValue& func) {
+ return createTimer(ms, func, false);
+}
+
+
+void FQTermScriptEngine::clearInterval(int id) {
+ destroyTimer(id);
+}
+
+void FQTermScriptEngine::serverRedraw() {
+ sendParsedString("^L");
+}
+
+void FQTermScriptEngine::clientRedraw() {
+ window_->refreshScreen();
+}
+
+void FQTermScriptEngine::setMenuRect(int row, int column, int len) {
+ if (column < 0 || column >= columns() ||
+ row < 0 || row >= rows())
+ return ;
+ if (column + len > columns() || len < 0) {
+ len = columns() - column;
+ }
+ row += screen_->getBufferStart();
+ session_->setMenuRect(row, column, len);
+}
+
+int FQTermScriptEngine::setTimeout(int ms, const QScriptValue& func) {
+ return createTimer(ms, func, true);
+}
+
+void FQTermScriptEngine::clearTimeout(int id) {
+ destroyTimer(id);
+}
+
+int FQTermScriptEngine::createTimer(int ms, const QScriptValue& func, bool singleShot) {
+ QTimer* timer = new QTimer(this);
+ timer->setInterval(ms);
+ timer->setSingleShot(singleShot);
+ int id = timerIDCount_++;
+ if (timerTable_.find(id) != timerTable_.end()) {
+ //actually impossible!
+ destroyTimer(id);
+ }
+ timerTable_[id] = timer;
+ bool res = qScriptConnect(timer, SIGNAL(timeout()), QScriptValue(), func);
+ timer->start();
+ return id;
+}
+
+void FQTermScriptEngine::destroyTimer(int id) {
+ if (timerTable_.find(id) != timerTable_.end()) {
+ timerTable_[id]->stop();
+ delete timerTable_[id];
+ timerTable_.erase(id);
+ }
+}
+
+int FQTermScriptEngine::getUIEventInterval() {
+ return engine_->processEventsInterval();
+}
+
+void FQTermScriptEngine::setUIEventInterval(int ms) {
+ engine_->setProcessEventsInterval(ms);
+}
+
+bool FQTermScriptEngine::isAntiIdle() {
+ return session_->isAntiIdle();
+}
+
+bool FQTermScriptEngine::isAutoReply() {
+ return session_->isAutoReply();
+}
+} // namespace FQTerm
+
+#include "fqterm_scriptengine.moc" \ No newline at end of file