summaryrefslogtreecommitdiff
path: root/src/unite
diff options
context:
space:
mode:
Diffstat (limited to 'src/unite')
-rw-r--r--src/unite/CMakeLists.txt46
-rw-r--r--src/unite/fqterm_mini_server.cpp71
-rw-r--r--src/unite/fqterm_mini_server.h69
-rw-r--r--src/unite/internal/article.cpp19
-rw-r--r--src/unite/internal/article.h28
-rw-r--r--src/unite/internal/board.cpp19
-rw-r--r--src/unite/internal/board.h28
-rw-r--r--src/unite/internal/session.cpp138
-rw-r--r--src/unite/internal/session.h77
-rw-r--r--src/unite/internal/state.cpp676
-rw-r--r--src/unite/internal/state.h219
-rw-r--r--src/unite/internal/statebuilder.cpp32
-rw-r--r--src/unite/internal/statebuilder.h16
-rw-r--r--src/unite/internal/unite.h35
-rw-r--r--src/unite/internal/user.cpp19
-rw-r--r--src/unite/internal/user.h35
16 files changed, 1527 insertions, 0 deletions
diff --git a/src/unite/CMakeLists.txt b/src/unite/CMakeLists.txt
new file mode 100644
index 0000000..b093576
--- /dev/null
+++ b/src/unite/CMakeLists.txt
@@ -0,0 +1,46 @@
+set(fqunite_SRCS
+ fqterm_mini_server.h
+ fqterm_mini_server.cpp
+)
+
+set(fqunite_internal_SRCS
+ internal/unite.h
+ internal/user.h
+ internal/user.cpp
+ internal/board.h
+ internal/board.cpp
+ internal/article.h
+ internal/article.cpp
+ internal/session.h
+ internal/session.cpp
+ internal/state.h
+ internal/state.cpp
+ internal/statebuilder.h
+ internal/statebuilder.cpp
+)
+
+qt4_automoc(
+ ${fqunite_SRCS}
+ ${fqunite_internal_SRCS}
+)
+
+include_directories(
+ ${QT_INCLUDE_DIR}
+ ${QT_QTCORE_INCLUDE_DIR}
+ ${QT_QTNETWORK_INCLUDE_DIR}
+ ${QT_QTXML_INCLUDE_DIR}
+ ${QT_QTGUI_INCLUDE_DIR}
+ ${OPENSSL_INCLUDE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/internal
+ ${CMAKE_CURRENT_SOURCE_DIR}/../common
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+add_library(fqterm_unite
+ ${fqunite_SRCS}
+ ${fqunite_internal_SRCS}
+)
+
+add_dependencies(fqterm_unite
+ fqterm_common
+)
diff --git a/src/unite/fqterm_mini_server.cpp b/src/unite/fqterm_mini_server.cpp
new file mode 100644
index 0000000..2b18faf
--- /dev/null
+++ b/src/unite/fqterm_mini_server.cpp
@@ -0,0 +1,71 @@
+/***************************************************************************
+* 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_mini_server.h"
+#include "fqterm_trace.h"
+#include "fqterm_path.h"
+#include "fqterm.h"
+#include <QByteArray>
+#include <QTimer>
+#include <QFile>
+#include <QtGui/QApplication>
+#include <queue>
+namespace FQTerm {
+
+
+void FQTermMiniServerThread::run()
+{
+ setTerminationEnabled();
+ FQTermMiniServer miniServer;
+ //miniServer.setMaxPendingConnections(1);
+ miniServer.listen(QHostAddress::LocalHost, 35172);
+ exec();
+ miniServer.close();
+ miniServer.finalizeMiniServer();
+}
+
+FQTermMiniServer::FQTermMiniServer(QObject * parent)
+ : QTcpServer(parent) {
+}
+
+
+FQTermMiniServer::~FQTermMiniServer() {
+}
+
+void FQTermMiniServer::incomingConnection( int socketDescriptor ) {
+ FQTermUniteSession* session = new FQTermUniteSession(socketDescriptor);
+ FQ_VERIFY(connect(this, SIGNAL(quit()), session, SLOT(quit()), Qt::QueuedConnection));
+ session->start();
+}
+
+void FQTermMiniServer::finalizeMiniServer() {
+ emit quit();
+}
+
+
+
+
+
+
+
+
+} //namespace FQTerm
+
+#include "fqterm_mini_server.moc"
diff --git a/src/unite/fqterm_mini_server.h b/src/unite/fqterm_mini_server.h
new file mode 100644
index 0000000..3295137
--- /dev/null
+++ b/src/unite/fqterm_mini_server.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef FQTERM_MINI_SERVER_H
+#define FQTERM_MINI_SERVER_H
+
+#include <QThread>
+#include <QByteArray>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <QString>
+#include "internal/session.h"
+
+namespace FQTerm {
+
+
+class FQTermMiniServer : public QTcpServer {
+ Q_OBJECT;
+public:
+ FQTermMiniServer( QObject * parent = 0 );
+ ~FQTermMiniServer();
+ void finalizeMiniServer();
+protected:
+ void incomingConnection(int socketDescriptor);
+signals:
+ void quit();
+};
+
+
+class FQTermMiniServerThread : public QThread{
+protected:
+ virtual void run();
+
+};
+//----------------------------------------------------------------------------------
+// this for FSM
+class FQTermUniteDecode;
+
+//----------------------------------------------------------------------------------
+
+
+class FQTermUniteSession;
+class FQTermUniteState;
+
+
+
+//use XML to describe the site.
+//each session contains user info, not in the reverse way.
+//each session has 1. state (edit, read, menu), 2. strategy (decided by state) 3. context (with which strategy could decide next step. i.e. inner state)
+} //namespace FQTerm
+#endif
diff --git a/src/unite/internal/article.cpp b/src/unite/internal/article.cpp
new file mode 100644
index 0000000..c5905f8
--- /dev/null
+++ b/src/unite/internal/article.cpp
@@ -0,0 +1,19 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
diff --git a/src/unite/internal/article.h b/src/unite/internal/article.h
new file mode 100644
index 0000000..43ca0cb
--- /dev/null
+++ b/src/unite/internal/article.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef FQTERM_UNITE_ARTICLE
+#define FQTERM_UNITE_ARTICLE
+
+namespace FQTerm {
+
+} //namespace FQTerm
+
+#endif //FQTERM_UNITE_USER \ No newline at end of file
diff --git a/src/unite/internal/board.cpp b/src/unite/internal/board.cpp
new file mode 100644
index 0000000..c5905f8
--- /dev/null
+++ b/src/unite/internal/board.cpp
@@ -0,0 +1,19 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
diff --git a/src/unite/internal/board.h b/src/unite/internal/board.h
new file mode 100644
index 0000000..a23db18
--- /dev/null
+++ b/src/unite/internal/board.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef FQTERM_UNITE_BOARD
+#define FQTERM_UNITE_BOARD
+
+namespace FQTerm {
+
+} //namespace FQTerm
+
+#endif //FQTERM_UNITE_USER \ No newline at end of file
diff --git a/src/unite/internal/session.cpp b/src/unite/internal/session.cpp
new file mode 100644
index 0000000..6964287
--- /dev/null
+++ b/src/unite/internal/session.cpp
@@ -0,0 +1,138 @@
+/***************************************************************************
+* 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 "state.h"
+#include "fqterm.h"
+#include <QApplication>
+#include <algorithm>
+#include "statebuilder.h"
+namespace FQTerm{
+
+void FQTermUniteSessionContext::write(const QByteArray& str) {
+ session_->write(str);
+}
+
+FQTermUniteSessionContext::FQTermUniteSessionContext(FQTermUniteSession* session) : QObject(session), session_(session) {
+ stateTable_[WELCOME] = new FQTermWelcomeState(this);
+ stateTable_[EXITING] = new FQTermExitState(this);
+ stateTable_[READING] = new FQTermReadingState(this);
+ stateTable_[HELP] = new FQTermHelpState(this);
+ setCurrentState(WELCOME);
+}
+
+void FQTermUniteSessionContext::processInput(const QByteArray& input) {
+ inputBuffer_ += input;
+ while(true) {
+ int consumed = currentState_->processInput(inputBuffer_);
+ inputBuffer_ = inputBuffer_.mid(consumed);
+ if (!consumed || inputBuffer_.size() == 0) {
+ break;
+ }
+ }
+}
+
+void FQTermUniteSessionContext::quit() {
+ session_->quit();
+}
+
+
+
+FQTermUniteState* FQTermUniteSessionContext::setCurrentState(int state, bool init /*= true*/) {
+ StateTableIterator it = stateTable_.find(state);
+ if (it != stateTable_.end()) {
+ currentState_ = it->second;
+ if (init)
+ currentState_->initialize();
+ }
+ return currentState_;
+}
+
+
+
+FQTermUniteSession::FQTermUniteSession(int socketDescriptor ) : context_(NULL) {
+ moveToThread(this);
+ socket_ = new QTcpSocket;
+ FQ_VERIFY(connect(socket_, SIGNAL(readyRead()),
+ this, SLOT(readyRead()),Qt::DirectConnection));
+ FQ_VERIFY(connect(socket_, SIGNAL(disconnected()),
+ this, SLOT(disconnected()),Qt::DirectConnection));
+ FQ_VERIFY(connect(socket_, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+ this, SLOT(stateChanged(QAbstractSocket::SocketState)),Qt::DirectConnection));
+ FQ_VERIFY(connect(socket_, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SLOT(error(QAbstractSocket::SocketError)),Qt::DirectConnection));
+
+ // FQ_VERIFY(connect(socket_, SIGNAL(connected()),
+ // this, SLOT(welcome()),Qt::DirectConnection));
+
+ socket_->setSocketDescriptor(socketDescriptor);
+ socket_->moveToThread(this);
+ setTerminationEnabled();
+
+ StateBuilder sb;
+ sb.BuildState();
+}
+
+
+FQTermUniteSession::~FQTermUniteSession() {
+ socket_->close();
+ delete socket_;
+ socket_ = NULL;
+}
+
+void FQTermUniteSession::welcome()
+{
+ context_ = new FQTermUniteSessionContext(this);
+}
+
+void FQTermUniteSession::readyRead() {
+ if (context_) {
+ context_->processInput(socket_->readAll());
+ }
+}
+
+void FQTermUniteSession::write( const QByteArray& output ) {
+ socket_->write(output);
+}
+
+void FQTermUniteSession::run() {
+ welcome();
+ exec();
+ disconnected();
+}
+
+
+void FQTermUniteSession::disconnected() {
+ if (!isRunning())
+ return;
+ quit();
+ moveToThread(QApplication::instance()->thread());
+ deleteLater();
+}
+
+void FQTermUniteSession::stateChanged( QAbstractSocket::SocketState socketState ) {
+}
+
+void FQTermUniteSession::error(QAbstractSocket::SocketError socketError) {
+}
+
+
+}
+
+#include "session.moc" \ No newline at end of file
diff --git a/src/unite/internal/session.h b/src/unite/internal/session.h
new file mode 100644
index 0000000..a5959a1
--- /dev/null
+++ b/src/unite/internal/session.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+#ifndef FQTERM_UNITE_SESSION
+#define FQTERM_UNITE_SESSION
+
+#include <QObject>
+#include <QThread>
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <map>
+namespace FQTerm {
+
+class FQTermUniteState;
+class FQTermUniteSession;
+class FQTermUniteSessionContext : public QObject {
+ Q_OBJECT;
+public:
+ FQTermUniteSessionContext(FQTermUniteSession* session);
+ void write(const QByteArray& str);
+ void processInput(const QByteArray& input);
+ void quit();
+ enum STATE{WELCOME = 0, EXITING = 1, READING = 2, HELP = 3};
+ FQTermUniteState* setCurrentState(int state, bool init = true);
+
+ int row() {return 24;}
+ int column() {return 80;}
+private:
+ FQTermUniteSession* session_;
+ FQTermUniteState* currentState_;
+ QByteArray inputBuffer_;
+ typedef std::map<int, FQTermUniteState*> StateTable;
+ typedef std::map<int, FQTermUniteState*>::iterator StateTableIterator;
+ StateTable stateTable_;
+};
+
+
+class FQTermUniteSession : public QThread {
+ Q_OBJECT;
+public:
+ FQTermUniteSession(int socketDescriptor);
+ ~FQTermUniteSession();
+ void write(const QByteArray& output);
+
+protected:
+ virtual void run();
+ protected slots:
+ void readyRead();
+ void disconnected();
+ void stateChanged(QAbstractSocket::SocketState socketState);
+ void error(QAbstractSocket::SocketError socketError);
+ void welcome();
+private:
+ QTcpSocket* socket_;
+ FQTermUniteSessionContext* context_;
+
+};
+
+} //namespace FQTerm
+
+#endif //FQTERM_UNITE_USER \ No newline at end of file
diff --git a/src/unite/internal/state.cpp b/src/unite/internal/state.cpp
new file mode 100644
index 0000000..39241b0
--- /dev/null
+++ b/src/unite/internal/state.cpp
@@ -0,0 +1,676 @@
+#include "fqterm.h"
+#include "fqterm_path.h"
+#include <algorithm>
+#include "state.h"
+#include <QDomDocument>
+
+namespace FQTerm{
+
+int FQTermUniteMenu::addEntry( char key )
+{
+ entries_.push_back(tolower(key));
+ return entries_.size() - 1;
+}
+
+int FQTermUniteMenu::findEntry( char key )
+{
+ std::vector<char>::iterator it = std::find(entries_.begin(), entries_.end(), tolower(key));
+ if (it == entries_.end()) {return -1;}
+ return std::distance(entries_.begin(), it);
+}
+
+void FQTermUniteMenu::clearEntry()
+{
+ entries_.clear();
+ clearPointer(current_);
+ current_ = 0;
+}
+
+int FQTermUniteMenu::currentEntry()
+{
+ return current_;
+}
+
+int FQTermUniteMenu::setCurrentEntry( char key )
+{
+ int next = findEntry(key);
+ if (next == -1)
+ return currentEntry();
+ clearPointer(current_);
+ current_ = next;
+ drawPointer(current_);
+ return current_;
+}
+
+int FQTermUniteMenu::setCurrentIndex( int index )
+{
+ clearPointer(current_);
+ current_ = index;
+ drawPointer(current_);
+ return current_;
+}
+
+int FQTermUniteMenu::nextEntry()
+{
+ if (!entries_.size())
+ return current_;
+ clearPointer(current_);
+ current_++;
+ current_ %= entries_.size();
+ drawPointer(current_);
+ return current_;
+}
+
+int FQTermUniteMenu::prevEntry()
+{
+ if (!entries_.size())
+ return current_;
+ clearPointer(current_);
+ current_--;
+ current_ += entries_.size();
+ current_ %= entries_.size();
+ drawPointer(current_);
+ return current_;
+}
+
+
+StateOption FQTermUniteDecode::EscStateMachine::normal_state_[] = {
+ {
+ CHAR_ESC, 0, esc_state_
+ }, {
+ CHAR_NORMAL, &FQTermUniteDecode::normalInput, normal_state_
+ }
+};
+
+// state after a ESC_CHAR
+StateOption FQTermUniteDecode::EscStateMachine::esc_state_[] = {
+ {
+ '[', &FQTermUniteDecode::clearParam, bracket_state_
+ }, {
+ CHAR_ESC, &FQTermUniteDecode::doubleEsc, normal_state_
+ },{
+ CHAR_NORMAL, 0, normal_state_
+ }
+};
+
+// state after ESC [
+StateOption FQTermUniteDecode::EscStateMachine::bracket_state_[] = {
+ {
+ '0', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '1', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '2', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '3', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '4', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '5', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '6', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '7', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '8', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ '9', &FQTermUniteDecode::paramDigit, bracket_state_
+ }, {
+ 'A', &FQTermUniteDecode::cursorUp, normal_state_
+ }, {
+ 'B', &FQTermUniteDecode::cursorDown, normal_state_
+ }, {
+ 'C', &FQTermUniteDecode::cursorRight, normal_state_
+ }, {
+ 'D', &FQTermUniteDecode::cursorLeft, normal_state_
+ }, {
+ '~', &FQTermUniteDecode::functionKey, normal_state_
+ }, {
+ CHAR_NORMAL, 0, normal_state_
+ }
+};
+
+int FQTermUniteDecode::processInput(const QByteArray& input) {
+ data_ = input.data();
+ currentByte_ = 0;
+ inputLength_ = input.size();
+ /*
+ for (int i = 0; i < input.size(); ++i) {
+ bool res = keyReceived(input[i]);
+ if (!res) {
+ return i + 1;
+ }
+ }
+ */
+
+ int i;
+ StateOption *lastState;
+
+ while (currentByte_ < inputLength_) {
+ // current state always be initialized to point to the beginning of three structures
+ // ( normalState, escState, bracketState )
+ i = 0;
+ while (current_state_[i].byte != CHAR_NORMAL && current_state_[i].byte !=
+ data_[currentByte_]) {
+ i++;
+ }
+
+ lastState = current_state_ + i;
+
+ bool stopDecode;
+ if (lastState->action != 0) {
+ stopDecode = (this->*(lastState->action))();
+ }
+
+ // reinit current state
+ current_state_ = lastState->nextState;
+
+ currentByte_++;
+ if (stopDecode)
+ break;
+
+ }
+
+ return currentByte_;
+}
+
+FQTermUniteDecode::FQTermUniteDecode() {
+ current_state_ = EscStateMachine::normal_state_;
+ data_ = NULL;
+ inputLength_ = 0;
+ currentByte_ = 0;
+}
+
+bool FQTermUniteDecode::clearParam() {
+ param_ = -1;
+ return true;
+}
+
+bool FQTermUniteDecode::cursorLeft() {
+ return keyReceived(LEFT);
+}
+
+bool FQTermUniteDecode::cursorDown() {
+ return keyReceived(DOWN);
+}
+
+bool FQTermUniteDecode::cursorRight() {
+ return keyReceived(RIGHT);
+}
+
+bool FQTermUniteDecode::cursorUp() {
+ return keyReceived(UP);
+}
+
+bool FQTermUniteDecode::normalInput() {
+ return keyReceived(data_[currentByte_]);
+}
+
+bool FQTermUniteDecode::doubleEsc() {
+ return keyReceived(DOUBLEESC);
+}
+
+bool FQTermUniteDecode::paramDigit() {
+ if (param_ < 0) {
+ param_ = 0;
+ }
+ param_ = param_ * 10 + (data_[currentByte_] - '0');
+ return true;
+}
+
+bool FQTermUniteDecode::functionKey() {
+ int key;
+ switch (param_) {
+ case 1: key = HOME; break;
+ case 3: key = DELETE; break;
+ case 4: key = END; break;
+ case 5: key = PGUP; break;
+ case 6: key = PGDOWN; break;
+ case 11: key = F1; break;
+ case 12: key = F2; break;
+ case 13: key = F3; break;
+ case 14: key = F4; break;
+ case 15: key = F5; break;
+ case 17: key = F6; break;
+ case 18: key = F7; break;
+ case 19: key = F8; break;
+ case 20: key = F9; break;
+ case 21: key = F10; break;
+ case 23: key = F11; break;
+ case 24: key = F12; break;
+ default:
+ break;
+ }
+ return keyReceived(key);
+}
+
+FQTermUniteState::FQTermUniteState(FQTermUniteSessionContext* context) : context_(context) {
+
+}
+
+void FQTermUniteState::write( const QByteArray& output ) {
+ context_->write(output);
+}
+
+QByteArray FQTermUniteState::escape() {
+ return "\x1b";
+}
+
+void FQTermUniteState::moveCursorRelative(int dx, int dy) {
+ //Esc[ValueA Move cursor up n lines CUU
+ //Esc[ValueB Move cursor down n lines CUD
+ //Esc[ValueC Move cursor right n lines CUF
+ //Esc[ValueD Move cursor left n lines CUB
+ if (dy > 0) {
+ write(escape() + QString("[%1").arg(dy).toLocal8Bit() + "B");
+ }
+ if (dy < 0) {
+ write(escape() + QString("[%1").arg(-dy).toLocal8Bit() + "A");
+ }
+ if (dx > 0) {
+ write(escape() + QString("[%1").arg(dx).toLocal8Bit() + "C");
+ }
+ if (dx < 0) {
+ write(escape() + QString("[%1").arg(-dx).toLocal8Bit() + "D");
+ }
+
+}
+
+
+void FQTermUniteState::moveCursorAbsolute(int x, int y) {
+ //Esc[Line;ColumnH Move cursor to screen location v,h CUP
+ write(escape() + QString("[%1;%2H").arg(y).arg(x).toLocal8Bit());
+}
+
+void FQTermUniteState::moveCursorHome() {
+ write(escape() + "[H");
+}
+
+void FQTermUniteState::scrollWindow(int dy) {
+ //EscD Move/scroll window up one line IND
+ //EscM Move/scroll window down one line RI
+
+ if (dy > 0) {
+ for (int i = 0; i < dy; ++i)
+ write(escape() + "D");
+ }
+ if (dy < 0) {
+ dy = -dy;
+ for (int i = 0; i < dy; ++i)
+ write(escape() + "M");
+ }
+}
+
+void FQTermUniteState::moveCursorNextLine() {
+ //EscE Move to next line NEL
+ write(escape() + "E");
+
+}
+
+void FQTermUniteState::saveCursor() {
+ //Esc7 Save cursor position and attributes DECSC
+ write(escape() + "7");
+}
+
+void FQTermUniteState::restoreCursor() {
+ //Esc8 Restore cursor position and attributes DECSC
+ write(escape() + "8");
+}
+
+void FQTermUniteState::setAttr(int attr) {
+ if (attr == -1) {
+ write(escape() + "[m");
+ } else {
+ write(escape() + QString("[%1m").arg(attr).toLocal8Bit());
+ }
+}
+
+void FQTermUniteState::setForegroundColor(int color, bool highlight /*= true*/) {
+ int hl = highlight?1:0;
+ write(escape() + QString("[%1;3%2m").arg(hl).arg(color).toLocal8Bit());
+}
+
+void FQTermUniteState::setBackgroundColor(int color) {
+ write(escape() + QString("[4%1m").arg(color).toLocal8Bit());
+}
+
+void FQTermUniteState::clearLine(int part) {
+ write(escape() + QString("[%1K").arg(part).toLocal8Bit());
+}
+
+void FQTermUniteState::clearScreen(int part) {
+ write(escape() + QString("[%1J").arg(part).toLocal8Bit());
+}
+
+void FQTermUniteState::setWindowRange(int startLine, int endLine) {
+ write(escape() + QString("[%1;%2r").arg(startLine).arg(endLine).toLocal8Bit());
+}
+
+
+QByteArray FQTermUniteState::cursorStr() {
+ QChar c(0x25c6);
+ QString str(c);
+ return str.toUtf8();
+}
+FQTermWelcomeState::FQTermWelcomeState( FQTermUniteSessionContext* context ) : FQTermUniteState(context) {
+ addEntry('h');
+ addEntry('x');
+}
+
+void FQTermWelcomeState::initialize() {
+ moveCursorHome();
+ clearScreen(WHOLESCREEN);
+
+
+
+ QFile welcomeFile(getPath(RESOURCE) + "unite/welcome");
+ welcomeFile.open(QIODevice::ReadOnly);
+ QByteArray str = welcomeFile.readAll();
+ write(str);
+ setCurrentIndex(currentEntry());
+ return;
+}
+
+bool FQTermWelcomeState::keyReceived(int key) {
+ if (tolower(key) == 'j' || key == UP) {
+ prevEntry();
+ } else if (tolower(key) == 'k' || key == DOWN) {
+ nextEntry();
+ } else if (key == '\r' || key == RIGHT) {
+ enterEntry();
+ return false;
+ } else if (tolower(key) <= 'z' && tolower(key) >= 'a') {
+ setCurrentEntry(key);
+ }
+ return true;
+}
+
+void FQTermWelcomeState::enterEntry() {
+ if (currentEntry() == 1) {
+ setNextState(FQTermUniteSessionContext::EXITING);
+ } else if (currentEntry() == 0) {
+ setNextState(FQTermUniteSessionContext::HELP);
+ }
+}
+
+void FQTermWelcomeState::clearPointer(int index) {
+ moveCursorAbsolute(7, 11 + index);
+ write(" ");
+ moveCursorHome();
+}
+
+void FQTermWelcomeState::drawPointer(int index) {
+ moveCursorAbsolute(7, 11 + index);
+ write(cursorStr());
+ moveCursorHome();
+}
+
+
+
+void FQTermExitState::initialize() {
+ clearScreen(WHOLESCREEN);
+ QFile welcomeFile(getPath(RESOURCE) + "unite/exit");
+ welcomeFile.open(QIODevice::ReadOnly);
+ QByteArray str = welcomeFile.readAll();
+ write(str);
+ setCurrentIndex(0);
+}
+
+void FQTermExitState::clearPointer(int index) {
+ moveCursorAbsolute(28, 10 + index);
+ setBackgroundColor(BLUE);
+ write(" ");
+ //moveCursorHome();
+}
+
+void FQTermExitState::drawPointer( int index ) {
+ moveCursorAbsolute(28, 10 + index);
+ setBackgroundColor(BLUE);
+ write(cursorStr());
+ //moveCursorHome();
+}
+
+void FQTermExitState::enterEntry() {
+ if (currentEntry() == 1) {
+ quit();
+ } else {
+ setNextState(FQTermUniteSessionContext::WELCOME);
+ }
+}
+
+bool FQTermExitState::keyReceived( int key )
+{
+ if (tolower(key) == 'j' || key == UP) {
+ prevEntry();
+ } else if (tolower(key) == 'k' || key == DOWN) {
+ nextEntry();
+ } else if (key == '\r') {
+ enterEntry();
+ return false;
+ } else if (key >= '0' && key <= '9') {
+ setCurrentEntry(key);
+ } else if (tolower(key) == 'c') {
+ setCurrentIndex(0);
+ enterEntry();
+ return false;
+ }
+ //moveCursorHome();
+ return true;
+}
+
+FQTermExitState::FQTermExitState( FQTermUniteSessionContext* context ) : FQTermUniteState(context) {
+ addEntry('1');
+ addEntry('2');
+}
+
+SplittedArticleBuffer::SplittedArticleBuffer(const QByteArray& utf8Content, int column, int row) {
+ std::vector<QString> strList;
+ QString content = QString::fromUtf8(utf8Content);
+ lines_.reserve(row);
+ int start = 0;
+ for(;;) {
+ int newStart = findNextLine(content, start, column);
+ if (newStart == -1) {
+ lines_.push_back(content.mid(start).toUtf8());
+ break;
+ } else {
+ lines_.push_back(content.mid(start, newStart - start).toUtf8());
+ start = newStart;
+ }
+ }
+}
+
+int SplittedArticleBuffer::findNextLine(const QString& str, int start, int column) {
+ int count = 0;
+ for (int i = start; i < str.length(); ++i) {
+ if (str[i] == '\t') {
+ count += 2;
+ } else {
+ count += str[i] <= 0x7F ? 1 : 2;
+ }
+ if (count > column) {
+ return i;
+ }
+ if (str[i] == '\n') {
+ if (i + 1 < str.length())
+ return i + 1;
+ }
+ }
+ return -1;
+}
+
+void FQTermReadingState::initialize() {
+ clearScreen(WHOLESCREEN);
+ moveCursorHome();
+ drawLines(row() - 1, 1);
+ drawFooter();
+ moveCursorAbsolute(column(), row());
+}
+
+
+void FQTermReadingState::setFile(const QString& filename) {
+ currentStartLine_ = 0;
+ QFile file(filename);
+ file.open(QIODevice::ReadOnly);
+ content_ = file.readAll();
+ delete saBuffer_;
+ saBuffer_ = new SplittedArticleBuffer(content_, column(), row());
+}
+
+FQTermReadingState::FQTermReadingState( FQTermUniteSessionContext* context ) : FQTermUniteState(context) {
+ returnState_ = FQTermUniteSessionContext::WELCOME;
+ currentStartLine_ = 0;
+ saBuffer_ = 0;
+}
+
+bool FQTermReadingState::keyReceived( int key ) {
+ if (tolower(key) == 'q' || key == LEFT || !saBuffer_) {
+ setNextState(returnState_);
+ return false;
+ } else if (tolower(key) == 'k' || key == DOWN) {
+ adjustLineByDiff(1);
+ drawLines(row() - 1, 1);
+ drawFooter();
+ } else if (tolower(key) == 'j' || key == UP) {
+ adjustLineByDiff(-1);
+ drawLines(row() - 1, 1);
+ drawFooter();
+ } else if (key == PGDOWN || key == ' ' || key == RIGHT) {
+ adjustLineByDiff(row() - 2);
+ drawLines(row() - 1, 1);
+ drawFooter();
+ } else if (key == PGUP) {
+ adjustLineByDiff(-row() + 2);
+ drawLines(row() - 1, 1);
+ drawFooter();
+ } else if (key == HOME) {
+ adjustLineByDiff(-saBuffer_->count());
+ drawLines(row() - 1, 1);
+ drawFooter();
+ } else if (key == END) {
+ adjustLineByDiff(saBuffer_->count());
+ drawLines(row() - 1, 1);
+ drawFooter();
+ }
+ return true;
+}
+
+void FQTermReadingState::drawFooter() {
+ if (!saBuffer_)
+ return;
+ cursorGuard(*this);
+ moveCursorAbsolute(1, row());
+ setBackgroundColor(BLUE);
+ QByteArray footer = QString("Current Line: (%1-%2) Total: %3").arg(currentStartLine_ + 1).arg(qMin(saBuffer_->count(), currentStartLine_ + row() - 1)).arg(saBuffer_->count()).toLocal8Bit();
+ footer += QByteArray(column() - footer.size(), ' ');
+ write(footer);
+ setAttr(CLEARATTR);
+}
+
+void FQTermReadingState::adjustLineByDiff(int delta) {
+ if (!saBuffer_)
+ return;
+ currentStartLine_ += delta;
+ if (currentStartLine_ + row() - 1 >= saBuffer_->count())
+ currentStartLine_ = saBuffer_->count() - (row() - 1);
+ if (currentStartLine_ < 0)
+ currentStartLine_ = 0;
+}
+
+
+void FQTermReadingState::drawLines(int count, int yPos) {
+ if (!saBuffer_)
+ return;
+ cursorGuard cg(*this);
+ QByteArray blankLine(column(), ' ');
+ for (int i = 0; i < count; ++i) {
+ moveCursorAbsolute(1, yPos + i);
+ clearLine(WHOLELINE);
+ if (currentStartLine_ + yPos + i - 1 >= saBuffer_->count()) {
+ write(blankLine);
+ } else {
+ write(saBuffer_->retriveLine(currentStartLine_ + yPos + i - 1));
+ }
+ }
+}
+
+FQTermReadingState::~FQTermReadingState() {
+ delete saBuffer_;
+}
+
+
+
+
+
+FQTermHelpState::FQTermHelpState(FQTermUniteSessionContext* context) : FQTermUniteState(context) {
+ addEntry('s'); //0.entry for script
+ addEntry('t'); //1.entry for shortcut
+ addEntry('u'); //2.entry for unix host
+ addEntry('x'); //3.entry for quit to welcome
+}
+
+void FQTermHelpState::initialize() {
+ moveCursorHome();
+ clearScreen(WHOLESCREEN);
+ QFile welcomeFile(getPath(RESOURCE) + "unite/help");
+ welcomeFile.open(QIODevice::ReadOnly);
+ QByteArray str = welcomeFile.readAll();
+ write(str);
+ setCurrentIndex(currentEntry());
+ return;
+}
+
+bool FQTermHelpState::keyReceived(int key) {
+ if (tolower(key) == 'j' || key == UP) {
+ prevEntry();
+ } else if (tolower(key) == 'k' || key == DOWN) {
+ nextEntry();
+ } else if (key == '\r' || key == RIGHT) {
+ enterEntry();
+ return false;
+ } else if (tolower(key) <= 'z' && tolower(key) >= 'a') {
+ setCurrentEntry(key);
+ }
+ return true;
+}
+
+void FQTermHelpState::enterEntry() {
+ if (currentEntry() == 3) {
+ setNextState(FQTermUniteSessionContext::WELCOME);
+ return;
+ }
+
+ QString doc;
+ switch(currentEntry())
+ {
+ case 0:
+ doc = "script-doc";
+ break;
+ case 1:
+ doc = "shortcut-doc";
+ break;
+ case 2:
+ doc = "ssh-unix-doc";
+ break;
+ }
+ FQTermUniteState* reader = setNextState(FQTermUniteSessionContext::READING, false);
+ ((FQTermReadingState*)reader)->setFile(getPath(RESOURCE) + "unite/" + doc);
+ ((FQTermReadingState*)reader)->setReturnState(FQTermUniteSessionContext::HELP);
+ reader->initialize();
+}
+
+void FQTermHelpState::clearPointer(int index) {
+ moveCursorAbsolute(7, 11 + index);
+ write(" ");
+ moveCursorHome();
+}
+
+void FQTermHelpState::drawPointer(int index) {
+ moveCursorAbsolute(7, 11 + index);
+ write(cursorStr());
+ moveCursorHome();
+}
+
+} // namespace FQTerm
+
+#include "state.moc" \ No newline at end of file
diff --git a/src/unite/internal/state.h b/src/unite/internal/state.h
new file mode 100644
index 0000000..e294372
--- /dev/null
+++ b/src/unite/internal/state.h
@@ -0,0 +1,219 @@
+#ifndef FQTERM_UNITE_STATE
+#define FQTERM_UNITE_STATE
+
+#include <QByteArray>
+#include "session.h"
+
+namespace FQTerm {
+class FQTermUniteDecode;
+typedef bool (FQTermUniteDecode:: *StateFunc)();
+
+struct StateOption {
+ int byte; // char value to look for; -1==end/default
+ StateFunc action;
+ StateOption *nextState;
+};
+
+
+
+class FQTermUniteDecode {
+public:
+ FQTermUniteDecode();
+ virtual ~FQTermUniteDecode() {}
+ //should return number of chars consumed
+ virtual int processInput(const QByteArray& input);
+protected:
+ virtual bool keyReceived(int key) = 0;
+ //tab = 7, backspace = 8, delete is *[3~, page up is 5~, page down is 6~, home is 1~, end is 4~, double esc is double esc,
+ //up is A, down is B, left is D, right is C.
+ //F1 - F12 11~ 12~ 13~ 14~ 15~ 17~ 18~ 19~ 20~ 21~ 23~ 24~
+ //static char* specialKeys[];
+ enum SPECIALKEY{SPECIALKEYSTART = 0x10000, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
+ UP, DOWN, LEFT, RIGHT, DOUBLEESC, INSERT, HOME, END, PGUP, PGDOWN, DELETE};
+
+ // Virtual Keys: move cursor
+ bool cursorLeft();
+ bool cursorDown();
+ bool cursorRight();
+ bool cursorUp();
+
+ // other escape sequence actions
+ bool normalInput();
+
+ //double esc pressed
+ bool doubleEsc();
+
+ // action parameters
+ bool clearParam();
+ bool paramDigit();
+ //function key map
+ bool functionKey();
+private:
+ // ********** decoder states ****************
+ StateOption *current_state_;
+ int param_; //valid when > 0.
+ const char* data_;
+ int inputLength_;
+ int currentByte_;
+ QByteArray leftToDecode_;
+ struct EscStateMachine {
+ static StateOption normal_state_[], esc_state_[], bracket_state_[];
+ };
+};
+
+class FQTermUniteState : public QObject,
+ public FQTermUniteDecode {
+ Q_OBJECT;
+public:
+ FQTermUniteState(FQTermUniteSessionContext* context);
+ virtual ~FQTermUniteState() {}
+ virtual void initialize() = 0;
+
+
+protected:
+ //util functions
+ //cursor manipulations
+ void moveCursorRelative(int dx, int dy);
+ void moveCursorAbsolute(int x, int y);
+ void moveCursorHome();
+ //To scroll up, dy < 0, scroll down, dy > 0.
+ void scrollWindow(int dy);
+ void moveCursorNextLine();
+ void saveCursor();
+ void restoreCursor();
+
+ //attr control
+ enum CHARATTR{DEFAULTATTR = -1, CLEARATTR = 0, BOLD = 1, LOWINTENSITY = 2, UNDERLINE = 4, BLINK = 5, REVERSECOLOR = 7, INVISIBLE = 8};
+ void setAttr(int attr);
+ enum CHARCOLOR{BLACK = 0, RED = 1, GREEN = 2, YELLOW = 3, BLUE = 4, PURPLE = 5, INDIGO = 6, WHITE = 7};
+ void setForegroundColor(int color, bool highlight = true);
+ void setBackgroundColor(int color);
+
+ //clear lines/screen
+ enum CLEARLINE{CURSORRIGHT = 0, CURSORLEFT = 1, WHOLELINE = 2};
+ void clearLine(int part);
+ enum CLEARSCREEN{CURSORDOWN = 0, CURSORUP = 1, WHOLESCREEN = 2};
+ void clearScreen(int part);
+
+ //window setting
+ void setWindowRange(int startLine, int endLine);
+
+ QByteArray escape();
+ QByteArray cursorStr();
+ void write(const QByteArray& output);
+ void quit() {context_->quit();}
+ FQTermUniteState* setNextState(int state, bool init = true) {return context_->setCurrentState(state, init);}
+ int row() {return context_->row();}
+ int column() {return context_->column();}
+
+
+ friend struct cursorGuard;
+ struct cursorGuard {
+ cursorGuard(FQTermUniteState& state) : state_(state) {state_.saveCursor();}
+ ~cursorGuard() {state_.restoreCursor();}
+ private:
+ FQTermUniteState& state_;
+ };
+private:
+ FQTermUniteSessionContext* context_;
+ int lastState_;
+};
+
+class FQTermUniteMenu {
+public:
+ FQTermUniteMenu() {current_ = 0;}
+ virtual ~FQTermUniteMenu() {}
+protected:
+ int addEntry(char key);
+ int findEntry(char key);
+ void clearEntry();
+ int currentEntry();
+ int setCurrentEntry(char key);
+ int setCurrentIndex(int index);
+
+ int nextEntry();
+ int prevEntry();
+ virtual void clearPointer(int index) = 0;
+ virtual void drawPointer(int index) = 0;
+ virtual void enterEntry() = 0;
+private:
+ std::vector<char> entries_;
+ int current_;
+};
+
+
+class FQTermWelcomeState : public FQTermUniteState, public FQTermUniteMenu {
+ Q_OBJECT;
+public:
+ FQTermWelcomeState(FQTermUniteSessionContext* context);
+ virtual void initialize();
+protected:
+ virtual bool keyReceived(int key);
+private:
+ virtual void clearPointer(int index);
+ virtual void drawPointer(int index);
+ virtual void enterEntry();
+};
+
+class FQTermExitState : public FQTermUniteState, public FQTermUniteMenu {
+ Q_OBJECT;
+public:
+ FQTermExitState(FQTermUniteSessionContext* context);
+ virtual void initialize();
+protected:
+ virtual bool keyReceived(int key);
+private:
+ virtual void clearPointer(int index);
+ virtual void drawPointer(int index);
+ void enterEntry();
+};
+
+class SplittedArticleBuffer {
+public:
+ SplittedArticleBuffer(const QByteArray& utf8Content, int column, int row = 24);
+ ~SplittedArticleBuffer() {}
+ int count() {return lines_.size();}
+ QByteArray& retriveLine(size_t index) {return lines_[index];}
+private:
+ static int findNextLine(const QString& str, int start, int column);
+ std::vector<QByteArray> lines_;
+};
+
+//TODO: content should be shared.
+//TODO: buffer should be opt-ed.
+class FQTermReadingState : public FQTermUniteState {
+ Q_OBJECT;
+public:
+ FQTermReadingState(FQTermUniteSessionContext* context);
+ ~FQTermReadingState();
+ virtual void initialize();
+ void setFile(const QString& filename);
+ void setReturnState(int state) {returnState_ = state;}
+protected:
+ virtual bool keyReceived(int key);
+private:
+ void drawLines(int count, int yPos);
+ void drawFooter();
+ void adjustLineByDiff(int delta);
+ SplittedArticleBuffer* saBuffer_;
+ QByteArray content_;
+ int currentStartLine_;
+ int returnState_;
+};
+
+
+class FQTermHelpState : public FQTermUniteState, public FQTermUniteMenu {
+ Q_OBJECT;
+public:
+ FQTermHelpState(FQTermUniteSessionContext* context);
+ virtual void initialize();
+protected:
+ virtual bool keyReceived(int key);
+private:
+ virtual void clearPointer(int index);
+ virtual void drawPointer(int index);
+ virtual void enterEntry();
+};
+
+} // namespace FQTerm
+#endif \ No newline at end of file
diff --git a/src/unite/internal/statebuilder.cpp b/src/unite/internal/statebuilder.cpp
new file mode 100644
index 0000000..48ea6f6
--- /dev/null
+++ b/src/unite/internal/statebuilder.cpp
@@ -0,0 +1,32 @@
+
+#include "statebuilder.h"
+#include "fqterm.h"
+#include "fqterm_path.h"
+
+#include <QDomDocument>
+#include <QFile>
+
+namespace FQTerm {
+
+void StateBuilder::BuildState()
+{
+ QDomDocument domDocument;
+ QFile welcome(getPath(RESOURCE) + "unite/welcom.xml");
+ welcome.open(QIODevice::ReadOnly);
+ QString errorStr;
+ int errorLine;
+ int errorColumn;
+ domDocument.setContent(welcome.readAll(), true, &errorStr, &errorLine, &errorColumn);
+ QDomElement root = domDocument.firstChildElement("page");
+ if (root.isNull())
+ {
+
+ }
+ QDomAttr a = root.attributeNode("type");
+ //cout << a.value() << endl;
+
+
+}
+
+
+} \ No newline at end of file
diff --git a/src/unite/internal/statebuilder.h b/src/unite/internal/statebuilder.h
new file mode 100644
index 0000000..f323ecd
--- /dev/null
+++ b/src/unite/internal/statebuilder.h
@@ -0,0 +1,16 @@
+
+#ifndef FQTERM_UNITE_STATEBUILDER
+#define FQTERM_UNITE_STATEBUILDER
+
+namespace FQTerm {
+
+class FQTermState;
+
+class StateBuilder
+{
+public:
+ void BuildState();
+};
+
+}
+#endif \ No newline at end of file
diff --git a/src/unite/internal/unite.h b/src/unite/internal/unite.h
new file mode 100644
index 0000000..cc614a7
--- /dev/null
+++ b/src/unite/internal/unite.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef FQTERM_UNITE_USER
+#define FQTERM_UNITE_USER
+
+namespace FQTerm {
+//to make it more clear, a general method to serialize c++
+//classes is needed.
+class FQUUser {
+public:
+private:
+
+};
+
+} //namespace FQTerm
+
+#endif //FQTERM_UNITE_USER \ No newline at end of file
diff --git a/src/unite/internal/user.cpp b/src/unite/internal/user.cpp
new file mode 100644
index 0000000..c5905f8
--- /dev/null
+++ b/src/unite/internal/user.cpp
@@ -0,0 +1,19 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
diff --git a/src/unite/internal/user.h b/src/unite/internal/user.h
new file mode 100644
index 0000000..cc614a7
--- /dev/null
+++ b/src/unite/internal/user.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+* 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. *
+***************************************************************************/
+
+#ifndef FQTERM_UNITE_USER
+#define FQTERM_UNITE_USER
+
+namespace FQTerm {
+//to make it more clear, a general method to serialize c++
+//classes is needed.
+class FQUUser {
+public:
+private:
+
+};
+
+} //namespace FQTerm
+
+#endif //FQTERM_UNITE_USER \ No newline at end of file