summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt36
-rw-r--r--src/common/common.cpp53
-rw-r--r--src/common/common.h64
-rw-r--r--src/common/fqterm.h350
-rw-r--r--src/common/fqterm_config.cpp181
-rw-r--r--src/common/fqterm_config.h61
-rw-r--r--src/common/fqterm_exif_extractor.cpp647
-rw-r--r--src/common/fqterm_exif_extractor.h126
-rw-r--r--src/common/fqterm_filedialog.cpp157
-rw-r--r--src/common/fqterm_filedialog.h49
-rw-r--r--src/common/fqterm_font.cpp261
-rw-r--r--src/common/fqterm_font.h34
-rw-r--r--src/common/fqterm_param.cpp274
-rw-r--r--src/common/fqterm_param.h221
-rw-r--r--src/common/fqterm_path.cpp601
-rw-r--r--src/common/fqterm_path.h46
-rw-r--r--src/common/fqterm_shortcuthelper.cpp298
-rw-r--r--src/common/fqterm_shortcuthelper.h175
-rw-r--r--src/common/fqterm_sound.cpp733
-rw-r--r--src/common/fqterm_sound.h79
-rw-r--r--src/common/fqterm_trace.cpp328
-rw-r--r--src/common/fqterm_trace.h331
22 files changed, 5105 insertions, 0 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
new file mode 100644
index 0000000..d3f0c09
--- /dev/null
+++ b/src/common/CMakeLists.txt
@@ -0,0 +1,36 @@
+set(fqterm_common_SRCS
+ common.h
+ common.cpp
+ fqterm.h
+ fqterm_trace.h
+ fqterm_trace.cpp
+ fqterm_config.h
+ fqterm_config.cpp
+ fqterm_sound.h
+ fqterm_sound.cpp
+ fqterm_param.h
+ fqterm_param.cpp
+ fqterm_path.h
+ fqterm_path.cpp
+ fqterm_font.h
+ fqterm_font.cpp
+ fqterm_exif_extractor.h
+ fqterm_exif_extractor.cpp
+ fqterm_filedialog.h
+ fqterm_filedialog.cpp
+ fqterm_shortcuthelper.h
+ fqterm_shortcuthelper.cpp
+)
+
+qt4_automoc(${fqterm_common_SRCS})
+
+include_directories(
+ ${QT_INCLUDE_DIR}
+ ${QT_QTCORE_INCLUDE_DIR}
+ ${QT_QTGUI_INCLUDE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+add_library(fqterm_common
+ ${fqterm_common_SRCS}
+)
diff --git a/src/common/common.cpp b/src/common/common.cpp
new file mode 100644
index 0000000..ec08bef
--- /dev/null
+++ b/src/common/common.cpp
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * 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 <stdlib.h>
+
+#include <QString>
+#include <QProcess>
+#include <QStringList>
+#include "common.h"
+
+namespace FQTerm {
+
+void runProgram(const QString &cmd, const QString& arg, bool bg) {
+ if (bg) {
+ QProcess::startDetached(cmd, QStringList(arg));
+ } else {
+ QProcess::execute(cmd, QStringList(arg));
+ }
+
+ return;
+ /*
+#if defined(WIN32)
+ QString strCmd = "\"\"" + cmd + "\" \"" + arg + "\"\"";
+#else
+ QString strCmd = "'" + cmd + "' '" + arg + "'";
+#endif
+#if !defined(WIN32)
+ if (bg) {
+ strCmd += " &";
+ }
+#endif
+ system(strCmd.toLocal8Bit());
+ */
+}
+
+} // namespace FQTerm
diff --git a/src/common/common.h b/src/common/common.h
new file mode 100644
index 0000000..5720ddc
--- /dev/null
+++ b/src/common/common.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * 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_COMMON_H
+#define FQTERM_COMMON_H
+
+#if defined(WIN32)
+#define OS_NEW_LINE "\r\n"
+#elif defined(__APPLE__)
+#define OS_NEW_LINE "\r"
+#else
+#define OS_NEW_LINE "\n"
+#endif
+
+class QString;
+
+namespace FQTerm {
+
+enum Directions {
+ kHome = 0,
+ kEnd = 1,
+ kPageUp = 2,
+ kPageDown = 3,
+ kUp = 4,
+ kDown = 5,
+ kLeft = 6,
+ kRight = 7
+};
+
+const char * const kDirections[] = {
+ // 4
+ "\x1b[1~", // 0 HOME
+ "\x1b[4~", // 1 END
+ "\x1b[5~", // 2 PAGE UP
+ "\x1b[6~", // 3 PAGE DOWN
+ // 3
+ "\x1b[A", // 4 UP
+ "\x1b[B", // 5 DOWN
+ "\x1b[D", // 6 LEFT
+ "\x1b[C" // 7 RIGHT
+};
+
+void runProgram(const QString &cmd, const QString& arg = "", bool bg = true);
+
+} // namespace FQTerm
+
+#endif // FQTERM_COMMON_H
diff --git a/src/common/fqterm.h b/src/common/fqterm.h
new file mode 100644
index 0000000..515cedc
--- /dev/null
+++ b/src/common/fqterm.h
@@ -0,0 +1,350 @@
+/***************************************************************************
+ * 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_GLOBAL_H
+#define FQTERM_GLOBAL_H
+
+#ifndef BUFSIZE
+#define BUFSIZE (1024)
+#endif
+
+#include <QTextCodec>
+#include <QString>
+#include "fqterm_trace.h"
+
+namespace FQTerm {
+
+#if defined(WIN32) && (_MSC_VER >= 1400)
+ //Using vc2005 or +
+#define fq_strdup _strdup
+#else
+#define fq_strdup strdup
+#endif
+
+#ifdef FOUND_PYTHON
+//#define HAVE_PYTHON
+#endif //FOUND_PYTHON
+
+#define USE_GLOBAL_HOTKEY
+
+//code convert
+enum EncodingID {FQTERM_ENCODING_GBK = 0, FQTERM_ENCODING_BIG5 = 1,
+ FQTERM_ENCODING_UTF8 = 2, FQTERM_ENCODING_HKSCS = 3,
+ FQTERM_ENCODING_UAO = 4};
+
+#if QT_VERSION >= 0X040700
+#define GBK_CODECS_NAME "GB18030"
+#else
+#define GBK_CODECS_NAME "GBK"
+#endif
+
+#define G2U(s) ( QTextCodec::codecForName(GBK_CODECS_NAME)->toUnicode(s) )
+#define U2G(s) ( QTextCodec::codecForName(GBK_CODECS_NAME)->fromUnicode(s) )
+#define B2U(s) ( QTextCodec::codecForName("Big5")->toUnicode(s) )
+#define U2B(s) ( QTextCodec::codecForName("Big5")->fromUnicode(s) )
+#define H2U(s) ( QTextCodec::codecForName("Big5-HKSCS")->toUnicode(s) )
+#define U2H(s) ( QTextCodec::codecForName("Big5-HKSCS")->fromUnicode(s) )
+#define U2U8(s) ( s.toUtf8() )
+#define U82U(s) ( QString::fromUtf8(s) )
+#define A2U(s) (QTextCodec::codecForName("UAO")->toUnicode(s) )
+#define U2A(s) ( QTextCodec::codecForName("UAO")->fromUnicode(s) )
+
+inline QByteArray unicode2encoding(const QString &text, int encoding) {
+ switch(encoding)
+ {
+ case FQTERM_ENCODING_GBK:
+ return(U2G(text));
+ case FQTERM_ENCODING_BIG5:
+ return(U2B(text));
+ case FQTERM_ENCODING_UTF8:
+ return(U2U8(text));
+ case FQTERM_ENCODING_HKSCS:
+ return (U2H(text));
+ case FQTERM_ENCODING_UAO:
+ return (U2A(text));
+ }
+
+ return "";
+}
+
+inline QString encoding2unicode(const QByteArray &text, int encoding) {
+ switch(encoding)
+ {
+ case FQTERM_ENCODING_GBK:
+ return(G2U(text));
+ case FQTERM_ENCODING_BIG5:
+ return(B2U(text));
+ case FQTERM_ENCODING_UTF8:
+ return(U82U(text));
+ case FQTERM_ENCODING_HKSCS:
+ return (H2U(text));
+ case FQTERM_ENCODING_UAO:
+ return (A2U(text));
+ }
+
+ return "";
+}
+
+#define FQTERM_CTRL(c) ((c)&0x1f)
+
+// every character has a 16-bit description
+// low 8 for colors
+// hight 8 for attributes
+#define COLORMASK 0x00ff
+#define ATTRMASK 0xff00
+
+// color 8-bit
+// bit 0-2 foreground
+// 0 black
+// 1 red
+// 2 green
+// 3 yellow
+// 4 blue
+// 5 magenta
+// 6 cyan
+// 7 white
+// bit 3 highlight foreground
+// 0 no
+// 1 highlight
+// bit 4-6 background
+// 0 black
+// 1 red
+// 2 green
+// 3 yellow
+// 4 blue
+// 5 magenta
+// 6 cyan
+// 7 white
+// bit 7 highlight background (unused)
+// 0 no
+// 1 highlight
+
+#define FGMASK 0x0f
+#define BGMASK 0xf0
+#define FG_HIGHLIGHT_MASK 0x08
+#define BG_HIGHLIGHT_MASK 0x80
+
+//set color
+#define SETFG(c) ( (c) & FGMASK )
+#define SETBG(c) ( ( (c) << 4 ) & BGMASK )
+#define SET_FG_HIGHLIGHT(c) ( ( (c) << 3 ) & FG_HIGHLIGHT_MASK )
+#define SET_BG_HIGHLIGHT(c) ( ( (c) << 7 ) & BG_HIGHLIGHT_MASK )
+
+//get color
+#define GETFG(c) ( (c) & FGMASK )
+#define GETBG(c) ( ( (c) & BGMASK ) >> 4 )
+
+#define GET_FG_HIGHLIGHT(c) ( ( (c) & FG_HIGHLIGHT_MASK ) >> 3 )
+#define GET_BG_HIGHLIGHT(c) ( ( (c) & BG_HIGHLIGHT_MASK ) >> 7 )
+
+//#define GET_INVERSE_COLOR(c) ( SETFG( (7 - (c & 0x7)) | (c & 0x08) ) | SETBG(15-GETBG(c)) )
+#define GET_INVERSE_COLOR(c) ( SETFG(15-GETFG(c)) | SETBG(15-GETBG(c)) )
+
+// mask for attr
+#define BRIGHTMASK 0x01
+#define DIMMASK 0x02
+#define UNDERLINEMASK 0x08
+#define BLINKMASK 0x10
+#define RAPIDBLINKMASK 0x20
+#define REVERSEMASK 0x40
+#define INVISIBLEMASK 0x80
+
+//set attributes
+#define SETBRIGHT(a) ( (a) | BRIGHTMASK )
+#define SETDIM(a) ( (a) | DIMMASK )
+#define SETUNDERLINE(a) ( (a) | UNDERLINEMASK )
+#define SETBLINK(a) ( (a) | BLINKMASK )
+#define SETRAPIDBLINK(a) ( (a) | RAPIDBLINKMASK )
+#define SETREVERSE(a) ( (a) | REVERSEMASK )
+#define SETINVISIBLE(a) ( (a) | INVISIBLEMASK )
+
+//get attributes
+#define GETBRIGHT(a) ( (a) & BRIGHTMASK )
+#define GETDIM(a) ( (a) & DIMMASK )
+#define GETUNDERLINE(a) ( (a) & UNDERLINEMASK )
+#define GETBLINK(a) ( (a) & BLINKMASK )
+#define GETRAPIDBLINK(a) ( (a) & RAPIDBLINKMASK )
+#define GETREVERSE(a) ( (a) & REVERSEMASK )
+#define GETINVISIBLE(a) ( (a) & INVISIBLEMASK )
+
+//default color
+#define NO_COLOR ( SETFG(7) | SETBG(0) )
+//default attribute
+#define NO_ATTR 0x04
+
+// other definations
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define DAE_FINISH 10001
+#define DAE_TIMEOUT 10002
+
+#define PYE_ERROR 10003
+#define PYE_FINISH 10004
+
+// some keys
+#define CHAR_NUL 0x00 // ^@
+#define CHAR_ENQ 0x05 // ^E
+#define CHAR_BELL 0x07 // ^G
+#define CHAR_BS 0x08 // ^H
+#define CHAR_TAB 0x09 // ^I
+#define CHAR_LF 0x0a // ^J
+#define CHAR_VT 0x0b // ^K
+#define CHAR_FF 0x0c // ^L
+#define CHAR_CR 0x0d // ^M
+#define CHAR_SO 0x0e // ^N
+#define CHAR_SI 0x0f // ^O
+#define CHAR_CAN 0x18 // ^X
+#define CHAR_ESC 0x1b // ^[
+#define CHAR_DEL 0x7f // DEL
+
+#define CHAR_NORMAL -1
+
+const char ANSWERBACK_MESSAGE[] = "This is fqterm.";
+
+// telnet state
+#define TSRESOLVING 30
+#define TSHOSTFOUND 31
+#define TSHOSTNOTFOUND 32
+#define TSCONNECTING 33
+#define TSHOSTCONNECTED 34
+#define TSPROXYCONNECTED 35
+#define TSPROXYAUTH 36
+#define TSPROXYFAIL 38
+#define TSREFUSED 39
+#define TSREADERROR 40
+#define TSCLOSED 41
+#define TSCLOSEFINISH 42
+#define TSCONNECTVIAPROXY 43
+#define TSEGETHOSTBYNAME 44
+#define TSEINIWINSOCK 45
+#define TSERROR 46
+#define TSPROXYERROR 47
+#define TSWRITED 48
+
+// zmodem types
+#define RcvByteCount 0 /* value is # bytes received */
+#define SndByteCount 1 /* value is # bytes sent */
+#define RcvTimeout 2 /* receiver did not respond, aborting */
+#define SndTimeout 3 /* value is # of consecutive send timeouts */
+#define RmtCancel 4 /* remote end has cancelled */
+#define ProtocolErr 5 /* protocol error has occurred, val=hdr */
+#define RemoteMessage 6 /* message from remote end */
+#define DataErr 7 /* data error, val=error count */
+#define FileErr 8 /* error writing file, val=errno */
+#define FileBegin 9 /* file transfer begins, str=name */
+#define FileEnd 10 /* file transfer ends, str=name */
+#define FileSkip 11 /* file being skipped, str=name */
+
+
+// proxy type
+#define NOPROXY 0
+#define WINGATE 1
+#define SOCKS4 2
+#define SOCKS5 3
+#define HTTP 4
+
+// UI ID
+#define ID_FILE_CONNECT 0x00
+#define ID_FILE_DISCONNECT 0x01
+#define ID_FILE_ADDRESS 0x02
+#define ID_FILE_QUICK 0x03
+#define ID_FILE_EXIT 0x04
+
+#define ID_EDIT_COPY 0x10
+#define ID_EDIT_PASTE 0x11
+#define ID_EDIT_COLOR 0x12
+#define ID_EDIT_RECT 0x13
+#define ID_EDIT_AUTO 0x14
+#define ID_EDIT_WW 0x15
+
+#define ID_EDIT_ESC_NO 0x17
+#define ID_EDIT_ESC_ESC 0x18
+#define ID_EDIT_ESC_U 0x19
+#define ID_EDIT_ESC_CUS 0x1a
+
+#define ID_EDIT_CODEC_GBK 0x1b
+#define ID_EDIT_CODEC_BIG5 0x1c
+
+
+#define ID_VIEW_FONT 0x20
+#define ID_VIEW_COLOR 0x21
+#define ID_VIEW_REFRESH 0x22
+#define ID_VIEW_LANG 0x23
+#define ID_VIEW_FULL 0x24
+#define ID_VIEW_BOSS 0x25
+#define ID_VIEW_SCROLL_HIDE 0x26
+#define ID_VIEW_SCROLL_LEFT 0x27
+#define ID_VIEW_SCROLL_RIGHT 0x28
+#define ID_VIEW_SWITCH 0x29
+#define ID_VIEW_STATUS 0x3a
+
+#define ID_OPTION_CURRENT 0x30
+#define ID_OPTION_DEFAULT 0x31
+#define ID_OPTION_PREF 0x32
+
+#define ID_SPEC_ANTI 0x40
+#define ID_SPEC_AUTO 0x41
+#define ID_SPEC_MESSAGE 0x42
+#define ID_SPEC_BEEP 0x43
+#define ID_SPEC_MOUSE 0x44
+#define ID_SPEC_ARTICLE 0x45
+
+#define ID_SCRIPT_RUN 0x50
+#define ID_SCRIPT_STOP 0x51
+
+#define ID_HELP_ABOUT 0x60
+#define ID_HELP_HOMEPAGE 0x61
+
+//for open last addr
+#define LAST_ADDRESS_INDEX -321
+
+//script function names:
+#define SFN_ANTI_IDLE "antiIdle"
+#define SFN_ON_BELL "onBell"
+#define SFN_AUTO_REPLY "autoReply"
+#define SFN_DATA_EVENT "dataEvent"
+#define SFN_KEY_EVENT "keyEvent"
+#define SFN_MOUSE_EVENT "mouseEvent"
+#define SFN_DETECT_MENU "detectMenu"
+
+//script key event type
+#define SKET_KEY_PRESS 0
+
+//script mouse event type
+#define SMET_UNKOWN -1
+#define SMET_MOUSE_PRESS 0
+#define SMET_MOUSE_RELEASE 1
+#define SMET_MOUSE_MOVE 2
+#define SMET_MOUSE_DBCLICK 3
+#define SMET_WHEEL 4
+
+//script button state & key modifier
+#define SBS_LEFT_BUTTON 0x01
+#define SBS_RIGHT_BUTTON 0x02
+#define SBS_MID_BUTTON 0x04
+#define SBS_ALT 0x08
+#define SBS_CTRL 0x10
+#define SBS_SHIFT 0x20
+
+} // namespace FQTerm
+
+#endif // FQTERM_GLOBAL_H
diff --git a/src/common/fqterm_config.cpp b/src/common/fqterm_config.cpp
new file mode 100644
index 0000000..19e0db4
--- /dev/null
+++ b/src/common/fqterm_config.cpp
@@ -0,0 +1,181 @@
+/***************************************************************************
+ * 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 <QTextStream>
+#include <QFile>
+#include <QString>
+#include <QTextCodec>
+
+#include "fqterm_trace.h"
+#include "fqterm_config.h"
+
+namespace FQTerm {
+
+FQTermConfig::FQTermConfig(const QString &szFileName) {
+ load(szFileName);
+}
+
+FQTermConfig::~FQTermConfig(){
+
+}
+
+bool FQTermConfig::save(const QString &szFileName) {
+ QFile file(szFileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ FQ_TRACE("config", 0) << "Failed to open the file for writing: "
+ << szFileName;
+ return false;
+ }
+
+ QTextStream os;
+ os.setDevice(&file);
+ saveToStream(os);
+ // os.unsetDevice();
+ file.close();
+
+
+ return true;
+}
+
+bool FQTermConfig::loadFromStream(QTextStream &is) {
+ QString strLine, strSection;
+
+ data.clear();
+
+ is.setCodec(QTextCodec::codecForName("UTF-8"));
+
+ while (!is.atEnd()) {
+ strLine = is.readLine().trimmed();
+ if (strLine.isEmpty() || strLine[0] == '#') {
+ continue;
+ }
+
+ if (strLine.left(1) == "[" && strLine.right(1) == "]") {
+ strSection = strLine.mid(1, strLine.length() - 2);
+ addSection(strSection);
+ } else {
+ QString strValue = strLine.section('=', 1).trimmed();
+ setItemValue(strSection, strLine.section('=', 0, 0).trimmed(),
+ strValue.isNull() ? QString(""): strValue);
+ }
+ }
+ return true;
+}
+
+bool FQTermConfig::saveToStream(QTextStream &os) {
+ QString strLine, strSection;
+ Section::iterator iStr;
+
+ os.setCodec(QTextCodec::codecForName("UTF-8"));
+
+ for (StrSecMap::iterator iSec = data.begin(); iSec != data.end(); ++iSec) {
+ os << '[' << iSec.key() << "]\n";
+ for (iStr = iSec.value().begin(); iStr != iSec.value().end(); ++iStr) {
+ os << iStr.key() << '=' << iStr.value() << '\n';
+ }
+ os << '\n';
+ }
+ return true;
+}
+
+
+bool FQTermConfig::addSection(const QString &szSection) {
+ if (hasSection(szSection)) {
+ return false;
+ }
+ Section sec;
+ data[szSection] = sec;
+ return true;
+}
+
+bool FQTermConfig::hasSection(const QString &szSection) const
+{
+ return data.find(szSection) != data.end();
+}
+
+bool FQTermConfig::setItemValue(const QString &szSection, const QString
+ &szItemName, const QString &szItemValue) {
+ if (!hasSection(szSection))
+ if (!addSection(szSection)) {
+ return false;
+ }
+
+ data[szSection][szItemName] = szItemValue;
+ return true;
+}
+
+QString FQTermConfig::getItemValue(const QString &szSection,
+ const QString &szItemName) const {
+ if (hasSection(szSection))
+ if (data[szSection].find(szItemName) != data[szSection].end())
+ if (!data[szSection][szItemName].isEmpty()) {
+ return data[szSection][szItemName];
+ }
+ return "";
+}
+
+bool FQTermConfig::renameSection(const QString &szSection, const QString
+ &szNewName) {
+ if (hasSection(szNewName) || !hasSection(szSection)) {
+ return false;
+ }
+
+ if (!addSection(szNewName)) {
+ return false;
+ }
+ data[szNewName] = data[szSection];
+
+ return deleteSection(szSection);
+}
+
+bool FQTermConfig::deleteSection(const QString &szSection) {
+ if (hasSection(szSection)) {
+ data.remove(szSection);
+ return true;
+ }
+ return false;
+}
+
+bool FQTermConfig::deleteItem(const QString &szSection, const QString
+ &szItemName) {
+ if (hasSection(szSection))
+ if (data[szSection].find(szItemName) != data[szSection].end()) {
+ data[szSection].remove(szItemName);
+ return true;
+ }
+ return false;
+}
+
+bool FQTermConfig::load(const QString &filename) {
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ FQ_TRACE("config", 0) << "Failed to open the file for reading "
+ << filename;
+ return false;
+ }
+ QTextStream is;
+ is.setDevice(&file);
+ loadFromStream(is);
+ //is.unsetDevice();
+ file.close();
+ return true;
+}
+
+} // namespace FQTerm
diff --git a/src/common/fqterm_config.h b/src/common/fqterm_config.h
new file mode 100644
index 0000000..2f88602
--- /dev/null
+++ b/src/common/fqterm_config.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * 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_CFG_H
+#define FQTERM_CFG_H
+
+#include <QTextStream>
+#include <QMap>
+#include <QObject>
+
+namespace FQTerm {
+typedef QMap<QString, QString> Section;
+typedef QMap<QString, Section> StrSecMap;
+
+class FQTermConfig {
+ private:
+ StrSecMap data;
+ bool loadFromStream(QTextStream &);
+ bool saveToStream(QTextStream &);
+
+ bool addSection(const QString &sectionName);
+ public:
+ FQTermConfig(const QString &fileName);
+ ~FQTermConfig();
+
+ bool load(const QString &filename);
+ bool save(const QString &fileName);
+
+ bool setItemValue(const QString &sectionName, const QString &itemName,
+ const QString &itemValue);
+
+ QString getItemValue(const QString &sectionName,
+ const QString &itemName) const;
+
+ bool deleteItem(const QString &sectionName, const QString &itemName);
+ bool deleteSection(const QString &sectionName);
+
+ bool renameSection(const QString &sectionName, const QString &newName);
+ bool hasSection(const QString &sectionName) const;
+};
+
+} // namespace FQTerm
+
+#endif // FQTERM_CFG_H
diff --git a/src/common/fqterm_exif_extractor.cpp b/src/common/fqterm_exif_extractor.cpp
new file mode 100644
index 0000000..05d318e
--- /dev/null
+++ b/src/common/fqterm_exif_extractor.cpp
@@ -0,0 +1,647 @@
+/***************************************************************************
+ * 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_exif_extractor.h"
+
+namespace FQTerm {
+
+const ExifExtractor::uint16 ExifExtractor::IFD0Tag[16] = {0x010e, 0x010f, 0x0110, 0x0112, 0x011a,
+ 0x011b, 0x0128, 0x0131, 0x0132, 0x013e,
+ 0x013f, 0x0211, 0x0213, 0x0214, 0x8298, 0x8769
+};
+
+const char ExifExtractor::IFD0TagName[16][30] = { "ImageDescription", "Make", "Model", "Orientation",
+ "XResolution", "YResolution", "ResolutionUnit", "Software",
+ "DateTime", "WhitePoint", "PrimaryChromaticities", "YCbCrCoefficients",
+ "YCbCrPositioning", "ReferenceBlackWhite", "Copyright", "ExifOffset"
+};
+
+const ExifExtractor::uint16 ExifExtractor::SubIFDTag[38] = {0x829a,0x829d,0x8822,0x8827,0x9000,0x9003,0x9004,0x9101,0x9102,0x9201,0x9202,0x9203,0x9204,
+ 0x9205,0x9206,0x9207,0x9208,0x9209,0x920a,0x927c,0x9286,0x9290,0x9291,0x9292,0xa000,0xa001,
+ 0xa002,0xa003,0xa004,0xa005,0xa20e,0xa20f,0xa210,0xa215,0xa217,0xa300,0xa301,0xa302};
+
+const char ExifExtractor::SubIFDTagName[38][30] = {"ExposureTime","FNumber","ExposureProgram","ISOSpeedRatings","ExifVersion","DateTimeOriginal","DateTimeDigitized",
+ "ComponentsConfiguration","CompressedBitsPerPixel","ShutterSpeedValue","ApertureValue","BrightnessValue","ExposureBiasValue",
+ "MaxApertureValue","SubjectDistance","MeteringMode","LightSource","Flash","FocalLength","MakerNote","UserComment","SubsecTime",
+ "SubsecTimeOriginal","SubsecTimeDigitized","FlashPixVersion","ColorSpace","ExifImageWidth","ExifImageHeight","RelatedSoundFile",
+ "ExifInteroperabilityOffset","FocalPlaneXResolution","FocalPlaneYResolution","FocalPlaneResolutionUnit","ExposureIndex",
+ "SensingMethod","FileSource","SceneType","CFAPattern"};
+
+const char ExifExtractor::exifHeaderStandard[6] = {'E', 'x', 'i', 'f', '\0', '\0'};
+
+ExifExtractor::ExifExtractor()
+{
+ exifFile_ = NULL;
+ reset();
+}
+
+ExifExtractor::~ExifExtractor()
+{
+ reset();
+}
+
+std::string ExifExtractor::extractExifInfo(std::string fileName) {
+ return extractExifInfo(fopen(fileName.c_str(), "rb"));
+}
+
+std::string ExifExtractor::extractExifInfo(FILE* file) {
+ reset();
+ exifFile_ = file;
+ if (!exifFile_ || !isReadable() || !checkEndian()) {
+ return exifInformation_;
+ }
+ if (!readIFD0())
+ return exifInformation_;
+ readSubIFD();
+ postRead();
+ std::map<std::string, std::string>::iterator ii;
+ for (ii = exifKeyValuePairs_.begin();
+ ii != exifKeyValuePairs_.end();
+ ++ii) {
+ if ((*ii).first == "UserComment") {
+ continue;
+ }
+ exifInformation_ += (*ii).first + " : " + (*ii).second + "\n";
+ }
+ fclose(exifFile_);
+ exifFile_ = NULL;
+ return exifInformation_;
+}
+std::string ExifExtractor::info() {
+ return exifInformation_;
+}
+
+std::string ExifExtractor::operator[]( const std::string& key ) {
+ std::map<std::string, std::string>::iterator ii;
+ if ((ii = exifKeyValuePairs_.find(key)) != exifKeyValuePairs_.end()) {
+ return (*ii).second;
+ }
+ return "";
+}
+
+void ExifExtractor::postRead() {
+ std::map<std::string, std::string>::iterator ii;
+ if ((ii = exifKeyValuePairs_.find("Orientation")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ switch((*ii).second[0]) {
+ case '1': (*ii).second = "1st row - 1st col : top - left side"; break;
+ case '2': (*ii).second = "1st row - 1st col : top - right side"; break;
+ case '3': (*ii).second = "1st row - 1st col : bottom - right side"; break;
+ case '4': (*ii).second = "1st row - 1st col : bottom - left side"; break;
+ case '5': (*ii).second = "1st row - 1st col : left side - top"; break;
+ case '6': (*ii).second = "1st row - 1st col : right side - top"; break;
+ case '7': (*ii).second = "1st row - 1st col : right side - bottom"; break;
+ case '8': (*ii).second = "1st row - 1st col : left side - bottom"; break;
+ default: exifKeyValuePairs_.erase(ii); break;
+
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("ResolutionUnit")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ switch((*ii).second[0]) {
+ case '1': (*ii).second = "no-unit"; break;
+ case '2': (*ii).second = "inch"; break;
+ case '3': (*ii).second = "centimeter"; break;
+ default: (*ii).second = "inch"; break;
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("DateTime")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ for (size_t i = 0; i < (*ii).second.length() && i < 11; ++i) {
+ if ((*ii).second[i] == ':'){
+ (*ii).second[i] = '.';
+ }
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("DateTimeOriginal")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ for (size_t i = 0; i < (*ii).second.length() && i < 11; ++i) {
+ if ((*ii).second[i] == ':'){
+ (*ii).second[i] = '.';
+ }
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("DateTimeDigitized")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ for (size_t i = 0; i < (*ii).second.length() && i < 11; ++i) {
+ if ((*ii).second[i] == ':'){
+ (*ii).second[i] = '.';
+ }
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("YCbCrPositioning")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ switch((*ii).second[0]) {
+ case '1': (*ii).second = "The center of pixel array"; break;
+ case '2': (*ii).second = "The datum point"; break;
+ default: exifKeyValuePairs_.erase(ii); break;
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("MeteringMode")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ uint16 value = 123;
+ sscanf((*ii).second.c_str(), "%hu", &value);
+ switch(value) {
+ case 0: (*ii).second = "Unknown"; break;
+ case 1: (*ii).second = "Average"; break;
+ case 2: (*ii).second = "CenterWeightedAverage"; break;
+ case 3: (*ii).second = "Spot"; break;
+ case 4: (*ii).second = "Multi-spot"; break;
+ case 5: (*ii).second = "Pattern"; break;
+ case '6': (*ii).second = "Partial"; break;
+ case 255: (*ii).second = "Other"; break;
+ default: exifKeyValuePairs_.erase(ii); break;
+
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("LightSource")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ uint16 value = 123;
+ sscanf((*ii).second.c_str(), "%hu", &value);
+ switch(value) {
+ case 0: (*ii).second = "unknown"; break;
+ case 1: (*ii).second = "daylight"; break;
+ case 2: (*ii).second = "fluorescent"; break;
+ case 3: (*ii).second = "tungsten"; break;
+ case 10: (*ii).second = "flash"; break;
+ case 17: (*ii).second = "standard light A"; break;
+ case 18: (*ii).second = "standard light B"; break;
+ case 19: (*ii).second = "standard light C"; break;
+ case 20: (*ii).second = "D55"; break;
+ case 21: (*ii).second = "D65"; break;
+ case 22: (*ii).second = "D75"; break;
+ case 255: (*ii).second = "other"; break;
+ default: exifKeyValuePairs_.erase(ii); break;
+
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("Flash")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ uint16 value = 123;
+ sscanf((*ii).second.c_str(), "%hu", &value);
+ value &= 0x07;
+ switch(value) {
+ case 0: (*ii).second = "Flash did not fire"; break;
+ case 1: (*ii).second = "Flash fired"; break;
+ case 5: (*ii).second = "Flash fired but strobe return light not detected"; break;
+ case 7: (*ii).second = "Flash fired and strobe return light detected"; break;
+ default: exifKeyValuePairs_.erase(ii); break;
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("ColorSpace")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ switch((*ii).second[0]) {
+ case '1': (*ii).second = "sRGB color space"; break;
+ case '6': (*ii).second = "Uncalibrated"; break;
+ default: exifKeyValuePairs_.erase(ii); break;
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("FocalPlaneResolutionUnit")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ switch((*ii).second[0]) {
+ case '1': (*ii).second = "no-unit"; break;
+ case '2': (*ii).second = "inch"; break;
+ case '3': (*ii).second = "centimeter"; break;
+ default: exifKeyValuePairs_.erase(ii); break;
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("SensingMethod")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ switch((*ii).second[0]) {
+ case '2': (*ii).second = "1 chip color area sensor"; break;
+ default: (*ii).second = "other"; break;
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("ExifVersion")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() != 4) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ (*ii).second = 'V' + (*ii).second.substr(0, 2) + '.' + (*ii).second.substr(2);
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("ComponentsConfiguration")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() != 4) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ static const char CCName[7][10] = {"", "[Y]", "[Cb]", "[Cr]", "[Red]", "[Green]", "[Blue]"};
+ std::string cc;
+ for(int i = 0; i < 4; ++i) {
+ int index = (*ii).second[i];
+ if (index < 0 || index >= 7) {
+ index = 0;
+ }
+ cc += CCName[index];
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("ExifVersion")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() != 4) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ (*ii).second = 'V' + (*ii).second.substr(0, 2) + '.' + (*ii).second.substr(2);
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("MakerNote")) != exifKeyValuePairs_.end()) {
+ exifKeyValuePairs_.erase(ii);
+ }
+ if ((ii = exifKeyValuePairs_.find("CFAPattern")) != exifKeyValuePairs_.end()) {
+ exifKeyValuePairs_.erase(ii);
+ }
+ if ((ii = exifKeyValuePairs_.find("UserComment")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() < 8) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ //Leave it to higher level which can deal with encoding.
+ //"\0x41\0x53\0x43\0x49\0x49\0x00\0x00\0x00"//ASCII
+ //"\0x4a\0x49\0x53\0x00\0x00\0x00\0x00\0x00"//JIS
+ //"\0x55\0x4e\0x49\0x43\0x4f\0x44\0x45\0x00"//Unicode
+ //"\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00"//Undefined
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("FlashPixVersion")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() != 4) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ (*ii).second = 'V' + (*ii).second.substr(0, 2) + '.' + (*ii).second.substr(2);
+ }
+ }
+ //FileSource
+ if ((ii = exifKeyValuePairs_.find("FileSource")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() != 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ if ((*ii).second[0] == '\003') {
+ (*ii).second = "Digital still camera";
+ } else {
+ exifKeyValuePairs_.erase(ii);
+ }
+ }
+ }
+ if ((ii = exifKeyValuePairs_.find("SceneType")) != exifKeyValuePairs_.end()) {
+ if ((*ii).second.length() != 1) {
+ exifKeyValuePairs_.erase(ii);
+ } else {
+ if ((*ii).second[0] == '\001') {
+ (*ii).second = "Directly photographed";
+ } else {
+ exifKeyValuePairs_.erase(ii);
+ }
+ }
+ }
+
+}
+
+std::string ExifExtractor::readInfo() {
+ uint32 count;
+ uint32 offset;
+ uint16 shortValue;
+ uint32 longValue;
+ uint32 urationalp;
+ uint32 urationalc;
+ uint32 urationalgcd;
+ int32 rationalp;
+ int32 rationalc;
+ int32 rationalgcd;
+ int32 sign;
+ DATATYPE dataType;
+ char* buffer;
+ std::string ret = "";
+
+ if (!read(&shortValue, 2,1) || shortValue == 0 || shortValue > MAXGUARD) {
+ return ret;
+ }
+ dataType = (DATATYPE)shortValue;
+
+ if (!read(&count, 4,1)) {
+ return ret;
+ }
+
+ switch(dataType) {
+ case UNDEFINED:
+ buffer = new char[count + 1];
+
+ if (count < 4) {
+ if (!read(buffer, 1, count)) {
+ return ret;
+ }
+ } else {
+ if (!read(&offset, 4, 1)) {
+ return ret;
+ }
+ seek(12 + offset, SEEK_SET);
+ memset(buffer, 0, count + 1);
+ read(buffer, 1, count);
+ }
+ ret = std::string(buffer, count);
+ delete []buffer;
+ break;
+ case ASCIISTRING:
+ if (!read(&offset, 4, 1)) {
+ break;
+ }
+ seek(12 + offset, SEEK_SET);
+ buffer = new char[count + 1];
+ memset(buffer, 0, count + 1);
+ read(buffer, 1, count);
+ ret = buffer;
+ delete []buffer;
+ break;
+ case UNSIGNEDINT16:
+ if (!read(&shortValue, 2, 1)) {
+ break;
+ }
+ buffer = new char[256];
+ sprintf(buffer, "%hu", shortValue);
+ ret = buffer;
+ delete []buffer;
+ break;
+ case UNSIGNEDINT32:
+ if (!read(&longValue, 4, 1)) {
+ break;
+ }
+ buffer = new char[256];
+ sprintf(buffer, "%u", longValue);
+ ret = buffer;
+ delete []buffer;
+
+ break;
+ case UNSIGNEDRATIONAL:
+ if (!read(&offset, 4, 1)) {
+ break;
+ }
+ seek(12 + offset, SEEK_SET);
+ if (!read(&urationalc, 4, 1)) {
+ break;
+ }
+ if (!read(&urationalp, 4, 1)) {
+ break;
+ }
+ urationalgcd = gcd(urationalp, urationalc);
+ if (urationalgcd == 0) urationalgcd = 1;
+ buffer = new char[256];
+ sprintf(buffer, "%u/%u", urationalc / urationalgcd, urationalp / urationalgcd);
+ ret = buffer;
+ delete []buffer;
+ break;
+ case RATIONAL:
+ if (!read(&offset, 4, 1)) {
+ break;
+ }
+ sign = 1;
+ seek(12 + offset, SEEK_SET);
+ if (!read(&rationalc, 4, 1)) {
+ break;
+ }
+ if (rationalc < 0) {
+ sign *= -1;
+ rationalc = -rationalc;
+ }
+ if (!read(&rationalp, 4, 1)) {
+ break;
+ }
+ if (rationalp < 0) {
+ sign *= -1;
+ rationalp = -rationalp;
+ }
+ rationalgcd = gcd(rationalp, rationalc);
+ if (rationalgcd == 0) rationalgcd = 1;
+ buffer = new char[256];
+ sprintf(buffer, "%d/%d", sign * rationalc / rationalgcd, rationalp / rationalgcd);
+ ret = buffer;
+ delete []buffer;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+bool ExifExtractor::analyzeIFD0TagInfo() {
+ bool res = true;
+ uint16 tag;
+ if (!read(&tag, 2, 1))
+ res = false;
+ int index;
+ for (index = 0; index < 16; ++index) {
+ if (IFD0Tag[index] == tag) {
+ break;
+ }
+ }
+ if (index == 16) {
+ res = false;
+ }
+ long pos = ftell(exifFile_) + 10;
+
+ if (res) {
+ std::string info = readInfo();
+ if (info != "")
+ exifKeyValuePairs_[IFD0TagName[index]] = info;
+ }
+
+ seek(pos, SEEK_SET);
+ return res;
+}
+
+bool ExifExtractor::analyzeSubIFDTagInfo() {
+ bool res = true;
+ uint16 tag;
+ if (!read(&tag, 2, 1))
+ res = false;
+ int index;
+ for (index = 0; index < 38; ++index) {
+ if (SubIFDTag[index] == tag) {
+ break;
+ }
+ }
+ if (index == 38) {
+ res = false;
+ }
+ long pos = ftell(exifFile_) + 10;
+
+ if (res) {
+ std::string info = readInfo();
+ if (info != "")
+ exifKeyValuePairs_[SubIFDTagName[index]] = info;
+ }
+
+ seek(pos, SEEK_SET);
+ return res;
+}
+
+bool ExifExtractor::readIFD0() {
+ seek(16, SEEK_SET);
+ if (!read(&ifdOffset_, 4, 1)) {
+ return false;
+ }
+ seek(ifdOffset_ + 12, SEEK_SET);
+ uint16 entryCount = 0;
+ if (!read(&entryCount, 2, 1)) {
+ return false;
+ }
+ int app1Entry = entryCount;
+ while (app1Entry >= 0) {
+ analyzeIFD0TagInfo();
+ app1Entry--;
+ }
+ return true;
+}
+
+bool ExifExtractor::readSubIFD() {
+ std::map<std::string, std::string>::iterator ii;
+ if ((ii = exifKeyValuePairs_.find("ExifOffset")) == exifKeyValuePairs_.end()) {
+ return false;
+ }
+ uint32 exifOffset = 0;
+ sscanf((*ii).second.c_str(), "%u", &exifOffset);
+ seek(12 + exifOffset, SEEK_SET);
+
+ uint16 entryCount = 0;
+ if (!read(&entryCount, 2, 1)) {
+ return false;
+ }
+ int app1Entry = entryCount;
+ while (app1Entry >= 0) {
+ analyzeSubIFDTagInfo();
+ app1Entry--;
+ }
+ return true;
+}
+
+bool ExifExtractor::isReadable() {
+ rewind();
+ unsigned char soi[2];
+ if (!read(soi, 2, 1))
+ return false;
+ if (soi[0] != 0xFF || soi[1] != 0xD8) {
+ return false;
+ }
+ unsigned char app1[2];
+ if (!read(app1, 2, 1))
+ return false;
+ if (app1[0] != 0xFF || app1[1] != 0xE1) {
+ return false;
+ }
+ seek(2, SEEK_CUR);
+ char exifHeader[6];
+ if (!read(exifHeader, 1, 6)) {
+ return false;
+ }
+ for (int i = 0; i < 6; ++i) {
+ if (exifHeader[i] != exifHeaderStandard[i])
+ return false;
+ }
+ return true;
+}
+
+bool ExifExtractor::checkEndian() {
+ toggle_ = false;
+ seek(12, SEEK_SET);
+ uint16 endian = 0;
+ if (!read(&endian, 2, 1)) {
+ return false;
+ }
+ if (endian == 0x4949) {
+ //II
+ toggle_ = false;
+ }
+ else if (endian == 0x4d4d) {
+ //MM
+ toggle_ = true;
+ }
+ return true;
+}
+
+void ExifExtractor::toggleEndian( void* buf, size_t s ) {
+ char* buffer = (char*)buf;
+ if (!toggle_) {
+ return;
+ }
+ for (size_t i = 0; i < s / 2; ++i) {
+ char tmp;
+ tmp = buffer[i];
+ buffer[i] = buffer[s - i - 1];
+ buffer[s - i - 1] = tmp;
+ }
+}
+
+void ExifExtractor::reset() {
+ toggle_ = false;
+ exifKeyValuePairs_.clear();
+ if (exifFile_) {
+ fclose(exifFile_);
+ exifFile_ = NULL;
+ }
+ ifdOffset_ = 0;
+ exifInformation_.clear();
+}
+
+bool ExifExtractor::read( void* buffer, size_t elementSize, size_t count ) {
+ for (size_t i = 0; i < count; ++i) {
+ if (fread((char*)buffer + i * elementSize, elementSize, 1, exifFile_) != 1)
+ return false;
+ toggleEndian((char*)buffer + i * elementSize, elementSize);
+ }
+ return true;
+}
+
+void ExifExtractor::seek( long offset, int origin ) {
+ fseek(exifFile_, offset, origin);
+}
+
+void ExifExtractor::rewind() {
+ ::rewind(exifFile_);
+}
+} //namespace FQTerm
diff --git a/src/common/fqterm_exif_extractor.h b/src/common/fqterm_exif_extractor.h
new file mode 100644
index 0000000..7f05798
--- /dev/null
+++ b/src/common/fqterm_exif_extractor.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ * 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_EXIF_EXTRACTOR
+#define FQTERM_EXIF_EXTRACTOR
+
+//#include <QtGlobal>
+
+#include "fqterm_trace.h"
+
+#include <iostream>
+#include <vector>
+#include <stdio.h>
+#include <stdlib.h>
+#include <algorithm>
+#include <map>
+#include <string>
+//using namespace std;
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdint>
+#endif
+
+namespace FQTerm {
+
+class ExifExtractor
+{
+public:
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ typedef std::uint32_t uint32;
+ typedef std::uint16_t uint16;
+ typedef std::int32_t int32;
+ typedef std::int16_t int16;
+#elif defined(QT_VERSION)
+ typedef quint32 uint32;
+ typedef quint16 uint16;
+ typedef qint32 int32;
+ typedef qint16 int16;
+#else
+ typedef unsigned int uint32;
+ typedef unsigned short int uint16;
+ typedef short int int16;
+ typedef int int32;
+#endif
+
+ enum DATATYPE {ZEORGARD = 0, UNSIGNEDCHAR = 1, ASCIISTRING = 2, UNSIGNEDINT16 = 3, UNSIGNEDINT32 = 4,
+ UNSIGNEDRATIONAL = 5, SIGNEDCHAR = 6, UNDEFINED = 7, SIGNEDSHORT = 8, SIGNEDLONG = 9, RATIONAL = 10,
+ SIGNEDFLOAT = 11, DOUBLEFLOAT = 12, MAXGUARD = 13};
+
+
+ ExifExtractor();
+ ~ExifExtractor();
+ std::string extractExifInfo(std::string fileName);
+ std::string extractExifInfo(FILE* file);
+
+ std::string info();
+
+ std::string operator[](const std::string& key);
+
+private:
+ void postRead();
+
+ std::string readInfo();
+ bool analyzeIFD0TagInfo();
+
+ bool analyzeSubIFDTagInfo();
+
+ bool readIFD0();
+ bool readSubIFD();
+ bool isReadable();
+ bool checkEndian();
+ void toggleEndian(void* buf, size_t s);
+
+ void reset();
+
+ bool read(void* buffer, size_t elementSize, size_t count);
+
+ void seek(long offset, int origin);
+
+ void rewind();
+
+ template<class T>
+ T gcd(T a, T b) {
+ if (a == 0 || b == 0)
+ return a + b;
+ return gcd(b, a % b);
+ }
+
+
+ bool toggle_;
+ std::map<std::string, std::string> exifKeyValuePairs_;
+ FILE* exifFile_;
+ uint32 ifdOffset_;
+ uint32 subIfdOffset_;
+
+ static const uint16 IFD0Tag[16];
+ static const char IFD0TagName[16][30];
+ static const uint16 SubIFDTag[38];
+ static const char SubIFDTagName[38][30];
+ static const char exifHeaderStandard[6];
+
+ std::string exifInformation_;
+};
+
+
+
+} //namespace FQTerm
+
+#endif
diff --git a/src/common/fqterm_filedialog.cpp b/src/common/fqterm_filedialog.cpp
new file mode 100644
index 0000000..958fff9
--- /dev/null
+++ b/src/common/fqterm_filedialog.cpp
@@ -0,0 +1,157 @@
+/***************************************************************************
+ * 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_filedialog.h"
+#include "fqterm_trace.h"
+#include "fqterm_path.h"
+#include "fqterm_config.h"
+
+/*
+ * Constructs a articleDialog as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+
+namespace FQTerm {
+
+FQTermFileDialog::FQTermFileDialog(FQTermConfig *config, QWidget *parent, Qt::WFlags fl)
+ : QFileDialog(parent, fl) {
+
+ configDir = getPath(USER_CONFIG) + "/";
+ userConfig = configDir + "fqterm.cfg";
+ strSection = "previous";
+ strSave = "save";
+ strOpen = "open";
+ config_ = config;
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+FQTermFileDialog::~FQTermFileDialog() {
+ // no need to delete child widgets, Qt does it all for us
+}
+
+
+
+QString FQTermFileDialog::getSaveName(const QString &fileToSave, const QString &hints, QWidget *widget) {
+ QString saveFile;
+ QString strPrevSave, saveName;
+ QFileDialog fileDialog(widget);
+
+ if (config_->load(userConfig)) {
+ strPrevSave = config_->getItemValue(strSection, strSave);
+ }
+
+ QString strTmp(fileToSave);
+#if !defined(Q_OS_WIN32) || !defined(_OS_WIN32_)
+ if (strTmp.toLocal8Bit().contains("/")) {
+ strTmp.replace(QString("/"), QString("_"));
+ }
+#endif
+
+ if (strPrevSave.isEmpty()) {
+ saveFile = configDir + strTmp;
+ } else {
+ saveFile = strPrevSave + "/" + strTmp;
+ }
+
+ QString realHints = (hints.isEmpty() ? "*" : hints);
+ saveName = fileDialog.getSaveFileName(widget,
+ tr("Save As..."),
+ saveFile, realHints);
+
+ QFileInfo fi(saveName);
+
+ if (!saveName.isEmpty()) {
+ config_->setItemValue(strSection, strSave, fi.absolutePath());
+ config_->save(userConfig);
+ }
+
+ return saveName;
+}
+
+QString FQTermFileDialog::getOpenName(const QString &title, const QString &hints, QWidget *widget) {
+ QString strPrevOpen;
+ QString openName;
+ QFileDialog fileDialog(widget);
+
+ strPrevOpen = (config_->load(userConfig) ? config_->getItemValue(strSection, strOpen) : "./");
+
+ QString realHints = (hints.isEmpty() ? "*" : hints);
+ QString realTitle = (title.isEmpty() ? "Choose a file to open" : title);
+ openName = fileDialog.getOpenFileName(widget, realTitle, strPrevOpen, realHints);
+
+ if (!openName.isEmpty()) {
+ config_->setItemValue(strSection, strOpen, QFileInfo(openName).absolutePath());
+ config_->save(userConfig);
+ }
+
+ return openName;
+}
+
+QStringList FQTermFileDialog::getOpenNames(const QString &title, const QString &hints, QWidget *widget) {
+ QString openDir, strPrevOpen;
+ QStringList openNames;
+ QFileDialog fileDialog(widget);
+
+ strPrevOpen = (config_->load(userConfig) ? config_->getItemValue(strSection, strOpen) : "./");
+
+ QString realHints = (hints.isEmpty() ? "*" : hints);
+ QString realTitle = (title.isEmpty() ? "Choose files to open" : title);
+ openNames = fileDialog.getOpenFileNames(widget, realTitle, strPrevOpen, realHints);
+
+ if (!openNames.isEmpty() && !openNames.at(0).isEmpty()) {
+ openDir = QFileInfo(openNames.at(0)).absolutePath();
+ config_->setItemValue(strSection, strOpen, openDir);
+ config_->save(userConfig);
+ }
+
+ return openNames;
+}
+
+QString FQTermFileDialog::getExistingDirectory(const QString &title, const QString &hints, QWidget *widget) {
+
+ QString strPrevOpen;
+ QFileDialog fileDialog(widget);
+
+ if (hints.isEmpty()) {
+ strPrevOpen = (config_->load(userConfig) ? config_->getItemValue(strSection, strOpen) : "./");
+ } else {
+ strPrevOpen = hints;
+ }
+
+ QString realTitle = (title.isEmpty() ? "Open a directory" : title);
+ QString dir = fileDialog.getExistingDirectory(widget,
+ realTitle,
+ strPrevOpen,
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+
+ if (!dir.isEmpty()) {
+ config_->setItemValue(strSection, strOpen, QFileInfo(dir).absolutePath());
+ config_->save(userConfig);
+ }
+
+ return dir;
+}
+
+} // namespace FQTerm
diff --git a/src/common/fqterm_filedialog.h b/src/common/fqterm_filedialog.h
new file mode 100644
index 0000000..5248ffd
--- /dev/null
+++ b/src/common/fqterm_filedialog.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * 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_FILEDIALOG_H
+#define FQTERM_FILEDIALOG_H
+
+#include <QFileDialog>
+#include <QMessageBox>
+
+namespace FQTerm {
+
+class FQTermConfig;
+
+class FQTermFileDialog: public QFileDialog {
+public:
+ FQTermFileDialog(FQTermConfig *config, QWidget *parent_ = 0, Qt::WFlags fl = 0);
+ ~FQTermFileDialog();
+
+ QString getSaveName(const QString &filename, const QString &hints, QWidget *widget = 0);
+ QString getOpenName(const QString &title, const QString &hints, QWidget *widget = 0);
+ QStringList getOpenNames(const QString &title, const QString &hints, QWidget *widget = 0);
+ QString getExistingDirectory(const QString &title, const QString &hints, QWidget *widget = 0);
+
+private:
+ QString strSection, strSave, strOpen;
+ FQTermConfig *config_;
+ QString configDir, userConfig;
+};
+
+} // name space FQTerm
+
+#endif // FQTERM_FILEEDIALOG_H
diff --git a/src/common/fqterm_font.cpp b/src/common/fqterm_font.cpp
new file mode 100644
index 0000000..f2dcfbd
--- /dev/null
+++ b/src/common/fqterm_font.cpp
@@ -0,0 +1,261 @@
+/***************************************************************************
+ * 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 <list>
+#include <set>
+#include <utility>
+#include <map>
+
+#include <QFontDatabase>
+#include <QFontInfo>
+#include <QFile>
+#include <QTextStream>
+#include <QTextCodec>
+#include <QLocale>
+
+#include "fqterm_trace.h"
+#include "fqterm_font.h"
+#include "fqterm_path.h"
+#include "fqterm_config.h"
+
+using namespace std;
+
+namespace FQTerm {
+
+namespace Font {
+
+enum Language{US_ENGLISH = 0,
+ SIMPLIFIED_CHINESE,
+ LANGUAGE_COUNT };
+
+QString getLanguageName(Language lang) {
+ switch (lang){
+ case US_ENGLISH:
+ return "en_US";
+ case SIMPLIFIED_CHINESE:
+ return "zh_CN";
+ default:
+ return "C";
+ }
+}
+
+Language getLanguageByName(QString langName) {
+ if (langName == "zh_CN") {
+ return SIMPLIFIED_CHINESE;
+ }
+ if (langName == "en_US") {
+ return US_ENGLISH;
+ }
+ return LANGUAGE_COUNT;
+}
+
+} // namespace Language
+
+typedef set<Font::Language> LanguageSet;
+typedef map<QString, pair<QString, LanguageSet> > FontLanguagesList;
+
+typedef map<QString, map<Font::Language, QStringList> > FontSets;
+
+// This function will be called only once.
+static const FontSets &getPreferedFontSets() {
+ static FontSets font_sets;
+ const QString &res_path = getPath(RESOURCE);
+
+ QString filename = res_path + "default_font.conf";
+
+ if (!QFile::exists(filename)) {
+ filename = res_path + "/dict/" + "default_font.conf";
+ }
+
+
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ FQ_TRACE("font", 0) << "Failed to open the default font configurations file:"
+ << filename;
+ return font_sets;
+ }
+
+ QTextStream is;
+ is.setDevice(&file);
+ is.setCodec(QTextCodec::codecForName("UTF-8"));
+
+#if defined(WIN32)
+ QString expected_section = "Windows";
+#elif defined(__APPLE__)
+ QString expected_section = "Apple";
+#else
+ QString expected_section = "Linux";
+#endif
+
+ QString line;
+
+ QString current_section;
+ while (!is.atEnd()) {
+ line = is.readLine().trimmed();
+ if (line.isEmpty() || line[0] == '#') {
+ continue;
+ }
+
+ if (line.left(1) == "[" && line.right(1) == "]") {
+ current_section = line.mid(1, line.length() - 2);
+ continue;
+ }
+
+ if (current_section == expected_section) {
+ QString en_font = line.section('=', 0, 0).trimmed().toLower();
+ QString fonts_for_lang = line.section('=', 1).trimmed();
+
+ map<Font::Language, QStringList> &font_set = font_sets[en_font];
+
+ QString lang = fonts_for_lang.section(":", 0, 0).trimmed();
+ QString fonts = fonts_for_lang.section(":", 1).trimmed();
+
+ QStringList font_list = fonts.split(",", QString::SkipEmptyParts);
+
+ for (int i = 0; i < font_list.size(); ++i) {
+ font_list[i] = font_list[i].trimmed();
+ }
+
+ font_set[Font::getLanguageByName(lang)] = font_list;
+ }
+ }
+
+ return font_sets;
+}
+
+#if 0
+//Not used
+static int outputAllSystemFonts(const QStringList &fonts) {
+ if (isAllowedCategory("font", 9)) {
+ for (int i = 0; i < fonts.size(); ++i) {
+ FQ_TRACE("font", 9) << "Found a font: "
+ << (QFontInfo(QFont(fonts.at(i))).fixedPitch() ?
+ "fixed-pitch " : "variable-pitch ")
+ << fonts.at(i);
+ }
+ }
+ return 0;
+}
+#endif
+
+static QStringList &getSystemFontFamilies() {
+ static QStringList list = QFontDatabase().families();
+ // static int tmp = outputAllSystemFonts(list);
+
+ return list;
+}
+
+static FontSets &getUserConfigFontSets() {
+ static FontSets font_sets = getPreferedFontSets();
+ return font_sets;
+}
+
+static QString getEnglishFontFamily() {
+ static const QStringList &families = getSystemFontFamilies();
+ static const FontSets &font_sets = getUserConfigFontSets();
+ static QString en_font_name;
+
+ if (!en_font_name.isEmpty()) {
+ return en_font_name;
+ }
+
+ FontSets::const_iterator it = font_sets.find("default");
+ if (it != font_sets.end()) {
+ map<Font::Language, QStringList>::const_iterator itt
+ = it->second.find(Font::US_ENGLISH);
+ if (itt != it->second.end()) {
+ for (int i = 0; i < itt->second.size(); ++i) {
+ const QString &font = itt->second[i];
+ if (families.contains(font)) {
+ en_font_name = font;
+ break;
+ }
+ }
+ }
+ }
+
+ return en_font_name;
+}
+
+
+static QString getFontFamilyForLang(Font::Language lang) {
+ static const QStringList &families = getSystemFontFamilies();
+ static const FontSets &font_sets = getUserConfigFontSets();
+
+ const QString en_font_name = getEnglishFontFamily();
+
+ if (lang == Font::US_ENGLISH) {
+ return en_font_name;
+ }
+
+ FontSets::const_iterator it = font_sets.find(en_font_name.toLower());
+ if (it != font_sets.end()) {
+ map<Font::Language, QStringList>::const_iterator itt
+ = it->second.find(lang);
+ if (itt != it->second.end()) {
+ for (int i = 0; i < itt->second.size(); ++i) {
+ const QString &font = itt->second[i];
+ if (families.contains(font)) {
+ return font;
+ } else {
+ FQ_TRACE("font", 5) << "Font " << font << " for "
+ << en_font_name << " not found.";
+ }
+ }
+ }
+ } else {
+ FQ_TRACE("font", 3) << "NO fontset for " << en_font_name << " found.";
+ }
+
+ return en_font_name;
+}
+
+QString getDefaultFontFamilyForLanguage(bool isEnglish) {
+ Font::Language lang = isEnglish ? Font::US_ENGLISH : Font::SIMPLIFIED_CHINESE;
+
+ static map<Font::Language, QString> langs_fonts_list;
+
+ map<Font::Language, QString>::iterator it = langs_fonts_list.find(lang);
+ if (it == langs_fonts_list.end()) {
+ langs_fonts_list.insert(
+ make_pair(lang, getFontFamilyForLang(lang)));
+ it = langs_fonts_list.find(lang);
+
+ FQ_TRACE("font", 3) << "Defaut font for "
+ << Font::getLanguageName(lang)
+ << " is: "
+ << it->second
+ << " (" << it->second.size() << ")";
+ }
+
+ return it->second;
+}
+
+#if 0
+//Not used.
+static Font::Language getCurrentSystemLanguage() {
+ if (QLocale::system().language() == QLocale::Chinese) {
+ return Font::SIMPLIFIED_CHINESE;
+ }
+
+ return Font::US_ENGLISH;
+}
+#endif
+} // namespace FQTerm
diff --git a/src/common/fqterm_font.h b/src/common/fqterm_font.h
new file mode 100644
index 0000000..7d28ffb
--- /dev/null
+++ b/src/common/fqterm_font.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * 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_FONT_H
+#define FQTERM_FONT_H
+
+#include <QString>
+
+#include "fqterm_param.h"
+
+namespace FQTerm {
+
+QString getDefaultFontFamilyForLanguage(bool isEnglish);
+
+} // namespace FQTerm
+
+#endif // FQTERM_FONT_H
diff --git a/src/common/fqterm_param.cpp b/src/common/fqterm_param.cpp
new file mode 100644
index 0000000..9490bdd
--- /dev/null
+++ b/src/common/fqterm_param.cpp
@@ -0,0 +1,274 @@
+/***************************************************************************
+ * 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_param.h"
+#include "fqterm_font.h"
+
+namespace FQTerm {
+
+FQTermParam::FQTermParam() {
+ name_ = "NEW SMTH";
+ hostAddress_ = "newsmth.net";
+ port_ = 23;
+ hostType_ = 0; // 0--BBS 1--*NIX
+ isAutoLogin_ = false;
+ preLoginCommand_ = "";
+ userName_ = "";
+ password_ = "";
+ postLoginCommand_ = "";
+ // Display
+ serverEncodingID_ = 0;
+ isFontAutoFit_ = 1;
+ isAlwaysHighlight_ = 0;
+ isAnsiColor_ = 1;
+
+ englishFontName_ = getDefaultFontFamilyForLanguage(true);
+ englishFontSize_ = 14;
+ otherFontName_ = getDefaultFontFamilyForLanguage(false);
+ otherFontSize_ = 14;
+ alignMode_ = 0;
+ charSpacing_ = 0;
+ lineSpacing_ = 0;
+ //charRatio_ = 0;
+
+ backgroundColor_ = QColor(0, 0, 0);
+ foregroundColor_ = QColor(198, 195, 198);
+ schemaFileName_ = "";
+ // Terminal
+ virtualTermType_ = "vt102";
+ keyboardType_ = 0;
+ backspaceType_ = 0;
+ numColumns_ = 80;
+ numRows_ = 24;
+ numScrollLines_ = 240;
+ cursorType_ = 1; // 0--Block 1--Underline 2--I Type
+ escapeString_ = "^[^[[";
+ // Connection
+ proxyType_ = 0; // 0--None 1--Wingate 2--SOCKS4 3--SOCKS5 4--HTTP
+ proxyHostName_ = "";
+ proxyPort_ = 0;
+ isAuthentation_ = false;
+ proxyUserName_ = "";
+ proxyPassword_ = "";
+ protocolType_ = 0; // 0--Telnet 1--SSH1 2--SSH2
+ sshUserName_ = "";
+ sshPassword_ = "";
+ // Misc
+ maxIdleSeconds_ = 120;
+ replyKeyCombination_ = "^Z";
+ antiIdleMessage_ = "^@";
+ isAntiIdle_ = true;
+ isAutoReply_ = false;
+ autoReplyMessage_ = "(FQTerm) Sorry, I am not around";
+ isAutoReconnect_ = false;
+ reconnectInterval_ = 3;
+ retryTimes_ = 0;
+ isAutoCloseWin_ = false;
+ isAutoLoadScript_ = false;
+ enableZmodem_ = true;
+ autoLoadedScriptFileName_ = "";
+ isBeep_ = true;
+ isBuzz_ = false;
+
+ // Mouse
+ isSupportMouse_ = true;
+ // Mouse
+ menuType_ = 2;
+ menuColor_ = QColor(0, 65, 132);
+
+ isColorCopy_ = false;
+ isRectSelect_ = false;
+ isAutoCopy_ = true;
+ isAutoWrap_ = false;
+}
+
+FQTermParam::FQTermParam(const FQTermParam &param) {
+ copy(param);
+}
+
+FQTermParam::~FQTermParam(){}
+
+FQTermParam &FQTermParam::operator = (const FQTermParam &param) {
+ if (this == &param)
+ return *this;
+ copy(param);
+ return *this;
+}
+
+void FQTermParam::copy(const FQTermParam& param) {
+ name_ = param.name_;
+ hostAddress_ = param.hostAddress_;
+ port_ = param.port_;
+ hostType_ = param.hostType_; // 0--BBS 1--*NIX
+ isAutoLogin_ = param.isAutoLogin_;
+ preLoginCommand_ = param.preLoginCommand_;
+ userName_ = param.userName_;
+ password_ = param.password_;
+ postLoginCommand_ = param.postLoginCommand_;
+ // Display
+ serverEncodingID_ = param.serverEncodingID_;
+ isFontAutoFit_ = param.isFontAutoFit_;
+ isAlwaysHighlight_ = param.isAlwaysHighlight_;
+ isAnsiColor_ = param.isAnsiColor_;
+ englishFontName_ = param.englishFontName_;
+ englishFontSize_ = param.englishFontSize_;
+ otherFontName_ = param.otherFontName_;
+ otherFontSize_ = param.otherFontSize_;
+ alignMode_ = param.alignMode_;
+ charSpacing_ = param.charSpacing_;
+ lineSpacing_ = param.lineSpacing_;
+ //charRatio_ = param.charRatio_;
+ backgroundColor_ = param.backgroundColor_;
+ foregroundColor_ = param.foregroundColor_;
+ schemaFileName_ = param.schemaFileName_;
+ // Terminal
+ virtualTermType_ = param.virtualTermType_;
+ keyboardType_ = param.keyboardType_;
+ backspaceType_ = param.backspaceType_;
+ numColumns_ = param.numColumns_;
+ numRows_ = param.numRows_;
+ numScrollLines_ = param.numScrollLines_;
+ cursorType_ = param.cursorType_; // 0--Block 1--Underline 2--I Type
+ escapeString_ = param.escapeString_; // 0--ESC ESC 1--Ctrl+u
+ // Connection
+ proxyType_ = param.proxyType_;
+ // 0--None 1--Wingate 2--SOCKS4 3--SOCKS5 4--HTTP
+ proxyHostName_ = param.proxyHostName_;
+ proxyPort_ = param.proxyPort_;
+ isAuthentation_ = param.isAuthentation_;
+ proxyUserName_ = param.proxyUserName_;
+ proxyPassword_ = param.proxyPassword_;
+ protocolType_ = param.protocolType_; // 0--Telnet 1--SSH1 2--SSH2
+ sshUserName_ = param.sshUserName_;
+ sshPassword_ = param.sshPassword_;
+ // Misc
+ maxIdleSeconds_ = param.maxIdleSeconds_;
+ replyKeyCombination_ = param.replyKeyCombination_;
+ antiIdleMessage_ = param.antiIdleMessage_;
+ isAntiIdle_ = param.isAntiIdle_;
+ isAutoReply_ = param.isAutoReply_;
+ autoReplyMessage_ = param.autoReplyMessage_;
+ isAutoReconnect_ = param.isAutoReconnect_;
+ reconnectInterval_ = param.reconnectInterval_;
+ retryTimes_ = param.retryTimes_;
+ isAutoCloseWin_ = param.isAutoCloseWin_;
+ isAutoLoadScript_ = param.isAutoLoadScript_;
+ enableZmodem_ = param.enableZmodem_;
+ autoLoadedScriptFileName_ = param.autoLoadedScriptFileName_;
+ isBeep_ = param.isBeep_;
+ isBuzz_ = param.isBuzz_;
+
+ isSupportMouse_ = param.isSupportMouse_;
+ // Mouse
+ menuType_ = param.menuType_;
+ menuColor_ = param.menuColor_;
+
+ isColorCopy_ = param.isColorCopy_;
+ isRectSelect_ = param.isRectSelect_;
+ isAutoCopy_ = param.isAutoCopy_;
+ isAutoWrap_ = param.isAutoWrap_;
+}
+
+bool FQTermParam::operator==(const FQTermParam& param)
+{
+ if (name_ != param.name_) return false;
+ if (hostAddress_ != param.hostAddress_) return false;
+ if (port_ != param.port_) return false;
+ if (hostType_ != param.hostType_) return false;
+ if (isAutoLogin_ != param.isAutoLogin_) return false;
+ if (preLoginCommand_ != param.preLoginCommand_) return false;
+ if (userName_ != param.userName_) return false;
+ if (password_ != param.password_) return false;
+ if (postLoginCommand_ != param.postLoginCommand_) return false;
+ if (serverEncodingID_ != param.serverEncodingID_) return false;
+ if (isFontAutoFit_ != param.isFontAutoFit_) return false;
+ if (isAlwaysHighlight_ != param.isAlwaysHighlight_) return false;
+ if (isAnsiColor_ != param.isAnsiColor_) return false;
+ if (englishFontName_ != param.englishFontName_) return false;
+ if (englishFontSize_ != param.englishFontSize_) return false;
+ if (otherFontName_ != param.otherFontName_) return false;
+ if (otherFontSize_ != param.otherFontSize_) return false;
+ if (alignMode_ != param.alignMode_) return false;
+ if (charSpacing_ != param.charSpacing_) return false;
+ if (lineSpacing_ != param.lineSpacing_) return false;
+ if (backgroundColor_ != param.backgroundColor_) return false;
+ if (foregroundColor_ != param.foregroundColor_) return false;
+ if (schemaFileName_ != param.schemaFileName_) return false;
+ if (virtualTermType_ != param.virtualTermType_) return false;
+ if (keyboardType_ != param.keyboardType_) return false;
+ if (backspaceType_ != param.backspaceType_) return false;
+ if (numColumns_ != param.numColumns_) return false;
+ if (numRows_ != param.numRows_) return false;
+ if (numScrollLines_ != param.numScrollLines_) return false;
+ if (cursorType_ != param.cursorType_) return false;
+ if (escapeString_ != param.escapeString_) return false;
+ if (proxyType_ != param.proxyType_) return false;
+ if (proxyHostName_ != param.proxyHostName_) return false;
+ if (proxyPort_ != param.proxyPort_) return false;
+ if (isAuthentation_ != param.isAuthentation_) return false;
+ if (proxyUserName_ != param.proxyUserName_) return false;
+ if (proxyPassword_ != param.proxyPassword_) return false;
+ if (protocolType_ != param.protocolType_) return false;
+ if (sshUserName_ != param.sshUserName_) return false;
+ if (sshPassword_ != param.sshPassword_) return false;
+ if (maxIdleSeconds_ != param.maxIdleSeconds_) return false;
+ if (replyKeyCombination_ != param.replyKeyCombination_) return false;
+ if (antiIdleMessage_ != param.antiIdleMessage_) return false;
+ if (isAntiIdle_ != param.isAntiIdle_) return false;
+ if (isAutoReply_ != param.isAutoReply_) return false;
+ if (autoReplyMessage_ != param.autoReplyMessage_) return false;
+ if (isAutoReconnect_ != param.isAutoReconnect_) return false;
+ if (reconnectInterval_ != param.reconnectInterval_) return false;
+ if (retryTimes_ != param.retryTimes_) return false;
+ if (isAutoCloseWin_ != param.isAutoCloseWin_) return false;
+ if (isAutoLoadScript_ != param.isAutoLoadScript_) return false;
+ if (enableZmodem_ != param.enableZmodem_) return false;
+ if (isBuzz_ != param.isBuzz_) return false;
+ if (isBeep_ != param.isBeep_) return false;
+ if (isSupportMouse_ != param.isSupportMouse_) return false;
+ if (autoLoadedScriptFileName_ != param.autoLoadedScriptFileName_) return false;
+ if (menuType_ != param.menuType_) return false;
+ if (isColorCopy_ != param.isColorCopy_) return false;
+ if (isRectSelect_ != param.isRectSelect_) return false;
+ if (isAutoCopy_ != param.isAutoCopy_) return false;
+ if (isAutoWrap_ != param.isAutoWrap_) return false;
+ return true;
+}
+
+QString FQTermParam::getLanguageName(bool isEnglish, bool translate /* = true */)
+{
+ if (isEnglish) {
+ return QString(translate ? QObject::tr("&English") : "English");
+ }
+ return QString(translate ? QObject::tr("&Non-English") : "Non-English");
+}
+
+const FQTermParam& FQTermParam::getFQBBSParam() {
+ static bool inited = false;
+ static FQTermParam param;
+ if (!inited) {
+ param.name_ = "FQTermHelp";
+ param.hostAddress_ = "127.0.0.1";
+ param.port_ = 35172;
+ param.serverEncodingID_ = 2;
+ }
+ return param;
+}
+} // namespace FQTerm
diff --git a/src/common/fqterm_param.h b/src/common/fqterm_param.h
new file mode 100644
index 0000000..ef44f59
--- /dev/null
+++ b/src/common/fqterm_param.h
@@ -0,0 +1,221 @@
+/***************************************************************************
+ * 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_PARAM_H
+#define FQTERM_PARAM_H
+
+#include <QString>
+#include <QColor>
+
+namespace FQTerm {
+
+
+//The FQTerm Pref also contains global settings.
+//TODO: move all global settings into FQTermPref.
+struct FQTermPref {
+ static FQTermPref* getInstance()
+ {
+ //Though Singleton, I didn't define a ctor and make it private
+ //Why?
+ //I'm lazy.
+ static FQTermPref* pThis = new FQTermPref();
+ return pThis;
+ }
+ int displayOffset_;
+ int vsetting_;
+ int imeEncodingID_; // 0--GBK 1--BIG5
+ int widthToWrapWord_;
+ // bool bSmartWW;
+ bool isWheelSupported_;
+ bool openWarnOnClose_;
+ bool openTabBlinking_;
+ bool replyENQ_;
+ // bool bLogMsg;
+ QString httpBrowser_;
+ int openBeep_;
+ QString beepSoundFileName_;
+ int beepMethodID_;
+ QString beepPlayerName_;
+ bool openUrlCheck_;
+ // bool bAutoCopy;
+ bool openAntiAlias_;
+ bool openMinimizeToTray_;
+ bool needClearZmodemPoolOnClose_;
+ bool useStyleSheet_;
+ QString styleSheetFile_;
+ QString zmodemDir_;
+ QString poolDir_;
+ QString imageViewerName_;
+ QString externalEditor_;
+ QString externalEditorArg_;
+ QString searchEngine_;
+ //global settings
+ bool isBossColor_;
+ bool isAnsciiEnhance_;
+ QString escapeString_;
+ int termScrollBarPosition_; // 0--hide 1--LEFT 2--RIGHT
+ bool runServer_;
+};
+
+
+class FQTermParam {
+ public:
+ FQTermParam();
+ FQTermParam(const FQTermParam &);
+ ~FQTermParam();
+
+ FQTermParam &operator = (const FQTermParam &);
+
+ bool operator==(const FQTermParam &);
+
+ static const FQTermParam& getFQBBSParam();
+ static QString getLanguageName(bool isEnglish, bool translate = true);
+ // General
+ // Name
+ QString name_;
+ // Address
+ QString hostAddress_;
+ // Port
+ quint16 port_;
+ // Host Type
+ int hostType_; // 0--BBS 1--*NIX
+ // Auto Login
+ bool isAutoLogin_;
+ // Pre Login
+ QString preLoginCommand_;
+ // User Name
+ QString userName_;
+ // Password
+ QString password_;
+ // Post Login
+ QString postLoginCommand_;
+
+ // Display
+ // {FQTERM_ENCODING_GBK = 0, FQTERM_ENCODING_BIG5 = 1, FQTERM_ENCODING_UTF8 = 2, FQTERM_ENCODING_HKSCS = 3, FQTERM_ENCODING_UAO = 4};
+ int serverEncodingID_;
+
+ // 0 - keep column/row, adjust font
+ // 1 - keep font, adjust column/row
+ // 2 - keep column/row/font
+ int isFontAutoFit_;
+ // Always Highlight
+ bool isAlwaysHighlight_;
+ // ANSI Color
+ bool isAnsiColor_;
+ // Font Name
+ QString englishFontName_;
+ QString otherFontName_;
+ // Font Size
+ int englishFontSize_;
+ int otherFontSize_;
+
+ int alignMode_; //how to align english char/chinese char in vertical direction 0 -- vcenter, 1 -- bottom 2 -- top
+ int charSpacing_; //additional char spacing for English char.
+ int lineSpacing_; //additional line spacing
+ //int charRatio_; //height of english char / width of english char
+ // Background Color
+ QColor backgroundColor_;
+ // Foreground Color
+ QColor foregroundColor_;
+ // Schema File
+ QString schemaFileName_;
+
+ // Terminal
+ // Terminal Type
+ QString virtualTermType_;
+ // Key Type
+ int keyboardType_; // 0--BBS 1--XTERM 2--VT100
+ // Columns & Rows
+ int numColumns_, numRows_;
+ // Scroll Lines
+ int numScrollLines_;
+ // Curor Type
+ int cursorType_; // 0--Block 1--Underline 2--I Type
+ // the esacpe string
+ QString escapeString_;
+
+ //Keyboard
+ int backspaceType_; //0--^H 1--^?(127)
+
+
+ // Connection
+ // Proxy Type
+ int proxyType_; // 0--None 1--Wingate 2--SOCKS4 3--SOCKS5 4--HTTP
+ // Address
+ QString proxyHostName_;
+ // Port
+ quint16 proxyPort_;
+ // Authentation
+ bool isAuthentation_;
+ // User Name
+ QString proxyUserName_;
+ // Password
+ QString proxyPassword_;
+ // Protocol
+ int protocolType_; // 0--Telnet 1--SSH1 2--SSH2 3--Local
+ // User Name
+ QString sshUserName_;
+ // Password
+ QString sshPassword_;
+ // Misc
+ // Max Idle Time %s
+ int maxIdleSeconds_;
+ QString replyKeyCombination_;
+ // Send When Idle
+ QString antiIdleMessage_;
+ bool isAntiIdle_;
+ // wether autoreply
+ bool isAutoReply_;
+ // Auto Reply Messages
+ QString autoReplyMessage_;
+ // Reconnect When Disconnected By Host
+ bool isAutoReconnect_;
+ // Reconnect Interval (s)
+ int reconnectInterval_;
+ // Retry times
+ int retryTimes_; // -1 -- infinite
+ // Close Window When Disconnected By Host
+ bool isAutoCloseWin_;
+
+ bool isBeep_;
+ bool isBuzz_;
+
+ // Mouse
+ bool isSupportMouse_;
+ int menuType_; // 0--underline 1--reverse 2--color
+ QColor menuColor_;
+ // Script
+ bool isAutoLoadScript_;
+ QString autoLoadedScriptFileName_;
+ // Zmodem
+ bool enableZmodem_;
+
+ bool isColorCopy_;
+ bool isRectSelect_;
+ bool isAutoCopy_;
+ bool isAutoWrap_;
+
+ private:
+ void copy(const FQTermParam& parm);
+};
+
+} // namespace FQTerm
+
+#endif // FQTERM_PARAM_H
diff --git a/src/common/fqterm_path.cpp b/src/common/fqterm_path.cpp
new file mode 100644
index 0000000..88ee385
--- /dev/null
+++ b/src/common/fqterm_path.cpp
@@ -0,0 +1,601 @@
+/***************************************************************************
+ * 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. *
+ ***************************************************************************/
+
+#ifdef WIN32
+#include <windows.h>
+#include <shlobj.h>
+#endif // WIN32
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QFont>
+
+#include "fqterm_config.h"
+#include "fqterm_trace.h"
+#include "fqterm_param.h"
+#include "fqterm_path.h"
+#include "fqterm_font.h"
+
+namespace FQTerm {
+
+static QString getUserDataDir();
+static QString getInstallPrefix();
+static QString getResourceDir(const QString &prefix);
+
+const QString &getPath(PathCategory category) {
+ static QString null_dir = "";
+ static QString user_config = getUserDataDir();
+ static QString prefix = getInstallPrefix();
+ static QString resource = getResourceDir(prefix);
+
+ switch (category) {
+ case RESOURCE:
+ return resource;
+ break;
+ case USER_CONFIG:
+ return user_config;
+ break;
+ }
+ return null_dir;
+}
+
+void clearDir(const QString &path) {
+ QDir dir(path);
+ if (dir.exists()) {
+ const QFileInfoList list = dir.entryInfoList();
+ //QFileInfoListIterator it( *list );
+ //QFileInfo *fi;
+ foreach(QFileInfo fi, list) {
+ if (fi.isFile()) {
+ dir.remove(fi.fileName());
+ }
+ }
+ }
+}
+
+bool checkPath(const QString &path) {
+ QDir dir(path);
+ if (!dir.exists()) {
+ if (!dir.mkpath(path)) {
+ FQ_TRACE("path", 0) << "Failed to create directory " << path;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool checkFile(const QString &src, const QString &dst) {
+ if (QFile(dst).exists()) {
+ return true;
+ }
+
+ if (!QFile::copy(src, dst)) {
+ FQ_TRACE("path", 0) << "Failed to copy a file from " << src
+ << " to " << dst;
+ return false;
+ }
+
+ FQ_TRACE("path", 5) << "A file copied from " << src
+ << " to " << dst;
+
+ if (!QFile::setPermissions(dst, QFile::ReadOwner | QFile::WriteOwner)) {
+ FQ_TRACE("path", 0) << "Failed to change access attributs of "<< dst
+ << " to make only the owner have rights to "
+ << "read/write it.";
+ return false;
+ }
+
+ return true;
+}
+
+bool iniSettings() {
+ if (!checkPath(getPath(USER_CONFIG))) {
+ return false;
+ }
+
+ if (!checkFile(getPath(RESOURCE) + "userconf/fqterm.cfg.orig",
+ getPath(USER_CONFIG) + "fqterm.cfg")) {
+ return false;
+ }
+
+ if (!checkFile(getPath(RESOURCE) + "userconf/address.cfg.orig",
+ getPath(USER_CONFIG) + "address.cfg")) {
+ return false;
+ }
+
+ if (!checkFile(getPath(RESOURCE) + "userconf/language.cfg.orig",
+ getPath(USER_CONFIG) + "language.cfg")) {
+ return false;
+ }
+
+ //Copy schema files
+ if (checkPath(getPath(USER_CONFIG) + "schema")) {
+ checkFile(getPath(RESOURCE) + "schema/default.schema",
+ getPath(USER_CONFIG) + "schema/default.schema");
+
+ checkFile(getPath(RESOURCE) + "schema/Linux.schema",
+ getPath(USER_CONFIG) + "schema/Linux.schema");
+
+ checkFile(getPath(RESOURCE) + "schema/Softness.schema",
+ getPath(USER_CONFIG) + "schema/Softness.schema");
+
+ checkFile(getPath(RESOURCE) + "schema/VIM.schema",
+ getPath(USER_CONFIG) + "schema/VIM.schema");
+
+ checkFile(getPath(RESOURCE) + "schema/XTerm.schema",
+ getPath(USER_CONFIG) + "schema/XTerm.schema");
+ }
+
+
+ //read settings from fqterm.cfg
+ FQTermConfig *conf = new FQTermConfig(getPath(USER_CONFIG) + "fqterm.cfg");
+
+ //set font
+ QString family = (conf->getItemValue("global", "font"));
+
+ QString pointsize = conf->getItemValue("global", "pointsize");
+ QString pixelsize = conf->getItemValue("global", "pixelsize");
+ if (!family.isEmpty()) {
+ QFont font(family);
+ if (pointsize.toInt() > 0) {
+ font.setPointSize(pointsize.toInt());
+ }
+ if (pixelsize.toInt() > 0) {
+ font.setPixelSize(pixelsize.toInt());
+ }
+ QString openAntiAlias_ = conf->getItemValue("global", "antialias");
+ if (openAntiAlias_ != "0") {
+ font.setStyleStrategy(QFont::PreferAntialias);
+ }
+ qApp->setFont(font);
+ }
+
+ // zmodem and pool directory
+ QString pathZmodem = conf->getItemValue("preference", "zmodem");
+ if (pathZmodem.isEmpty()) {
+ pathZmodem = getPath(USER_CONFIG) + "zmodem";
+ }
+
+ if (!checkPath(pathZmodem)) {
+ return false;
+ }
+
+ QString pathPool = conf->getItemValue("preference", "pool");
+
+ if (pathPool.isEmpty()) {
+ pathPool = getPath(USER_CONFIG) + "pool/";
+ }
+
+ if (pathPool.right(1) != "/") {
+ pathPool.append('/');
+ }
+
+ QString pathCache = pathPool + "shadow-cache/";
+
+ if (!checkPath(pathPool) || !checkPath(pathCache)) {
+ return false;
+ }
+
+ delete conf;
+ return true;
+}
+
+void checkHelpExists(FQTermConfig* pConf) {
+ QString strTmp = pConf->getItemValue("bbs list", "num");
+ int bbsCount = strTmp.toInt();
+
+ QString strSection;
+
+ for (int i = 0; i < bbsCount; i++) {
+ strSection.sprintf("bbs %d", i);
+ strTmp = pConf->getItemValue(strSection, "name");
+ if (strTmp == "FQTermHelp")
+ return;
+ }
+ pConf->setItemValue("bbs list", "num", QString("%1").arg(bbsCount + 1));
+ saveAddress(pConf, bbsCount, FQTermParam::getFQBBSParam());
+ pConf->save(getPath(USER_CONFIG) + "address.cfg");
+}
+
+void loadNameList(FQTermConfig *pConf, QStringList &listName) {
+ QString strTmp = pConf->getItemValue("bbs list", "num");
+
+ QString strSection;
+
+ for (int i = 0; i < strTmp.toInt(); i++) {
+ strSection.sprintf("bbs %d", i);
+ listName.append(pConf->getItemValue(strSection, "name"));
+ }
+}
+
+bool loadAddress(FQTermConfig *pConf, int n, FQTermParam &param) {
+ QString strTmp, strSection;
+ if (n < 0) {
+ strSection = "default";
+ } else {
+ strSection.sprintf("bbs %d", n);
+ }
+
+ if (!pConf->hasSection(strSection))
+ return false;
+
+ // check if larger than existence
+ strTmp = pConf->getItemValue("bbs list", "num");
+ if (n >= strTmp.toInt()) {
+ return false;
+ }
+ param.name_ = pConf->getItemValue(strSection, "name");
+ param.hostAddress_ = pConf->getItemValue(strSection, "addr");
+ strTmp = pConf->getItemValue(strSection, "port");
+ param.port_ = strTmp.toUShort();
+ strTmp = pConf->getItemValue(strSection, "hosttype");
+ param.hostType_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "autologin");
+ param.isAutoLogin_ = (strTmp != "0");
+ param.preLoginCommand_ = pConf->getItemValue(strSection, "prelogin");
+ param.userName_ = pConf->getItemValue(strSection, "user");
+ param.password_ = pConf->getItemValue(strSection, "password");
+ param.postLoginCommand_ = pConf->getItemValue(strSection, "postlogin");
+
+ strTmp = pConf->getItemValue(strSection, "bbscode");
+ param.serverEncodingID_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "autofont");
+ if (strTmp == "0") {
+ param.isFontAutoFit_ = 0;
+ } else if (strTmp == "2") {
+ param.isFontAutoFit_ = 2;
+ } else {
+ param.isFontAutoFit_ = 1;
+ }
+ strTmp = pConf->getItemValue(strSection, "alwayshighlight");
+ param.isAlwaysHighlight_ = (strTmp != "0");
+ strTmp = pConf->getItemValue(strSection, "ansicolor");
+ param.isAnsiColor_ = (strTmp != "0");
+ QString language;
+ QString font_name;
+ QString font_size;
+ language = FQTermParam::getLanguageName(true, false);
+ font_name = pConf->getItemValue(strSection, language + "fontname");
+ font_size = pConf->getItemValue(strSection, language + "fontsize");
+ if (!font_name.isEmpty()) {
+ param.englishFontName_ = font_name;
+ }
+ if (!font_size.isEmpty()) {
+ param.englishFontSize_ = font_size.toInt();
+ }
+ //FIXME: Should be removed in next release!!!!! (Since 0.9.7)
+ if (font_name.isEmpty()) {
+ language = FQTermParam::getLanguageName(true);
+ font_name = pConf->getItemValue(strSection, language + "fontname");
+ if (!font_name.isEmpty()) {
+ param.englishFontName_ = font_name;
+ }
+ }
+
+ language = FQTermParam::getLanguageName(false, false);
+ font_name = pConf->getItemValue(strSection, language + "fontname");
+ font_size = pConf->getItemValue(strSection, language + "fontsize");
+ if (!font_name.isEmpty()) {
+ param.otherFontName_ = font_name;
+ }
+ if (!font_size.isEmpty()) {
+ param.otherFontSize_ = font_size.toInt();
+ }
+
+ //FIXME: Should be removed in next release!!!!!
+ if (font_name.isEmpty()) {
+ language = FQTermParam::getLanguageName(false);
+ font_name = pConf->getItemValue(strSection, language + "fontname");
+ if (!font_name.isEmpty()) {
+ param.englishFontName_ = font_name;
+ }
+ }
+
+ param.foregroundColor_.setNamedColor(pConf->getItemValue(strSection, "fgcolor"));
+ param.backgroundColor_.setNamedColor(pConf->getItemValue(strSection, "bgcolor"));
+ param.schemaFileName_ = pConf->getItemValue(strSection, "schemafile");
+
+ param.virtualTermType_ = pConf->getItemValue(strSection, "termtype");
+ strTmp = pConf->getItemValue(strSection, "keytype");
+ param.keyboardType_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "backspacetype");
+ param.backspaceType_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "column");
+ param.numColumns_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "row");
+ param.numRows_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "scroll");
+ param.numScrollLines_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "cursor");
+ param.cursorType_ = strTmp.toInt();
+ param.escapeString_ = pConf->getItemValue(strSection, "escape");
+
+ strTmp = pConf->getItemValue(strSection, "proxytype");
+ param.proxyType_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "proxyauth");
+ param.isAuthentation_ = (strTmp != "0");
+ param.proxyHostName_ = pConf->getItemValue(strSection, "proxyaddr");
+ strTmp = pConf->getItemValue(strSection, "proxyport");
+ param.proxyPort_ = strTmp.toInt();
+ param.proxyUserName_ = pConf->getItemValue(strSection, "proxyuser");
+ param.proxyPassword_ = pConf->getItemValue(strSection, "proxypassword");
+ strTmp = pConf->getItemValue(strSection, "protocol");
+ param.protocolType_ = strTmp.toInt();
+ param.sshUserName_ = pConf->getItemValue(strSection, "sshuser");
+ param.sshPassword_ = pConf->getItemValue(strSection, "sshpassword");
+
+ strTmp = pConf->getItemValue(strSection, "maxidle");
+ param.maxIdleSeconds_ = strTmp.toInt();
+ param.replyKeyCombination_ = pConf->getItemValue(strSection, "replykey");
+ if (param.replyKeyCombination_.isNull()) {
+ Q_ASSERT(false);
+ }
+
+ param.antiIdleMessage_ = pConf->getItemValue(strSection, "antiidlestring");
+ strTmp = pConf->getItemValue(strSection, "isantiidle");
+ param.isAntiIdle_ = (strTmp != "0");
+ param.autoReplyMessage_ = pConf->getItemValue(strSection, "autoreply");
+ strTmp = pConf->getItemValue(strSection, "bautoreply");
+ param.isAutoReply_ = (strTmp != "0");
+
+ strTmp = pConf->getItemValue(strSection, "reconnect");
+ param.isAutoReconnect_ = (strTmp != "0");
+ strTmp = pConf->getItemValue(strSection, "interval");
+ param.reconnectInterval_ = strTmp.toInt();
+ strTmp = pConf->getItemValue(strSection, "retrytimes");
+ param.retryTimes_ = strTmp.toInt();
+
+ strTmp = pConf->getItemValue(strSection, "autoclosewin");
+ param.isAutoCloseWin_ = (strTmp == "1");
+
+ strTmp = pConf->getItemValue(strSection, "alignmode");
+ param.alignMode_ = strTmp.toInt();
+
+
+ strTmp = pConf->getItemValue(strSection, "charspacing");
+ param.charSpacing_ = strTmp.toInt();
+
+ strTmp = pConf->getItemValue(strSection, "linespacing");
+ param.lineSpacing_ = strTmp.toInt();
+
+ strTmp = pConf->getItemValue(strSection, "loadscript");
+ param.isAutoLoadScript_ = (strTmp != "0");
+ param.autoLoadedScriptFileName_ = pConf->getItemValue(strSection, "scriptfile");
+
+ strTmp = pConf->getItemValue(strSection, "enablezmodem");
+ param.enableZmodem_ = (strTmp != "0");
+
+ strTmp = pConf->getItemValue(strSection, "isbeep");
+ param.isBeep_ = (strTmp != "0");
+
+ strTmp = pConf->getItemValue(strSection, "isbuzz");
+ param.isBuzz_ = (strTmp != "0");
+
+ strTmp = pConf->getItemValue(strSection, "ismouse");
+ param.isSupportMouse_ = (strTmp != "0");
+
+ strTmp = pConf->getItemValue(strSection, "menutype");
+ param.menuType_ = strTmp.toInt();
+ param.menuColor_.setNamedColor(pConf->getItemValue(strSection, "menucolor"));
+
+ param.isColorCopy_ = (pConf->getItemValue(strSection, "colorcopy") != "0");
+ param.isAutoCopy_ = (pConf->getItemValue(strSection, "autocopy") != "0");
+ param.isRectSelect_ = (pConf->getItemValue(strSection, "rectselect") != "0");
+ param.isAutoWrap_ = (pConf->getItemValue(strSection, "autowrap" ) == "1");
+
+ return true;
+}
+
+void saveAddress(FQTermConfig *pConf, int n, const FQTermParam &param) {
+ QString strTmp, strSection;
+ if (n < 0) {
+ strSection = "default";
+ } else {
+ strSection.sprintf("bbs %d", n);
+ }
+
+ pConf->setItemValue(strSection, "name", param.name_);
+ pConf->setItemValue(strSection, "addr", param.hostAddress_);
+ strTmp.setNum(param.port_);
+ pConf->setItemValue(strSection, "port", strTmp);
+ strTmp.setNum(param.hostType_);
+ pConf->setItemValue(strSection, "hosttype", strTmp);
+ pConf->setItemValue(strSection, "autologin", param.isAutoLogin_ ? "1" : "0");
+ pConf->setItemValue(strSection, "prelogin", param.preLoginCommand_);
+ pConf->setItemValue(strSection, "user", param.userName_);
+ pConf->setItemValue(strSection, "password", param.password_);
+ pConf->setItemValue(strSection, "postlogin", param.postLoginCommand_);
+
+ strTmp.setNum(param.serverEncodingID_);
+ pConf->setItemValue(strSection, "bbscode", strTmp);
+ pConf->setItemValue(strSection, "autofont", strTmp.setNum(param.isFontAutoFit_));
+ pConf->setItemValue(strSection, "alwayshighlight", param.isAlwaysHighlight_ ?
+ "1" : "0");
+ pConf->setItemValue(strSection, "ansicolor", param.isAnsiColor_ ? "1" : "0");
+
+ pConf->setItemValue(strSection, FQTermParam::getLanguageName(true, false) + "fontname", param.englishFontName_);
+ strTmp.setNum(param.englishFontSize_);
+ pConf->setItemValue(strSection, FQTermParam::getLanguageName(true, false) + "fontsize", strTmp);
+
+ pConf->setItemValue(strSection, FQTermParam::getLanguageName(false, false) + "fontname", param.otherFontName_);
+ strTmp.setNum(param.otherFontSize_);
+ pConf->setItemValue(strSection, FQTermParam::getLanguageName(false, false) + "fontsize", strTmp);
+
+ pConf->setItemValue(strSection, "alignmode", strTmp.setNum(param.alignMode_));
+ pConf->setItemValue(strSection, "charspacing", strTmp.setNum(param.charSpacing_));
+ pConf->setItemValue(strSection, "linespacing", strTmp.setNum(param.lineSpacing_));
+
+ pConf->setItemValue(strSection, "bgcolor", param.backgroundColor_.name());
+ pConf->setItemValue(strSection, "fgcolor", param.foregroundColor_.name());
+
+ pConf->setItemValue(strSection, "schemafile", param.schemaFileName_);
+
+ pConf->setItemValue(strSection, "termtype", param.virtualTermType_);
+ strTmp.setNum(param.keyboardType_);
+ pConf->setItemValue(strSection, "keytype", strTmp);
+ strTmp.setNum(param.backspaceType_);
+ pConf->setItemValue(strSection, "backspacetype", strTmp);
+ strTmp.setNum(param.numColumns_);
+ pConf->setItemValue(strSection, "column", strTmp);
+ strTmp.setNum(param.numRows_);
+ pConf->setItemValue(strSection, "row", strTmp);
+ strTmp.setNum(param.numScrollLines_);
+ pConf->setItemValue(strSection, "scroll", strTmp);
+ strTmp.setNum(param.cursorType_);
+ pConf->setItemValue(strSection, "cursor", strTmp);
+ pConf->setItemValue(strSection, "escape", param.escapeString_);
+
+ strTmp.setNum(param.proxyType_);
+ pConf->setItemValue(strSection, "proxytype", strTmp);
+ pConf->setItemValue(strSection, "proxyauth", param.isAuthentation_ ? "1" : "0");
+ pConf->setItemValue(strSection, "proxyaddr", param.proxyHostName_);
+ strTmp.setNum(param.proxyPort_);
+ pConf->setItemValue(strSection, "proxyport", strTmp);
+ pConf->setItemValue(strSection, "proxyuser", param.proxyUserName_);
+ pConf->setItemValue(strSection, "proxypassword", param.proxyPassword_);
+ strTmp.setNum(param.protocolType_);
+ pConf->setItemValue(strSection, "protocol", strTmp);
+ pConf->setItemValue(strSection, "sshuser", param.sshUserName_);
+ pConf->setItemValue(strSection, "sshpassword", param.sshPassword_);
+
+ strTmp.setNum(param.maxIdleSeconds_);
+ pConf->setItemValue(strSection, "maxidle", strTmp);
+ pConf->setItemValue(strSection, "replykey", param.replyKeyCombination_);
+ pConf->setItemValue(strSection, "antiidlestring", param.antiIdleMessage_);
+ pConf->setItemValue(strSection, "isantiidle", param.isAntiIdle_?"1" : "0");
+ pConf->setItemValue(strSection, "bautoreply", param.isAutoReply_ ? "1" : "0");
+ pConf->setItemValue(strSection, "autoreply", param.autoReplyMessage_);
+ pConf->setItemValue(strSection, "reconnect", param.isAutoReconnect_? "1" : "0");
+ strTmp.setNum(param.reconnectInterval_);
+ pConf->setItemValue(strSection, "interval", strTmp);
+ strTmp.setNum(param.retryTimes_);
+ pConf->setItemValue(strSection, "retrytimes", strTmp);
+ pConf->setItemValue(strSection, "autoclosewin", param.isAutoCloseWin_? "1" : "0");
+
+ pConf->setItemValue(strSection, "loadscript", param.isAutoLoadScript_ ? "1" : "0");
+ pConf->setItemValue(strSection, "scriptfile", param.autoLoadedScriptFileName_);
+
+ pConf->setItemValue(strSection, "enablezmodem", param.enableZmodem_? "1" : "0");
+
+ pConf->setItemValue(strSection, "isbeep", param.isBeep_? "1" : "0");
+ pConf->setItemValue(strSection, "isbuzz", param.isBuzz_? "1" : "0");
+ pConf->setItemValue(strSection, "ismouse", param.isSupportMouse_? "1" : "0");
+
+ strTmp.setNum(param.menuType_);
+ pConf->setItemValue(strSection, "menutype", strTmp);
+ pConf->setItemValue(strSection, "menucolor", param.menuColor_.name());
+
+ pConf->setItemValue(strSection, "colorcopy", param.isColorCopy_? "1" : "0");
+ pConf->setItemValue(strSection, "autocopy", param.isAutoCopy_? "1" : "0");
+ pConf->setItemValue(strSection, "rectselect", param.isRectSelect_? "1" : "0");
+ pConf->setItemValue(strSection, "autowrap", param.isAutoWrap_?"1":"0");
+
+}
+
+static QString getResourceDir(const QString &prefix) {
+ QString res;
+
+ std::string fqterm_resource;
+
+ char *p = NULL;
+ if ((p = getenv("FQTERM_RESOURCE")) != NULL)
+ fqterm_resource = p;
+
+ if (fqterm_resource.size() == 0) {
+#if defined(WIN32)
+ res = prefix;
+#elif defined(__APPLE__)
+ res = prefix + "../Resources/";
+#else
+ res = prefix + "share/FQTerm/";
+#endif
+ } else {
+ res = QString::fromLocal8Bit(fqterm_resource.c_str());
+ }
+
+ if (res[res.size() - 1] != '/')
+ res += '/';
+
+ return res;
+}
+
+static QString getInstallPrefix() {
+ QString res;
+
+ std::string fqterm_prefix;
+
+ char *p = NULL;
+ if ((p = getenv("FQTERM_PREFIX")) != NULL)
+ fqterm_prefix = p;
+
+ if (fqterm_prefix.size() == 0) {
+ res = QCoreApplication::applicationDirPath() + "/";
+ } else {
+ res = QString::fromLocal8Bit(fqterm_prefix.c_str());
+ }
+
+ if (res[res.size() - 1] != '/')
+ res += '/';
+
+ return res;
+}
+
+static QString getUserDataDir() {
+ char *evnDataDir = NULL;
+ if ((evnDataDir = getenv("FQTERM_DATADIR")) != NULL) {
+ std::string fqterm_data = evnDataDir;
+ if (fqterm_data[fqterm_data.size() - 1] != '/'
+#ifdef WIN32
+ || fqterm_data[fqterm_data.size() - 1] != '\\'
+#endif
+ )
+ fqterm_data += '/';
+ if (fqterm_data.length() != 0) {
+ return QString::fromLocal8Bit(fqterm_data.c_str());
+ }
+ }
+
+#ifdef WIN32
+ char buffer[MAX_PATH];
+ SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, buffer);
+ std::string dir(buffer);
+
+ if (dir[dir.size() - 1] != '\\') {
+ dir += '\\';
+ }
+ return QString::fromLocal8Bit(dir.c_str()) + "FQTerm/";
+#else
+ char *p = NULL;
+
+ std::string home;
+ if ((p = getenv("HOME")) != NULL)
+ home = p;
+ if (home.size() == 0)
+ home = "/root/";
+
+ if (home[home.size() - 1] != '/')
+ home += '/';
+
+ return QString::fromLocal8Bit(home.c_str()) + ".fqterm/";
+#endif
+}
+
+} // namespace FQTerm
diff --git a/src/common/fqterm_path.h b/src/common/fqterm_path.h
new file mode 100644
index 0000000..08611be
--- /dev/null
+++ b/src/common/fqterm_path.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * 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_PATH_H
+#define FQTERM_PATH_H
+
+class QString;
+class QStringList;
+
+class FQTermConfig;
+class FQTermParam;
+
+namespace FQTerm {
+
+enum PathCategory {RESOURCE, USER_CONFIG};
+
+const QString &getPath(PathCategory category);
+
+bool iniSettings();
+
+void checkHelpExists(FQTermConfig*);
+void loadNameList(FQTermConfig *, QStringList &);
+bool loadAddress(FQTermConfig *, int, FQTermParam &);
+void saveAddress(FQTermConfig *, int, const FQTermParam &);
+
+void clearDir(const QString &path);
+} // namespace FQTerm
+
+#endif // FQTERM_PATH_H
diff --git a/src/common/fqterm_shortcuthelper.cpp b/src/common/fqterm_shortcuthelper.cpp
new file mode 100644
index 0000000..8c18643
--- /dev/null
+++ b/src/common/fqterm_shortcuthelper.cpp
@@ -0,0 +1,298 @@
+/***************************************************************************
+ * 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_shortcuthelper.h"
+#include "fqterm_config.h"
+#include "fqterm_path.h"
+
+#include <QWidget>
+#include <QAction>
+#include <QPixmap>
+namespace FQTerm
+{
+
+FQTermShortcutHelper::FQTermShortcutHelper(FQTermConfig* config, QWidget* actionParent) :
+ config_(config),
+ actionParent_(actionParent)
+{
+ initShortcutDescriptionTable();
+}
+
+QString FQTermShortcutHelper::getShortcutText(int shortcut)
+{
+ if (!config_)
+ return "";
+ QString result = getShortcutConfig(shortcut);
+ if (result == "")
+ result = getShortcutDefaultText(shortcut);
+ else if (result == "Undefined")
+ result = "";
+ return result;
+}
+
+void FQTermShortcutHelper::initShortcutDescriptionTable()
+{
+ initShortcutDescriptionTableEntry(CONNECT, "connect", tr(""), tr("Connect Host"), "connect");
+ initShortcutDescriptionTableEntry(CASCADEWINDOWS, "cascadewindows", tr(""), tr("Cascade Windows"));
+ initShortcutDescriptionTableEntry(TILEWINDOWS, "tilewindows", tr(""), tr("Tils Windows"));
+ initShortcutDescriptionTableEntry(DISCONNECT, "disconnect", tr(""), tr("Disconnect Host"), "disconnect");
+ initShortcutDescriptionTableEntry(ADDRESSBOOK, "addressbook", tr("F2"), tr("Address Book"), "address_book");
+ initShortcutDescriptionTableEntry(QUICKLOGIN, "quicklogin", tr("F3"), tr("Quick Login"), "quick_login");
+#if defined(__APPLE__)
+ initShortcutDescriptionTableEntry(COPY, "copy", tr("Ctrl+C"), tr("Copy"), "copy");
+ initShortcutDescriptionTableEntry(PASTE, "paste", tr("Ctrl+V"), tr("Paste"), "paste");
+#else
+ initShortcutDescriptionTableEntry(COPY, "copy", tr("Ctrl+Ins"), tr("Copy"), "copy");
+ initShortcutDescriptionTableEntry(PASTE, "paste", tr("Shift+Insert"), tr("Paste"), "paste");
+#endif
+ initShortcutDescriptionTableEntry(COPYWITHCOLOR, "copywithcolor", tr(""), tr("Copy With Color"), "copy_with_color");
+ getAction(COPYWITHCOLOR)->setCheckable(true);
+ initShortcutDescriptionTableEntry(RECTANGLESELECTION, "rectangleselection", tr(""), tr("Rectangle Selection"), "rectangle_selection");
+ getAction(RECTANGLESELECTION)->setCheckable(true);
+ initShortcutDescriptionTableEntry(AUTOCOPYSELECTION, "autocopyselection", tr(""), tr("Auto Copy Selection"));
+ getAction(AUTOCOPYSELECTION)->setCheckable(true);
+ initShortcutDescriptionTableEntry(PASTEWORDWRAP, "pastewordwrap", tr(""), tr("Paste With Word Wrap"));
+ getAction(PASTEWORDWRAP)->setCheckable(true);
+ initShortcutDescriptionTableEntry(ENGLISHFONT, "englishfont", tr(""), tr("Set English Font"));
+ initShortcutDescriptionTableEntry(OTHERFONT, "nonenglishfont", tr(""), tr("Set Other Font"));
+ initShortcutDescriptionTableEntry(COLORSETTING, "colorsetting", tr(""), tr("Color Setting"), "ansi_color");
+ initShortcutDescriptionTableEntry(REFRESHSCREEN, "refreshscreen", tr(""), tr("Refresh Screen"), "refresh");
+ initShortcutDescriptionTableEntry(ANSICOLOR, "ansicolor", tr(""), tr("Toggle Ansi Color"), "toggle_ansi_color");
+ getAction(ANSICOLOR)->setCheckable(true);
+ initShortcutDescriptionTableEntry(UIFONT, "uifont", tr(""), tr("Set UI Font"));
+ initShortcutDescriptionTableEntry(FULLSCREEN, "fullscreen", tr("F6"), tr("Toggle Full Screen"));
+ getAction(FULLSCREEN)->setCheckable(true);
+ initShortcutDescriptionTableEntry(BOSSCOLOR, "bosscolor", tr("F12"), tr("Toggle Boss Color"));
+ getAction(BOSSCOLOR)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SWITCHBAR, "switchbar", tr(""), tr("Toggle Switch Bar"));
+ getAction(SWITCHBAR)->setCheckable(true);
+ initShortcutDescriptionTableEntry(CURRENTSETTING, "currentsetting", tr(""), tr("Current Session Setting"), "preferences");
+ initShortcutDescriptionTableEntry(SEARCHIT, "googleit", tr("Ctrl+Alt+G"), tr("Google selected words"));
+ initShortcutDescriptionTableEntry(WEIBOSHARE, "shareit", tr("Alt+`"), tr("Share selected text and highlighted URL to weibo"));
+ initShortcutDescriptionTableEntry(EXTERNALEDITOR, "externaleditor", tr("Ctrl+Alt+E"), tr("Invoke external editor"));
+ initShortcutDescriptionTableEntry(FASTPOST, "fastpost", tr("Ctrl+Alt+F"), tr("Fast post from clipboard"));
+ initShortcutDescriptionTableEntry(DEFAULTSETTING, "defaultsetting", tr(""), tr("Default Setting"));
+ initShortcutDescriptionTableEntry(PREFERENCE, "preference", tr(""), tr("Preference"), "preferences");
+ initShortcutDescriptionTableEntry(EDITSCHEMA, "schema", tr(""), tr("Edit Schema"));
+ initShortcutDescriptionTableEntry(SHORTCUTSETTING, "shortcut", tr(""), tr("Shorcut Setting"));
+ initShortcutDescriptionTableEntry(COPYARTICLE, "copyarticle", tr("F9"), tr("Copy Article"), "get_article_fulltext");
+ initShortcutDescriptionTableEntry(ANTIIDLE, "antiidle", tr(""), tr("Toggle Anti Idle"), "anti_idle");
+ getAction(ANTIIDLE)->setCheckable(true);
+ initShortcutDescriptionTableEntry(AUTOREPLY, "autoreply", tr(""), tr("Toggle Auto Reply"), "auto_reply");
+ getAction(AUTOREPLY)->setCheckable(true);
+ initShortcutDescriptionTableEntry(VIEWMESSAGE, "viewmessage", tr("F10"), tr("View Messages"), "view_messages");
+ initShortcutDescriptionTableEntry(IPLOOKUP, "iplookup", tr(""), tr("IP Lookup"));
+ initShortcutDescriptionTableEntry(BEEP, "beep", tr(""), tr("Toggle Beep"), "beep");
+ getAction(BEEP)->setCheckable(true);
+ initShortcutDescriptionTableEntry(MOUSESUPPORT, "mousesupport", tr(""), tr("Toggle Mouse Support"), "mouse");
+ getAction(MOUSESUPPORT)->setCheckable(true);
+ initShortcutDescriptionTableEntry(IMAGEVIEWER, "imageviewer", tr(""), tr("Image Viewer"), "image_viewer");
+ initShortcutDescriptionTableEntry(RUNSCRIPT, "runscript", tr("F7"), tr("Run Script"));
+ initShortcutDescriptionTableEntry(STOPSCRIPT, "stop", tr("F8"), tr("Stop Script"));
+#ifdef HAVE_PYTHON
+ initShortcutDescriptionTableEntry(RUNPYTHONSCRIPT, "runpythonscript", tr("Ctrl+F1"), tr("Run Python Script"));
+#endif //HAVE_PYTHON
+ initShortcutDescriptionTableEntry(ABOUT, "about", tr("Shift+F1"), tr("About"));
+ initShortcutDescriptionTableEntry(HOMEPAGE, "homepage", tr(""), tr("Homepage"));
+ initShortcutDescriptionTableEntry(EXIT, "exit", tr(""), tr("Exit FQTerm"));
+ initShortcutDescriptionTableEntry(COLORCTL_NO, "colorctlno", tr(""), tr("Set Color Ctrl to None"));
+ getAction(COLORCTL_NO)->setCheckable(true);
+ initShortcutDescriptionTableEntry(COLORCTL_SMTH, "colorctlsmth", tr(""), tr("Set Color Ctrl to **["));
+ getAction(COLORCTL_SMTH)->setCheckable(true);
+ initShortcutDescriptionTableEntry(COLORCTL_PTT, "colorctlptt", tr(""), tr("Set Color Ctrl to ^u["));
+ getAction(COLORCTL_PTT)->setCheckable(true);
+ initShortcutDescriptionTableEntry(COLORCTL_OLD_CUSTOM, "colorctloldcustom", tr(""), tr("Set Color Ctrl to old custom"));
+ getAction(COLORCTL_OLD_CUSTOM)->setCheckable(true);
+ initShortcutDescriptionTableEntry(COLORCTL_CUSTOM, "colorctlcustom", tr(""), tr("Set Color Ctrl to custom"));
+ getAction(COLORCTL_CUSTOM)->setCheckable(false);
+ initShortcutDescriptionTableEntry(AUTORECONNECT, "autoreconnect", tr(""), tr("Toggle Auto Reconnect"), "auto_reconnect");
+ getAction(AUTORECONNECT)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SCROLLBAR_LEFT, "scrollbarleft", tr(""), tr("Set Scrollbar to Left"));
+ getAction(SCROLLBAR_LEFT)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SCROLLBAR_RIGHT, "scrollbarright", tr(""), tr("Set Scrollbar to Right"));
+ getAction(SCROLLBAR_RIGHT)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SCROLLBAR_HIDDEN, "scrollbarhidden", tr(""), tr("Set Scrollbar Hidden"));
+ getAction(SCROLLBAR_HIDDEN)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SEARCH_GOOGLE, "searchgoogle", tr(""), tr("Use Google"));
+ getAction(SEARCH_GOOGLE)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SEARCH_BAIDU, "searchbaidu", tr(""), tr("Use Baidu"));
+ getAction(SEARCH_BAIDU)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SEARCH_BING, "searchbing", tr(""), tr("Use Bing"));
+ getAction(SEARCH_BING)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SEARCH_YAHOO, "searchyahoo", tr(""), tr("Use Yahoo!"));
+ getAction(SEARCH_YAHOO)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SEARCH_CUSTOM, "searchcustom", tr(""), tr("Use Customized SE"));
+ getAction(SEARCH_CUSTOM)->setCheckable(true);
+ initShortcutDescriptionTableEntry(LANGUAGE_ENGLISH, "languageenglish", tr(""), tr("Choose UI Language: English"));
+ getAction(LANGUAGE_ENGLISH)->setCheckable(true);
+ initShortcutDescriptionTableEntry(SAVESETTING, "savesetting", tr(""), tr("Save Current Session Setting"), "save_setting");
+
+#if defined(__APPLE__)
+ QString opt(tr("Ctrl"));
+#else
+ QString opt(tr("Alt"));
+#endif
+
+ initShortcutDescriptionTableEntry(NEXTWINDOW, "nextwindow", opt + tr("+Right"), tr("Next Window"));
+ initShortcutDescriptionTableEntry(PREVWINDOW, "prevwindow", opt + tr("+Left"), tr("Prev Window"));
+
+ initShortcutDescriptionTableEntry(GLOBAL_SHOW_FQTERM, "showfqterm", tr("Ctrl+Alt+Q"), tr("Show FQTerm"));
+ //index, key, default shortcut, descritption
+
+ retranslateActions();
+}
+
+void FQTermShortcutHelper::retranslateAction(int shortcut, const QString& text)
+{
+ if (getAction(shortcut))
+ getAction(shortcut)->setText(text);
+}
+
+void FQTermShortcutHelper::retranslateActions() {
+ retranslateAction(CONNECT, tr("&Connect"));
+ retranslateAction(DISCONNECT, tr("&Disconnect"));
+ retranslateAction(ADDRESSBOOK, tr("&Address book"));
+ retranslateAction(QUICKLOGIN, tr("&Quick login"));
+ retranslateAction(COPY, tr("&Copy"));
+ retranslateAction(PASTE, tr("&Paste"));
+ retranslateAction(COPYWITHCOLOR, tr("C&opy with color"));
+ retranslateAction(RECTANGLESELECTION, tr("&Rectangle select"));
+ retranslateAction(AUTOCOPYSELECTION, tr("Auto copy &select"));
+ retranslateAction(PASTEWORDWRAP, tr("P&aste with wordwrap"));
+ retranslateAction(ENGLISHFONT, tr("&English Font"));
+ retranslateAction(OTHERFONT, tr("O&ther Font"));
+ retranslateAction(COLORSETTING, tr("&Color Setting"));
+ retranslateAction(ANSICOLOR, tr("&Use ANSI Color"));
+ retranslateAction(REFRESHSCREEN, tr("&Refresh"));
+ retranslateAction(UIFONT, tr("U&I font"));
+ retranslateAction(FULLSCREEN, tr("Fullscree&n"));
+ retranslateAction(BOSSCOLOR, tr("B&oss Color"));
+ retranslateAction(SWITCHBAR, tr("S&witch Bar"));
+ retranslateAction(SEARCHIT, tr("&Search It"));
+ retranslateAction(WEIBOSHARE, tr("Sha&re It"));
+ retranslateAction(EXTERNALEDITOR, tr("E&xternal Editor"));
+ retranslateAction(FASTPOST, tr("&Fast Post"));
+ retranslateAction(CURRENTSETTING, tr("&Setting for current session"));
+ retranslateAction(DEFAULTSETTING, tr("&Default setting"));
+ retranslateAction(PREFERENCE, tr("&Preferences..."));
+ retranslateAction(SHORTCUTSETTING, tr("Short&cut Setting"));
+ retranslateAction(EDITSCHEMA, tr("&Edit Schema"));
+ retranslateAction(COPYARTICLE, tr("&Copy article"));
+ retranslateAction(ANTIIDLE, tr("Anti &idle"));
+ retranslateAction(AUTOREPLY, tr("Auto &reply"));
+ retranslateAction(VIEWMESSAGE, tr("&View messages"));
+ retranslateAction(IPLOOKUP, tr("I&P Lookup"));
+ retranslateAction(BEEP, tr("&Beep"));
+ retranslateAction(MOUSESUPPORT, tr("&Mouse support"));
+ retranslateAction(IMAGEVIEWER, tr("Ima&ge viewer"));
+ retranslateAction(RUNSCRIPT, tr("&Run..."));
+ retranslateAction(STOPSCRIPT, tr("&Stop"));
+ retranslateAction(RUNPYTHONSCRIPT, tr("Run &Python..."));
+ retranslateAction(ABOUT, tr("About &FQTerm"));
+ retranslateAction(HOMEPAGE, tr("FQTerm's &Homepage"));
+ retranslateAction(CASCADEWINDOWS, tr("&Cascade"));
+ retranslateAction(TILEWINDOWS, tr("&Tile"));
+ retranslateAction(EXIT, tr("&Exit"));
+ retranslateAction(COLORCTL_NO, tr("&None"));
+ retranslateAction(COLORCTL_SMTH, tr("&ESC ESC ["));
+ retranslateAction(COLORCTL_PTT, tr("Ctrl+&U["));
+ retranslateAction(COLORCTL_CUSTOM, tr("&Custom..."));
+ retranslateAction(AUTORECONNECT, tr("Reconnect When Disconnected By Host"));
+ retranslateAction(NEXTWINDOW, tr("Next Window"));
+ retranslateAction(PREVWINDOW, tr("Prev Window"));
+ retranslateAction(LANGUAGE_ENGLISH, tr("&English"));
+ retranslateAction(SCROLLBAR_HIDDEN, tr("&Hide"));
+ retranslateAction(SCROLLBAR_RIGHT, tr("&Right"));
+ retranslateAction(SCROLLBAR_LEFT, tr("&Left"));
+ retranslateAction(SEARCH_GOOGLE, tr("&Google"));
+ retranslateAction(SEARCH_BAIDU, tr("&Baidu"));
+ retranslateAction(SEARCH_BING, tr("&Bing"));
+ retranslateAction(SEARCH_YAHOO, tr("&Yahoo!"));
+ retranslateAction(SEARCH_CUSTOM, tr("&Custom"));
+ retranslateAction(SAVESETTING, tr("Save Settin&g"));
+}
+
+
+void FQTermShortcutHelper::resetAllShortcutText()
+{
+ for (int i = FQTERM_APPLICATION_SHORTCUT_START + 1; i < FQTERM_APPLICATION_SHORTCUT_END; ++i)
+ {
+ resetShortcutText(i);
+ }
+}
+
+void FQTermShortcutHelper::resetShortcutText(int shortcut)
+{
+ if (!config_)
+ return;
+ setShortcutText(shortcut, getShortcutDefaultText(shortcut));
+}
+
+void FQTermShortcutHelper::setShortcutText(int shortcut, const QString& text)
+{
+ if (!config_)
+ return;
+ QString val = text.trimmed();
+ if (val == "")
+ val = "Undefined";
+ setShortcutConfig(shortcut, val);
+ if (getAction(shortcut))
+ getAction(shortcut)->setShortcut(val);
+}
+
+FQTermShortcutHelper::~FQTermShortcutHelper()
+{
+}
+
+QString FQTermShortcutHelper::getShortcutConfig(int shortcut)
+{
+ return config_->getItemValue(getShortcutSection(), getShortcutKey(shortcut));
+}
+
+void FQTermShortcutHelper::setShortcutConfig(int shortcut, const QString& text)
+{
+ config_->setItemValue(getShortcutSection(), getShortcutKey(shortcut), text);
+}
+
+void FQTermShortcutHelper::initShortcutDescriptionTableEntry(int index, const QString& key, const QString& defaultshortcuttext, const QString& description, const QString& actionSkin) {
+ shortcutDescriptionTable_[index] = ShortcutDescriptionEntry(key, defaultshortcuttext, description);
+ shortcutDescriptionTable_[index].action_ = new QAction(actionParent_);
+ if (actionParent_) {
+ actionParent_->addAction(shortcutDescriptionTable_[index].action_);
+ }
+ shortcutDescriptionTable_[index].action_->setShortcut(getShortcutText(index));
+ if (actionSkin != QString::null)
+ shortcutDescriptionTable_[index].action_->setIcon(QPixmap(getPath(RESOURCE) + "pic/" + actionSkin + ".png"));
+}
+
+
+FQTermShortcutHelper::ShortcutDescriptionEntry::ShortcutDescriptionEntry(const QString& key /*= QString("")*/,
+ const QString& defaultshortcuttext /*= QString("")*/,
+ const QString& description /*= QString("")*/) :
+ key_(key),
+ defaultshortcuttext_(defaultshortcuttext),
+ description_(description),
+ action_(NULL) {}
+
+FQTermShortcutHelper::ShortcutDescriptionEntry::~ShortcutDescriptionEntry() {
+ delete action_;
+}
+}//namespace FQTerm
+
+#include "fqterm_shortcuthelper.moc" \ No newline at end of file
diff --git a/src/common/fqterm_shortcuthelper.h b/src/common/fqterm_shortcuthelper.h
new file mode 100644
index 0000000..7e77df7
--- /dev/null
+++ b/src/common/fqterm_shortcuthelper.h
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * 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_SHORTCUTHELPER__
+#define __FQTERM_SHORTCUTHELPER__
+
+#include "fqterm.h"
+#include <QObject>
+#include <QString>
+#include <QMap>
+
+class QWidget;
+class QAction;
+namespace FQTerm
+{
+class FQTermConfig;
+
+
+#define FQTERM_ADDACTION(WIDGET, NAME, RECEIVER, FUNCTION) \
+ do{ \
+ QAction *action = getAction((FQTermShortcutHelper::NAME));\
+ QObject::disconnect(action, SIGNAL(triggered()), (RECEIVER), SLOT(FUNCTION())); \
+ FQ_VERIFY(connect(action, SIGNAL(triggered()), (RECEIVER), SLOT(FUNCTION()))); \
+ (WIDGET)->addAction(action);\
+ } while(0)
+
+
+
+class FQTermShortcutHelper : public QObject
+{
+ Q_OBJECT;
+public:
+ enum FQTERM_SHORTCUT
+ {
+ FQTERM_APPLICATION_SHORTCUT_START = 0,
+ CONNECT,
+ DISCONNECT,
+ ADDRESSBOOK, //F2
+ QUICKLOGIN, //F3
+ COPY, //Ctrl+Ins under lin & win, Ctrl+C under mac
+ PASTE, //Shift+Insert under lin & win, Ctrl+V under mac
+ COPYWITHCOLOR,
+ RECTANGLESELECTION,
+ AUTOCOPYSELECTION,
+ PASTEWORDWRAP,
+ ENGLISHFONT,
+ OTHERFONT,
+ COLORSETTING,
+ ANSICOLOR,
+ REFRESHSCREEN, //F5
+ UIFONT,
+ FULLSCREEN, //F6
+ BOSSCOLOR, //F12
+ SWITCHBAR,
+ SEARCHIT, //Ctrl+Alt+G
+ WEIBOSHARE,
+ EXTERNALEDITOR, //Ctrl+Alt+E
+ FASTPOST, //Ctrl+Alt+F
+ CURRENTSETTING,
+ DEFAULTSETTING,
+ SAVESETTING,
+ PREFERENCE,
+ SHORTCUTSETTING,
+ EDITSCHEMA,
+ COPYARTICLE, //F9
+ ANTIIDLE,
+ AUTOREPLY,
+ VIEWMESSAGE, //F10
+ IPLOOKUP,
+ BEEP,
+ MOUSESUPPORT,
+ IMAGEVIEWER,
+ RUNSCRIPT, //F7
+ STOPSCRIPT, //F8
+ RUNPYTHONSCRIPT, //Ctrl+F1
+ ABOUT, //F1
+ HOMEPAGE,
+ CASCADEWINDOWS,
+ TILEWINDOWS,
+ EXIT,
+ COLORCTL_NO,
+ COLORCTL_SMTH,
+ COLORCTL_PTT,
+ COLORCTL_OLD_CUSTOM,
+ COLORCTL_CUSTOM,
+ AUTORECONNECT,
+ SCROLLBAR_LEFT,
+ SCROLLBAR_RIGHT,
+ SCROLLBAR_HIDDEN,
+ SEARCH_GOOGLE,
+ SEARCH_BAIDU,
+ SEARCH_BING,
+ SEARCH_YAHOO,
+ SEARCH_CUSTOM,
+ LANGUAGE_ENGLISH,
+ NEXTWINDOW,
+ PREVWINDOW,
+ GLOBAL_SHOW_FQTERM,
+ FQTERM_APPLICATION_SHORTCUT_END,
+ };
+
+
+public:
+ FQTermShortcutHelper(FQTermConfig* config, QWidget* actionParent);
+ ~FQTermShortcutHelper();
+
+private:
+ struct ShortcutDescriptionEntry
+ {
+ ShortcutDescriptionEntry(const QString& key = QString(""), const QString& defaultshortcuttext = QString(""), const QString& description = QString(""));
+ ~ShortcutDescriptionEntry();
+ QString key_;
+ QString defaultshortcuttext_;
+ QString description_;
+ QAction* action_;
+ };
+ void initShortcutDescriptionTable();
+ FQTermConfig* config_;
+ QWidget* actionParent_;
+ QMap<int, ShortcutDescriptionEntry> shortcutDescriptionTable_;
+ void initShortcutDescriptionTableEntry(int index, const QString& key, const QString& defaultshortcuttext, const QString& description, const QString& actionSkin = QString::null);
+
+public:
+
+ QString getShortcutText(int shortcut) ;
+ QString getShortcutDescription(int shortcut) {
+ return shortcutDescriptionTable_[shortcut].description_;
+ }
+ QString getShortcutDefaultText(int shortcut) {
+ return shortcutDescriptionTable_[shortcut].defaultshortcuttext_;
+ }
+ void setShortcutText(int shortcut, const QString& text);
+ void resetShortcutText(int shortcut);
+ void resetAllShortcutText();
+
+ QAction* getAction(int shortcut) {
+ return shortcutDescriptionTable_[shortcut].action_;
+ }
+ void retranslateActions();
+private:
+ //These functions are used to save shortcut
+ QString getShortcutSection() {
+ return QString("shortcutsettings");
+ }
+ QString getShortcutKey(int shortcut) {
+ return shortcutDescriptionTable_[shortcut].key_;
+ }
+
+ QString getShortcutConfig(int shortcut);
+ void setShortcutConfig(int shortcut, const QString& text);
+ void retranslateAction(int shortcut, const QString& text);
+};
+
+
+}//namespace FQTerm
+
+
+#endif
diff --git a/src/common/fqterm_sound.cpp b/src/common/fqterm_sound.cpp
new file mode 100644
index 0000000..96bcc83
--- /dev/null
+++ b/src/common/fqterm_sound.cpp
@@ -0,0 +1,733 @@
+/***************************************************************************
+ * 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 <QSound>
+#include <QFile>
+#include <QMessageBox>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*******************************************************/
+/********** OSS code is from OpenSound System **********/
+/*******************************************************/
+#ifdef AUDIO_OSS
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#if defined(_OS_FREEBSD_) || defined(_OS_LINUX_)
+#include <sys/soundcard.h>
+#define FQ_AUDIO_DEV "/dev/dsp"
+#else
+#include <machine/soundcard.h>
+#define FQ_AUDIO_DEV "/dev/audio"
+#endif
+
+#define WAVE_FORMAT_PCM 0x0001
+#define WAVE_FORMAT_ADPCM 0x0002
+#define WAVE_FORMAT_ALAW 0x0006
+#define WAVE_FORMAT_MULAW 0x0007
+#define WAVE_FORMAT_IMA_ADPCM 0x0011
+
+#ifndef AFMT_S32_LE
+#define AFMT_S32_LE 0x00001000 /* Little endian signed 32-bit */
+#endif
+
+typedef struct {
+ int coeff1, coeff2;
+} adpcm_coeff;
+
+#endif /* AUDIO_OSS */
+
+/* 2008.07.06, ecore.cn@gmail.com, alsa sound for FQTerm ... */
+#ifdef AUDIO_ALSA
+#include <alsa/asoundlib.h>
+#include <stdint.h>
+typedef struct tag_FQ_WAVE_FILE_HEADER {
+ uint32_t rid; /* RIFF ID */
+ uint32_t rsz; /* RIFF SIZE */
+ uint32_t wid; /* WAVE ID */
+}
+FQWFH;
+
+typedef struct tag_FQ_WAVE_FORMAT_HEADER {
+ uint32_t fid; /* FORMAT ID */
+ uint32_t fsz; /* FORMAT SIZE */
+ uint16_t aid; /* AUDIO ID */
+ uint16_t ach; /* AUDIO CHANNELS */
+ uint32_t asr; /* AUDIO SAMPLE RATE */
+ uint32_t abr; /* AUDIO BYTE RATE */
+ uint16_t aba; /* AUDIO BLOCK ALIGNMENT */
+ uint16_t abps; /* AUDIO BITS PER SAMPLE */
+}
+FQWMH;
+
+typedef struct tag_FQ_WAVE_DATA_HEADER {
+ uint32_t did; /* DATA ID */
+ uint32_t dsz; /* DATA SIZE */
+}
+FQWDH;
+
+#endif /* AUDIO_ALSA */
+
+#include "common.h"
+#include "fqterm_sound.h"
+
+namespace FQTerm {
+
+FQTermSound::FQTermSound(const QString &filename, QObject *parent,
+ const char *name)
+ : QThread(parent), soundFile_(filename) {
+ connect(this, SIGNAL(finished()), SLOT(deleteInstance()));
+ connect(this, SIGNAL(terminated()), SLOT(deleteInstance()));
+}
+
+FQTermSound::~FQTermSound() {
+}
+
+void FQTermSound::deleteInstance() {
+ FQ_TRACE("sound", 3) << "sound instance [" << (void*)this << "] is to be deleted!";
+ delete this;
+}
+
+void FQTermSound::run() {
+ if (QFile::exists(soundFile_)) {
+#if !defined(AUDIO_OSS) && !defined(AUDIO_ALSA)
+ QSound::play(soundFile_);
+#else
+ this->play();
+#endif
+ }
+}
+
+void FQTermExternalSound::setPlayer(const QString &playername) {
+ playerName_ = playername;
+}
+
+void FQTermExternalSound::play() {
+ if (QFile::exists(soundFile_)) {
+ runProgram(playerName_, soundFile_, false);
+ }
+}
+
+/*******************************************************/
+/********** OSS code is from OpenSound System **********/
+/*******************************************************/
+#ifdef AUDIO_OSS
+static int le_int (unsigned char *p, int l) {
+
+ int i, val;
+ val = 0;
+
+ for (i = l - 1; i >= 0; i--) {
+ val = (val << 8) | p[i];
+ }
+
+ return val;
+}
+
+static int setupDevice(int audiofd, int channels, int bits, int speed) {
+
+ int tmp;
+
+ tmp = bits;
+ if (ioctl(audiofd, SNDCTL_DSP_SETFMT, &tmp) == -1) {
+ return 0;
+ }
+
+ if (tmp != bits) {
+ return 0;
+ }
+
+ tmp = channels;
+ if (ioctl(audiofd, SNDCTL_DSP_CHANNELS, &tmp) == -1) {
+ return 0;
+ }
+
+ if (tmp != channels) {
+ return 0;
+ }
+
+ tmp = speed;
+ if (ioctl(audiofd, SNDCTL_DSP_SPEED, &tmp) == -1) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static void dumpData(int audiofd, int soundfd, int filesize) {
+
+ int bsize, l;
+ unsigned char buf[1024];
+ bsize = sizeof(buf);
+
+ while (filesize) {
+
+ l = bsize;
+
+ if (l > filesize) {
+ l = filesize;
+ }
+
+ if ((l = read(soundfd, buf, l)) <= 0) {
+ return;
+ }
+
+ if (write(audiofd, buf, l) == -1) {
+ return;
+ }
+
+ filesize -= l;
+ }
+}
+
+static void dumpData24 (int audiofd, int soundfd, int filesize) {
+
+ int bsize, i, l;
+ unsigned char buf[1024];
+ int outbuf[1024], outlen=0;
+ int sample_s32;
+ bsize = sizeof(buf);
+
+ filesize -= filesize % 3;
+
+ while(filesize >= 3) {
+
+ l = bsize - bsize % 3;
+ if (l > filesize) {
+ l = filesize;
+ }
+
+ if(l < 3) {
+ break;
+ }
+
+ if ((l = read(soundfd, buf, l)) <= 0) {
+ return;
+ }
+
+ outlen=0;
+
+ for(i=0; i<l; i+= 3) {
+
+ unsigned int *u32 = (unsigned int *)&sample_s32; /* Alias */
+
+ /* Read the litle endian input samples */
+ *u32 = (buf[i] << 8) | (buf[i+1] << 16) | (buf[i+2]<<24);
+ outbuf[outlen++]=sample_s32;
+
+ }
+
+ if (write(audiofd, outbuf, outlen*sizeof(int)) == -1) {
+ return;
+ }
+
+ filesize -= l;
+ }
+}
+
+static void playAdpcmWave(int audiofd, int soundfd, unsigned char *hdr, int l) {
+
+ int i, n, dataleft, x;
+
+ adpcm_coeff coeff[32];
+ static int AdaptionTable[] = { 230, 230, 230, 230, 307, 409, 512, 614,
+ 768, 614, 512, 409, 307, 230, 230, 230
+ };
+
+ unsigned char buf[4096];
+
+ int channels = 1;
+ int bits = 8;
+ int speed = 11025;
+ int p = 12, max, outp;
+ int nBlockAlign, wSamplesPerBlock, wNumCoeff;
+ int fmt = -1;
+ int nib;
+
+ unsigned char outbuf[64 * 1024];
+
+ while (p < l - 16 && memcmp(&hdr[p], "data", 4) != 0) {
+
+ n = le_int(&hdr[p + 4], 4);
+ if (memcmp(&hdr[p], "fmt ", 4) == 0) {
+
+ fmt = le_int(&hdr[p + 8], 2);
+ channels = le_int(&hdr[p + 10], 2);
+ speed = le_int(&hdr[p + 12], 4);
+ nBlockAlign = le_int(&hdr[p + 20], 2);
+ bits = AFMT_S16_LE;
+ wSamplesPerBlock = le_int(&hdr[p + 26], 2);
+ wNumCoeff = le_int(&hdr[p + 28], 2);
+
+ x = p + 30;
+
+ for (i = 0; i < wNumCoeff; i++) {
+
+ coeff[i].coeff1 = (short)le_int(&hdr[x], 2);
+ x += 2;
+ coeff[i].coeff2 = (short)le_int(&hdr[x], 2);
+ x += 2;
+ }
+ }
+
+ p += n + 8;
+ }
+
+ if (p < l - 16 && memcmp(&hdr[p], "data", 4) == 0) {
+
+ dataleft = n = le_int(&hdr[p + 4], 4);
+ p += 8;
+
+ if (lseek(soundfd, p, SEEK_SET) == -1) {
+ return;
+ }
+
+ if (fmt != WAVE_FORMAT_ADPCM) {
+ return;
+ }
+
+ if (!setupDevice(audiofd, channels, bits, speed)) {
+ return;
+ }
+
+#define OUT_SAMPLE(s) { \
+ if (s>32767)s=32767;else if(s<-32768)s=-32768; \
+ outbuf[outp++] = (unsigned char)(s & 0xff); \
+ outbuf[outp++] = (unsigned char)((s>>8) & 0xff); \
+ n+=2; \
+ if (outp>=max){write(audiofd, outbuf, outp);outp=0;}\
+ }
+
+#define GETNIBBLE \
+ ((nib==0) ? \
+ (buf[x + nib++] >> 4) & 0x0f : \
+ buf[x++ + --nib] & 0x0f \
+ )
+
+ max = 1024;
+ outp = 0;
+
+ while (dataleft > nBlockAlign &&
+ read(soundfd, buf, nBlockAlign) == nBlockAlign) {
+
+ int predictor[2], delta[2], samp1[2], samp2[2];
+ int x = 0;
+ dataleft -= nBlockAlign;
+
+ nib = 0;
+ n = 0;
+
+ for (i = 0; i < channels; i++) {
+ predictor[i] = buf[x];
+ x++;
+ }
+
+ for (i = 0; i < channels; i++) {
+ delta[i] = (short)le_int(&buf[x], 2);
+ x += 2;
+ }
+
+ for (i = 0; i < channels; i++) {
+ samp1[i] = (short)le_int(&buf[x], 2);
+ x += 2;
+ OUT_SAMPLE(samp1[i]);
+ }
+
+ for (i = 0; i < channels; i++) {
+ samp2[i] = (short)le_int(&buf[x], 2);
+ x += 2;
+ OUT_SAMPLE(samp2[i]);
+ }
+
+ while (n < (wSamplesPerBlock * 2 * channels)) {
+
+ for (i = 0; i < channels; i++) {
+
+ int pred, new_pred, error_delta, i_delta;
+
+ pred = ((samp1[i] * coeff[predictor[i]].coeff1)
+ + (samp2[i] * coeff[predictor[i]].coeff2)) / 256;
+ i_delta = error_delta = GETNIBBLE;
+
+ if (i_delta & 0x08) {
+ i_delta -= 0x10; /* Convert to signed */
+ }
+
+ new_pred = pred + (delta[i] * i_delta);
+ OUT_SAMPLE(new_pred);
+
+ delta[i] = delta[i] * AdaptionTable[error_delta] / 256;
+ if (delta[i] < 16) {
+ delta[i] = 16;
+ }
+
+ samp2[i] = samp1[i];
+ samp1[i] = new_pred;
+ }
+ }
+ }
+ }
+
+ if (outp > 0) {
+ write (audiofd, outbuf, outp /*(outp+3) & ~3 */ );
+ }
+}
+
+static void playWave(int audiofd, int soundfd, unsigned char *hdr, int l) {
+
+ int filelen;
+ int n;
+ int channels = 1;
+ int bits = 8;
+ int file_bits = 8;
+ int speed = 11025;
+ int p = 12;
+ int fmt = -1;
+
+ filelen = le_int(&hdr[4], 4);
+
+ while(p < l - 16 && memcmp(&hdr[p], "data", 4) != 0) {
+
+ n = le_int(&hdr[p + 4], 4);
+
+ if (memcmp(&hdr[p], "fmt ", 4) == 0) {
+
+ fmt = le_int(&hdr[p + 8], 2);
+ channels = le_int(&hdr[p + 10], 2);
+ speed = le_int(&hdr[p + 12], 4);
+ bits = le_int(&hdr[p + 22], 2);
+
+ if (fmt == WAVE_FORMAT_ADPCM) {
+ playAdpcmWave(audiofd, soundfd, hdr, l);
+ return;
+ }
+
+ p += n + 8;
+ } else {
+ break;
+ }
+ }
+
+ if (p < l - 16 && memcmp(&hdr[p], "data", 4) == 0) {
+
+ n = le_int(&hdr[p + 4], 4);
+ p += 8;
+
+ if (lseek(soundfd, p, SEEK_SET) == -1) {
+ return;
+ }
+
+ if (fmt != WAVE_FORMAT_PCM) {
+ switch (fmt) {
+ case WAVE_FORMAT_ALAW:
+ bits = AFMT_A_LAW;
+ break;
+ case WAVE_FORMAT_MULAW:
+ bits = AFMT_MU_LAW;
+ break;
+ case WAVE_FORMAT_IMA_ADPCM:
+ bits = AFMT_IMA_ADPCM;
+ break;
+ default:
+ return;
+ }
+ }
+
+ file_bits = bits;
+
+ if (bits == 32) {
+ bits = AFMT_S32_LE;
+ } else if (bits == 24) {
+ bits = AFMT_S32_LE;
+ }
+
+ if (!setupDevice(audiofd, channels, bits, speed)) {
+ return;
+ }
+
+ if (file_bits != 24) {
+ dumpData (audiofd, soundfd, n);
+ } else {
+ dumpData24 (audiofd, soundfd, n);
+ }
+ }
+}
+#endif /* AUDIO_OSS */
+
+void FQTermSystemSound::play() {
+
+#ifdef AUDIO_OSS
+ int audio_fd = -1;
+ if ((audio_fd = open(FQ_AUDIO_DEV, O_WRONLY, 0)) == -1) {
+ FQ_TRACE("sound", 0) << "Error opening device: " << FQ_AUDIO_DEV;
+ return;
+ }
+
+ int sound_fd = -1;
+ QFile soundFile(soundFile_);
+
+ if (soundFile.open(QFile::ReadOnly)) {
+ sound_fd = soundFile.handle();
+ } else {
+ FQ_TRACE("sound", 0) << "Error opening file: " << soundFile_;
+ close(audio_fd);
+ return;
+ }
+
+ int l;
+ unsigned char sound_buf[1024];
+
+ if ((l = read(sound_fd, sound_buf, sizeof(sound_buf))) == -1) {
+ FQ_TRACE("sound", 0) << "Error reading file into buffer." << soundFile_;
+ soundFile.close();
+ close(audio_fd);
+ return;
+ }
+
+ if (l == 0) {
+ FQ_TRACE("sound", 0) << "Empty file: " << soundFile_;
+ soundFile.close();
+ close(audio_fd);
+ return;
+ }
+
+ lseek(sound_fd, 0, SEEK_SET); /* Start from the beginning */
+
+ if (l > 16 &&
+ memcmp(&sound_buf[0], "RIFF", 4) == 0 && memcmp(&sound_buf[8], "WAVE", 4) == 0) {
+
+ playWave(audio_fd, sound_fd, sound_buf, l);
+ } else {
+ FQ_TRACE("sound", 0) << "We play WAVE files only: " << soundFile_;
+ }
+
+ soundFile.close();
+ close(audio_fd);
+
+#undef OUTSAMPLE
+#undef GETNIBBLE
+#endif /* AUDIO_OSS */
+
+/* 2008.07.06, ecore.cn@gmail.com, alsa sound for FQTerm ... */
+#ifdef AUDIO_ALSA
+ FILE *fp;
+ FQWFH wfh;
+ FQWMH wmh;
+ FQWDH wdh;
+ int endian, sz, len, count, ret;
+ unsigned int val;
+ snd_pcm_t *handle;
+ snd_pcm_hw_params_t *hwparams;
+ snd_pcm_sw_params_t *swparams;
+ snd_pcm_format_t format;
+ snd_pcm_uframes_t csz, vsz;
+ void *data;
+
+#define WAVE_UINT16(_x) (endian? ( \
+ (((_x) & 0x00FF) << 8) | \
+ (((_x) & 0xFF00) >> 8)): \
+ (_x))
+
+#define WAVE_UINT32(_x) (endian? ( \
+ (((_x) & 0x000000FF) << 24) | \
+ (((_x) & 0x0000FF00) << 8) | \
+ (((_x) & 0x00FF0000) >> 8) | \
+ (((_x) & 0xFF000000) >> 24)): \
+ (_x))
+
+ do {
+ if ((fp = fopen(this->soundFile_.toLocal8Bit(), "r")) == NULL) {
+ continue;
+ }
+
+ if (fread(&wfh, sizeof(FQWFH), 1, fp) != 1) {
+ continue;
+ }
+
+ switch (wfh.rid) {
+ case 0x52494646:
+ endian = 1; /* Big-Endian */
+ break;
+ case 0x46464952:
+ endian = 0; /* Small-Endian */
+ break;
+ default:
+ continue;
+ }
+
+ if (WAVE_UINT32(wfh.wid) != 0x45564157) { /* "WAVE" */
+ continue;
+ }
+
+ if (fread(&wmh, sizeof(FQWMH), 1, fp) != 1) {
+ continue;
+ }
+
+ if (WAVE_UINT32(wmh.fid) != 0x20746d66) { /* "FMT " */
+ continue;
+ }
+
+ if (WAVE_UINT32(wmh.fsz) != 16 || WAVE_UINT16(wmh.aid) != 1) { /* PCM */
+ continue;
+ }
+
+ if (fread(&wdh, sizeof(FQWDH), 1, fp) != 1) {
+ continue;
+ }
+
+ if (WAVE_UINT32(wdh.did) != 0x61746164) { /* "DATA" */
+ continue;
+ }
+
+ if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) {
+ continue;
+ }
+
+ snd_pcm_hw_params_alloca(&hwparams);
+ snd_pcm_sw_params_alloca(&swparams);
+
+ if (snd_pcm_hw_params_any(handle, hwparams) < 0) {
+ continue;
+ }
+
+ if (snd_pcm_hw_params_set_access(handle, hwparams,
+ SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
+ continue;
+ }
+
+ switch(WAVE_UINT16(wmh.abps)) {
+ case 8:
+ format = SND_PCM_FORMAT_U8;
+ break;
+ case 16:
+ format = SND_PCM_FORMAT_S16_LE;
+ break;
+ case 24:
+ switch (WAVE_UINT16(wmh.aba) / WAVE_UINT16(wmh.ach)) {
+ case 3:
+ format = SND_PCM_FORMAT_S24_3LE;
+ break;
+ case 4:
+ format = SND_PCM_FORMAT_S24_LE;
+ break;
+ default:
+ continue;
+ }
+
+ break;
+ case 32:
+ format = SND_PCM_FORMAT_S32_LE;
+ break;
+ default:
+ continue;
+ }
+
+ if (snd_pcm_hw_params_set_format(handle, hwparams, format) < 0) {
+ continue;
+ }
+
+ if (snd_pcm_hw_params_set_channels(handle, hwparams,
+ WAVE_UINT16(wmh.ach)) < 0) {
+ continue;
+ }
+
+ val = WAVE_UINT32(wmh.asr);
+
+ if (snd_pcm_hw_params_set_rate_near(handle, hwparams, &val, NULL) < 0) {
+ continue;
+ }
+
+ if (snd_pcm_hw_params(handle, hwparams) < 0) {
+ continue;
+ }
+
+ snd_pcm_hw_params_get_period_size(hwparams, &csz, NULL);
+ snd_pcm_hw_params_get_buffer_size(hwparams, &vsz);
+
+ if (csz == vsz) {
+ continue;
+ }
+
+ snd_pcm_sw_params_current(handle, swparams);
+
+ if (snd_pcm_sw_params_set_avail_min(handle, swparams, csz) < 0) {
+ continue;
+ }
+
+ if (snd_pcm_sw_params_set_start_threshold(handle, swparams, vsz) < 0) {
+ continue;
+ }
+
+ if (snd_pcm_sw_params_set_stop_threshold(handle, swparams, vsz) < 0) {
+ continue;
+ }
+
+ if (snd_pcm_sw_params(handle, swparams) < 0) {
+ continue;
+ }
+
+ sz = csz * snd_pcm_format_physical_width(format)
+ * WAVE_UINT16(wmh.ach) / 8;
+
+ if ((data = malloc(sz)) == NULL) {
+ continue;
+ }
+
+ len = WAVE_UINT32(wdh.dsz);
+
+ while (len > 0) {
+ count = (len < sz)? len: sz;
+
+ ret = fread(data, 1, count, fp);
+
+ len -= ret;
+
+ if (ret != count) {
+ continue;
+ }
+
+ count = ret * csz / sz;
+
+ ret = snd_pcm_writei(handle, data, count);
+
+ if (ret == -EAGAIN || (ret >= 0 && ret < count)) {
+ snd_pcm_wait(handle, 200);
+ }
+ }
+
+ free(data);
+
+ snd_pcm_drain(handle);
+ snd_pcm_close(handle);
+
+ fclose(fp);
+ }
+ while (0);
+
+#undef WAVE_UINT16
+#undef WAVE_UINT32
+#endif /* AUDIO_ALSA */
+}
+
+} // namespace FQTerm
+
+#include "fqterm_sound.moc"
diff --git a/src/common/fqterm_sound.h b/src/common/fqterm_sound.h
new file mode 100644
index 0000000..ab18645
--- /dev/null
+++ b/src/common/fqterm_sound.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * 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_SOUND_H
+#define FQTERM_SOUND_H
+
+#include <QObject>
+#include <QString>
+#include <QThread>
+
+#include "fqterm.h"
+
+namespace FQTerm {
+// By using QThread, we avoid blocking the main app.
+// FIXME: However, whichever play method we use (ext|int),
+// there are some WAVE files we can't play...
+
+class FQTermSound: public QThread {
+ Q_OBJECT;
+
+ public:
+ FQTermSound(const QString &filename, QObject *parent = 0,
+ const char *name = 0);
+
+ ~FQTermSound();
+
+ public slots:
+ void deleteInstance();
+
+ protected:
+ QString soundFile_;
+ virtual void play() = 0;
+ void run();
+};
+
+class FQTermSystemSound: public FQTermSound {
+ public:
+ FQTermSystemSound(const QString &filename, QObject *parent = 0,
+ const char *name = 0)
+ : FQTermSound(filename, parent, name) {
+ }
+
+ protected:
+ void play();
+};
+
+class FQTermExternalSound: public FQTermSound {
+ public:
+ FQTermExternalSound(const QString &playername, const QString &filename,
+ QObject *parent = 0, const char *name = 0)
+ : FQTermSound(filename, parent, name), playerName_(playername) {
+ }
+
+ protected:
+ QString playerName_;
+ void play();
+ void setPlayer(const QString &playername);
+};
+
+} // namespace FQTerm
+
+#endif // FQTERM_SOUND_H
diff --git a/src/common/fqterm_trace.cpp b/src/common/fqterm_trace.cpp
new file mode 100644
index 0000000..867b7ad
--- /dev/null
+++ b/src/common/fqterm_trace.cpp
@@ -0,0 +1,328 @@
+/***************************************************************************
+ * 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 <string>
+
+#ifdef WIN32
+#include <hash_set>
+#else
+#include <set>
+#endif
+
+#include "fqterm_trace.h"
+
+namespace FQTerm {
+
+int *getDefaultMaxTraceLevel() {
+ static int max_trace_level = 10;
+ return &max_trace_level;
+}
+
+int getMaxTraceLevel() {
+ return *getDefaultMaxTraceLevel();
+}
+
+void setMaxTraceLevel(int max_trace_level) {
+ *getDefaultMaxTraceLevel() = max_trace_level;
+ FQ_TRACE("info", 0) << "The upper bound of maximum trace level is "
+ << FQTERM_MAX_TRACE_LEVEL;
+ FQ_TRACE("info", 0) << "The maximum trace level is set to "
+ << max_trace_level;
+}
+
+#ifdef WIN32
+typedef stdext::hash_set<std::string> CategorySet;
+#else
+typedef std::set<std::string> CategorySet;
+#endif
+
+CategorySet *getAllowedCategories() {
+ static CategorySet *allowed_categories
+ = new CategorySet;
+ return allowed_categories;
+}
+
+int isAllowedCategory(const char *category, int trace_level) {
+ if (trace_level <= 0) return true;
+
+ const CategorySet &categories = *getAllowedCategories();
+ if (categories.empty()
+ || categories.find(category) != categories.end()) {
+ return true;
+ }
+ return false;
+}
+
+void addAllowedCategory(const char *category) {
+ CategorySet &categories = *getAllowedCategories();
+
+ categories.insert(category);
+
+ FQ_TRACE("info", 0) << "Allow category: " << category;
+}
+
+// Event name from event type id (updated to Qt4.3.0).
+static const char *kEventName[] = {
+ "QEvent::None", // 0
+ "QEvent::Timer", // 1
+ "QEvent::MouseButtonPress", // 2
+ "QEvent::MouseButtonRelease", // 3
+ "QEvent::MouseButtonDblClick", // 4
+ "QEvent::MouseMove", // 5
+ "QEvent::KeyPress", // 6
+ "QEvent::KeyRelease", // 7
+ "QEvent::FocusIn", // 8
+ "QEvent::FocusOut", // 9
+ "QEvent::Enter", // 10
+ "QEvent::Leave", // 11
+ "QEvent::Paint", // 12
+ "QEvent::Move", // 13
+ "QEvent::Resize", // 14
+ "None", // 15
+ "None", // 16
+ "QEvent::Show", // 17
+ "QEvent::Hide", // 18
+ "QEvent::Close", // 19
+ "None", // 20
+ "QEvent::ParentChange", // 21
+ "None", // 22
+ "None", // 23
+ "QEvent::WindowActivate", // 24
+ "QEvent::WindowDeactivate", // 25
+ "QEvent::ShowToParent", // 26
+ "QEvent::HideToParent", // 27
+ "None", // 28
+ "None", // 29
+ "None", // 30
+ "QEvent::Wheel", // 31
+ "None", // 32
+ "QEvent::WindowTitleChange", // 33
+ "QEvent::WindowIconChange", // 34
+ "QEvent::ApplicationWindowIconChange", // 35
+ "QEvent::ApplicationFontChange", // 36
+ "QEvent::ApplicationLayoutDirectionChange", // 37
+ "QEvent::ApplicationPaletteChange", // 38
+ "QEvent::PaletteChange", // 39
+ "QEvent::Clipboard", // 40
+ "None", // 41
+ "None", // 42
+ "QEvent::MetaCall", // 43
+ "None", // 44
+ "None", // 45
+ "None", // 46
+ "None", // 47
+ "None", // 48
+ "None", // 49
+ "QEvent::SockAct", // 50
+ "QEvent::ShortcutOverride", // 51
+ "QEvent::DeferredDelete", // 52
+ "None", // 53
+ "None", // 54
+ "None", // 55
+ "None", // 56
+ "None", // 57
+ "None", // 58
+ "None", // 59
+ "QEvent::DragEnter", // 60
+ "QEvent::DragMove", // 61
+ "QEvent::DragLeave", // 62
+ "QEvent::Drop", // 63
+ "None", // 64
+ "None", // 65
+ "None", // 66
+ "None", // 67
+ "QEvent::ChildAdded", // 68
+ "QEvent::ChildPolished", // 69
+ "None", // 70
+ "QEvent::ChildRemoved", // 71
+ "None", // 72
+ "None", // 73
+ "QEvent::PolishRequest", // 74
+ "QEvent::Polish", // 75
+ "QEvent::LayoutRequest", // 76
+ "QEvent::UpdateRequest", // 77
+ "QEvent::UpdateLater", // 78
+ "None", // 79
+ "None", // 80
+ "None", // 81
+ "QEvent::ContextMenu", // 82
+ "QEvent::InputMethod", // 83
+ "None", // 84
+ "None", // 85
+ "QEvent::AccessibilityPrepare", // 86
+ "QEvent::TabletMove", // 87
+ "QEvent::LocaleChange", // 88
+ "QEvent::LanguageChange", // 89
+ "QEvent::LayoutDirectionChange", // 90
+ "None", // 91
+ "QEvent::TabletPress", // 92
+ "QEvent::TabletRelease", // 93
+ "None", // 94
+ "None", // 95
+ "QEvent::IconDrag", // 96
+ "QEvent::FontChange", // 97
+ "QEvent::EnabledChange", // 98
+ "QEvent::ActivationChange", // 99
+ "QEvent::StyleChange", // 100
+ "QEvent::IconTextChange", // 101
+ "QEvent::ModifiedChange", // 102
+ "QEvent::WindowBlocked", // 103
+ "QEvent::WindowUnblocked", // 104
+ "QEvent::WindowStateChange", // 105
+ "None", // 106
+ "None", // 107
+ "None", // 108
+ "QEvent::MouseTrackingChange", // 109
+ "QEvent::ToolTip", // 110
+ "QEvent::WhatsThis", // 111
+ "QEvent::StatusTip", // 112
+ "QEvent::ActionChanged", // 113
+ "QEvent::ActionAdded", // 114
+ "QEvent::ActionRemoved", // 115
+ "QEvent::FileOpen", // 116
+ "QEvent::Shortcut", // 117
+ "QEvent::WhatsThisClicked", // 118
+ "QEvent::AccessibilityHelp", // 119
+ "QEvent::ToolBarChange", // 120
+ "QEvent::ApplicationActivate", // 121
+ "QEvent::ApplicationDeactivate", // 122
+ "QEvent::QueryWhatsThis", // 123
+ "QEvent::EnterWhatsThisMode", // 124
+ "QEvent::LeaveWhatsThisMode", // 125
+ "QEvent::ZOrderChange", // 126
+ "QEvent::HoverEnter", // 127
+ "QEvent::HoverLeave", // 128
+ "QEvent::HoverMove", // 129
+ "QEvent::AccessibilityDescription", // 130
+ "QEvent::ParentAboutToChange", // 131
+ "QEvent::WinEventAct", // 132
+ "None", // 133
+ "None", // 134
+ "None", // 135
+ "None", // 136
+ "None", // 137
+ "None", // 138
+ "None", // 139
+ "None", // 140
+ "None", // 141
+ "None", // 142
+ "None", // 143
+ "None", // 144
+ "None", // 145
+ "None", // 146
+ "None", // 147
+ "None", // 148
+ "None", // 149
+ "QEvent::EnterEditFocus", // 150
+ "QEvent::LeaveEditFocus", // 151
+ "None", // 152
+ "QEvent::MenubarUpdated", // 153
+ "None", // 154
+ "QEvent::GraphicsSceneMouseMove", // 155
+ "QEvent::GraphicsSceneMousePress", // 156
+ "QEvent::GraphicsSceneMouseRelease", // 157
+ "QEvent::GraphicsSceneMouseDoubleClick", // 158
+ "QEvent::GraphicsSceneContextMenu", // 159
+ "QEvent::GraphicsSceneHoverEnter", // 160
+ "QEvent::GraphicsSceneHoverMove", // 161
+ "QEvent::GraphicsSceneHoverLeave", // 162
+ "QEvent::GraphicsSceneHelp", // 163
+ "QEvent::GraphicsSceneDragEnter", // 164
+ "QEvent::GraphicsSceneDragMove", // 165
+ "QEvent::GraphicsSceneDragLeave", // 166
+ "QEvent::GraphicsSceneDrop", // 167
+ "QEvent::GraphicsSceneWheel", // 168
+ "QEvent::KeyboardLayoutChange", // 169
+ "QEvent::DynamicPropertyChange", // 170
+ "QEvent::TabletEnterProximity", // 171
+ "QEvent::TabletLeaveProximity", // 172
+ // "QEvent::User", // 1000
+ // "QEvent::MaxUser", // 65535
+};
+
+const char *getEventName(unsigned int type) {
+ if (type > 1000) {
+ return "User defined event";
+ }
+
+ if (type > 172) {
+ return "None";
+ }
+
+ return kEventName[type];
+}
+
+} // namespace FQTerm
+
+#ifdef WIN32
+/*
+ * Number of micro-seconds between the beginning of the Windows epoch
+ * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970).
+ *
+ * This assumes all Win32 compilers have 64-bit support.
+ */
+
+#include <Windows.h>
+
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) || defined(__WATCOMC__)
+ #define DELTA_EPOCH_IN_USEC 11644473600000000Ui64
+#else
+ #define DELTA_EPOCH_IN_USEC 11644473600000000ULL
+#endif
+
+static unsigned long long filetime_to_unix_epoch (const FILETIME *ft)
+{
+ unsigned long long res = (unsigned long long) ft->dwHighDateTime << 32;
+
+ res |= ft->dwLowDateTime;
+ res /= 10; /* from 100 nano-sec periods to usec */
+ res -= DELTA_EPOCH_IN_USEC; /* from Win epoch to Unix epoch */
+ return (res);
+}
+
+int gettimeofday (struct timeval *tv, int unused)
+{
+ FILETIME ft;
+ unsigned long long tim;
+
+ GetSystemTimeAsFileTime (&ft);
+ tim = filetime_to_unix_epoch (&ft);
+ tv->tv_sec = (long) (tim / 1000000L);
+ tv->tv_usec = (long) (tim % 1000000L);
+ return (0);
+}
+#else
+
+#include <sys/time.h>
+#include <time.h>
+
+#endif
+
+namespace FQTerm {
+
+long long getTraceTime() {
+ struct timeval t;
+ gettimeofday(&t, 0);
+ long long sec = t.tv_sec;
+ long long usec = t.tv_usec;
+ return sec * 1000 + usec/1000;
+}
+
+} // namespace FQTerm
diff --git a/src/common/fqterm_trace.h b/src/common/fqterm_trace.h
new file mode 100644
index 0000000..287a8a8
--- /dev/null
+++ b/src/common/fqterm_trace.h
@@ -0,0 +1,331 @@
+/***************************************************************************
+ * 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_TRACE_H
+#define FQTERM_TRACE_H
+
+#include <cassert>
+#ifndef WIN32
+#include <unistd.h>
+#endif // WIN32
+
+#include <QtDebug>
+#include <QFileInfo>
+
+namespace FQTerm {
+
+// define NO_FQTERM_TRACE to avoid all trace output.
+// #define NO_FQTERM_TRACE
+
+// define NO_FQTERM_TRACE_FILE_LINE_NUM to avoid file line number in trace
+// output.
+
+// define NO_FQTERM_TRACE_FUNCTION_NAME to avoid function name in trace output.
+// define integer FQTERM_MAX_TRACE_LEVEL to determine the maximize outputed
+// trace level.
+//#define NO_FQTERM_TRACE
+#if defined(NDEBUG)
+#define FQTERM_MAX_TRACE_LEVEL 1
+#endif
+
+#ifndef FQTERM_MAX_TRACE_LEVEL
+#define FQTERM_MAX_TRACE_LEVEL 20
+#endif // FQTERM_MAX_TRACE_LEVEL
+
+int getMaxTraceLevel();
+
+void setMaxTraceLevel(int max_trace_level);
+
+long long getTraceTime();
+
+int isAllowedCategory(const char *category, int trace_level);
+
+void addAllowedCategory(const char *category);
+
+static void soft_break() {
+#if defined(WIN32)
+ __asm int 03h;
+#else
+ pause();
+#endif
+}
+
+template<int trace_level>
+class FQTermTrace {
+ public:
+ FQTermTrace(const char *category, const char *file_name, int line_num, const char *func_name)
+ : category_(category),
+ is_dummy_(!isAllowedCategory(category, trace_level)),
+ trace_output_((trace_level <= FQTERM_MAX_TRACE_LEVEL
+ && trace_level <= getMaxTraceLevel())
+ ? new QDebug(qDebug().nospace())
+ : NULL),
+ dump_string_(false) {
+
+ if (is_dummy_) return;
+
+#ifdef NO_FQTERM_TRACE_FILE_LINE_NUM
+#ifdef NO_FQTERM_TRACE_FUNCTION_NAME
+ return;
+#endif // NO_FQTERM_TRACE_FUNCTION_NAME
+#endif // NO_FQTERM_TRACE_FILE_LINE_NUM
+
+ (*this) << "[" << category_ << " " << trace_level << " ";
+
+#ifndef NO_FQTERM_TRACE_FILE_LINE_NUM
+ (*this) << QFileInfo(file_name).fileName().toAscii().constData()
+ << ": " << line_num;
+#endif // NO_FQTERM_TRACE_FILE_LINE_NUM
+
+#ifndef NO_FQTERM_TRACE_FUNCTION_NAME
+#ifndef NO_FQTERM_TRACE_FILE_LINE_NUM
+ (*this) << ", ";
+#endif // NO_FQTERM_TRACE_FILE_LINE_NUM
+ (*this) << func_name;
+#endif // NO_FQTERM_TRACE_FUNCTION_NAME
+
+ (*this) << "] ";
+ }
+
+ ~FQTermTrace() {
+ if (is_dummy_) return;
+
+ if (trace_level <= FQTERM_MAX_TRACE_LEVEL && trace_level <= getMaxTraceLevel()) {
+ delete trace_output_;
+
+ if (trace_level < 0) {
+ soft_break();
+ assert(false);
+ qFatal("Fatal error occured!\n");
+ }
+ }
+ }
+
+ template<class T>
+ FQTermTrace &operator << (const T &t) {
+ if (is_dummy_) return *this;
+
+ if (trace_level <= FQTERM_MAX_TRACE_LEVEL && trace_level <= getMaxTraceLevel()) {
+ *trace_output_ << t;
+ }
+ return *this;
+ }
+
+ FQTermTrace &operator << (const std::string &t) {
+ return output_raw_string(t);
+ }
+
+ FQTermTrace &operator << (const char *t) {
+ return output_raw_string(t);
+ }
+
+ FQTermTrace &operator << (void (*setter)(FQTermTrace<trace_level> &)) {
+ (*setter)(*this);
+ return *this;
+ }
+
+ private:
+ FQTermTrace &output_raw_string(const std::string &t) {
+ if (is_dummy_) return *this;
+
+ if (trace_level <= FQTERM_MAX_TRACE_LEVEL && trace_level <= getMaxTraceLevel()) {
+ if (!dump_string_) {
+ for (std::string::size_type i = 0; i < t.size(); ++i) {
+ *trace_output_ << t[i];
+ }
+ } else {
+ for (std::string::size_type i = 0; i < t.size(); ++i) {
+ unsigned char a = t[i];
+ unsigned char b = a / 0x10;
+ unsigned char c = a % 0x10;
+ char h = (char) (b < 10 ? '0' + b : 'A' + b - 10);
+ char l = (char) (c < 10 ? '0' + c : 'A' + c - 10);
+
+ *trace_output_ << h << l << ' ';
+ }
+ }
+ }
+ return *this;
+ }
+
+ private:
+ const char *category_;
+ bool is_dummy_;
+ QDebug *trace_output_;
+
+ public:
+ bool dump_string_; // whether we print string in hex mode.
+
+};
+
+template<int trace_level>
+class FQTermDummyTrace {
+ public:
+ template<class T>
+ FQTermDummyTrace &operator << (const T &) {
+ return *this;
+ }
+
+ FQTermDummyTrace &operator << (void (*setter)(FQTermTrace<trace_level> &)) {
+ return *this;
+ }
+};
+
+template<int trace_level>
+void dumpHexString(FQTermTrace<trace_level> &tracer) {
+ tracer.dump_string_ = true;
+}
+
+template<int trace_level>
+void dumpNormalString(FQTermTrace<trace_level> &tracer) {
+ tracer.dump_string_ = false;
+}
+
+template<int trace_level>
+class FQTermScopeTrace {
+ public:
+ FQTermScopeTrace(const char *category, const char *file_name, int line_num,
+ const char *func_name, const char *scope_name)
+ : category_(category),
+ is_dummy_(!isAllowedCategory(category, trace_level)),
+ file_name_(file_name),
+ line_num_(line_num),
+ func_name_(func_name),
+ scope_name_(scope_name) {
+ if (is_dummy_) return;
+ FQTermTrace<trace_level>(category_, file_name_, line_num_, func_name_)
+ << "Entering " << scope_name_;
+ }
+
+ ~FQTermScopeTrace() {
+ if (is_dummy_) return;
+ FQTermTrace<trace_level>(category_, file_name_, line_num_, func_name_)
+ << "Leaving " << scope_name_;
+ }
+
+ private:
+ const char *category_;
+ bool is_dummy_;
+
+ const char *file_name_;
+ const int line_num_;
+ const char *func_name_;
+ const char *scope_name_;
+};
+
+template<int trace_level>
+class FQTermTimerTrace {
+ public:
+ FQTermTimerTrace(const char *category, const char *file_name, int line_num,
+ const char *func_name, const char *msg)
+ : category_(category),
+ is_dummy_(!isAllowedCategory(category, trace_level)),
+ file_name_(file_name),
+ line_num_(line_num),
+ func_name_(func_name),
+ msg_(msg),
+ start_time(is_dummy_? 0: getTraceTime()) {
+ }
+
+ ~FQTermTimerTrace() {
+ if (is_dummy_) return;
+
+ long long total_time = getTraceTime() - start_time;
+
+ long long num_sec = total_time / 1000;
+ long long num_ms = total_time % 1000;
+
+ FQTermTrace<trace_level>(category_, file_name_, line_num_, func_name_)
+ << msg_ << num_sec << "s" << num_ms << "ms";
+ }
+
+ private:
+ const char *category_;
+ bool is_dummy_;
+
+ const char *file_name_;
+ const int line_num_;
+ const char *func_name_;
+ const char *msg_;
+
+ long long start_time; // in millisecond.
+};
+
+// Some macros work in both debug & release version.
+#define FQ_FATAL(file, line, func) \
+ do {FQTerm::soft_break(); qFatal("%s", (QString(file) + ": %1 " + QString(func)).arg(line).toUtf8().constData());} while(false)
+
+#define FQ_VERIFY(expr) do { \
+ if(!(expr)) { \
+ FQ_FATAL(__FILE__, __LINE__, __FUNCTION__); \
+ } \
+ } while(false)
+
+
+
+#ifdef NO_FQTERM_TRACE
+
+#define FQ_TRACE(category, trace_level) FQTermDummyTrace<trace_level>()
+#define FQ_SCOPE_TRACE(category, trace_level, scope_name) do {} while (false)
+#define FQ_FUNC_TRACE(category, trace_level) do {} while(false)
+
+#define FQ_ASSERT(expr) do {} while(false)
+
+#define FQ_SCOPE_TIMER(category, trace_level, msg) do {} while(false)
+#define FQ_FUNC_TIMER(category, trace_level) do {} while(false)
+
+
+#else // NO_FQTERM_TRACE
+
+#define FQ_TRACE(category, trace_level) \
+ FQTermTrace<trace_level>(category, __FILE__, __LINE__, __FUNCTION__)
+
+#define FQ_SCOPE_TRACE_PRIVATE(file, line, func, category, trace_level, scope_name) \
+ FQTermScopeTrace<trace_level> file##line##func(category, file, line, func, scope_name);
+
+#define FQ_SCOPE_TRACE(category, trace_level, scope_name) \
+ FQ_SCOPE_TRACE_PRIVATE(__FILE__, __LINE__, __FUNCTION__, category, trace_level, scope_name)
+
+#define FQ_FUNC_TRACE(category, trace_level) \
+ FQ_SCOPE_TRACE_PRIVATE(__FILE__, __LINE__, __FUNCTION__, category, trace_level, "function")
+
+
+#define FQ_ASSERT(expr) \
+ do {if(!(expr)) {FQ_TRACE("assert", -1) << "assertion failed." << #expr;}} while(false)
+
+
+#define FQ_SCOPE_TIMER_PRIVATE(file, line, func, category, trace_level, msg) \
+ FQTermTimerTrace<trace_level> file##line##func(category, file, line, func, msg);
+
+#define FQ_SCOPE_TIMER(category, trace_level, msg) \
+ FQ_SCOPE_TIMER_PRIVATE(__FILE__, __LINE__, __FUNCTION__, category, trace_level, msg)
+
+#define FQ_FUNC_TIMER(category, trace_level) \
+ FQ_SCOPE_TIMER_PRIVATE(__FILE__, __LINE__, __FUNCTION__, category, trace_level, "The function runs for ")
+
+
+#endif // NO_FQTERM_TRACE
+
+
+const char *getEventName(unsigned int type);
+
+} // namespace FQTerm
+
+#endif // FQTERM_TRACE_H