diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644
index 0000000..6857a8d
--- /dev/null
+++ b/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644
index 0000000..c206706
--- /dev/null
+++ b/.pc/.quilt_series
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/.pc/.version
@@ -0,0 +1 @@
+2
diff --git a/.pc/applied-patches b/.pc/applied-patches
new file mode 100644
index 0000000..9eb6d3e
--- /dev/null
+++ b/.pc/applied-patches
@@ -0,0 +1,2 @@
+pkg-config-instead-of-freetype-config.patch
+fix-bug-missing-leading-char.patch
diff --git a/.pc/fix-bug-missing-leading-char.patch/src/mainframe.cpp b/.pc/fix-bug-missing-leading-char.patch/src/mainframe.cpp
new file mode 100644
index 0000000..35856f2
--- /dev/null
+++ b/.pc/fix-bug-missing-leading-char.patch/src/mainframe.cpp
@@ -0,0 +1,2109 @@
+/* -*- coding: utf-8; indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*- */
+/**
+ * Copyright (c) 2005 PCMan <pcman.tw@gmail.com>
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef __GNUG__
+ #pragma implementation "mainframe.h"
+#endif
+
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <ltdl.h>
+
+#include "mainframe.h"
+
+#include "telnetview.h"
+#include "notebook.h"
+#include "telnetcon.h"
+#include "editor.h"
+
+#include "inputdialog.h"
+#include "editfavdlg.h"
+#include "sitedlg.h"
+#include "prefdlg.h"
+#include "appconfig.h"
+#include "sitelistdlg.h"
+#include "emoticondlg.h"
+#include "downarticledlg.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+
+#ifdef USE_NOTIFIER
+#ifdef USE_LIBNOTIFY
+#include <libnotify/notify.h>
+#else
+#include "notifier/api.h"
+#endif
+#endif
+
+#ifdef USE_SCRIPT
+#include "script/api.h"
+#endif
+
+const gchar COLOR_BLOCK[] = "\u2588\u2588\u2588\u2588\u2588\u2588";
+
+#ifdef USE_DOCKLET
+#include "docklet/api.h"
+
+void CMainFrame::OnTrayButton_Toggled(
+ GtkToggleButton *button UNUSED,
+ CMainFrame *_this)
+{
+ GtkToggleAction *action = (GtkToggleAction*) gtk_action_group_get_action(
+ _this->m_ActionGroup, "showhide");
+ gtk_toggle_action_set_active(action,
+ ! gtk_toggle_action_get_active(action));
+}
+
+
+void CMainFrame::OnShowHide(GtkToggleAction *toggleaction, CMainFrame *_this)
+{
+ bool show_tray_icon = AppConfig.ShowTrayIcon;
+
+ if (show_tray_icon)
+ {
+ if (gtk_toggle_action_get_active(toggleaction))
+ _this->Show();
+ else
+ _this->Hide();
+ }
+ else
+ {
+ gtk_window_iconify((GtkWindow*)_this->m_Widget);
+ }
+}
+#endif
+
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
+
+void CMainFrame::OnToggleToolBar(GtkToggleAction *toggleaction, CMainFrame *_this)
+{
+ AppConfig.ShowToolbar = gtk_toggle_action_get_active(toggleaction);
+ if (AppConfig.ShowToolbar) {
+ gtk_widget_show_all((GtkWidget *)_this->m_Toolbar);
+ } else {
+ gtk_widget_hide_all((GtkWidget *)_this->m_Toolbar);
+ }
+}
+
+void CMainFrame::OnToggleStatusBar(GtkToggleAction *toggleaction, CMainFrame *_this)
+{
+ AppConfig.ShowStatusBar = gtk_toggle_action_get_active(toggleaction);
+ if (AppConfig.ShowStatusBar) {
+ gtk_widget_show_all((GtkWidget *)_this->m_Statusbar);
+ } else {
+ gtk_widget_hide_all((GtkWidget *)_this->m_Statusbar);
+ }
+}
+
+/*
+void CMainFrame::OnTrayButton_Changed(GtkWidget* widget, GtkAllocation *allocation, CMainFrame* _this)
+{
+ if (! _this->m_MainIcon)
+ return;
+ _this->set_tray_icon();
+}
+*/
+
+#ifdef USE_DOCKLET
+void CMainFrame::OnTray_Popup(GtkStatusIcon *status_icon UNUSED,
+ guint button, guint activate_time,
+ CMainFrame *_this)
+{
+ gtk_menu_popup((GtkMenu*)_this->m_TrayPopup, NULL, NULL, NULL, NULL
+ , button, activate_time);
+}
+#endif
+
+CMainFrame* CMainFrame::g_pMyself = NULL;
+
+gboolean CMainFrame::OnSize( GtkWidget* widget, GdkEventConfigure* evt,
+ CMainFrame* _this UNUSED )
+{
+ gtk_window_get_position( GTK_WINDOW(widget), &AppConfig.MainWndX, & AppConfig.MainWndY );
+ AppConfig.MainWndW = evt->width;
+ AppConfig.MainWndH = evt->height;
+ INFO("x=%d, y=%d, w=%d, h=%d", evt->x, evt->y, evt->width, evt->height );
+ INFO("get_pos: x=%d, y=%d", AppConfig.MainWndX, AppConfig.MainWndY );
+ return false;
+}
+
+
+CMainFrame::CMainFrame()
+{
+ char* desktop = getenv("XDG_CURRENT_DESKTOP");
+
+ m_eView = NULL;
+ m_pView = NULL;
+ m_FavoritesMenuItem = NULL;
+ m_FavoritesMenu = NULL;
+ m_IsFlashing = false;
+ m_Mode = NORMAL_MODE;
+#ifdef USE_DOCKLET
+ m_TrayIcon = NULL;
+#endif
+
+ /* Detecting Unity desktop environment */
+ if (desktop != NULL && strcmp("Unity", desktop) == 0) {
+ m_Unity = true;
+ } else {
+ m_Unity = false;
+ }
+
+ m_dlhandle = lt_dlopen("libappindicator.so.1");
+
+ m_Widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_wmclass(GTK_WINDOW(m_Widget), "pcmanx", "PCManX");
+
+ PostCreate();
+
+#if defined(USE_DOCKLET) || defined(USE_NOTIFIER)
+ /* We need to make sure m_MainIcon is null at startup. */
+ m_MainIcon = (GdkPixbuf *) NULL;
+#endif
+
+ LoadIcons();
+
+
+ gtk_window_set_title (GTK_WINDOW (m_Widget), "PCManX "VERSION );
+
+ m_pNotebook = new CNotebook();
+ gtk_notebook_set_scrollable(GTK_NOTEBOOK(m_pNotebook->m_Widget), TRUE);
+ g_signal_connect( G_OBJECT(m_pNotebook->m_Widget), "button_press_event",
+ G_CALLBACK(CMainFrame::OnNotebookPopupMenu), this );
+
+ MakeUI();
+
+
+ gtk_window_set_icon((GtkWindow*)m_Widget, m_MainIcon);
+
+ GtkWidget* vbox = gtk_vbox_new(false, 0);
+ gtk_widget_show (vbox);
+
+ //GtkWidget* m_Statusbar = gtk_statusbar_new ();
+ m_Statusbar = gtk_statusbar_new ();
+
+ gtk_container_add(GTK_CONTAINER(m_Widget), vbox);
+
+ gtk_box_pack_start (GTK_BOX (vbox), m_Menubar, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), m_Toolbar, FALSE, FALSE, 0);
+ if (AppConfig.ShowToolbar) {
+ gtk_widget_show_all(m_Toolbar);
+ } else {
+ gtk_widget_hide_all(m_Toolbar);
+ }
+ gtk_box_pack_start (GTK_BOX (vbox), m_pNotebook->m_Widget, TRUE, TRUE, 0);
+ gtk_widget_set_size_request(m_pNotebook->m_Widget, 300, 200);
+ gtk_box_pack_start (GTK_BOX (vbox), m_Statusbar, FALSE, FALSE, 0);
+
+ // Tab key to quick switch keyboard focus to m_URLEntry
+ GList *focus_chain = NULL;
+ focus_chain = g_list_append(focus_chain, m_Toolbar);
+ focus_chain = g_list_append(focus_chain, m_URLEntry);
+ gtk_container_set_focus_chain(GTK_CONTAINER(vbox), focus_chain);
+ g_list_free(focus_chain);
+
+
+// gtk_widget_grab_focus(m_pNotebook->m_Widget);
+
+// GTK_WIDGET_UNSET_FLAGS(m_pNotebook->m_Widget, GTK_CAN_FOCUS);
+//
+ g_signal_connect(G_OBJECT(m_Widget), "window-state-event", G_CALLBACK(CMainFrame::OnWindowStateEvent), this);
+
+ g_signal_connect(G_OBJECT(m_Widget), "delete-event", G_CALLBACK(CMainFrame::OnClose), this);
+
+ g_signal_connect(m_pNotebook->m_Widget, "switch-page", G_CALLBACK(CMainFrame::OnNotebookChangeCurPage), this);
+
+ g_signal_connect(m_Widget, "configure-event", G_CALLBACK(CMainFrame::OnSize), this);
+
+ g_signal_connect(G_OBJECT(m_Widget), "focus-in-event", G_CALLBACK(CMainFrame::OnActivated), this);
+
+// g_signal_connect(G_OBJECT(m_Widget), "focus-out-event", G_CALLBACK(CMainFrame::OnDeactivated), this);
+
+ gtk_box_set_spacing( GTK_BOX (m_Statusbar), 4 );
+#ifdef USE_NANCY
+ m_StatusBarBotState = (GtkLabel*)gtk_label_new("");
+ gtk_box_pack_start (GTK_BOX (m_Statusbar), (GtkWidget*)m_StatusBarBotState, FALSE, FALSE, 2);
+ GtkWidget* vsep = gtk_vseparator_new ();
+ gtk_box_pack_start (GTK_BOX (m_Statusbar), vsep, FALSE, FALSE, 2);
+#endif
+ m_StatusBarTime = (GtkLabel*)gtk_label_new("");
+ gtk_box_pack_start (GTK_BOX (m_Statusbar), (GtkWidget*)m_StatusBarTime, FALSE, FALSE, 2);
+ if (AppConfig.ShowStatusBar) {
+ gtk_widget_show_all(m_Statusbar);
+ } else {
+ gtk_widget_hide_all(m_Statusbar);
+ }
+
+ m_BlinkTimer = g_timeout_add(600, (GSourceFunc)CMainFrame::OnBlinkTimer, this );
+ m_EverySecondTimer = g_timeout_add(1000, (GSourceFunc)CMainFrame::OnEverySecondTimer, this );
+
+ CTelnetView::SetParentFrame(this);
+ CTelnetView::SetWebBrowser(AppConfig.WebBrowser);
+ CTelnetView::SetMailClient(AppConfig.MailClient);
+
+ if (AppConfig.Maximized) {
+ gtk_window_maximize((GtkWindow*) m_Widget);
+ }else{
+ gtk_window_unmaximize((GtkWindow*) m_Widget);
+ }
+
+ if(AppConfig.ShowInSimpleMode){
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(m_ActionGroup, "simple")), true);
+ }
+}
+
+
+CTelnetCon* CMainFrame::NewCon(string title, string url, CSite* site )
+{
+ /* Remove leading and trailing spaces from url. */
+ size_t first = url.find_first_not_of(" \t");
+ size_t last = url.find_last_not_of(" \t");
+ if (last >= first)
+ url = url.substr(first, last - first + 1);
+
+ /* Remove telnet:// from url */
+ first = url.find_first_not_of("telnet://");
+ if (first != string::npos)
+ url.erase(0, first);
+
+ if ( site == NULL )
+ site = &AppConfig.m_DefaultSite;
+
+ CTelnetCon* pCon;
+ CEditor* pEditor;
+
+ /**
+ * Since CEditor is extended from CTelnetCon and CEditorView extended from CTelnetView,
+ * there are lots of settings can be reused below.
+ * Therefore, the differences only lie in the new instance part.
+ * We use the magic url "ansi_editor" to identify if the Editor instance should be created or not.
+ */
+ if(url == "ansi_editor"){
+ m_eView = new CEditorView;
+ pEditor = new CEditor( m_eView, *site);
+ pCon = pEditor;
+ m_pView = m_eView;
+ }else{
+ m_pView = new CTelnetView;
+ pCon = new CTelnetCon( m_pView, *site );
+ pEditor = NULL;
+ }
+ m_Views.push_back(m_pView);
+
+ m_pView->m_pTermData = pCon;
+ m_pView->SetContextMenu(m_EditMenu);
+ m_pView->SetFont(AppConfig.FontFamily, AppConfig.FontSize, AppConfig.CompactLayout, AppConfig.AntiAliasFont, CTermView::FONT_DEFAULT);
+ m_pView->SetFont(AppConfig.FontFamilyEn, AppConfig.FontSizeEn, AppConfig.CompactLayout, AppConfig.AntiAliasFont, CTermView::FONT_EN);
+ m_pView->SetHyperLinkColor( &AppConfig.HyperLinkColor );
+ m_pView->SetHorizontalCenterAlign( site->m_bHorizontalCenterAlign );
+ m_pView->SetVerticalCenterAlign( site->m_bVerticalCenterAlign );
+ m_pView->m_CharPaddingX = AppConfig.CharPaddingX;
+ m_pView->m_CharPaddingY = AppConfig.CharPaddingY;
+
+ pCon->m_Site.m_Name = title;
+ pCon->m_Site.m_URL = url;
+ pCon->m_Encoding = pCon->m_Site.m_Encoding;
+
+ m_pView->SetUAO( site->m_UAO );
+
+ pCon->AllocScreenBuf( site->m_RowsPerPage, site->m_RowsPerPage, site->m_ColsPerPage );
+
+ int idx = m_pNotebook->AddPage( m_pView, title, true );
+ m_pNotebook->SetCurPage(idx);
+ m_pView->SetFocus();
+
+ if(url == "ansi_editor"){
+ pEditor->EditorActions(CEditor::Init_Ansi_Editor);
+ }else{
+ pCon->Connect();
+ }
+
+ return pCon;
+}
+
+
+#ifdef USE_NANCY
+GtkRadioActionEntry CMainFrame::cur_bot_entries[] =
+ {
+ {"disable_cur_bot", NULL, _("Disable Bot"), NULL, NULL, 0},
+ {"nancy_bot_current", NULL, _("Nancy Bot"), NULL, NULL, 1}
+ };
+
+GtkRadioActionEntry CMainFrame::all_bot_entries[] =
+ {
+ {"disable_all_bot", NULL, _("Disable Bot"), NULL, NULL, 0},
+ {"nancy_bot_all", NULL, _("Nancy Bot"), NULL, NULL, 1}
+ };
+#endif
+
+static const char *ui_info =
+ "<ui>"
+ " <menubar>"
+ " <menu action='connect_menu'>"
+ " <menuitem action='site_list'/>"
+ " <menuitem action='new_con'/>"
+ " <menuitem action='reconnect'/>"
+ " <menuitem action='close'/>"
+ " <separator/>"
+ " <menuitem action='next_con'/>"
+ " <menuitem action='previous_con'/>"
+ " <menuitem action='first_con'/>"
+ " <menuitem action='last_con'/>"
+ " <menuitem action='jump'/>"
+ " <separator/>"
+ " <menuitem action='quit'/>"
+ " </menu>"
+ " <menu action='edit_menu'>"
+ " <menuitem action='copy'/>"
+ " <menuitem action='copy_with_ansi'/>"
+ " <menuitem action='paste'/>"
+ " <menuitem action='paste_from_clipboard'/>"
+ " <menuitem action='select_all'/>"
+ " <menuitem action='down_article'/>"
+ " <separator/>"
+ " <menuitem action='emoticon'/>"
+ " <menuitem action='preference'/>"
+ " </menu>"
+ " <menu action='favorites_menu'>"
+ " <separator/>"
+ " <menuitem action='add_to_fav'/>"
+ " <menuitem action='edit_fav'/>"
+ " </menu>"
+ " <menu action='view_menu'>"
+ " <menuitem action='ascii_font'/>"
+ " <menuitem action='non_ascii_font'/>"
+ " <separator/>"
+ " <menuitem action='toolbar'/>"
+ " <menuitem action='statusbar'/>"
+ " <separator/>"
+#ifdef USE_DOCKLET
+ " <menuitem action='showhide'/>"
+#endif
+ " <menuitem action='fullscreen' />"
+ " <menuitem action='simple' />"
+#ifdef USE_NANCY
+ " <separator/>"
+ " <menu action='cur_bot_menu'>"
+ " <menuitem action='disable_cur_bot'/>"
+ " <menuitem action='nancy_bot_current'/>"
+ " </menu>"
+ " <menu action='all_bot_menu'>"
+ " <menuitem action='disable_all_bot'/>"
+ " <menuitem action='nancy_bot_all'/>"
+ " </menu>"
+#endif
+ " </menu>"
+ " <menu action='menu_ansi_editor'>"
+ " <menuitem action='openAnsiEditor'/>"
+ " <separator/>"
+ " <menuitem action='openAnsiFile'/>"
+ " <menuitem action='saveAnsiFile'/>"
+ " <menuitem action='clearScreen'/>"
+ " </menu>"
+ " <menu action='help_menu'>"
+ " <menuitem action='shortcut_list'/>"
+ " <menuitem action='about'/>"
+ " </menu>"
+ " </menubar>"
+ " <toolbar>"
+ " <separator/>"
+ " <toolitem action='site_list'/>"
+ " <toolitem action='new_con'/>"
+ " <toolitem action='reconnect'/>"
+ " <toolitem action='close'/>"
+ " <separator/>"
+ " <toolitem action='copy'/>"
+ " <toolitem action='copy_with_ansi'/>"
+ " <toolitem action='paste'/>"
+ " <toolitem action='down_article'/>"
+ " <separator/>"
+ " <toolitem action='add_to_fav'/>"
+ " <toolitem action='preference'/>"
+ " <toolitem action='about'/>"
+ " <separator/>"
+ " </toolbar>"
+ " <popup name='edit_popup'>"
+ " <menuitem action='copy'/>"
+ " <menuitem action='copy_with_ansi'/>"
+ " <menuitem action='paste'/>"
+ " <menuitem action='paste_from_clipboard'/>"
+ " <menuitem action='select_all'/>"
+ " <separator/>"
+ " <menuitem action='fullscreen' />"
+ " <menuitem action='simple' />"
+ " <separator/>"
+ " </popup>"
+#if defined(USE_DOCKLET)
+ " <popup name='tray_popup'>"
+ " <menuitem action='showhide' />"
+ " <separator />"
+ " <menuitem action='quit'/>"
+ " </popup>"
+ " <accelerator action='showhide' />"
+#endif
+
+ // alternative accelerators
+ " <accelerator action='close2'/>"
+ " <accelerator action='reconnect1'/>"
+ " <accelerator action='next_con1'/>"
+ " <accelerator action='previous_con1'/>"
+ " <accelerator action='new_con_gnome_term_sty'/>"
+ " <accelerator action='next_con_gnome_term_sty'/>"
+ " <accelerator action='previous_con_gnome_term_sty'/>"
+ " <accelerator action='copy_gnome_term_sty'/>"
+ " <accelerator action='paste_gnome_term_sty'/>"
+ "</ui>";
+
+void CMainFrame::MakeUI()
+{
+ m_ActionGroup = gtk_action_group_new("GlobalActions");
+
+ gtk_action_group_set_translation_domain(m_ActionGroup, GETTEXT_PACKAGE);
+
+
+ //move m_ActionEntries from class member to local.
+ GtkActionEntry actionEntries[] =
+ {
+ {"connect_menu", NULL, _("_Connect"), NULL, NULL, NULL},
+ {"site_list", GTK_STOCK_OPEN, _("_Site List"), AppConfig.keySiteList.data(), _("Site List"), G_CALLBACK (CMainFrame::OnSiteList)},
+ {"new_con", GTK_STOCK_NETWORK, _("_New Connection"), AppConfig.keyNewConn0.c_str(), _("New Connection"), G_CALLBACK (CMainFrame::OnNewCon)},
+ {"new_con_gnome_term_sty", GTK_STOCK_NETWORK, _("_New Connection"), AppConfig.keyNewConn1.data(), _("New Connection"), G_CALLBACK (CMainFrame::OnNewCon)},
+ {"reconnect", GTK_STOCK_UNDO, _("_Reconnect"), AppConfig.keyReconn0.data(), _("Reconnect"), G_CALLBACK (CMainFrame::OnReconnect)},
+ {"reconnect1",GTK_STOCK_UNDO, _("_Reconnect"), AppConfig.keyReconn1.data(), _("Reconnect"), G_CALLBACK(CMainFrame::OnReconnect)},
+ {"close", GTK_STOCK_CLOSE, _("_Close Connection"), AppConfig.keyClose0.data(), _("Close Connection"), G_CALLBACK (CMainFrame::OnCloseCon)},
+ {"close2", GTK_STOCK_CLOSE, _("_Close Connection"), AppConfig.keyClose1.data(), _("Close Connection"), G_CALLBACK(CMainFrame::OnCloseCon)},
+ {"next_con", GTK_STOCK_GO_DOWN, _("Ne_xt Page"), AppConfig.keyNextPage.data(), _("Next Page"), G_CALLBACK (CMainFrame::OnNextCon)},
+ {"next_con1", GTK_STOCK_GO_DOWN, _("Ne_xt Page"), "<Ctrl>Right", _("Next Page"), G_CALLBACK(CMainFrame::OnNextCon)},
+ {"next_con_gnome_term_sty", GTK_STOCK_GO_DOWN, _("Ne_xt Page"), "<Ctrl>Page_Down", _("Next Page"), G_CALLBACK(CMainFrame::OnNextCon)},
+ {"previous_con", GTK_STOCK_GO_UP, _("_Previous Page"), AppConfig.keyPrevPage.data(), _("Previous Page"), G_CALLBACK (CMainFrame::OnPrevCon)},
+ {"previous_con1", GTK_STOCK_GO_UP, _("_Previous Page"), "<Ctrl>Left", _("Previous Page"), G_CALLBACK(CMainFrame::OnPrevCon)},
+ {"previous_con_gnome_term_sty", GTK_STOCK_GO_UP, _("_Previous Page"), "<Ctrl>Page_Up", _("Previous Page"), G_CALLBACK(CMainFrame::OnPrevCon)},
+ {"first_con",GTK_STOCK_GO_UP, _("_First Page"), AppConfig.keyFirstPage.data(), _("First Page"), G_CALLBACK(CMainFrame::OnFirstCon)},
+ {"last_con", GTK_STOCK_GO_DOWN, _("_Last Page"), AppConfig.keyLastPage.data(), _("Last Page"), G_CALLBACK(CMainFrame::OnLastCon)},
+ {"jump", GTK_STOCK_JUMP_TO, _("_Jump to"), NULL, NULL, NULL},
+ {"quit", GTK_STOCK_QUIT, _("_Quit"), "", _("Quit"), G_CALLBACK (CMainFrame::OnQuit)},
+ {"edit_menu", NULL, _("_Edit"), NULL, NULL, NULL},
+ {"copy", GTK_STOCK_COPY, _("_Copy"), AppConfig.keyCopy0.data(), _("Copy"), G_CALLBACK (CMainFrame::OnCopy)},
+ {"copy_gnome_term_sty", GTK_STOCK_COPY, _("_Copy"), AppConfig.keyCopy1.data(), _("Copy"), G_CALLBACK (CMainFrame::OnCopy)},
+ {"copy_with_ansi", GTK_STOCK_SELECT_COLOR, _("Copy with A_NSI Color"), NULL, _("Copy with ANSI Color"), G_CALLBACK (CMainFrame::OnCopyWithColor)},
+ {"paste", GTK_STOCK_PASTE, _("_Paste"), AppConfig.keyPaste0.data(), _("Paste"), G_CALLBACK (CMainFrame::OnPaste)},
+ {"paste_gnome_term_sty", GTK_STOCK_PASTE, _("_Paste"), AppConfig.keyPaste1.data(), _("Paste"), G_CALLBACK (CMainFrame::OnPaste)},
+ {"paste_from_clipboard", GTK_STOCK_PASTE, _("Paste from Clipboard"), AppConfig.keyPasteClipboard.data(), NULL, G_CALLBACK (CMainFrame::pasteFromClipboard)},
+ {"down_article", GTK_STOCK_SELECT_ALL, _("_Download Article"), NULL, _("Download Article"), G_CALLBACK (CMainFrame::OnDownArticle)},
+ {"select_all", NULL, _("Select A_ll"), NULL, NULL, G_CALLBACK (CMainFrame::OnSelectAll)},
+ {"emoticon", NULL, _("_Emoticons"), AppConfig.keyEmotions.data(), NULL, G_CALLBACK (CMainFrame::OnEmoticons)},
+ {"preference", GTK_STOCK_PREFERENCES, _("_Preference"), NULL, _("Preference"), G_CALLBACK (CMainFrame::OnPreference)},
+ {"favorites_menu", NULL, _("F_avorites"), NULL, NULL, NULL},
+ {"add_to_fav", GTK_STOCK_ADD, _("_Add to Favorites"), NULL, _("Add to Favorites"), G_CALLBACK (CMainFrame::OnAddToFavorites)},
+ {"edit_fav", GTK_STOCK_EDIT, _("_Edit Favorites"), NULL, NULL, G_CALLBACK (CMainFrame::OnEditFavorites)},
+ {"view_menu", NULL, _("_View"), NULL, NULL, NULL},
+ {"ascii_font", GTK_STOCK_SELECT_FONT, _("_ASCII Font"), NULL, NULL, G_CALLBACK (CMainFrame::OnFont)},
+ {"non_ascii_font", GTK_STOCK_SELECT_FONT, _("Non-ASCII _Font"), NULL, NULL, G_CALLBACK (CMainFrame::OnFont)},
+ #ifdef USE_NANCY
+ {"cur_bot_menu", GTK_STOCK_EXECUTE, _("Bot (Current Connection)"), NULL, NULL, NULL},
+ {"all_bot_menu", GTK_STOCK_EXECUTE, _("Bot (All Opened Connections)"), NULL, NULL, NULL},
+ #endif
+ {"help_menu", NULL, _("_Help"), NULL, NULL, NULL},
+ {"shortcut_list", GTK_STOCK_DIALOG_INFO, _("_Shortcut List"), NULL, NULL, G_CALLBACK (CMainFrame::OnShortcutList)},
+ {"about", GTK_STOCK_ABOUT, NULL, NULL, _("About"), G_CALLBACK (CMainFrame::OnAbout)},
+ // Ansi Editor Menu
+ {"menu_ansi_editor", NULL, _("Ansi Editor"), NULL, NULL, NULL},
+ {"openAnsiEditor", NULL, _("Open Ansi Editor"), NULL, NULL, G_CALLBACK (CMainFrame::OnAnsiEditor)},
+ {"openAnsiFile", NULL, _("Open Ansi File"), NULL, NULL, G_CALLBACK (CMainFrame::OnOpenAnsiFile)},
+ {"saveAnsiFile", NULL, _("Save Ansi File"), NULL, NULL, G_CALLBACK (CMainFrame::OnSaveAnsiFile)},
+ {"clearScreen", NULL, _("Clear Screen"), NULL, NULL, G_CALLBACK (CMainFrame::OnClearScreen)}
+ };
+
+ //move m_ToggleActionEntries from class member to local
+ GtkToggleActionEntry ToggleActionEntries[] =
+ {
+ #ifdef USE_DOCKLET
+ // Show/Hide Main Window
+ {"showhide", NULL, _("Show _Main Window"), "<Alt>M", NULL, G_CALLBACK(CMainFrame::OnShowHide), true},
+ #endif
+ {"toolbar", NULL, _("Show Toolbar"), NULL, NULL, G_CALLBACK (CMainFrame::OnToggleToolBar), true},
+ {"statusbar", NULL, _("Show Status Bar on bottom"), NULL, NULL, G_CALLBACK (CMainFrame::OnToggleStatusBar), true},
+ {"fullscreen", NULL, _("F_ullscreen Mode"), AppConfig.keyFullscreen.data(), NULL, G_CALLBACK (CMainFrame::OnFullscreenMode), false},
+ {"simple", NULL, _("_Simple Mode"), AppConfig.keySimpleMode.data(), NULL, G_CALLBACK (CMainFrame::OnSimpleMode), false},
+ };
+
+ gtk_action_group_add_actions(m_ActionGroup, actionEntries, G_N_ELEMENTS(actionEntries), this);
+
+ gtk_action_group_add_toggle_actions(m_ActionGroup, ToggleActionEntries,
+ G_N_ELEMENTS(ToggleActionEntries), this);
+
+#ifdef USE_NANCY
+ gtk_action_group_add_radio_actions(m_ActionGroup,
+ cur_bot_entries,
+ G_N_ELEMENTS(cur_bot_entries),
+ 0,
+ G_CALLBACK (CMainFrame::OnChangeCurrentBot),
+ this);
+ gtk_action_group_add_radio_actions(m_ActionGroup,
+ all_bot_entries,
+ G_N_ELEMENTS(all_bot_entries),
+ 0,
+ G_CALLBACK (CMainFrame::OnChangeAllBot),
+ this);
+#endif
+
+ m_UIManager = gtk_ui_manager_new();
+ gtk_ui_manager_insert_action_group(m_UIManager, m_ActionGroup, 0);
+
+ GtkAccelGroup* accel_group = gtk_ui_manager_get_accel_group ( m_UIManager );
+ gtk_window_add_accel_group (GTK_WINDOW (m_Widget), accel_group);
+
+ GError * error = NULL;
+ if (!gtk_ui_manager_add_ui_from_string(m_UIManager, ui_info, -1, & error))
+ {
+ g_message("Building menu failed : %s", error->message);
+ g_error_free(error); exit(EXIT_FAILURE);
+ }
+
+ m_Menubar = gtk_ui_manager_get_widget (m_UIManager, "/ui/menubar");
+ m_Toolbar = gtk_ui_manager_get_widget (m_UIManager, "/ui/toolbar");
+ gtk_toolbar_set_style( (GtkToolbar*)m_Toolbar, GTK_TOOLBAR_ICONS );
+
+ m_EditMenu = gtk_ui_manager_get_widget (m_UIManager, "/ui/edit_popup");
+
+ m_FavoritesMenuItem = gtk_ui_manager_get_widget (m_UIManager, "/ui/menubar/favorites_menu");
+
+#ifdef USE_NANCY
+
+ m_DisableCurBotRadio = (GtkRadioMenuItem*) gtk_ui_manager_get_widget (m_UIManager,
+ "/ui/menubar/view_menu/cur_bot_menu/disable_cur_bot");
+ m_CurBotNancyRadio = (GtkRadioMenuItem*) gtk_ui_manager_get_widget (m_UIManager,
+ "/ui/menubar/view_menu/cur_bot_menu/nancy_bot_current");
+
+ m_DisableAllBotRadio = (GtkRadioMenuItem*) gtk_ui_manager_get_widget (m_UIManager,
+ "/ui/menubar/view_menu/all_bot_menu/disable_all_bot");
+ m_AllBotNancyRadio = (GtkRadioMenuItem*) (gtk_ui_manager_get_widget (m_UIManager,
+ "/ui/menubar/view_menu/all_bot_menu/nancy_bot_all"));
+
+#endif
+
+ GtkWidget* jump = gtk_ui_manager_get_widget (m_UIManager, "/ui/menubar/connect_menu/jump");
+
+ GtkWidget* jump_menu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (jump), jump_menu);
+
+ const char* page_str = _("Page");
+ for(int i = 1; i < 11; i++)
+ {
+ char title[32], name[32];
+ sprintf(title, "%s %d_%d", page_str, i / 10, i % 10);
+ sprintf(name, "jumpto_%d", i);
+ GtkAction *action = gtk_action_new(name, title, NULL, NULL);
+ gtk_action_set_accel_group(action, accel_group);
+ g_signal_connect( G_OBJECT(action), "activate",
+ G_CALLBACK (CMainFrame::OnJumpToPage),
+ this);
+ sprintf(name, "<Alt>%d", i % 10);
+ gtk_action_group_add_action_with_accel(m_ActionGroup, action, name);
+ gtk_container_add (GTK_CONTAINER (jump_menu),
+ gtk_action_create_menu_item(action));
+ m_JumpTos[i-1] = G_OBJECT(action);
+ }
+
+ // Ansi Editor widget: blink check box, click to set the text blink.
+ m_chkBlink = gtk_check_button_new_with_label("blink");
+ GtkToolItem *itemBlink = gtk_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(itemBlink), m_chkBlink);
+ gtk_widget_show_all ( (GtkWidget*)itemBlink);
+ gtk_toolbar_insert(GTK_TOOLBAR(m_Toolbar), itemBlink, -1);
+
+ // Ansi Editor widget: Set Text color.
+ GtkTreeModel *model;
+ model = GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING));
+ m_cbTextColor = gtk_combo_box_new_with_model(model);
+
+ GtkCellRenderer *cell;
+ cell = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(m_cbTextColor), cell, TRUE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(m_cbTextColor), cell, "text", 0);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(m_cbTextColor), cell, "foreground", 1);
+
+ GtkTreeIter iter;
+ GtkListStore *store = GTK_LIST_STORE(model);
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter, 0, "Front", 1, "#000000", -1);
+
+ for (int i = 0; i < 16; i++)
+ {
+ gchar color[8];
+ ParseColor(&(CTermCharAttr::m_DefaultColorTable[i]), color, ARRAY_SIZE(color));
+ AppendRow(&iter, store, COLOR_BLOCK, color);
+ }
+ gtk_combo_box_set_active(GTK_COMBO_BOX(m_cbTextColor), 0);
+
+ GtkToolItem *itemTextColor = gtk_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(itemTextColor), m_cbTextColor);
+ gtk_widget_show_all ( (GtkWidget*)itemTextColor);
+ gtk_toolbar_insert(GTK_TOOLBAR(m_Toolbar), itemTextColor, -1);
+
+ // Ansi Editor widget: Set Background color.
+ GtkTreeModel *model_back;
+ model_back = GTK_TREE_MODEL(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING));
+ m_cbBgColor = gtk_combo_box_new_with_model(model_back);
+
+ GtkCellRenderer *cell_back;
+ cell_back = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(m_cbBgColor), cell_back, TRUE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(m_cbBgColor), cell_back, "text", 0);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(m_cbBgColor), cell_back, "foreground", 1);
+
+ GtkTreeIter iter_back;
+ GtkListStore *store_back = GTK_LIST_STORE(model_back);
+ gtk_list_store_append(store_back, &iter_back);
+ gtk_list_store_set(store_back, &iter_back, 0, "Background", 1, "#000000", -1);
+
+ for (int i = 0; i < 8; i++)
+ {
+ gchar color[8];
+ ParseColor(&(CTermCharAttr::m_DefaultColorTable[i]), color, ARRAY_SIZE(color));
+ AppendRow(&iter_back, store_back, COLOR_BLOCK, color);
+ }
+ gtk_combo_box_set_active(GTK_COMBO_BOX(m_cbBgColor), 0);
+
+ GtkToolItem *itemBgColor = gtk_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(itemBgColor), m_cbBgColor);
+ gtk_widget_show_all ( (GtkWidget*)itemBgColor);
+ gtk_toolbar_insert(GTK_TOOLBAR(m_Toolbar), itemBgColor, -1);
+
+ GtkWidget* sep = (GtkWidget*)gtk_separator_tool_item_new();
+ gtk_widget_show(sep);
+ gtk_container_add (GTK_CONTAINER (m_Toolbar), sep);
+ // Create the URL address bar
+ GtkWidget* url_bar = gtk_hbox_new (FALSE, 0);
+ GtkWidget* url_label = (GtkWidget*) gtk_label_new_with_mnemonic(_("A_ddress:"));
+ m_URLEntry = (GtkWidget*) gtk_entry_new();
+ gtk_widget_set_size_request(m_URLEntry, 0, -1);
+ GtkTooltips* tooltips = gtk_tooltips_new();
+ gtk_tooltips_set_tip(tooltips, m_URLEntry, _("Type URL here, then hit \"Enter\""), NULL);
+ gtk_label_set_mnemonic_widget(GTK_LABEL(url_label), m_URLEntry);
+ gtk_box_pack_start( GTK_BOX(url_bar), url_label, FALSE, FALSE, 4);
+ gtk_box_pack_start( GTK_BOX(url_bar), m_URLEntry, TRUE, TRUE, 4);
+
+ GtkToolItem* url_bar_item = gtk_tool_item_new();
+ gtk_tool_item_set_expand(url_bar_item, true);
+ gtk_container_add (GTK_CONTAINER (url_bar_item), url_bar);
+ gtk_widget_show_all ( (GtkWidget*)url_bar_item);
+ gtk_toolbar_insert(GTK_TOOLBAR(m_Toolbar), url_bar_item, -1);
+
+ g_signal_connect ((gpointer) m_URLEntry, "key-press-event",
+ G_CALLBACK (CMainFrame::OnURLEntryKeyDown),
+ this);
+ g_signal_connect ((gpointer) m_URLEntry, "focus-out-event",
+ G_CALLBACK (CMainFrame::OnURLEntryKillFocus),
+ this);
+
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(m_ActionGroup, "toolbar")), AppConfig.ShowToolbar);
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(m_ActionGroup, "statusbar")), AppConfig.ShowStatusBar);
+
+ // Ansi Editor widget events
+ g_signal_connect(GTK_OBJECT(m_cbTextColor), "changed", G_CALLBACK(SetTextColor), this);
+ g_signal_connect(GTK_OBJECT(m_cbBgColor), "changed", G_CALLBACK(SetBgColor), this);
+ g_signal_connect(GTK_OBJECT(m_chkBlink), "toggled", G_CALLBACK(SetBlink), this);
+
+ CreateFavoritesMenu();
+ CreateTrayIcon();
+}
+
+void CMainFrame::OnNewCon(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ CInputDialog* dlg = new CInputDialog( _this, _("Connect"), _("Host IP Address:\nAppend port number to IP with a separating colon if it's not 23."), NULL, true );
+ if( dlg->ShowModal() == GTK_RESPONSE_OK && !dlg->GetText().empty() )
+ {
+ _this->NewCon( dlg->GetText(), dlg->GetText() );
+ }
+ dlg->Destroy();
+}
+
+void CMainFrame::OnQuit(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ if( _this->CanClose() )
+ {
+ _this->Hide();
+ _this->Destroy();
+ }
+}
+
+static void inverse_pixbuf(GdkPixbuf* pixbuf)
+{
+ int x = 0, y = 0;
+ int channels = gdk_pixbuf_get_n_channels(pixbuf);
+ int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
+ int width = gdk_pixbuf_get_width(pixbuf);
+ int height = gdk_pixbuf_get_height(pixbuf);
+ guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
+ for (x = 0; x < width; x++) {
+ for (y = 0; y < height; y++) {
+ guchar *ptr = pixels + y * rowstride + x * channels;
+ ptr[0] ^= 0xFF; //red
+ ptr[1] ^= 0xFF; //green
+ ptr[2] ^= 0xFF; //blue
+ }
+ }
+ return;
+}
+
+void CMainFrame::LoadIcons()
+{
+ GtkImage* image = GTK_IMAGE(gtk_image_new_from_file(DATADIR "/pixmaps/pcmanx.svg"));
+ GdkPixbuf* icon = gtk_image_get_pixbuf(image);
+ if (icon) {
+ m_MainIcon = gdk_pixbuf_scale_simple(icon, 32, 32, GDK_INTERP_BILINEAR);
+ m_InverseMainIcon = gdk_pixbuf_copy(m_MainIcon);
+ inverse_pixbuf(m_InverseMainIcon);
+ g_object_unref(icon);
+ } else {
+ m_MainIcon = NULL;
+ m_InverseMainIcon = NULL;
+ }
+}
+
+void CMainFrame::OnFont(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ GtkWidget* dlg = gtk_font_selection_dialog_new(_("Font"));
+ gtk_window_set_modal( (GtkWindow*)dlg, true);
+ gtk_window_set_transient_for( (GtkWindow*)dlg, (GtkWindow*)_this->m_Widget);
+
+ GtkFontSelectionDialog* fsdlg = (GtkFontSelectionDialog*)dlg;
+ GtkWidget* apply_to_all = gtk_check_button_new_with_label( _("Apply to all opened pages") );
+ gtk_widget_show(apply_to_all);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(apply_to_all), true);
+ gtk_box_pack_start( GTK_BOX(fsdlg->action_area), apply_to_all, true, true, 4);
+ gtk_box_reorder_child( GTK_BOX(fsdlg->action_area), apply_to_all, 0 );
+ gtk_box_set_homogeneous(GTK_BOX(fsdlg->action_area), false);
+
+ // This is not a good method because fontsel is a private member of GtkFontSelectionDialog.
+ // But we need this functionality.
+ GtkFontSelection* fontsel = GTK_FONT_SELECTION(fsdlg->fontsel);
+ gtk_widget_set_sensitive(fontsel->face_list, false);
+
+ char pango_font_name[32];
+ int *font_size = NULL;
+ string *font_family = NULL;
+ int font_type;
+ const char *font_action = gtk_action_get_name(GTK_ACTION(mitem));
+ if (!strcmp(font_action, "non_ascii_font")) {
+ font_size = &AppConfig.FontSize;
+ font_family = &AppConfig.FontFamily;
+ font_type = CTermView::FONT_DEFAULT;
+ }
+ else if (!strcmp(font_action, "ascii_font")) {
+ font_size = &AppConfig.FontSizeEn;
+ font_family = &AppConfig.FontFamilyEn;
+ font_type = CTermView::FONT_EN;
+ }
+ else {
+ g_assert_not_reached();
+ }
+
+ sprintf( pango_font_name, "%s %d", (*font_family).c_str(), (*font_size > 6 && *font_size <= 72) ? *font_size : 12 );
+ gtk_font_selection_dialog_set_font_name(fsdlg, pango_font_name);
+
+ if( gtk_dialog_run((GtkDialog*)dlg) == GTK_RESPONSE_OK )
+ {
+ gchar* name = gtk_font_selection_dialog_get_font_name( fsdlg );
+ PangoFontDescription* desc = pango_font_description_from_string( name );
+ g_free( name );
+ const char* family = pango_font_description_get_family(desc);
+ *font_family = family;
+ *font_size = pango_font_description_get_size(desc) / PANGO_SCALE;
+ pango_font_description_free(desc);
+
+ if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(apply_to_all) ) )
+ {
+ vector<CTelnetView*>::iterator it;
+ for( it = _this->m_Views.begin(); it != _this->m_Views.end(); ++it )
+ (*it)->SetFontFamily(*font_family, font_type);
+ /// FIXME: Poor design! Different connection must be allowed to use different fonts in the future.
+ }
+ else if( _this->GetCurView() )
+ _this->GetCurView()->SetFontFamily(*font_family, font_type);
+
+ gtk_widget_destroy(dlg);
+
+ if( _this->GetCurView() )
+ _this->GetCurView()->Refresh();
+ }
+ else
+ gtk_widget_destroy(dlg);
+}
+
+void CMainFrame::OnFullscreenMode(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ if(_this->m_Mode == SIMPLE_MODE) {
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(_this->m_ActionGroup, "simple")), false);
+ }
+
+ if (_this->m_Mode != FULLSCREEN_MODE) {
+ _this->m_Mode = FULLSCREEN_MODE;
+ gtk_window_fullscreen((GtkWindow *)_this->m_Widget);
+ gtk_widget_hide_all((GtkWidget *)_this->m_Menubar);
+ gtk_widget_hide_all((GtkWidget *)_this->m_Toolbar);
+ gtk_widget_hide_all((GtkWidget *)_this->m_Statusbar);
+ _this->m_pNotebook->HideTabs();
+ } else {
+ _this->m_Mode = NORMAL_MODE;
+ gtk_window_unfullscreen((GtkWindow *)_this->m_Widget);
+ gtk_widget_show_all((GtkWidget *)_this->m_Menubar);
+ if (AppConfig.ShowToolbar)
+ gtk_widget_show_all((GtkWidget *)_this->m_Toolbar);
+ if (AppConfig.ShowStatusBar)
+ gtk_widget_show_all((GtkWidget *)_this->m_Statusbar);
+ _this->m_pNotebook->ShowTabs();
+ }
+}
+
+void CMainFrame::OnSimpleMode(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ if(_this->m_Mode == FULLSCREEN_MODE) {
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_action_group_get_action(_this->m_ActionGroup, "fullscreen")), false);
+ }
+
+ if (_this->m_Mode != SIMPLE_MODE) {
+ _this->m_Mode = SIMPLE_MODE;
+ gtk_window_unfullscreen((GtkWindow *)_this->m_Widget);
+ if (_this->m_Unity == false) {
+ gtk_widget_hide_all((GtkWidget *)_this->m_Menubar);
+ }
+ gtk_widget_hide_all((GtkWidget *)_this->m_Toolbar);
+ gtk_widget_hide_all((GtkWidget *)_this->m_Statusbar);
+ _this->m_pNotebook->HideTabs();
+ } else {
+ _this->m_Mode = NORMAL_MODE;
+ gtk_window_unfullscreen((GtkWindow *)_this->m_Widget);
+ if (_this->m_Unity == false) {
+ gtk_widget_show_all((GtkWidget *)_this->m_Menubar);
+ }
+ if (AppConfig.ShowToolbar)
+ gtk_widget_show_all((GtkWidget *)_this->m_Toolbar);
+ if (AppConfig.ShowStatusBar)
+ gtk_widget_show_all((GtkWidget *)_this->m_Statusbar);
+ _this->m_pNotebook->ShowTabs();
+ }
+}
+
+void CMainFrame::OnShortcutList(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ char* connect_shortcuts= _(
+ "Site List Alt+S\n\n"
+ "New Connection Alt+Q\n"
+ "New Connection Ctrl+Shift+T\n\n"
+ "Reconnection Alt+R\n"
+ "Reconnection Ctrl+Ins\n\n"
+ "Close Alt+W\n"
+ "Close Ctrl+Del\n\n"
+ "Next Page Alt+X\n"
+ "Next Page Alt+?\n"
+ "Next Page Ctrl+Shift+PgDn\n\n"
+ "Previous Page Alt+Z\n"
+ "Previous Page Alt+?\n"
+ "Previous Page Ctrl+Shift+PgUp\n\n"
+ "First Page Ctrl+Home\n"
+ "Last Page Ctrl+End");
+
+ char* edit_shortcuts= _(
+ "Copy Alt+O\n"
+ "Copy Ctrl+Shift+C\n\n"
+ "Paste Alt+P\n"
+ "Paste Ctrl+Shift+V\n\n"
+ "Paste from Clipboard Shift+Ins\n\n"
+ "Emotions Ctrl+Enter");
+
+ char* view_shortcuts= _(
+ "Full Screen Mode Alt+Enter\n"
+ "Simple Mode Shift+Enter\n"
+#ifdef USE_DOCKLET
+ "Show Main Window Alt+M"
+#endif
+ );
+ GtkWidget* dlg = gtk_message_dialog_new_with_markup( (GtkWindow*)_this->m_Widget,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
+ _("<b>Connect Shortcuts</b>\n%s\n\n"
+ "<b>Edit Shortcuts</b>\n%s\n\n"
+ "<b>View Shortcuts</b>\n%s\n\n"),
+ connect_shortcuts, edit_shortcuts, view_shortcuts );
+
+ gtk_image_set_from_pixbuf((GtkImage*) ((GtkMessageDialog*)dlg)->image, _this->m_MainIcon);
+ gtk_dialog_run((GtkDialog*) dlg); // == GTK_RESPONSE_OK
+ gtk_widget_destroy(dlg);
+}
+
+
+void CMainFrame::OnAbout(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ char* authors = _(
+ "Hong Jen Yee (Main developer) <pcman.tw@gmail.com>\n"
+ "Jim Huang (Developer) <jserv.tw@gmail.com>\n"
+ "Kan-Ru Chen (Developer) <kanru@kanru.info>\n"
+ "Chia I Wu (Developer) <b90201047@ntu.edu.tw>\n"
+ "Shih-Yuan Lee (Developer) <fourdollars@gmail.com>\n"
+ "Youchen Lee (Developer) <copyleft@utcr.org>\n"
+ "Emfox Zhou (Developer) <emfoxzhou@gmail.com>\n"
+ "Jason Xia (Developer) <jasonxh@gmail.com>"
+ );
+ char* translators = _( "Chinese Simplified (zh_CN): Haifeng Chen <optical.dlz@gmail.com>" );
+
+ GtkWidget* dlg = gtk_message_dialog_new_with_markup( (GtkWindow*)_this->m_Widget,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
+ _("<b>PCManX %s</b>\nA free BBS client developed with GTK+ 2.x\n\n"
+ "Copyright © 2005-2012\n"
+ "License: GNU Genral Public License\n"
+ "Project: <a href=\"%s\">%s</a>\n"
+ "Mailing List: <a href=\"%s\">%s</a>\n"
+ "Bug Report: <a href=\"%s\">%s</a>\n\n"
+ "<b>Authors</b>:\n%s\n\n"
+ "<b>Translators</b>:\n%s\n\n"), PACKAGE_VERSION, PROJECT_SITE, PROJECT_SITE,
+ PROJECT_FORUM, PROJECT_FORUM, PACKAGE_BUGREPORT, PACKAGE_BUGREPORT, authors, translators );
+
+// GTK+ supports this API since ver 2.6.
+/* gtk_message_dialog_format_secondary_text((GtkMessageDialog*)dlg,
+ _("Copyright (C) 2005\n"
+ "License: GNU Genral Public License\n"
+ "Project Homepage: http://code.google.com/p/pcmanx-gtk2/\n\n"
+ "Authors:\n%s\n")
+ , authors );
+*/
+ gtk_image_set_from_pixbuf((GtkImage*)((GtkMessageDialog*)dlg)->image, _this->m_MainIcon);
+ gtk_dialog_run((GtkDialog*)dlg); // == GTK_RESPONSE_OK
+ gtk_widget_destroy(dlg);
+}
+
+void CMainFrame::pasteFromClipboard(GtkMenuItem* pMenuItem UNUSED, CMainFrame* pMainFrame)
+{
+ CTelnetView* t_pView = pMainFrame->GetCurView();
+ if (t_pView != NULL)
+ t_pView->PasteFromClipboard(false);
+}
+
+void CMainFrame::OnPopupMenuSelectCon(GtkWidget* widget,
+ GtkWidget* menu,
+ GdkEventButton* event,
+ CMainFrame* _this)
+{
+ /**
+ * Popup menu on correct tab.
+ * Switch to the tab closest to the cursor first and then popup menu
+ */
+ int number_of_closet_tab;
+ number_of_closet_tab = _this->GetNearestTab(widget, event);
+
+ // switch to the page which is clicked.
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(widget), number_of_closet_tab);
+ _this->SetCurView( _this->m_Views[number_of_closet_tab] );
+
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time);
+}
+
+void CMainFrame::OnCloseSelectCon(GtkWidget *notebook, GtkMenuItem* mitem, CMainFrame* _this)
+{
+ /**
+ * Close pages selected by middle click of tabs.
+ *
+ * At first choose which tab is the closet tab to the click location.
+ * Then switch to the selected page.
+ * Finally close it, and then switch back to the original page.
+ *
+ * TODO:
+ * The most right hand tab will be selected
+ * even the click location is not exactly on the tab.
+ */
+ int window_w = 0;
+ int window_h = 0;
+ gtk_window_get_size(GTK_WINDOW(gtk_widget_get_toplevel(notebook)), &window_w, &window_h);
+
+ int closet_tab_x = window_w;
+ int number_of_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
+ int nth_page_number = 0;
+ int number_of_closet_tab = 0;
+ /* pick up the tab which is closet to the click location. */
+ for(nth_page_number = 0; nth_page_number < number_of_pages; nth_page_number++)
+ {
+ GtkWidget *tab_label;
+ tab_label = gtk_notebook_get_tab_label( GTK_NOTEBOOK(notebook),
+ gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
+ nth_page_number));
+ int lx, ly;
+ gtk_widget_get_pointer(tab_label, &lx, &ly);
+ if(lx > 0 && lx < closet_tab_x)
+ {
+ closet_tab_x = lx;
+ number_of_closet_tab = nth_page_number;
+ }
+ }
+
+ /* switch to the page which is clicked. */
+ int page_idx_before_close = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), number_of_closet_tab);
+ _this->SetCurView( _this->m_Views[number_of_closet_tab] );
+
+ if ( !(_this->QueryOnCloseCon(_this)) )
+ {
+ return;
+ }
+
+ int page_idx_after_close = 0;
+ page_idx_before_close < number_of_closet_tab ? page_idx_after_close = page_idx_before_close : page_idx_after_close = page_idx_before_close - 1;
+ /* close the current page and then switch page back to the original one. */
+ _this->CloseConAndPageSwitch(_this->m_pNotebook->GetCurPage(), true, notebook, page_idx_after_close);
+}
+
+
+void CMainFrame::OnCloseCon(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ if ( !(_this->QueryOnCloseCon(_this)) )
+ {
+ return;
+ }
+ _this->CloseCon(_this->m_pNotebook->GetCurPage(), true);
+}
+
+bool CMainFrame::QueryOnCloseCon(CMainFrame* _this)
+{
+ CTelnetCon* con = _this->GetCurCon();
+ if( !con )
+ return false;
+ if( AppConfig.QueryOnCloseCon && !con->IsClosed() )
+ {
+ GtkWidget* dlg = gtk_message_dialog_new(GTK_WINDOW(_this->m_Widget),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_OK_CANCEL,
+ _("Close Connection?"));
+ bool can_close = ( gtk_dialog_run(GTK_DIALOG(dlg)) == GTK_RESPONSE_OK );
+ gtk_widget_destroy(dlg);
+ if ( !can_close )
+ return false;
+ }
+ return true;
+}
+
+void CMainFrame::OnCopy(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ if( _this->GetCurView() )
+ {
+ _this->GetCurView()->CopyToClipboard(false, false, AppConfig.CopyTrimTail);
+ if( AppConfig.CancelSelAfterCopy )
+ {
+ _this->GetCurCon()->m_Sel->NewStart(0, 0);
+ _this->GetCurView()->Refresh();
+ }
+ }
+}
+
+
+void CMainFrame::OnCopyWithColor(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ if( _this->GetCurView() )
+ {
+ _this->GetCurView()->CopyToClipboard(false, true, AppConfig.CopyTrimTail);
+ if( AppConfig.CancelSelAfterCopy )
+ {
+ _this->GetCurCon()->m_Sel->NewStart(0, 0);
+ _this->GetCurView()->Refresh();
+ }
+ }
+}
+
+
+void CMainFrame::OnNextCon(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ int i = _this->GetNotebook()->GetCurPage() + 1;
+ int n = _this->GetNotebook()->GetPageCount();
+ _this->GetNotebook()->SetCurPage( i < n ? i : 0 );
+}
+
+void CMainFrame::OnFirstCon(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ _this->GetNotebook()->SetCurPage( 0 );
+}
+
+void CMainFrame::OnLastCon(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ int n = _this->GetNotebook()->GetPageCount();
+ _this->GetNotebook()->SetCurPage( n - 1 );
+}
+
+void CMainFrame::OnPaste(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ if(_this->GetCurView())
+ _this->GetCurView()->PasteFromClipboard(true);
+}
+
+void CMainFrame::OnDownArticle(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ int uao = 0;
+ CTelnetCon *con = _this->GetCurCon();
+ if (!con)
+ return;
+ if(_this->GetCurView())
+ uao = _this->GetCurView()->m_UAO;
+
+ CDownArticleDlg *dlg = new CDownArticleDlg(_this, con, uao);
+ //dlg->Show();
+ dlg->ShowModal();
+ dlg->Destroy();
+}
+
+void CMainFrame::OnPreference(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+#ifdef USE_DOCKLET
+ bool show_tray_icon = AppConfig.ShowTrayIcon;
+#endif
+ CPrefDlg* dlg = new CPrefDlg(_this);
+ dlg->ShowModal();
+ dlg->Destroy();
+
+ CTelnetView::SetWebBrowser(AppConfig.WebBrowser);
+ CTelnetView::SetMailClient(AppConfig.MailClient);
+
+#if defined(USE_NOTIFIER) && !defined(USE_LIBNOTIFY)
+ popup_notifier_set_timeout( AppConfig.PopupTimeout );
+#endif
+
+#ifdef USE_DOCKLET
+ if (AppConfig.ShowTrayIcon != show_tray_icon) {
+ if (_this->m_dlhandle != NULL) {
+ void (*app_indicator_set_status)(void*, gint) =
+ (void (*)(void*, gint)) lt_dlsym(_this->m_dlhandle, "app_indicator_set_status");
+ if (AppConfig.ShowTrayIcon) {
+ app_indicator_set_status(_this->m_indicator, 1);
+ }
+ else {
+ app_indicator_set_status(_this->m_indicator, 0);
+ }
+ }
+ else {
+ if (AppConfig.ShowTrayIcon) {
+ _this->ShowTrayIcon();
+ }
+ else {
+ _this->HideTrayIcon();
+ }
+ }
+ }
+#endif
+
+ if (_this->m_Mode == NORMAL_MODE) {
+ if (AppConfig.ShowToolbar)
+ gtk_widget_show_all(_this->m_Toolbar);
+ else
+ gtk_widget_hide_all(_this->m_Toolbar);
+ if (AppConfig.ShowStatusBar)
+ gtk_widget_show_all(_this->m_Statusbar);
+ else
+ gtk_widget_hide_all(_this->m_Statusbar);
+ }
+}
+
+
+void CMainFrame::OnPrevCon(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ int i = _this->GetNotebook()->GetCurPage() - 1;
+ int n = _this->GetNotebook()->GetPageCount();
+ _this->GetNotebook()->SetCurPage( i >= 0 ? i : n-1 );
+
+}
+
+void CMainFrame::OnSiteList(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ CSiteListDlg* dlg = new CSiteListDlg(_this);
+ dlg->ShowModal();
+ dlg->Destroy();
+}
+
+
+void CMainFrame::OnJumpToPage(GObject* obj, CMainFrame* _this)
+{
+ INFO("On jump to, obj=%p, _this->m_JumpTos[0]=%p",
+ obj, _this->m_JumpTos[0]);
+ for( int i = 0; i < 10; ++i )
+ if( obj == _this->m_JumpTos[i] )
+ {
+ _this->GetNotebook()->SetCurPage(i);
+ break;
+ }
+}
+
+void CMainFrame::OnTelnetConBell(CTelnetView* con)
+{
+ if( !IsActivated() )
+ FlashWindow(true);
+
+ if( AppConfig.BeepOnBell )
+ gdk_display_beep(gdk_display_get_default());
+ if( GetCurView() == con )
+ return;
+ string markup = "<span foreground=\"red\">";
+ markup += con->GetCon()->m_Site.m_Name;
+ markup += "</span>";
+ m_pNotebook->SetPageTitle( con, markup);
+}
+
+void CMainFrame::OnTelnetConClose(CTelnetView* con)
+{
+ if( !con )
+ return;
+ string markup = "<span foreground=\"#808080\">";
+ markup += con->GetCon()->m_Site.m_Name;
+ markup += "</span>";
+ m_pNotebook->SetPageTitle( con, markup);
+}
+
+void CMainFrame::OnTelnetConConnect(CTelnetView* con)
+{
+ if( !con )
+ return;
+ m_pNotebook->SetPageTitle( con, con->GetCon()->m_Site.m_Name );
+}
+
+
+void CMainFrame::OnTelnetConRecv(CTelnetView* con)
+{
+ if( !con )
+ return;
+
+ // If the text color of the label is red which indicate
+ // there is new incoming message, we should return.
+// if( )
+// return;
+ string markup = "<span foreground=\"green\">";
+ markup += con->GetCon()->m_Site.m_Name;
+ markup += "</span>";
+ m_pNotebook->SetPageTitle( con, markup);
+}
+
+
+void CMainFrame::OnNotebookChangeCurPage(GtkNotebook* widget UNUSED,
+ GtkNotebookPage* page UNUSED,
+ gint page_num,
+ CMainFrame* _this)
+{
+ _this->SetCurView( _this->m_Views[page_num] );
+ if( _this->GetCurEditor() != NULL )
+ _this->m_eView = (CEditorView *) _this->m_Views[page_num];
+}
+
+gboolean CMainFrame::OnNotebookPopupMenu(GtkWidget *widget,
+ GdkEventButton *event,
+ CMainFrame* _this)
+{
+ /* initialized once */
+ static GtkWidget *menu = NULL;
+ static GtkWidget *menu_item_close = NULL;
+
+ if (menu == NULL) {
+ // set menu items
+ GtkWidget *menu_item_close =
+ gtk_image_menu_item_new_with_label( _("Close") );
+ GtkWidget *menu_item_reconnect =
+ gtk_image_menu_item_new_with_label( _("Reconnect") );
+ GtkWidget *menu_item_add2fav =
+ gtk_image_menu_item_new_with_label( _("Add to Favorites") );
+
+ // set images
+ GtkWidget *image_close =
+ gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+ GtkWidget *image_reconnect =
+ gtk_image_new_from_stock (GTK_STOCK_UNDO, GTK_ICON_SIZE_MENU);
+ GtkWidget *image_add2fav =
+ gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+
+ gtk_image_menu_item_set_image (
+ (GtkImageMenuItem *) menu_item_close, image_close);
+ gtk_image_menu_item_set_image (
+ (GtkImageMenuItem *) menu_item_reconnect, image_reconnect);
+ gtk_image_menu_item_set_image (
+ (GtkImageMenuItem *) menu_item_add2fav, image_add2fav);
+
+ menu = gtk_menu_new();
+
+ // widgets show
+ gtk_widget_show (menu_item_reconnect);
+ gtk_container_add (GTK_CONTAINER (menu), menu_item_reconnect);
+
+ gtk_widget_show (menu_item_close);
+ gtk_container_add (GTK_CONTAINER (menu), menu_item_close);
+
+ gtk_widget_show (menu_item_add2fav);
+ gtk_container_add (GTK_CONTAINER (menu), menu_item_add2fav);
+
+ // signals
+ g_signal_connect ( G_OBJECT(menu_item_reconnect), "activate",
+ G_CALLBACK (CMainFrame::OnReconnect),
+ _this);
+ g_signal_connect ( G_OBJECT(menu_item_close), "activate",
+ G_CALLBACK (CMainFrame::OnCloseCon),
+ _this);
+ g_signal_connect ( G_OBJECT(menu_item_add2fav), "activate",
+ G_CALLBACK (CMainFrame::OnAddToFavorites),
+ _this);
+ }
+
+
+ if (event->button == 1) {
+ // Left-click
+ return FALSE;
+
+ } else if (event->button == 2 && AppConfig.MidClickAsClose) {
+ // Feature: let mouse middle click be able to close tab
+ // similar to the behavior under Firefox
+ _this->OnCloseSelectCon(widget, GTK_MENU_ITEM(menu_item_close), _this);
+ return TRUE;
+
+ } else if (event->button == 3) {
+ // Let right-click be able to popup menu on the right tab
+ _this->OnPopupMenuSelectCon(widget, menu, event, _this);
+ return TRUE;
+
+ } else {
+ return FALSE;
+ }
+
+}
+
+void CMainFrame::CloseConAndPageSwitch(int idx, bool confirm UNUSED, GtkWidget *notebook, int page_idx)
+{
+ m_pNotebook->RemovePage(idx);
+ m_Views.erase( m_Views.begin() + idx );
+
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_idx);
+ SetCurView( page_idx >= 0 ? m_Views[page_idx] : NULL );
+}
+
+void CMainFrame::CloseCon(int idx, bool confirm UNUSED)
+{
+ m_pNotebook->RemovePage(idx);
+ m_Views.erase( m_Views.begin() + idx );
+
+ int n = m_pNotebook->GetCurPage();
+ SetCurView( n >= 0 ? m_Views[n] : NULL );
+}
+
+gboolean CMainFrame::OnBlinkTimer(CMainFrame* _this)
+{
+ if( _this->m_IsFlashing )
+ {
+ if( gtk_window_get_icon( GTK_WINDOW(_this->m_Widget) ) == _this->m_MainIcon )
+ gtk_window_set_icon( GTK_WINDOW(_this->m_Widget), _this->m_InverseMainIcon );
+ else
+ gtk_window_set_icon( GTK_WINDOW(_this->m_Widget), _this->m_MainIcon );
+ }
+
+ if(_this->GetCurView() && _this->GetCurView()->IsVisible() )
+ _this->GetCurView()->OnBlinkTimer();
+ return true;
+}
+
+gboolean CMainFrame::OnWindowStateEvent(GtkWindow* window,
+ GdkEventWindowState* event,
+ CMainFrame* _this)
+{
+ if ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) == GDK_WINDOW_STATE_MAXIMIZED) {
+ if ((event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == GDK_WINDOW_STATE_MAXIMIZED) {
+ AppConfig.Maximized = true;
+ } else {
+ AppConfig.Maximized = false;
+ }
+ }
+ return true;
+}
+
+gboolean CMainFrame::OnClose( GtkWidget* widget UNUSED,
+ GdkEvent* evt UNUSED,
+ CMainFrame* _this )
+{
+ return !_this->CanClose();
+}
+
+
+void CMainFrame::OnDestroy()
+{
+ g_source_remove( m_BlinkTimer );
+ g_source_remove( m_EverySecondTimer );
+
+ Hide();
+#ifdef USE_DOCKLET
+ g_object_unref( m_TrayIcon );
+#endif
+
+ //while( g_main_context_iteration(NULL, FALSE) );
+ while (gtk_events_pending())
+ gtk_main_iteration();
+
+ CWidget::OnDestroy();
+
+#ifdef USE_SCRIPT
+ FinalizeScriptInterface();
+#endif
+
+ gtk_main_quit();
+
+ if (m_dlhandle != NULL) {
+ lt_dlclose(m_dlhandle);
+ m_dlhandle = NULL;
+ }
+}
+
+
+void CMainFrame::OnCreate()
+{
+ CWidget::OnCreate();
+ LoadStartupSites();
+}
+
+bool CMainFrame::CanClose()
+{
+ if( GetNotebook()->GetPageCount() == 0 || !AppConfig.QueryOnExit )
+ return true;
+
+ GtkWidget* dlg = gtk_message_dialog_new( (GtkWindow*)m_Widget,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
+ _("Quit PCManX ?"));
+ bool close = gtk_dialog_run((GtkDialog*)dlg) == GTK_RESPONSE_OK;
+ gtk_widget_destroy(dlg);
+ return close;
+}
+
+
+void CMainFrame::NotImpl(const char* str)
+{
+ GtkWidget* dlg = gtk_message_dialog_new( (GtkWindow*)m_Widget,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ _("Function not implemented yet!\nDebug: %s"), str);
+ gtk_dialog_run((GtkDialog*)dlg);
+ gtk_widget_destroy(dlg);
+}
+
+
+void CMainFrame::OnAddToFavorites(GtkMenuItem* widget UNUSED,
+ CMainFrame* _this)
+{
+ if(_this->m_Views.empty() )
+ return;
+
+ CSite &site = _this->GetCurCon()->m_Site;
+ CSiteDlg* dlg = new CSiteDlg(_this, _("Add To Favorites"), site );
+ if(dlg->ShowModal() == GTK_RESPONSE_OK)
+ {
+ AppConfig.Favorites.push_back(dlg->m_Site);
+ CSite& newsite = AppConfig.Favorites.back();
+
+ GtkWidget* fav_item = gtk_image_menu_item_new_with_label( newsite.m_Name.c_str() );
+ gtk_widget_show (fav_item);
+ gtk_menu_shell_insert( GTK_MENU_SHELL(_this->m_FavoritesMenu), fav_item,
+ AppConfig.Favorites.size()>0 ? (AppConfig.Favorites.size()-1) : 0 );
+
+ GtkWidget* image = gtk_image_new_from_stock (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU);
+
+ gtk_widget_show (image);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (fav_item), image);
+
+ newsite.m_MenuItem = fav_item;
+
+ g_signal_connect( G_OBJECT(fav_item), "activate",
+ G_CALLBACK(CMainFrame::OnFavorite),
+ _this);
+ }
+ dlg->Destroy();
+}
+
+void CMainFrame::OnEditFavorites(GtkMenuItem* widget UNUSED, CMainFrame* _this)
+{
+ CEditFavDlg* dlg = new CEditFavDlg(_this, AppConfig.Favorites);
+ dlg->ShowModal();
+ AppConfig.Favorites.swap(dlg->m_Sites);
+ AppConfig.SaveFavorites();
+ dlg->Destroy();
+
+ _this->CreateFavoritesMenu();
+}
+
+
+void CMainFrame::CreateFavoritesMenu()
+{
+ GtkWidget* favorites_menu = gtk_menu_new();
+ vector<CSite>::iterator it;
+ for( it = AppConfig.Favorites.begin(); it != AppConfig.Favorites.end(); ++it )
+ {
+ CSite& site = *it;
+ GtkWidget* fav_item;
+ const size_t fav_string_len = 20;
+ fav_item = gtk_image_menu_item_new_with_label(
+ site.m_Name.length() <= fav_string_len ?
+ site.m_Name.c_str() :
+ (site.m_Name.substr(0, fav_string_len) + " ...").c_str());
+ gtk_widget_show (fav_item);
+ gtk_container_add (GTK_CONTAINER (favorites_menu), fav_item);
+
+ GtkWidget* image = gtk_image_new_from_stock (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU);
+ gtk_widget_show (image);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (fav_item), image);
+
+ site.m_MenuItem = fav_item;
+
+ g_signal_connect( G_OBJECT(fav_item), "activate",
+ G_CALLBACK(CMainFrame::OnFavorite),
+ this);
+ }
+
+ GtkWidget* separator3 = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator3);
+ gtk_container_add (GTK_CONTAINER (favorites_menu), separator3);
+ gtk_widget_set_sensitive (separator3, FALSE);
+
+ GtkWidget* add_to_fav_menu = gtk_image_menu_item_new_with_mnemonic (_("_Add to Favorites"));
+ gtk_widget_show (add_to_fav_menu);
+ gtk_container_add (GTK_CONTAINER (favorites_menu), add_to_fav_menu);
+
+ GtkWidget* image347 = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+ gtk_widget_show (image347);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_to_fav_menu), image347);
+
+ GtkWidget* edit_fav_menu = gtk_image_menu_item_new_with_mnemonic (_("_Edit Favorites"));
+
+ gtk_widget_show (edit_fav_menu);
+ gtk_container_add (GTK_CONTAINER (favorites_menu), edit_fav_menu);
+
+ GtkWidget* image348 = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
+ gtk_widget_show (image348);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (edit_fav_menu), image348);
+
+
+ g_signal_connect ((gpointer) add_to_fav_menu, "activate",
+ G_CALLBACK (CMainFrame::OnAddToFavorites),
+ this);
+ g_signal_connect ((gpointer) edit_fav_menu, "activate",
+ G_CALLBACK (CMainFrame::OnEditFavorites),
+ this);
+
+ m_FavoritesMenu = favorites_menu;
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(m_FavoritesMenuItem), favorites_menu);
+}
+
+void CMainFrame::CreateTrayIcon()
+{
+#ifdef USE_DOCKLET
+ // Setup popup menu
+ m_TrayPopup = gtk_ui_manager_get_widget(m_UIManager, "/ui/tray_popup");
+ if (m_dlhandle != NULL) {
+ void*(*app_indicator_new)(const gchar*, const gchar*, gint) =
+ (void*(*)(const gchar*, const gchar*, gint)) lt_dlsym(m_dlhandle, "app_indicator_new");
+ void (*app_indicator_set_menu)(void*, GtkMenu *) =
+ (void (*)(void*, GtkMenu *)) lt_dlsym(m_dlhandle, "app_indicator_set_menu");
+ void (*app_indicator_set_status)(void*, gint) =
+ (void (*)(void*, gint)) lt_dlsym(m_dlhandle, "app_indicator_set_status");
+ m_indicator = app_indicator_new("PCManX", DATADIR "/pixmaps/pcmanx.svg", 0);
+ app_indicator_set_menu(m_indicator, GTK_MENU(m_TrayPopup));
+ if (AppConfig.ShowTrayIcon) {
+ app_indicator_set_status(m_indicator, 1);
+ }
+ else {
+ app_indicator_set_status(m_indicator, 0);
+ }
+ }
+ else {
+ m_TrayIcon = gtk_status_icon_new();
+ gtk_status_icon_set_from_pixbuf(m_TrayIcon, m_MainIcon);
+ gtk_status_icon_set_tooltip(m_TrayIcon, "PCManX");
+
+ g_signal_connect (G_OBJECT (m_TrayIcon), "popup-menu",
+ G_CALLBACK (CMainFrame::OnTray_Popup), this);
+
+ g_signal_connect (G_OBJECT (m_TrayIcon), "activate",
+ G_CALLBACK (CMainFrame::OnTrayButton_Toggled), this);
+ }
+#endif
+}
+
+void CMainFrame::OnFavorite(GtkMenuItem* item, CMainFrame* _this)
+{
+ vector<CSite>::iterator it;
+ for( it = AppConfig.Favorites.begin(); it != AppConfig.Favorites.end(); ++it )
+ {
+ CSite& site = *it;
+ if( site.m_MenuItem == (GtkWidget*)item )
+ {
+ _this->NewCon( site.m_Name, site.m_URL, &site );
+ break;
+ }
+ }
+}
+
+
+static void format_elapsed_time_str( char* time_str, unsigned int sec )
+{
+ static const char* time_format = _("Time Elapsed : %02d : %02d : %02d");
+ unsigned int min = sec / 60;
+ sec %= 60;
+ unsigned int hr = min / 60;
+ min %= 60;
+ sprintf( time_str, time_format, hr, min, sec );
+}
+
+
+void CMainFrame::SetCurView(CTelnetView* view)
+{
+ m_pView = view;
+ if( !m_pView || !m_pView->GetCon() )
+ {
+ gtk_window_set_title (GTK_WINDOW (m_Widget), "PCManX "VERSION );
+ gtk_entry_set_text( GTK_ENTRY(m_URLEntry), "");
+ return;
+ }
+
+ CTelnetCon* con = GetCurCon();
+ gtk_entry_set_text( GTK_ENTRY(m_URLEntry), con->m_Site.m_URL.c_str());
+
+ string title = con->m_Site.m_Name;
+
+ if( ! con->IsClosed() )
+ m_pNotebook->SetPageTitle( m_pView, title );
+
+ title += " - PCManX "VERSION;
+ gtk_window_set_title (GTK_WINDOW (m_Widget), title.c_str() );
+
+ char time_str[100];
+ format_elapsed_time_str(time_str, con->m_Duration);
+ gtk_label_set_text( m_StatusBarTime, time_str );
+
+#ifdef USE_NANCY
+ UpdateBotStatus();
+#endif
+
+}
+
+void CMainFrame::OnSelectAll(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ CTelnetCon* con = _this->GetCurCon();
+ if( con )
+ {
+ con->m_Sel->SelectPage();
+ _this->GetCurView()->Refresh();
+ }
+}
+
+void CMainFrame::LoadStartupSites()
+{
+ vector<CSite>::iterator it=AppConfig.Favorites.begin();
+ for( it = AppConfig.Favorites.begin(); it != AppConfig.Favorites.end(); ++it )
+ {
+ CSite& site = *it;
+ if( site.m_Startup )
+ NewCon( site.m_Name, site.m_URL, &site);
+ }
+ m_pNotebook->SetCurPage(0);
+}
+
+gboolean CMainFrame::OnEverySecondTimer(CMainFrame* _this)
+{
+ vector<CTelnetView*>::iterator it;
+ for( it = _this->m_Views.begin(); it != _this->m_Views.end(); ++it )
+ {
+ CTelnetView* view = *it;
+ if( view->GetCon() )
+ view->GetCon()->OnTimer();
+ }
+ CTelnetCon* con = _this->GetCurCon();
+ if( con )
+ {
+ char time_str[100];
+ format_elapsed_time_str(time_str, con->m_Duration);
+ gtk_label_set_text( _this->m_StatusBarTime, time_str );
+ }
+ return true;
+}
+
+void CMainFrame::OnEmoticons(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ CEmoticonDlg* dlg = new CEmoticonDlg(_this);
+ if( dlg->ShowModal() == GTK_RESPONSE_OK )
+ {
+ CTelnetView* view = _this->GetCurView();
+ if( view )
+ view->OnTextInput( dlg->GetSelectedStr().c_str() );
+ }
+ dlg->Destroy();
+}
+
+void CMainFrame::OnReconnect(GtkMenuItem* mitem UNUSED, CMainFrame* _this)
+{
+ CTelnetCon* con = _this->GetCurCon();
+ if( !con )
+ return;
+ if( con->IsClosed() )
+ con->Reconnect();
+ else
+ _this->NewCon( con->m_Site.m_Name, con->m_Site.m_URL, &con->m_Site);
+}
+
+void CMainFrame::FlashWindow( bool flash )
+{
+ GdkPixbuf* icon = (m_IsFlashing = flash) ? m_InverseMainIcon : m_MainIcon;
+ gtk_window_set_icon((GtkWindow*)m_Widget, icon);
+}
+
+
+gboolean CMainFrame::OnActivated( GtkWidget* widget UNUSED,
+ GdkEventFocus* evt UNUSED,
+ CMainFrame* _this )
+{
+ if( _this->m_IsFlashing )
+ _this->FlashWindow(false);
+ return false;
+}
+
+gboolean CMainFrame::OnURLEntryKeyDown(GtkWidget *widget, GdkEventKey *evt, CMainFrame* _this)
+{
+ switch(evt->keyval)
+ {
+ case GDK_Return:
+ case GDK_KP_Enter:
+ {
+ string url = gtk_entry_get_text( GTK_ENTRY(widget) );
+ if( !url.empty() )
+ {
+ _this->NewCon( url, url );
+ return true;
+ }
+ // else goto case GDK_Escape
+ }
+ case GDK_Escape:
+ if( _this->GetCurView() )
+ _this->GetCurView()->SetFocus();
+ else
+ gtk_entry_set_text( GTK_ENTRY(widget), "" );
+ return true;
+ }
+ return false;
+}
+
+gboolean CMainFrame::OnURLEntryKillFocus(GtkWidget* entry,
+ GdkEventFocus* evt UNUSED,
+ CMainFrame* _this)
+{
+ if( _this && _this->GetCurView() )
+ {
+ gtk_entry_set_text( GTK_ENTRY(entry), _this->GetCurCon()->m_Site.m_URL.c_str());
+ gtk_editable_select_region(GTK_EDITABLE(entry), 0, 0);
+ }
+ return FALSE;
+}
+
+
+int CMainFrame::GetViewIndex(CTermView* view)
+{
+ DEBUG( "get view index, view = %p", view );
+ if( !view )
+ return -1;
+ DEBUG( "view->m_Widget = %p", view->m_Widget );
+ return gtk_notebook_page_num( GTK_NOTEBOOK(m_pNotebook->m_Widget), view->m_Widget );
+}
+
+int CMainFrame::GetNearestTab(GtkWidget *widget, GdkEventButton *event )
+{
+ /**
+ * Return the closest tab's number to the cursor
+ */
+ int window_w = 0;
+ int window_h = 0;
+ gtk_window_get_size(GTK_WINDOW(gtk_widget_get_toplevel(widget)), &window_w, &window_h);
+
+ int closet_tab_x = window_w;
+ int number_of_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(widget));
+ int nth_page_number = 0;
+ int number_of_closet_tab = 0;
+ // pick up the tab which is closest to the click location.
+ for(nth_page_number = 0; nth_page_number < number_of_pages; nth_page_number++)
+ {
+ GtkWidget *tab_label;
+ tab_label = gtk_notebook_get_tab_label( GTK_NOTEBOOK(widget),
+ gtk_notebook_get_nth_page(GTK_NOTEBOOK(widget), nth_page_number));
+ int lx, ly;
+ gtk_widget_get_pointer(tab_label, &lx, &ly);
+ if(lx > 0 && lx < closet_tab_x)
+ {
+ closet_tab_x = lx;
+ number_of_closet_tab = nth_page_number;
+ }
+ }
+
+ return number_of_closet_tab;
+}
+
+void CMainFrame::SwitchToCon(CTelnetCon* con)
+{
+ int idx = GetViewIndex( con->GetView() );
+ DEBUG( "switch to con %d", idx );
+ if( idx >= 0 )
+ m_pNotebook->SetCurPage(idx);
+}
+
+#ifdef USE_NANCY
+
+void CMainFrame::OnChangeCurrentBot(GtkRadioAction *action UNUSED,
+ GtkRadioAction *current,
+ CMainFrame* _this)
+{
+ CTelnetCon* con = _this->GetCurCon();
+ if( !con ) return;
+ if( gtk_radio_action_get_current_value(current) == 0 )
+ con->set__UseNancy(false);
+ else
+ con->set__UseNancy(true);
+
+ _this->UpdateBotStatus();
+}
+
+void CMainFrame::OnChangeAllBot(GtkRadioAction *action UNUSED,
+ GtkRadioAction *all,
+ CMainFrame* _this)
+{
+ if( _this->m_Views.empty() ) return;
+ gboolean use_nancy = ( gtk_radio_action_get_current_value(all) != 0 );
+ CTelnetCon::set__OpenConnectionWithNancySupport(use_nancy);
+
+ vector<CTelnetView*>::iterator it = _this->m_Views.begin();
+ for( ; it != _this->m_Views.end() ; ++it )
+ (*it)->GetCon()->set__UseNancy(use_nancy);
+
+ if( use_nancy )
+ gtk_check_menu_item_set_active( (GtkCheckMenuItem*)_this->m_CurBotNancyRadio, true );
+ else
+ gtk_check_menu_item_set_active( (GtkCheckMenuItem*)_this->m_DisableCurBotRadio, true );
+
+ _this->UpdateBotStatus();
+}
+
+void CMainFrame::UpdateBotStatus()
+{
+ if( GetCurCon()->get__UseNancy() )
+ {
+ gtk_check_menu_item_set_active( (GtkCheckMenuItem*)m_CurBotNancyRadio, true );
+ gchar* bot_state = g_markup_printf_escaped( "<span foreground=\"#ff0000\">%s</span>", _("Nancy Bot is enabled") );
+ gtk_label_set_markup( m_StatusBarBotState, bot_state );
+ g_free(bot_state);
+ }
+ else
+ {
+ gtk_check_menu_item_set_active( (GtkCheckMenuItem*)m_DisableCurBotRadio, true );
+ gchar* bot_state = g_markup_printf_escaped( "<span foreground=\"gray\">%s</span>", _("Nancy Bot is disabled") );
+ gtk_label_set_markup( m_StatusBarBotState, bot_state );
+ g_free(bot_state);
+ }
+}
+
+#endif // #ifdef USE_NANCY
+/* vim: set fileencodings=utf-8 tabstop=4 noexpandtab shiftwidth=4 softtabstop=4: */
+
+
+
+/**
+* Open Ansi Editor. Send url string "ansi_editor" to NewCon().
+* The NewCon() method will create CEditor object when the url is "ansi_editor".
+*/
+void CMainFrame::OnAnsiEditor(GtkMenuItem *mitem, CMainFrame *_this)
+{
+ _this->NewCon("Ansi Editor", "ansi_editor");
+}
+
+void CMainFrame::OnOpenAnsiFile(GtkMenuItem *mitem, CMainFrame *_this)
+{
+ GtkWidget *dialog = gtk_file_chooser_dialog_new (
+ "Open Ansi File",
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter, "Ansi file");
+ gtk_file_filter_add_pattern(filter, "*.ans");
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ string path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
+ size_t pos = path.find_last_of("/\\");
+ string filename = path.substr(pos + 1, -1);
+ string title = "AnsiEditor: ";
+ title += filename;
+ _this->NewCon(title, "ansi_editor");
+ _this->GetCurEditor()->EditorActions(CEditor::Load_Ansi_File, path);
+ _this->GetCurEditorView()->UpdateEditor();
+ }
+ gtk_widget_destroy (dialog);
+}
+
+void CMainFrame::OnSaveAnsiFile(GtkMenuItem *mitem, CMainFrame *_this)
+{
+ //do nothing if the current view is not Ansi Editor
+ if ( _this->GetCurEditor() == NULL )
+ return;
+
+ GtkWidget *dialog = gtk_file_chooser_dialog_new (
+ "Save Ansi File",
+ GTK_WINDOW(_this),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter, "Ansi file");
+ gtk_file_filter_add_pattern(filter, "*.ans");
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ string filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
+ _this->GetCurEditor()->EditorActions(CEditor::Save_Ansi_File, filename);
+ }
+ gtk_widget_destroy (dialog);
+}
+
+void CMainFrame::OnClearScreen(GtkMenuItem *mitem, CMainFrame *_this)
+{
+ //do nothing if the current view is not Ansi Editor
+ if ( _this->GetCurEditor() == NULL )
+ return;
+
+ _this->GetCurEditor()->EditorActions(CEditor::Clear_Screen);
+ _this->GetCurEditorView()->UpdateEditor();
+}
+
+/**
+* Set text to blink.
+*/
+void CMainFrame::SetBlink(GtkToggleButton *togglebutton, CMainFrame *_this)
+{
+ //do nothing if the current view is not Ansi Editor
+ if( _this->m_Views.empty() || _this->GetCurEditor() == NULL )
+ return;
+
+ bool blink = (togglebutton->active)? true: false;
+
+ _this->GetCurEditor()->ApplyAnsiColor(-1, blink, -1, -1);
+
+ _this->GetCurEditorView()->SetFocus();
+}
+
+
+void CMainFrame::SetTextColor(GtkComboBox *widget, CMainFrame* _this)
+{
+ //do nothing if the current view is not Ansi Editor
+ if( _this->GetCurEditor() == NULL )
+ return;
+
+ //do not change color if view is empty
+ if( _this->m_Views.empty() )
+ {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(_this->m_cbTextColor), 0);
+ return;
+ }
+
+ int cbIndex = gtk_combo_box_get_active(GTK_COMBO_BOX(_this->m_cbTextColor));
+
+ //index 0 is just a title, not a color. Do nothing
+ if( cbIndex == 0 )
+ return;
+
+ cbIndex--;
+
+ bool bright = (int)(cbIndex / 8);
+
+ int foreground;
+ stringstream ss;
+ ss << cbIndex % 8;
+ ss >> foreground;
+
+ _this->GetCurEditor()->ApplyAnsiColor(bright, -1, foreground, -1);
+ _this->GetCurEditorView()->SetFocus();
+}
+
+
+void CMainFrame::SetBgColor(GtkComboBox *widget, CMainFrame* _this)
+{
+ //do nothing if the current view is not Ansi Editor
+ if( _this->GetCurEditor() == NULL )
+ return;
+
+ //do not change color if view is empty
+ if( _this->m_Views.empty() )
+ {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(_this->m_cbBgColor), 0);
+ return;
+ }
+
+ int cbIndex = gtk_combo_box_get_active(GTK_COMBO_BOX(_this->m_cbBgColor));
+
+ //index 0 is just a title, not a bg color. Do nothing
+ if( cbIndex == 0 )
+ return;
+
+ cbIndex--;
+
+ stringstream ss;
+ ss << cbIndex % 8;
+ int bgColor;
+ ss >> bgColor;
+
+ _this->GetCurEditor()->ApplyAnsiColor(-1, -1, -1, bgColor);
+ _this->GetCurEditorView()->SetFocus();
+}
+
+void CMainFrame::AppendRow(GtkTreeIter *iter, GtkListStore *store, const gchar *display, const gchar *color)
+{
+ gtk_list_store_append(store, iter);
+ gtk_list_store_set(store, iter, 0, display, 1, color, -1);
+}
+
+/**
+* parse the output format from GdkColor: #rrrrggggbbbb to the normal format: #rrggbb
+*/
+void CMainFrame::ParseColor(GdkColor *color, gchar *res, size_t res_len)
+{
+ g_assert(res_len >= 8);
+
+ string color_present = gdk_color_to_string(color);
+
+ res[0] = color_present[0];
+ res[1] = color_present[1];
+ res[2] = color_present[2];
+ res[3] = color_present[5];
+ res[4] = color_present[6];
+ res[5] = color_present[9];
+ res[6] = color_present[10];
+ res[7] = 0;
+}
diff --git a/.pc/pkg-config-instead-of-freetype-config.patch/configure.ac b/.pc/pkg-config-instead-of-freetype-config.patch/configure.ac
new file mode 100644
index 0000000..58c2388
--- /dev/null
+++ b/.pc/pkg-config-instead-of-freetype-config.patch/configure.ac
@@ -0,0 +1,634 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT([pcmanx-gtk2],[1.3],[https://github.com/pcman-bbs/pcmanx/issues])
+AC_CONFIG_HEADERS([config.h])
+AM_INIT_AUTOMAKE([dist-xz no-dist-gzip silent-rules subdir-objects])
+
+LT_PREREQ([2.2.6])
+LT_CONFIG_LTDL_DIR([libltdl])
+LT_INIT([dlopen])
+LTDL_INIT
+
+AM_SILENT_RULES([yes])
+AM_MAINTAINER_MODE
+
+AC_PROG_CXX
+IT_PROG_INTLTOOL([],[no-xml])
+
+dnl define varible by OS
+case "$host" in
+ *solaris*)
+ LIBUTIL=""
+ ;;
+ *)
+ LIBUTIL="-lutil"
+ ;;
+esac
+AC_SUBST(LIBUTIL)
+
+dnl define a new autoconf test, AC_CSRG_BASED, which will define
+dnl CSRG_BASED for BSD systems in config.h.
+AC_DEFUN([AC_CSRG_BASED],
+[AC_MSG_CHECKING([for CSRG based system])
+AC_EGREP_CPP(yes,
+[#if defined(__Darwin__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+yes
+#endif
+],
+[AC_MSG_RESULT([yes])
+AC_DEFINE([CSRG_BASED],[],[Using a BSD system derived from CSRG sources])
+ac_csrg_based=yes],
+[AC_MSG_RESULT([no])
+ac_csrg_based=no])
+AM_CONDITIONAL([CSRG_BASED], test x$ac_csrg_based = xyes)
+])
+
+AC_CSRG_BASED
+
+# Init gettext
+ALL_LINGUAS="zh_TW zh_CN"
+#AM_GNU_GETTEXT([external])
+AM_GNU_GETTEXT_VERSION(0.14.1)
+GETTEXT_PACKAGE=pcmanx
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [The gettext domain])
+AM_GLIB_GNU_GETTEXT
+
+# Project Information
+AC_DEFINE(PROJECT_SITE, "http://code.google.com/p/pcmanx-gtk2/", "Project Site")
+AC_DEFINE(PROJECT_FORUM, "http://groups.google.com/d/forum/pcmanx", "Project Forum")
+
+dnl displaced from acconfig.h
+AH_VERBATIM([PREFIX],[#undef PREFIX])
+AH_VERBATIM([USE_DEBUG],[#undef USE_DEBUG])
+AH_VERBATIM([USE_IPV6],[#undef USE_IPV6])
+AH_VERBATIM([USE_DOCKLET],[#undef USE_DOCKLET])
+AH_VERBATIM([USE_NOTIFIER],[#undef USE_NOTIFIER])
+AH_VERBATIM([USE_LIBNOTIFY],[#undef USE_LIBNOTIFY])
+AH_VERBATIM([USE_SCRIPT],[#undef USE_SCRIPT])
+AH_VERBATIM([USE_NANCY],[#undef USE_NANCY])
+AH_VERBATIM([USE_MOUSE],[#undef USE_MOUSE])
+AH_VERBATIM([USE_EXTERNAL], [#undef USE_EXTERNAL])
+AH_VERBATIM([USE_IPLOOKUP], [#undef USE_IPLOOKUP])
+AH_VERBATIM([USE_PROXY], [#undef USE_PROXY])
+AH_VERBATIM([USE_SIGACTION],[#undef USE_SIGACTION])
+AH_VERBATIM([USING_FREEBSD],[#undef USING_FREEBSD])
+AH_VERBATIM([USING_LINUX],[#undef USING_LINUX])
+AH_VERBATIM([socklen_t],[#undef socklen_t])
+
+AC_PATH_PROG(unamepath, uname)
+if test "_$unamepath" = _; then
+ system="unknown"
+else
+ AC_MSG_CHECKING(system type)
+ system=`$unamepath -s`
+ AC_MSG_RESULT($system)
+ if test "$system" = "Linux"; then
+ AC_DEFINE(USING_LINUX)
+ fi
+ if test "$system" = "FreeBSD"; then
+ AC_DEFINE(USING_FREEBSD)
+ fi
+fi
+
+AM_CONDITIONAL([USING_LINUX], test "x$system" = "xLinux")
+
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [The version of pcmanx_gtk2])
+
+dnl *********************************************************************
+dnl ** configure switches ***********************************************
+dnl *********************************************************************
+
+AC_ARG_ENABLE([debug],
+ AS_HELP_STRING([--enable-debug],
+ [enable Debug (default: no)]),
+ debug=$enableval, debug="no")
+
+AC_ARG_ENABLE([docklet],
+ AS_HELP_STRING([--disable-docklet],
+ [disable docklet / system tray support (default: yes)]),
+ docklet=$enableval, docklet="yes")
+
+AC_ARG_ENABLE([notifier],
+ AS_HELP_STRING([--disable-notifier],
+ [disable popup notifier support (default: yes)]),
+ notifier=$enableval, notifier="yes")
+
+AC_ARG_ENABLE([libnotify],
+ AS_HELP_STRING([--enable-libnotify],
+ [enable popup notifier support by libnotify (default: no)]),
+ libnotify=$enableval, libnotify="no")
+
+dnl AC_ARG_ENABLE([script],
+dnl AS_HELP_STRING([--enable-script],
+dnl [enable script support (default: no)]),
+dnl script=$enableval, script="no")
+
+AC_ARG_ENABLE([nancy],
+ AS_HELP_STRING([--disable-nancy],
+ [disable nancy bot support (default: yes)]),
+ nancy=$enableval, nancy="yes")
+
+AC_ARG_ENABLE([mouse],
+ AS_HELP_STRING([--disable-mouse],
+ [disable mouse click and wheel support (default: yes)]),
+ mouse=$enableval, mouse="yes")
+
+AC_ARG_ENABLE([external],
+ AS_HELP_STRING([--disable-external],
+ [disable external SSH/Telnet support (default: yes)]),
+ external=$enableval, external="yes")
+
+AC_ARG_ENABLE([iplookup],
+ AS_HELP_STRING([--enable-iplookup],
+ [enable IP location lookup. For Simplified Chinese users. Need qqwry.dat. (default: no)]),
+ iplookup=$enableval, iplookup="no")
+
+AC_ARG_ENABLE([proxy],
+ AS_HELP_STRING([--enable-proxy],
+ [enable proxy support (default: no)]),
+ proxy=$enableval, proxy="no")
+
+dnl *********************************************************************
+dnl ** DEBUG ************************************************************
+dnl *********************************************************************
+
+if test "$debug" = yes; then
+ AC_DEFINE(USE_DEBUG)
+fi
+AM_CONDITIONAL(ENABLE_DEBUG, test "$debug" = "yes")
+
+dnl *********************************************************************
+dnl ** GLIB *************************************************************
+dnl *********************************************************************
+
+AM_PATH_GLIB_2_0([2.4.0], [
+ GUI_CFLAGS="$GUI_CFLAGS $GLIB_CFLAGS"
+ GUI_LIBS="$GUI_LIBS $GLIB_LIBS"
+ ], [AC_MSG_ERROR([Cannot find Glib 2.4 (or above version)!])], [gthread])
+
+dnl *********************************************************************
+dnl ** GTK **************************************************************
+dnl *********************************************************************
+
+AM_PATH_GTK_2_0([2.22.0], [
+ GUI_CFLAGS="$GUI_CFLAGS $GTK_CFLAGS"
+ GUI_LIBS="$GUI_LIBS $GTK_LIBS"
+ ], [AC_MSG_ERROR([Cannot find GTK+/X11 2.22 (or above version)!])])
+
+dnl *********************************************************************
+dnl ** Freetype2 ********************************************************
+dnl *********************************************************************
+
+AC_CHECK_FT2()
+GUI_CFLAGS="$GUI_CFLAGS $FT2_CFLAGS"
+GUI_LIBS="$GUI_LIBS $FT2_LIBS"
+
+dnl *********************************************************************
+dnl ** XFT **************************************************************
+dnl *********************************************************************
+
+PKG_CHECK_MODULES([LIBXFT], [xft], [
+ GUI_CFLAGS="$GUI_CFLAGS $LIBXFT_CFLAGS"
+ GUI_LIBS="$GUI_LIBS $LIBXFT_LIBS"
+ ],[AC_MSG_ERROR([pcmanx_gtk2 depends on Xft!])])
+
+dnl *********************************************************************
+dnl ** X11 **************************************************************
+dnl *********************************************************************
+
+PKG_CHECK_MODULES([LIBX11], [x11], [
+ GUI_CFLAGS="$GUI_CFLAGS $LIBX11_CFLAGS"
+ GUI_LIBS="$GUI_LIBS $LIBX11_LIBS"
+ ],[AC_MSG_ERROR([pcmanx_gtk2 depends on libx11-dev])])
+
+dnl *********************************************************************
+dnl ** IPv6 *************************************************************
+dnl *********************************************************************
+
+dnl purely for Solaris
+AC_CHECK_FUNC(select, ,
+ AC_CHECK_LIB(socket, select, ,
+ AC_CHECK_LIB(nsl, select, ,
+ AC_CHECK_LIB(inet, select, ,
+ AC_CHECK_LIB(cposix, select, ,
+ AC_CHECK_LIB(net, select, ,
+ AC_MSG_WARN(i can not find select. you might need to help me)))))))
+AC_CHECK_LIB(socket, select)
+
+if test "$ipv6" = yes; then
+ AC_CHECK_FUNCS(getaddrinfo, have_getaddrinfo=yes)
+ AC_MSG_CHECKING(whether to enable IPv6 support)
+ if test "$have_getaddrinfo" = yes; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_IPV6)
+ else
+ ipv6=no
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+dnl *********************************************************************
+dnl ** Docklet **********************************************************
+dnl *********************************************************************
+
+if test "$docklet" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_DOCKLET, [1], [Enable docklet / system tray support])
+fi
+
+AM_CONDITIONAL(USE_DOCKLET, test "$docklet" = "yes")
+AC_SUBST(USE_DOCKLET)
+
+
+dnl *********************************************************************
+dnl ** Notifier *********************************************************
+dnl *********************************************************************
+
+if test "$notifier" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_NOTIFIER, [1], [Enable popup notifier support])
+fi
+
+AM_CONDITIONAL(USE_NOTIFIER, test "$notifier" = "yes")
+AC_SUBST(USE_NOTIFIER)
+
+if test "$notifier" = "yes"; then
+ if test "$libnotify" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_LIBNOTIFY, [1], [Enable libnotify notifier support])
+ PKG_CHECK_MODULES(LIBNOTIFY, libnotify)
+ CFLAGS="$CFLAGS $LIBNOTIFY_CFLAGS"
+ LIBS="$LIBS $LIBNOTIFY_LIBS"
+ fi
+else
+ AC_MSG_WARN(popup notifier support is not enabled, so this option is invalid.)
+fi
+
+AM_CONDITIONAL(USE_LIBNOTIFY, test "$libnotify" = "yes")
+AC_SUBST(USE_LIBNOTIFY)
+
+dnl *********************************************************************
+dnl ** Script support ***************************************************
+dnl *********************************************************************
+
+dnl if test "$script" = "yes"; then
+dnl AC_MSG_CHECKING([for Python script support])
+dnl AC_DEFINE_UNQUOTED(USE_SCRIPT, [1], [Enable script support])
+dnl PYTHON_INC=`python -c 'import distutils.sysconfig;print distutils.sysconfig.get_python_inc()'`
+dnl real_python_inc="`cd ${PYTHON_INC} 2>/dev/null && pwd`"
+dnl if test -z "${real_python_inc}"; then
+dnl AC_MSG_ERROR([Fatal Error: no Python detected.])
+dnl fi
+dnl PYTHON_VERSION=`python -c 'import distutils.sysconfig;print distutils.sysconfig.get_python_version()'`
+dnl AC_MSG_RESULT([Python $PYTHON_VERSION found.])
+dnl PYTHON_CFLAGS="-I${PYTHON_INC}"
+dnl PYTHON_LIBS="-lpython${PYTHON_VERSION}"
+dnl fi
+
+dnl SCRIPT_CFLAGS="$PYTHON_CFLAGS"
+dnl SCRIPT_LIBS="$PYTHON_LIBS"
+
+AM_CONDITIONAL(USE_SCRIPT, test "$script" = "yes")
+AC_SUBST(USE_SCRIPT)
+dnl AC_SUBST(SCRIPT_CFLAGS)
+dnl AC_SUBST(SCRIPT_LIBS)
+
+dnl *********************************************************************
+dnl ** NancyBot ********************************************************
+dnl *********************************************************************
+
+if test "$nancy" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_NANCY, [1], [Enable NancyBot support])
+fi
+
+AM_CONDITIONAL(USE_NANCY, test "$nancy" = "yes")
+AC_SUBST(USE_NANCY)
+
+dnl *********************************************************************
+dnl ** Mouse Click and Wheel ********************************************
+dnl *********************************************************************
+
+if test "$mouse" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_MOUSE, [1], [Enable mouse click and wheel support])
+fi
+
+AM_CONDITIONAL(USE_MOUSE, test "$mouse" = "yes")
+AC_SUBST(USE_MOUSE)
+
+dnl *********************************************************************
+dnl ** External SSH/Telnet **********************************************
+dnl *********************************************************************
+
+if test "$external" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_EXTERNAL, [1], [Enable external SSH/Telnet support])
+ dnl We need tty utility functions from libutil on Linux
+ LIBS="$LIBS $LIBUTIL"
+fi
+
+AM_CONDITIONAL(USE_EXTERNAL, test "$external" = "yes")
+AC_SUBST(USE_EXTERNAL)
+
+dnl *********************************************************************
+dnl ** IP location lookup support ***********************************
+dnl *********************************************************************
+
+if test "$iplookup" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_IPLOOKUP, [1], [Enable IP location lookup])
+fi
+
+AM_CONDITIONAL(USE_IPLOOKUP, test "$iplookup" = "yes")
+AC_SUBST(USE_IPLOOKUP)
+
+dnl *********************************************************************
+dnl ** proxy support ***********************************
+dnl *********************************************************************
+
+if test "$proxy" = "yes"; then
+ AC_DEFINE_UNQUOTED(USE_PROXY, [1], [Enable proxy support])
+fi
+
+AM_CONDITIONAL(USE_PROXY, test "$proxy" = "yes")
+AC_SUBST(USE_PROXY)
+
+dnl *********************************************************************
+dnl ** GCC FLAGS ********************************************************
+dnl *********************************************************************
+
+dnl CACHED_TRY_COMPILE(<description>,<cachevar>,<include>,<program>,<ifyes>,<ifno>)
+AC_DEFUN([CACHED_TRY_COMPILE],[
+ AC_MSG_CHECKING($1)
+ AC_CACHE_VAL($2,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$3]], [[$4]])],[$2=yes],[$2=no])
+ ])
+ if test "x$$2" = xyes; then
+ true
+ $5
+ else
+ true
+ $6
+ fi
+])
+
+dnl GCC_ATTRIBUTE(<short-label>,<cachevar>,<func-params>,<attribute>,<HAVE>,<desc>,[<true-cmds>],[<false-cmds>])
+AC_DEFUN([GCC_ATTRIBUTE],[
+ CACHED_TRY_COMPILE(__attribute__(($1)),ac_cv_c_gcc_attribute_$2,,
+ [extern int testfunction($3) __attribute__(($4))],
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GNUC25_$5,,$6)
+ $7,
+ AC_MSG_RESULT(no)
+ $8)
+])
+
+AC_DEFUN([GCC_ATTRIBUTE_SUPPORTED],[
+ GCC_ATTRIBUTE([,,],supported,[int x],[,,],ATTRIB,[Define if function attributes a la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C attributes. */
+#ifndef FUNCATTR
+#ifdef HAVE_GNUC25_ATTRIB
+#define FUNCATTR(x) __attribute__(x)
+#else
+#define FUNCATTR(x)
+#endif
+#endif])
+
+])
+AC_DEFUN([GCC_ATTRIBUTE_CONST],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(const,const,[int x],const,CONST,[Define if constant functions a la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C constant functions, or null. */
+#ifndef ATTRCONST
+#ifdef HAVE_GNUC25_CONST
+#define ATTRCONST const
+#else
+#define ATTRCONST
+#endif
+#endif
+#ifndef CONSTANT
+#define CONSTANT FUNCATTR((ATTRCONST))
+#endif])
+])
+AC_DEFUN([GCC_ATTRIBUTE_NORETURN],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(noreturn,noreturn,[int x],noreturn,NORETURN,[Define if nonreturning functions a la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C nonreturning functions, or null. */
+#ifndef ATTRNORETURN
+#ifdef HAVE_GNUC25_NORETURN
+#define ATTRNORETURN noreturn
+#else /* ! HAVE_GNUC25_NORETURN */
+#define ATTRNORETURN
+#endif /* HAVE_GNUC25_NORETURN */
+#endif /* ATTRNORETURN */
+#ifndef NONRETURNING
+#define NONRETURNING FUNCATTR((ATTRNORETURN))
+#endif /* NONRETURNING */])
+])
+AC_DEFUN([GCC_ATTRIBUTE_UNUSED],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(unused,unused,[int x],unused,UNUSED,[Define if unused variables la GCC 2.5 and higher are available.])
+ AH_BOTTOM([/* GNU C unused functions, or null. */
+#ifndef ATTRUNUSED
+#ifdef HAVE_GNUC25_UNUSED
+#define ATTRUNUSED unused
+#else
+#define ATTRUNUSED
+#endif
+#endif
+#ifndef UNUSED
+#define UNUSED FUNCATTR((ATTRUNUSED))
+#endif])
+])
+AC_DEFUN([GCC_ATTRIBUTE_PACKED],[
+ AC_REQUIRE([GCC_ATTRIBUTE_SUPPORTED])
+ GCC_ATTRIBUTE(packed,packed,[int x],packed,PACKED,[Define if packing of struct members a la GCC 2.5 and higher is available.])
+ AH_BOTTOM([/* GNU C constant functions, or null. */
+#ifndef ATTRPACKED
+#ifdef HAVE_GNUC25_PACKED
+#define ATTRPACKED packed
+#else
+#define ATTRPACKED
+#endif
+#endif
+#ifndef PACKED
+#define PACKED FUNCATTR((ATTRPACKED))
+#endif])
+])
+
+dnl Only use -Wall and -pipe if we have gcc
+if test "x$GCC" = "xyes"; then
+ if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
+ CFLAGS="$CFLAGS -Wall"
+ fi
+ if test "$system" = "Linux" -o "$system" = "FreeBSD"; then
+ if test -z "`echo "$CFLAGS" | grep "\-pipe" 2> /dev/null`" ; then
+ CFLAGS="$CFLAGS -pipe"
+ fi
+ fi
+ if test -z "`echo "$CFLAGS" | grep "\-g " 2> /dev/null`" ; then
+ CFLAGS="$CFLAGS -g"
+ fi
+
+ GCC_ATTRIBUTE_CONST
+ GCC_ATTRIBUTE_NORETURN
+ GCC_ATTRIBUTE_PACKED
+ GCC_ATTRIBUTE_UNUSED
+fi
+
+dnl *********************************************************************
+dnl ** FUNCTIONS/LIBS/CFLAGS ********************************************
+dnl *********************************************************************
+
+AC_MSG_CHECKING(for modern sigaction)
+dnl libc5 on linux and FreeBSD 3.x doesn't have siginfo_t
+dnl and the sa_sigation field.
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <signal.h>]], [[struct sigaction act;
+ siginfo_t *si;
+ act.sa_sigaction = 0;]])],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_SIGACTION)
+ ],[AC_MSG_RESULT(no)])
+
+dnl if we don't have this, use g_snprintf instead
+AC_CHECK_FUNCS(snprintf)
+AC_CHECK_FUNCS(vsnprintf)
+AC_CHECK_FUNCS(memrchr)
+
+AC_CHECK_FUNC(gethostbyname, ,
+ AC_CHECK_LIB(resolv, gethostbyname, ,
+ AC_CHECK_LIB(nsl, gethostbyname)))
+
+AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(nsl, gethostname))
+
+dnl necessary for IRIX
+AC_CHECK_HEADERS(strings.h)
+
+dnl Check for type in sys/socket.h - from Squid source (GPL)
+AC_CACHE_CHECK(for socklen_t, ac_cv_type_socklen_t, [
+AC_EGREP_CPP([socklen_t[^a-zA-Z_0-9]], [#include <sys/types.h>
+#include <sys/socket.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif],
+ac_cv_type_socklen_t=yes,
+ac_cv_type_socklen_t=no)
+])
+if test $ac_cv_type_socklen_t = no; then
+ AC_DEFINE(socklen_t, int)
+fi
+
+dnl FreeBSD needs this
+LIBS="$LIBS $INTLLIBS"
+CFLAGS="$CFLAGS $CPPFLAGS"
+
+dnl Reduce C++ overhead
+if test "x$GCC" = "xyes"; then
+CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-rtti"
+fi
+LDFLAGS="$LDFLAGS $PACKAGE_LIBS" #-nodefaultlibs -lgcc -lc -lm"
+
+dnl linker optimizations
+AC_MSG_CHECKING([whether $LD accepts --as-needed])
+case `$LD --as-needed -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ LDFLAGS="$LDFLAGS -Wl,--as-needed"
+ AC_MSG_RESULT([yes])
+ ;;
+*)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+AC_MSG_CHECKING([whether $LD accepts -O1])
+case `$LD -O1 -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ LDFLAGS="$LDFLAGS -Wl,-O1"
+ AC_MSG_RESULT([yes])
+ ;;
+*)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+AC_MSG_CHECKING([whether $LD accepts -Bsymbolic-functions])
+case `$LD -Bsymbolic-functions -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ LDFLAGS="$LDFLAGS -Wl,-Bsymbolic-functions"
+ AC_MSG_RESULT([yes])
+ ;;
+*)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+AC_MSG_CHECKING([whether $LD accepts --sort-common])
+case `$LD --sort-common -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ LDFLAGS="$LDFLAGS -Wl,--sort-common"
+ AC_MSG_RESULT([yes])
+ ;;
+*)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+
+dnl Adds -fvisibility=hidden to CFLAGS if running with gcc 4 or greater.
+AC_MSG_CHECKING([whether the compiler supports the visibility arg])
+dnl Check for gcc4 or greater
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+void
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+foo () {};
+#endif
+]], [[]])],[
+ if test "$debug" = yes; then
+dnl It's important for collecting runtime information
+ has_visibility=no
+ else
+ has_visibility=yes
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ CXXFLAGS="$CXXFLAGS -fvisibility=hidden -fvisibility-inlines-hidden"
+ fi
+],[
+ has_visibility=no
+
+])
+AC_MSG_RESULT($has_visibility)
+
+dnl make these visible to all Makefiles
+AC_SUBST(GUI_LIBS)
+AC_SUBST(GUI_CFLAGS)
+LIBTOOL_EXPORT_OPTIONS='-export-symbols-regex "^[[^_]].*"'
+AC_SUBST(LIBTOOL_EXPORT_OPTIONS)
+AC_CONFIG_FILES([
+ Makefile
+ src/Makefile
+ src/charset/Makefile
+ src/core/Makefile
+ po/Makefile.in
+ data/Makefile
+ pcmanx.desktop
+ pcmanx-gtk2.spec
+ Doxygen
+])
+
+AC_OUTPUT
+
+echo
+echo pcmanx_gtk2 ..................... : Version $VERSION
+echo
+echo Prefix........................... : $prefix
+echo Debug support ................... : $debug
+echo Docklet / system tray support ... : $docklet
+echo Popup notifier support........... : $notifier
+echo Libnotify support................ : $libnotify
+echo Nancy bot support ............... : $nancy
+echo Mouse click and wheel support ... : $mouse
+dnl if test "x$script" = "xyes"; then
+dnl echo "Python script support............ : $script (Using Python $PYTHON_VERSION)"
+dnl else
+dnl echo "Python script support............ : $script"
+dnl fi
+echo External SSH/Telnet support...... : $external
+echo iplookup support................. : $iplookup
+echo proxy support.................... : $proxy
+echo
+echo The binary will be installed in $prefix/bin
+echo
+
+echo configure complete, now type \'make\' and pray.
+echo
diff --git a/configure.ac b/configure.ac
index 58c2388..590fc7e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,7 +180,7 @@ dnl *********************************************************************
dnl ** Freetype2 ********************************************************
dnl *********************************************************************
-AC_CHECK_FT2()
+PKG_CHECK_MODULES([FT2], [freetype2])
GUI_CFLAGS="$GUI_CFLAGS $FT2_CFLAGS"
GUI_LIBS="$GUI_LIBS $FT2_LIBS"
diff --git a/debian/changelog b/debian/changelog
index 94430ed..bce763a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+pcmanx-gtk2 (1.3-2) unstable; urgency=medium
+
+ * Use pkg-config instead of freetype-config. (Closes: #892346)
+ * Upstream patch fixing leading char of address missing. (Closes: #856687)
+ * Policy updated to 4.2.1, change priority from extra to optional.
+
+ -- Emfox Zhou <emfox@debian.org> Tue, 23 Oct 2018 11:38:56 +0800
+
pcmanx-gtk2 (1.3-1) unstable; urgency=low
* New upstream release
diff --git a/debian/control b/debian/control
index c609b00..3d5d44b 100644
--- a/debian/control
+++ b/debian/control
@@ -1,9 +1,9 @@
Source: pcmanx-gtk2
Section: x11
-Priority: extra
+Priority: optional
Maintainer: Emfox Zhou <emfox@debian.org>
-Build-Depends: debhelper (>= 9), dh-autoreconf, intltool, libgtk2.0-dev, libnotify-dev, libx11-dev, libltdl-dev
-Standards-Version: 3.9.7
+Build-Depends: debhelper (>= 9), dh-autoreconf, intltool, libgtk2.0-dev, libnotify-dev, libx11-dev, libltdl-dev, pkg-config
+Standards-Version: 4.2.1
Homepage: https://github.com/pcman-bbs/pcmanx/
Vcs-Browser: https://github.com/pcman-bbs/pcmanx/
Vcs-Git: https://github.com/pcman-bbs/pcmanx/
diff --git a/debian/patches/fix-bug-missing-leading-char.patch b/debian/patches/fix-bug-missing-leading-char.patch
new file mode 100644
index 0000000..0dbb7f3
--- /dev/null
+++ b/debian/patches/fix-bug-missing-leading-char.patch
@@ -0,0 +1,15 @@
+--- a/src/mainframe.cpp
++++ b/src/mainframe.cpp
+@@ -285,9 +285,9 @@
+ url = url.substr(first, last - first + 1);
+
+ /* Remove telnet:// from url */
+- first = url.find_first_not_of("telnet://");
+- if (first != string::npos)
+- url.erase(0, first);
++ const string telnetPrefix = "telnet://";
++ if(url.substr(0, telnetPrefix.size()) == telnetPrefix)
++ url.erase(0, telnetPrefix.size());
+
+ if ( site == NULL )
+ site = &AppConfig.m_DefaultSite;
diff --git a/debian/patches/pkg-config-instead-of-freetype-config.patch b/debian/patches/pkg-config-instead-of-freetype-config.patch
new file mode 100644
index 0000000..966fb1e
--- /dev/null
+++ b/debian/patches/pkg-config-instead-of-freetype-config.patch
@@ -0,0 +1,11 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -180,7 +180,7 @@
+ dnl ** Freetype2 ********************************************************
+ dnl *********************************************************************
+
+-AC_CHECK_FT2()
++PKG_CHECK_MODULES([FT2], [freetype2])
+ GUI_CFLAGS="$GUI_CFLAGS $FT2_CFLAGS"
+ GUI_LIBS="$GUI_LIBS $FT2_LIBS"
+
diff --git a/debian/patches/series b/debian/patches/series
index e69de29..9eb6d3e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -0,0 +1,2 @@
+pkg-config-instead-of-freetype-config.patch
+fix-bug-missing-leading-char.patch
diff --git a/src/mainframe.cpp b/src/mainframe.cpp
index 35856f2..89c4ee3 100644
--- a/src/mainframe.cpp
+++ b/src/mainframe.cpp
@@ -285,9 +285,9 @@ CTelnetCon* CMainFrame::NewCon(string title, string url, CSite* site )
url = url.substr(first, last - first + 1);
/* Remove telnet:// from url */
- first = url.find_first_not_of("telnet://");
- if (first != string::npos)
- url.erase(0, first);
+ const string telnetPrefix = "telnet://";
+ if(url.substr(0, telnetPrefix.size()) == telnetPrefix)
+ url.erase(0, telnetPrefix.size());
if ( site == NULL )
site = &AppConfig.m_DefaultSite;