diff --git a/gajim/data/style/gajim.css b/gajim/data/style/gajim.css
index c9f982e748e7a70d5f1818dfb249521186f2493a..33b93131937ad64ffc37f42cde0bb5f9f14b5e6f 100644
--- a/gajim/data/style/gajim.css
+++ b/gajim/data/style/gajim.css
@@ -88,6 +88,20 @@ .conversation-nickname {
     font-size: small;
     font-weight: bold;
 }
+.code-widget {
+    border: 1px solid @borders;
+    border-radius: 4px;
+}
+.code-widget-header {
+    background-color: alpha(@insensitive_fg_color, 0.4);
+    padding: 0 6px;
+}
+.code-widget-header label {
+    font-size: small;
+}
+.code-widget-header button {
+    padding: 0;
+}
 
 .link-button { min-height: 0px; }
 
diff --git a/gajim/gtk/conversation/code_widget.py b/gajim/gtk/conversation/code_widget.py
index 8601bce027c1a4b96ca93a2d8bc2cb2526b8711b..d347543fefac5be4306af5df45ef0005b67772cd 100644
--- a/gajim/gtk/conversation/code_widget.py
+++ b/gajim/gtk/conversation/code_widget.py
@@ -12,34 +12,77 @@
 # You should have received a copy of the GNU General Public License
 # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
 
+import logging
+
 import gi
 gi.require_version('GtkSource', '4')
 from gi.repository import GObject
+from gi.repository import Gdk
 from gi.repository import Gtk
 from gi.repository import GtkSource
 
+from gajim.common.i18n import _
+
+log = logging.getLogger('gajim.gui.conversation.code_widget')
+
 
 class CodeWidget(Gtk.Box):
     def __init__(self, account):
         Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
         self.set_vexpand(True)
+        self.get_style_context().add_class('code-widget')
 
         self._account = account
 
+        header = Gtk.Box()
+        header.set_spacing(6)
+        header.get_style_context().add_class('code-widget-header')
+        self._lang_label = Gtk.Label()
+        header.add(self._lang_label)
+
+        copy_button = Gtk.Button.new_from_icon_name(
+            'edit-copy-symbolic', Gtk.IconSize.MENU)
+        copy_button.set_tooltip_text(_('Copy code snippet'))
+        copy_button.connect('clicked', self._on_copy)
+        header.add(copy_button)
+        self.add(header)
+
         self._textview = CodeTextview()
-        # self._scrolled = Gtk.ScrolledWindow()
-        # self._scrolled.set_policy(Gtk.PolicyType.AUTOMATIC,
-        #                           Gtk.PolicyType.AUTOMATIC)
-        # self._scrolled.set_hexpand(True)
-        # self._scrolled.set_vexpand(True)
-        # self._scrolled.set_propagate_natural_height(True)
-        # self._scrolled.set_max_content_height(400)
-        # self._scrolled.add(self._textview)
+        self._scrolled = Gtk.ScrolledWindow()
+        self._scrolled.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        self._scrolled.set_hexpand(True)
+        self._scrolled.set_vexpand(True)
+        self._scrolled.set_propagate_natural_height(True)
+        self._scrolled.set_max_content_height(400)
+        self._scrolled.add(self._textview)
+
+        self.add(self._scrolled)
 
-        self.add(self._textview)
+    def _on_copy(self, _button):
+        text = self._textview.get_code()
+        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
+        clipboard.set_text(text, -1)
 
     def add_content(self, block):
-        self._textview.print_code(block)
+        code, lang = self._prepare_code(block.text)
+        lang_name = self._textview.set_language(lang)
+        if lang is None:
+            self._lang_label.set_text(_('Code snippet'))
+        else:
+            self._lang_label.set_text(_('Code snippet (%s)') % lang_name)
+
+        self._textview.print_code(code)
+
+    @staticmethod
+    def _prepare_code(text):
+        code_start = text.partition('\n')[0]
+        lang = None
+        if len(code_start) > 3:
+            lang = code_start[3:]
+
+        code = text.partition('\n')[2][:-4]
+        return code, lang
 
 
 class CodeTextview(GtkSource.View):
@@ -51,9 +94,21 @@ def __init__(self):
 
         self._source_manager = GtkSource.LanguageManager.get_default()
 
-    def print_code(self, block):
+    def set_language(self, language_string):
+        if language_string is None:
+            lang = self._source_manager.get_language('python3')
+        else:
+            lang = self._source_manager.get_language(language_string)
+        log.debug('Code snippet lang: %s', lang.get_name())
+        self.get_buffer().set_language(lang)
+        return lang.get_name()
+
+    def get_code(self):
         buffer_ = self.get_buffer()
-        lang = self._source_manager.get_language('python3')
-        buffer_.set_language(lang)
+        start, end = buffer_.get_bounds()
+        return buffer_.get_text(start, end, False)
+
+    def print_code(self, code):
         self.set_show_line_numbers(True)
-        buffer_.insert(buffer_.get_start_iter(), block.text)
+        buffer_ = self.get_buffer()
+        buffer_.insert(buffer_.get_start_iter(), code)