Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--CMakeLists.txt1
-rw-r--r--cmake/FindPCRE2.cmake23
-rw-r--r--data/ui/CMakeLists.txt9
-rw-r--r--data/ui/remmina_preferences.glade210
-rw-r--r--data/ui/remmina_search.glade270
-rw-r--r--data/ui/remmina_search_popover.glade265
-rw-r--r--snap/snapcraft.yaml2
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/remmina_pref.c6
-rw-r--r--src/remmina_pref.h1
-rw-r--r--src/remmina_pref_dialog.c3
-rw-r--r--src/remmina_pref_dialog.h1
-rw-r--r--src/remmina_ssh_plugin.c251
14 files changed, 1003 insertions, 51 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index aa87807bb..5f056cfe5 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -44,6 +44,7 @@ ubuntu:devel:
stage: build
before_script:
- apt-get update -qq
+ - apt-get install -y -qq libpcre2-8-0 libpcre2-dev
script:
- mkdir $BUILD_FOLDER
@@ -60,10 +61,11 @@ ubuntu:devel:
appimage:build:
# image: ubuntu:devel
# stage: cross_environment
- image: registry.gitlab.com/remmina/remmina/ubuntu:16.04
+ image: registry.gitlab.com/remmina/remmina/ubuntu:18.04
stage: build
before_script:
- apt-get update -qq
+ - apt-get install -y -qq libpcre2-8-0 libpcre2-dev wget
script:
- mkdir $BUILD_FOLDER
@@ -93,8 +95,6 @@ appimage:build:
expire_in: 7 days
only:
refs:
- - merge_requests
- - tags
- web
- schedules
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4a4db5e9f..214077ba2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,6 +48,7 @@ include(FindOptionalPackage)
include(ConfigOptions)
include(GtkUpdateIconCache)
include(CheckHasModule)
+include(FindPCRE2)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
diff --git a/cmake/FindPCRE2.cmake b/cmake/FindPCRE2.cmake
new file mode 100644
index 000000000..8654b4422
--- /dev/null
+++ b/cmake/FindPCRE2.cmake
@@ -0,0 +1,23 @@
+find_path(PCRE2_INCLUDE_DIR
+ NAMES pcre2.h
+ PATHS ../../../../libs
+ /usr
+ PATH_SUFFIXES include)
+
+find_library(PCRE2_LIBRARY
+ NAMES pcre2-8
+ PATHS ../../../../libs
+ /usr
+ PATH_SUFFIXES lib)
+
+if (PCRE2_INCLUDE_DIR AND PCRE2_LIBRARY)
+ message(STATUS "found pcre2 headers at ${PCRE2_INCLUDE_DIR}")
+ message(STATUS "found pcre2 libraries at ${PCRE2_LIBRARY}")
+ set(PCRE2_INCLUDE_DIRS ${PCRE2_INCLUDE_DIR})
+ set(PCRE2_LIBRARIES ${PCRE2_LIBRARY})
+ set(PCRE2_FOUND yes)
+else()
+ set(PCRE2_INCLUDE_DIRS)
+ set(PCRE2_LIBRARIES)
+ set(PCRE2_FOUND no)
+endif()
diff --git a/data/ui/CMakeLists.txt b/data/ui/CMakeLists.txt
index 36eb5e2b7..ae40a07ae 100644
--- a/data/ui/CMakeLists.txt
+++ b/data/ui/CMakeLists.txt
@@ -33,12 +33,13 @@
install(FILES remmina_about.glade DESTINATION "${REMMINA_UIDIR}")
+install(FILES remmina_key_chooser.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_main.glade DESTINATION "${REMMINA_UIDIR}")
+install(FILES remmina_mpc.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_news.glade DESTINATION "${REMMINA_UIDIR}")
-install(FILES remmina_spinner.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_preferences.glade DESTINATION "${REMMINA_UIDIR}")
-install(FILES remmina_key_chooser.glade DESTINATION "${REMMINA_UIDIR}")
-install(FILES remmina_string_list.glade DESTINATION "${REMMINA_UIDIR}")
-install(FILES remmina_mpc.glade DESTINATION "${REMMINA_UIDIR}")
+install(FILES remmina_search.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_snap_info_dialog.glade DESTINATION "${REMMINA_UIDIR}")
+install(FILES remmina_spinner.glade DESTINATION "${REMMINA_UIDIR}")
+install(FILES remmina_string_list.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_unlock.glade DESTINATION "${REMMINA_UIDIR}")
diff --git a/data/ui/remmina_preferences.glade b/data/ui/remmina_preferences.glade
index b2fc189bc..f979b906d 100644
--- a/data/ui/remmina_preferences.glade
+++ b/data/ui/remmina_preferences.glade
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.2
+<!-- Generated with glade 3.22.2
Remmina Preferences Dialog -
Copyright (C) Antenore Gatta & Giovanni Panozzo 2014-2020
@@ -1784,14 +1784,13 @@ Author: Antenore Gatta
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">(Host key+)</property>
- <property name="halign">start</property>
<property name="margin_right">18</property>
<signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
- <property name="width">8</property>
+ <property name="width">2</property>
</packing>
</child>
<child>
@@ -1802,14 +1801,13 @@ Author: Antenore Gatta
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">(Host key+)</property>
- <property name="halign">start</property>
<property name="margin_right">18</property>
<signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
- <property name="width">8</property>
+ <property name="width">2</property>
</packing>
</child>
<child>
@@ -1820,14 +1818,13 @@ Author: Antenore Gatta
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">(Host key+)</property>
- <property name="halign">start</property>
<property name="margin_right">18</property>
<signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
- <property name="width">8</property>
+ <property name="width">2</property>
</packing>
</child>
<child>
@@ -1892,7 +1889,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">14</property>
+ <property name="top_attach">15</property>
</packing>
</child>
<child>
@@ -1907,7 +1904,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">14</property>
+ <property name="top_attach">15</property>
<property name="width">8</property>
</packing>
</child>
@@ -1921,7 +1918,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -1933,7 +1930,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -1945,7 +1942,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">2</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -1957,7 +1954,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">3</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -1969,7 +1966,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">4</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -1981,7 +1978,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">5</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -1993,7 +1990,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">6</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -2005,7 +2002,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">7</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -2018,7 +2015,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">8</property>
- <property name="top_attach">13</property>
+ <property name="top_attach">14</property>
</packing>
</child>
<child>
@@ -2030,7 +2027,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2042,7 +2039,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">2</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2054,7 +2051,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">3</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2066,7 +2063,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">4</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2078,7 +2075,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">5</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2090,7 +2087,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">6</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2102,7 +2099,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">7</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2115,7 +2112,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">8</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2128,7 +2125,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">12</property>
+ <property name="top_attach">13</property>
</packing>
</child>
<child>
@@ -2141,7 +2138,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">11</property>
+ <property name="top_attach">12</property>
</packing>
</child>
<child>
@@ -2155,7 +2152,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">11</property>
+ <property name="top_attach">12</property>
<property name="width">8</property>
</packing>
</child>
@@ -2169,7 +2166,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">10</property>
+ <property name="top_attach">11</property>
</packing>
</child>
<child>
@@ -2183,7 +2180,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">10</property>
+ <property name="top_attach">11</property>
<property name="width">8</property>
</packing>
</child>
@@ -2198,7 +2195,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">1</property>
- <property name="top_attach">9</property>
+ <property name="top_attach">10</property>
<property name="width">8</property>
</packing>
</child>
@@ -2212,7 +2209,7 @@ Author: Antenore Gatta
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">9</property>
+ <property name="top_attach">10</property>
</packing>
</child>
<child>
@@ -2220,6 +2217,7 @@ Author: Antenore Gatta
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
+ <property name="margin_left">18</property>
<property name="label" translatable="yes">Increase font size</property>
</object>
<packing>
@@ -2232,6 +2230,7 @@ Author: Antenore Gatta
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
+ <property name="margin_left">18</property>
<property name="label" translatable="yes">Decrease font size</property>
</object>
<packing>
@@ -2247,13 +2246,13 @@ Author: Antenore Gatta
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">(Host key+)</property>
- <property name="halign">start</property>
+ <property name="margin_right">18</property>
<signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">7</property>
- <property name="width">8</property>
+ <property name="width">2</property>
</packing>
</child>
<child>
@@ -2264,15 +2263,152 @@ Author: Antenore Gatta
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">(Host key+)</property>
- <property name="halign">start</property>
+ <property name="margin_right">18</property>
<signal name="clicked" handler="remmina_pref_dialog_on_key_chooser" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">8</property>
- <property name="width">8</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_keyboard_search_text">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_left">18</property>
+ <property name="label" translatable="yes">Search text</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button_keyboard_search_text">
+ <property name="label">Search</property>
+ <property name="width_request">100</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">(Host key+)</property>
+ <property name="margin_right">18</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">9</property>
+ <property name="width">2</property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="position">6</property>
diff --git a/data/ui/remmina_search.glade b/data/ui/remmina_search.glade
new file mode 100644
index 000000000..388664cb8
--- /dev/null
+++ b/data/ui/remmina_search.glade
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.2
+
+-
+Copyright (C) 2016-2020 Antenore Gatta, Giovanni Panozzo
+
+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.
+
+Author: Antenore Gatta
+
+-->
+<interface>
+ <requires lib="gtk+" version="3.18"/>
+ <!-- interface-license-type gplv2 -->
+ <!-- interface-copyright 2016-2020 Antenore Gatta, Giovanni Panozzo -->
+ <!-- interface-authors Antenore Gatta -->
+ <object class="GtkWindow" id="RemminaSearchWidget">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">30</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <property name="placeholder_text" translatable="yes">Search</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_prev_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Search for previous occurrence</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-up-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_next_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Search for next occurrence</property>
+ <child>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-down-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="reveal_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Toggle search options</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ <accessibility>
+ <relation type="controller-for" target="revealer"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">window-close-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="revealer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="transition_type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="match_case_checkbutton">
+ <property name="label" translatable="yes">_Match case</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="entire_word_checkbutton">
+ <property name="label" translatable="yes">Match _entire word only</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="regex_checkbutton">
+ <property name="label" translatable="yes">Match as _regular expression</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="wrap_around_checkbutton">
+ <property name="label" translatable="yes">_Wrap around</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/data/ui/remmina_search_popover.glade b/data/ui/remmina_search_popover.glade
new file mode 100644
index 000000000..de1e21780
--- /dev/null
+++ b/data/ui/remmina_search_popover.glade
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.2
+
+-
+Copyright (C) Antenore Gatta & Giovanni Panozzo
+
+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.
+
+Author: Antenore Gatta
+
+-->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <!-- interface-license-type gplv2 -->
+ <!-- interface-copyright Antenore Gatta & Giovanni Panozzo -->
+ <!-- interface-authors Antenore Gatta -->
+ <object class="GtkPopover" id="SearchPopover">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">30</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <property name="placeholder_text" translatable="yes">Search</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_prev_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Search for previous occurrence</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-up-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_next_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Search for next occurrence</property>
+ <child>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">go-down-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="reveal_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <property name="tooltip_text" translatable="yes">Toggle search options</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ <accessibility>
+ <relation type="controller-for" target="revealer"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">window-close-symbolic</property>
+ <property name="use_fallback">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="revealer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="transition_type">none</property>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="match_case_checkbutton">
+ <property name="label" translatable="yes">_Match case</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="entire_word_checkbutton">
+ <property name="label" translatable="yes">Match _entire word only</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="regex_checkbutton">
+ <property name="label" translatable="yes">Match as _regular expression</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="wrap_around_checkbutton">
+ <property name="label" translatable="yes">_Wrap around</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">False</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 65f8e4015..0b1bb69de 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -159,6 +159,7 @@ parts:
- libvte-2.91-dev
- libxkbfile-dev
- libwebkit2gtk-4.0-dev
+ - libpcre2-dev
stage-packages:
- libgpm2
- libssh-4
@@ -265,6 +266,7 @@ parts:
- libxdmcp6
- libogg0
- libvorbis0a
+ - libpcre2-8-0
# Needed for the example .wav files for testing purposes
- alsa-utils
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 770e82615..1e32fc8ea 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -222,6 +222,12 @@ if(GTK3_FOUND)
endif()
endif()
+include(FindPCRE2)
+if (NOT PCRE2_FOUND)
+ message(FATAL_ERROR "require pcre2")
+endif ()
+include_directories(${PCRE2_INCLUDE_DIRS})
+
add_subdirectory(external_tools)
install(TARGETS remmina DESTINATION ${CMAKE_INSTALL_BINDIR})
diff --git a/src/remmina_pref.c b/src/remmina_pref.c
index 0f60a9a63..f1d8cbb7a 100644
--- a/src/remmina_pref.c
+++ b/src/remmina_pref.c
@@ -646,6 +646,12 @@ void remmina_pref_init(void)
else
remmina_pref.vte_shortcutkey_decrease_font = GDK_KEY_Page_Down;
+ if (g_key_file_has_key(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text", NULL))
+ remmina_pref.vte_shortcutkey_search_text = g_key_file_get_integer(gkeyfile, "remmina_pref", "vte_shortcutkey_search_text",
+ NULL);
+ else
+ remmina_pref.vte_shortcutkey_search_text = GDK_KEY_g;
+
/* If we have a color scheme file, we switch to it, GIO will merge it in the
* remmina.pref file */
diff --git a/src/remmina_pref.h b/src/remmina_pref.h
index 729cf983a..e13f2db81 100644
--- a/src/remmina_pref.h
+++ b/src/remmina_pref.h
@@ -171,6 +171,7 @@ typedef struct _RemminaPref {
guint vte_shortcutkey_select_all;
guint vte_shortcutkey_increase_font;
guint vte_shortcutkey_decrease_font;
+ guint vte_shortcutkey_search_text;
/* In View menu */
gboolean hide_toolbar;
gboolean small_toolbutton;
diff --git a/src/remmina_pref_dialog.c b/src/remmina_pref_dialog.c
index b19163272..de4863107 100644
--- a/src/remmina_pref_dialog.c
+++ b/src/remmina_pref_dialog.c
@@ -350,6 +350,7 @@ void remmina_pref_on_dialog_destroy(GtkWidget *widget, gpointer user_data)
remmina_pref.vte_shortcutkey_select_all = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_select_all));
remmina_pref.vte_shortcutkey_increase_font = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_increase_font));
remmina_pref.vte_shortcutkey_decrease_font = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_decrease_font));
+ remmina_pref.vte_shortcutkey_search_text = remmina_key_chooser_get_keyval(gtk_button_get_label(remmina_pref_dialog->button_keyboard_search_text));
remmina_pref_save();
remmina_pref_init();
@@ -609,6 +610,7 @@ static void remmina_pref_dialog_init(void)
remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_select_all, remmina_pref.vte_shortcutkey_select_all);
remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_increase_font, remmina_pref.vte_shortcutkey_increase_font);
remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_decrease_font, remmina_pref.vte_shortcutkey_decrease_font);
+ remmina_pref_dialog_set_button_label(remmina_pref_dialog->button_keyboard_search_text, remmina_pref.vte_shortcutkey_search_text);
remmina_plugin_manager_for_each_plugin(REMMINA_PLUGIN_TYPE_PREF, remmina_pref_dialog_add_pref_plugin, remmina_pref_dialog->dialog);
@@ -693,6 +695,7 @@ GtkDialog* remmina_pref_dialog_new(gint default_tab, GtkWindow *parent)
remmina_pref_dialog->button_keyboard_select_all = GTK_BUTTON(GET_OBJECT("button_keyboard_select_all"));
remmina_pref_dialog->button_keyboard_increase_font = GTK_BUTTON(GET_OBJECT("button_keyboard_increase_font"));
remmina_pref_dialog->button_keyboard_decrease_font = GTK_BUTTON(GET_OBJECT("button_keyboard_decrease_font"));
+ remmina_pref_dialog->button_keyboard_search_text = GTK_BUTTON(GET_OBJECT("button_keyboard_search_text"));
remmina_pref_dialog->label_terminal_foreground = GTK_LABEL(GET_OBJECT("label_terminal_foreground"));
remmina_pref_dialog->colorbutton_foreground = GTK_COLOR_BUTTON(GET_OBJECT("colorbutton_foreground"));
remmina_pref_dialog->label_terminal_background = GTK_LABEL(GET_OBJECT("label_terminal_background"));
diff --git a/src/remmina_pref_dialog.h b/src/remmina_pref_dialog.h
index 233713b29..2fc2a3cd8 100644
--- a/src/remmina_pref_dialog.h
+++ b/src/remmina_pref_dialog.h
@@ -114,6 +114,7 @@ typedef struct _RemminaPrefDialog {
GtkButton * button_keyboard_select_all;
GtkButton * button_keyboard_increase_font;
GtkButton * button_keyboard_decrease_font;
+ GtkButton * button_keyboard_search_text;
GtkLabel * label_terminal_cursor_color;
GtkLabel * label_terminal_normal_colors;
GtkLabel * label_terminal_bright_colors;
diff --git a/src/remmina_ssh_plugin.c b/src/remmina_ssh_plugin.c
index de533a20a..007d4ed42 100644
--- a/src/remmina_ssh_plugin.c
+++ b/src/remmina_ssh_plugin.c
@@ -43,6 +43,8 @@
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
#include <vte/vte.h>
#include <locale.h>
#include <langinfo.h>
@@ -55,11 +57,16 @@
#include "remmina_ssh_plugin.h"
#include "remmina_masterthread_exec.h"
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
+
#define REMMINA_PLUGIN_SSH_FEATURE_TOOL_COPY 1
#define REMMINA_PLUGIN_SSH_FEATURE_TOOL_PASTE 2
#define REMMINA_PLUGIN_SSH_FEATURE_TOOL_SELECT_ALL 3
#define REMMINA_PLUGIN_SSH_FEATURE_TOOL_INCREASE_FONT 4
#define REMMINA_PLUGIN_SSH_FEATURE_TOOL_DECREASE_FONT 5
+#define REMMINA_PLUGIN_SSH_FEATURE_TOOL_SEARCH 6
#define GET_PLUGIN_DATA(gp) (RemminaPluginSshData *)g_object_get_data(G_OBJECT(gp), "plugin-data");
@@ -200,6 +207,29 @@ static struct {
/** The SSH plugin implementation */
+typedef struct _RemminaSshSearch {
+ GtkWidget* parent;
+
+ GtkBuilder* builder;
+ GtkWidget* window;
+ GtkWidget* search_entry;
+ GtkWidget* search_prev_button;
+ GtkWidget* search_next_button;
+ GtkWidget* close_button;
+ GtkToggleButton* match_case_checkbutton;
+ GtkToggleButton* entire_word_checkbutton;
+ GtkToggleButton* regex_checkbutton;
+ GtkToggleButton* wrap_around_checkbutton;
+ GtkWidget* reveal_button;
+ GtkWidget* revealer;
+
+ //VteTerminal *terminal;
+ gboolean regex_caseless;
+ gboolean has_regex;
+ gchar* regex_pattern;
+
+} RemminaSshSearch;
+
typedef struct _RemminaPluginSshData {
RemminaSSHShell * shell;
GFile * vte_session_file;
@@ -208,9 +238,13 @@ typedef struct _RemminaPluginSshData {
const GdkRGBA * palette;
pthread_t thread;
+
+ RemminaSshSearch * search_widget;
} RemminaPluginSshData;
+#define GET_OBJECT(object_name) gtk_builder_get_object(search_widget->builder, object_name)
+
static RemminaPluginService *remmina_plugin_service = NULL;
static gboolean
@@ -343,12 +377,6 @@ void remmina_plugin_ssh_vte_terminal_set_encoding_and_pty(VteTerminal *terminal,
setlocale(LC_ALL, "");
if (codeset && codeset[0] != '\0') {
-#if VTE_CHECK_VERSION(0, 38, 0)
- vte_terminal_set_encoding(terminal, codeset, NULL);
-#else
- vte_terminal_set_emulation(terminal, "xterm");
- vte_terminal_set_encoding(terminal, codeset);
-#endif
}
vte_terminal_set_backspace_binding(terminal, VTE_ERASE_ASCII_DELETE);
@@ -504,6 +532,206 @@ static void remmina_ssh_keystroke(RemminaProtocolWidget *gp, const guint keystro
return;
}
+
+/* regex */
+
+static void jit_regex(VteRegex* regex, char const* pattern)
+{
+ TRACE_CALL(__func__);
+ GError *error;
+ if (!vte_regex_jit(regex, PCRE2_JIT_COMPLETE, &error) ||
+ !vte_regex_jit(regex, PCRE2_JIT_PARTIAL_SOFT, &error)) {
+ if (!g_error_matches(error, VTE_REGEX_ERROR, -45 /* PCRE2_ERROR_JIT_BADOPTION: JIT not supported */))
+ REMMINA_DEBUG("JITing regex \"%s\" failed: %s\n", pattern, error->message);
+ }
+}
+
+static VteRegex* compile_regex_for_search(char const* pattern, gboolean caseless, GError** error)
+{
+ TRACE_CALL(__func__);
+ uint32_t flags = PCRE2_UTF | PCRE2_NO_UTF_CHECK | PCRE2_MULTILINE;
+ if (caseless)
+ flags |= PCRE2_CASELESS;
+
+ VteRegex *regex = vte_regex_new_for_search(pattern, strlen(pattern), flags, error);
+ if (regex != NULL)
+ jit_regex(regex, pattern);
+
+ return regex;
+}
+
+static void
+remmina_search_widget_update_sensitivity(RemminaSshSearch* search_widget)
+{
+ TRACE_CALL(__func__);
+ gboolean can_search = search_widget->has_regex;
+
+ gtk_widget_set_sensitive(search_widget->search_next_button, can_search);
+ gtk_widget_set_sensitive(search_widget->search_prev_button, can_search);
+}
+
+static void
+remmina_search_widget_update_regex(RemminaPluginSshData* gpdata)
+{
+ TRACE_CALL(__func__);
+ GError *error = NULL;
+
+ RemminaSshSearch *search_widget = gpdata->search_widget;
+ char const* search_text = gtk_entry_get_text(GTK_ENTRY(search_widget->search_entry));
+ gboolean caseless = gtk_toggle_button_get_active(search_widget->match_case_checkbutton) == FALSE;
+
+ char* pattern;
+ if (gtk_toggle_button_get_active(search_widget->regex_checkbutton))
+ pattern = g_strdup(search_text);
+ else
+ pattern = g_regex_escape_string(search_text, -1);
+
+ if (gtk_toggle_button_get_active(search_widget->regex_checkbutton)) {
+ char* tmp = g_strdup_printf("\\b%s\\b", pattern);
+ g_free(pattern);
+ pattern = tmp;
+ }
+
+ if (caseless == search_widget->regex_caseless &&
+ g_strcmp0(pattern, search_widget->regex_pattern) == 0)
+ return;
+
+ search_widget->regex_caseless = caseless;
+ g_free(search_widget->regex_pattern);
+ search_widget->regex_pattern = NULL;
+
+ if (search_text[0] != '\0') {
+ REMMINA_DEBUG("Search text is: %s", search_text);
+ VteRegex *regex = compile_regex_for_search(pattern, caseless, &error);
+ vte_terminal_search_set_regex(VTE_TERMINAL(gpdata->vte), regex, 0);
+ if (regex != NULL)
+ vte_regex_unref(regex);
+
+ if (!error) {
+ search_widget->has_regex = TRUE;
+ search_widget->regex_pattern = pattern; /* adopt */
+ pattern = NULL; /* adopted */
+ gtk_widget_set_tooltip_text(search_widget->search_entry, NULL);
+ } else {
+ search_widget->has_regex = FALSE;
+ REMMINA_DEBUG ("Regex not set, cannot search");
+ gtk_widget_set_tooltip_text(search_widget->search_entry, error->message);
+ }
+ }
+
+ g_free(pattern);
+ g_free(error);
+
+ remmina_search_widget_update_sensitivity(search_widget);
+}
+
+static void
+remmina_search_widget_wrap_around_toggled(GtkToggleButton* button, RemminaPluginSshData* gpdata)
+{
+ TRACE_CALL(__func__);
+
+ vte_terminal_search_set_wrap_around(VTE_TERMINAL(gpdata->vte), gtk_toggle_button_get_active(button));
+}
+
+static void
+remmina_search_widget_search_forward(RemminaPluginSshData* gpdata)
+{
+ TRACE_CALL(__func__);
+
+ RemminaSshSearch *search_sidget = gpdata->search_widget;
+ if (!search_sidget->has_regex)
+ return;
+ vte_terminal_search_find_next(VTE_TERMINAL(gpdata->vte));
+}
+
+static void
+remmina_search_widget_search_backward(RemminaPluginSshData* gpdata)
+{
+ TRACE_CALL(__func__);
+
+ RemminaSshSearch *search_sidget = gpdata->search_widget;
+ if (!search_sidget->has_regex)
+ return;
+ vte_terminal_search_find_previous(VTE_TERMINAL(gpdata->vte));
+}
+
+GtkWidget * remmina_plugin_pop_search_new (GtkWidget *relative_to, RemminaProtocolWidget *gp)
+{
+ TRACE_CALL(__func__);
+ RemminaPluginSshData *gpdata = GET_PLUGIN_DATA(gp);
+
+ gpdata->search_widget = g_new0(RemminaSshSearch, 1);
+ RemminaSshSearch *search_widget = gpdata->search_widget;
+
+ search_widget->regex_caseless = FALSE;
+ search_widget->has_regex = FALSE;
+ search_widget->regex_pattern = NULL;
+
+ search_widget->builder = remmina_public_gtk_builder_new_from_file("remmina_search.glade");
+ search_widget->window = GTK_WIDGET(GET_OBJECT("RemminaSearchWidget"));
+ search_widget->search_entry = GTK_WIDGET(GET_OBJECT("search_entry"));
+ search_widget->search_prev_button = GTK_WIDGET(GET_OBJECT("search_prev_button"));
+ search_widget->search_next_button = GTK_WIDGET(GET_OBJECT("search_next_button"));
+ search_widget->close_button = GTK_WIDGET(GET_OBJECT("close_button"));
+ search_widget->match_case_checkbutton = GTK_TOGGLE_BUTTON(GET_OBJECT("match_case_checkbutton"));
+ search_widget->entire_word_checkbutton = GTK_TOGGLE_BUTTON(GET_OBJECT("entire_word_checkbutton"));
+ search_widget->regex_checkbutton = GTK_TOGGLE_BUTTON(GET_OBJECT("regex_checkbutton"));
+ search_widget->wrap_around_checkbutton = GTK_TOGGLE_BUTTON(GET_OBJECT("wrap_around_checkbutton"));
+ search_widget->reveal_button = GTK_WIDGET(GET_OBJECT("reveal_button"));
+ search_widget->revealer = GTK_WIDGET(GET_OBJECT("revealer"));
+
+ gtk_widget_set_can_default (search_widget->search_next_button, TRUE);
+ gtk_widget_grab_default (search_widget->search_next_button);
+
+ gtk_entry_set_activates_default (GTK_ENTRY(search_widget->search_entry), TRUE);
+
+ /* Connect signals */
+ gtk_builder_connect_signals(search_widget->builder, NULL);
+
+ g_signal_connect_swapped(search_widget->close_button, "clicked", G_CALLBACK(gtk_widget_destroy), GTK_WIDGET(search_widget->window));
+
+ g_object_bind_property(search_widget->reveal_button, "active",
+ search_widget->revealer, "reveal-child",
+ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+ g_signal_connect_swapped(search_widget->search_entry, "next-match", G_CALLBACK(remmina_search_widget_search_forward), gpdata);
+ g_signal_connect_swapped(search_widget->search_entry, "previous-match", G_CALLBACK(remmina_search_widget_search_backward), gpdata);
+ g_signal_connect_swapped(search_widget->search_entry, "search-changed", G_CALLBACK(remmina_search_widget_update_regex), gpdata);
+
+ g_signal_connect_swapped(search_widget->search_next_button,"clicked", G_CALLBACK(remmina_search_widget_search_forward), gpdata);
+ g_signal_connect_swapped(search_widget->search_prev_button,"clicked", G_CALLBACK(remmina_search_widget_search_backward), gpdata);
+
+ g_signal_connect_swapped(search_widget->match_case_checkbutton,"toggled", G_CALLBACK(remmina_search_widget_update_regex), gpdata);
+ g_signal_connect_swapped(search_widget->entire_word_checkbutton,"toggled", G_CALLBACK(remmina_search_widget_update_regex), gpdata);
+ g_signal_connect_swapped(search_widget->regex_checkbutton,"toggled", G_CALLBACK(remmina_search_widget_update_regex), gpdata);
+ g_signal_connect_swapped(search_widget->match_case_checkbutton, "toggled", G_CALLBACK(remmina_search_widget_update_regex), gpdata);
+
+ g_signal_connect(search_widget->wrap_around_checkbutton, "toggled", G_CALLBACK(remmina_search_widget_wrap_around_toggled), gpdata);
+
+ remmina_search_widget_update_sensitivity(search_widget);
+ return search_widget->window;
+
+}
+
+void remmina_plugin_pop_search (GtkMenuItem *menuitem, RemminaProtocolWidget *gp)
+{
+ TRACE_CALL(__func__);
+ RemminaPluginSshData *gpdata = GET_PLUGIN_DATA(gp);
+
+ GtkWindow *parent = NULL;
+
+ REMMINA_DEBUG ("Before popover");
+ GtkWidget *window = remmina_plugin_pop_search_new (gpdata->vte, gp);
+ GtkWidget *toplevel = gtk_widget_get_toplevel (gpdata->vte);
+ if (GTK_IS_WINDOW (toplevel)) {
+ parent = GTK_WINDOW(toplevel);
+ gtk_window_set_transient_for (GTK_WINDOW(window), parent);
+ gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER_ON_PARENT);
+ }
+ gtk_widget_show(window);
+ REMMINA_DEBUG ("After popover");
+}
+
gboolean
remmina_ssh_plugin_popup_menu(GtkWidget *widget, GdkEvent *event, GtkWidget *menu)
{
@@ -546,6 +774,7 @@ void remmina_plugin_ssh_popup_ui(RemminaProtocolWidget *gp)
GtkWidget *save = gtk_menu_item_new_with_label(_("Save session to file"));
GtkWidget *font_incr = gtk_menu_item_new_with_label(_("Increase font size (host+Page Up)"));
GtkWidget *font_decr = gtk_menu_item_new_with_label(_("Decrease font size (host+Page Down)"));
+ GtkWidget *find_text = gtk_menu_item_new_with_label(_("Find text (host+G)"));
gtk_menu_shell_append(GTK_MENU_SHELL(menu), select_all);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), copy);
@@ -553,6 +782,7 @@ void remmina_plugin_ssh_popup_ui(RemminaProtocolWidget *gp)
gtk_menu_shell_append(GTK_MENU_SHELL(menu), save);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), font_incr);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), font_decr);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), find_text);
g_signal_connect(G_OBJECT(gpdata->vte), "button_press_event",
G_CALLBACK(remmina_ssh_plugin_popup_menu), menu);
@@ -569,6 +799,8 @@ void remmina_plugin_ssh_popup_ui(RemminaProtocolWidget *gp)
G_CALLBACK(remmina_plugin_ssh_vte_increase_font), gpdata->vte);
g_signal_connect(G_OBJECT(font_decr), "activate",
G_CALLBACK(remmina_plugin_ssh_vte_decrease_font), gpdata->vte);
+ g_signal_connect(G_OBJECT(find_text), "activate",
+ G_CALLBACK(remmina_plugin_pop_search), gp);
gtk_widget_show_all(menu);
}
@@ -613,7 +845,7 @@ remmina_plugin_ssh_init(RemminaProtocolWidget *gp)
g_signal_connect(G_OBJECT(hbox), "focus-in-event", G_CALLBACK(remmina_plugin_ssh_on_focus_in), gp);
vte = vte_terminal_new();
- gtk_widget_show(vte);
+ //gtk_widget_show(vte);
vte_terminal_set_size(VTE_TERMINAL(vte), 80, 25);
vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(vte), TRUE);
#if !VTE_CHECK_VERSION(0, 38, 0)
@@ -836,6 +1068,7 @@ remmina_plugin_ssh_init(RemminaProtocolWidget *gp)
gpdata->vte_session_file = g_file_new_for_path(fp);
remmina_plugin_ssh_popup_ui(gp);
+ gtk_widget_show_all(hbox);
}
/**
@@ -957,6 +1190,8 @@ remmina_plugin_ssh_call_feature(RemminaProtocolWidget *gp, const RemminaProtocol
case REMMINA_PLUGIN_SSH_FEATURE_TOOL_DECREASE_FONT:
vte_terminal_set_font_scale(VTE_TERMINAL(gpdata->vte),
vte_terminal_get_font_scale(VTE_TERMINAL(gpdata->vte))-SCALE_FACTOR);
+ case REMMINA_PLUGIN_SSH_FEATURE_TOOL_SEARCH:
+ remmina_plugin_pop_search(NULL, gp);
return;
}
}
@@ -1048,6 +1283,7 @@ static RemminaProtocolFeature remmina_plugin_ssh_features[] =
{ REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_SSH_FEATURE_TOOL_SELECT_ALL, N_("Select all"), N_("_Select all"), NULL },
{ REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_SSH_FEATURE_TOOL_INCREASE_FONT, N_("Increase font size"), N_("_Increase font size"), NULL },
{ REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_SSH_FEATURE_TOOL_DECREASE_FONT, N_("Decrease font size"), N_("_Decrease font size"), NULL },
+ { REMMINA_PROTOCOL_FEATURE_TYPE_TOOL, REMMINA_PLUGIN_SSH_FEATURE_TOOL_SEARCH, N_("Find text"), N_("_Find text"), NULL },
{ REMMINA_PROTOCOL_FEATURE_TYPE_END, 0, NULL, NULL, NULL }
};
@@ -1255,6 +1491,7 @@ remmina_ssh_plugin_register(void)
remmina_plugin_ssh_features[2].opt3 = GUINT_TO_POINTER(remmina_pref.vte_shortcutkey_select_all);
remmina_plugin_ssh_features[3].opt3 = GUINT_TO_POINTER(remmina_pref.vte_shortcutkey_increase_font);
remmina_plugin_ssh_features[4].opt3 = GUINT_TO_POINTER(remmina_pref.vte_shortcutkey_decrease_font);
+ remmina_plugin_ssh_features[5].opt3 = GUINT_TO_POINTER(remmina_pref.vte_shortcutkey_search_text);
remmina_plugin_service = &remmina_plugin_manager_service;