← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~vthompson/ubuntu-terminal-app/testing-fix into lp:ubuntu-terminal-app

 

spookje has proposed merging lp:~vthompson/ubuntu-terminal-app/testing-fix into lp:ubuntu-terminal-app.

Requested reviews:
  Ubuntu Terminal Developers (ubuntu-terminal-dev)

For more details, see:
https://code.launchpad.net/~vthompson/ubuntu-terminal-app/testing-fix/+merge/330470
-- 
The attached diff has been truncated due to its size.
Your team Ubuntu Terminal Developers is requested to review the proposed merge of lp:~vthompson/ubuntu-terminal-app/testing-fix into lp:ubuntu-terminal-app.
=== added file '.bzrignore'
--- .bzrignore	1970-01-01 00:00:00 +0000
+++ .bzrignore	2017-09-09 05:25:54 +0000
@@ -0,0 +1,11 @@
+Makefile
+src/*.so
+*.pro.user
+
+.moc/
+.obj/
+
+debian/files
+debian/qtdeclarative5-konsole-qml-plugin/
+debian/*.debhelper.log
+debian/*.substvars
\ No newline at end of file

=== renamed file '.bzrignore' => '.bzrignore.moved'
=== added file 'README'
--- README	1970-01-01 00:00:00 +0000
+++ README	2017-09-09 05:25:54 +0000
@@ -0,0 +1,11 @@
+this is a repository for shared C++ QML plugin, offering access to
+terminal sessions.
+
+if you want to add something, please ask the maintainer of this library first to
+make sure it's a good fit
+
+the current maintainer is: Dmitry Zagnoyko <hiroshidi@xxxxxxxxx>
+
+current plugin consist:
+- KTerminal: offers access to terminal session from qml
+- KSessions: offers access to pty(s) from C++ layer
\ No newline at end of file

=== added directory 'assets'
=== added directory 'assets/color-schemes'
=== added file 'assets/color-schemes/BlackOnLightYellow.schema'
--- assets/color-schemes/BlackOnLightYellow.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/BlackOnLightYellow.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,42 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title Black on Light Yellow
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+color  1 255 255 221  1 0  # regular   background color (Light Yellow)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10   0   0   0  0 1  # intensive foreground color
+color 11 255 255 221  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/BlackOnRandomLight.colorscheme'
--- assets/color-schemes/BlackOnRandomLight.colorscheme	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/BlackOnRandomLight.colorscheme	2017-09-09 05:25:54 +0000
@@ -0,0 +1,104 @@
+[Background]
+Bold=false
+Color=247,247,214
+Transparency=true
+MaxRandomHue=340
+
+[BackgroundIntense]
+Bold=false
+Color=255,255,221
+Transparency=true
+
+[Color0]
+Bold=false
+Color=0,0,0
+Transparency=false
+
+[Color0Intense]
+Bold=false
+Color=104,104,104
+Transparency=false
+
+[Color1]
+Bold=false
+Color=178,24,24
+Transparency=false
+
+[Color1Intense]
+Bold=false
+Color=255,84,84
+Transparency=false
+
+[Color2]
+Bold=false
+Color=24,178,24
+Transparency=false
+
+[Color2Intense]
+Bold=false
+Color=84,255,84
+Transparency=false
+
+[Color3]
+Bold=false
+Color=178,104,24
+Transparency=false
+
+[Color3Intense]
+Bold=false
+Color=255,255,84
+Transparency=false
+
+[Color4]
+Bold=false
+Color=24,24,178
+Transparency=false
+
+[Color4Intense]
+Bold=false
+Color=84,84,255
+Transparency=false
+
+[Color5]
+Bold=false
+Color=178,24,178
+Transparency=false
+
+[Color5Intense]
+Bold=false
+Color=255,84,255
+Transparency=false
+
+[Color6]
+Bold=false
+Color=24,178,178
+Transparency=false
+
+[Color6Intense]
+Bold=false
+Color=84,255,255
+Transparency=false
+
+[Color7]
+Bold=false
+Color=178,178,178
+Transparency=false
+
+[Color7Intense]
+Bold=false
+Color=255,255,255
+Transparency=false
+
+[Foreground]
+Bold=false
+Color=0,0,0
+Transparency=false
+
+[ForegroundIntense]
+Bold=true
+Color=0,0,0
+Transparency=false
+
+[General]
+Description=Black on Random Light
+Opacity=1

=== added file 'assets/color-schemes/BlackOnWhite.schema'
--- assets/color-schemes/BlackOnWhite.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/BlackOnWhite.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,42 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title Black on White
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+color  1 255 255 255  1 0  # regular   background color (White)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10   0   0   0  0 1  # intensive foreground color
+color 11 255 255 255  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/DarkPastels.colorscheme'
--- assets/color-schemes/DarkPastels.colorscheme	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/DarkPastels.colorscheme	2017-09-09 05:25:54 +0000
@@ -0,0 +1,103 @@
+[Background]
+Bold=false
+Color=44,44,44
+Transparency=false
+
+[BackgroundIntense]
+Bold=true
+Color=44,44,44
+Transparency=false
+
+[Color0]
+Bold=false
+Color=63,63,63
+Transparency=false
+
+[Color0Intense]
+Bold=true
+Color=112,144,128
+Transparency=false
+
+[Color1]
+Bold=false
+Color=112,80,80
+Transparency=false
+
+[Color1Intense]
+Bold=true
+Color=220,163,163
+Transparency=false
+
+[Color2]
+Bold=false
+Color=96,180,138
+Transparency=false
+
+[Color2Intense]
+Bold=true
+Color=114,213,163
+Transparency=false
+
+[Color3]
+Bold=false
+Color=223,175,143
+Transparency=false
+
+[Color3Intense]
+Bold=true
+Color=240,223,175
+Transparency=false
+
+[Color4]
+Bold=false
+Color=154,184,215
+Transparency=false
+
+[Color4Intense]
+Bold=true
+Color=148,191,243
+Transparency=false
+
+[Color5]
+Bold=false
+Color=220,140,195
+Transparency=false
+
+[Color5Intense]
+Bold=true
+Color=236,147,211
+Transparency=false
+
+[Color6]
+Bold=false
+Color=140,208,211
+Transparency=false
+
+[Color6Intense]
+Bold=true
+Color=147,224,227
+Transparency=false
+
+[Color7]
+Bold=false
+Color=220,220,204
+Transparency=false
+
+[Color7Intense]
+Bold=true
+Color=255,255,255
+Transparency=false
+
+[Foreground]
+Bold=false
+Color=220,220,204
+Transparency=false
+
+[ForegroundIntense]
+Bold=true
+Color=220,220,204
+Transparency=false
+
+[General]
+Description=Dark Pastels
+Opacity=1

=== added file 'assets/color-schemes/GreenOnBlack.colorscheme'
--- assets/color-schemes/GreenOnBlack.colorscheme	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/GreenOnBlack.colorscheme	2017-09-09 05:25:54 +0000
@@ -0,0 +1,104 @@
+
+[Background]
+Bold=false
+Color=0,0,0
+Transparency=false
+
+[BackgroundIntense]
+Bold=false
+Color=0,0,0
+Transparency=false
+
+[Color0]
+Bold=false
+Color=0,0,0
+Transparency=false
+
+[Color0Intense]
+Bold=false
+Color=104,104,104
+Transparency=false
+
+[Color1]
+Bold=false
+Color=250,75,75
+Transparency=false
+
+[Color1Intense]
+Bold=false
+Color=255,84,84
+Transparency=false
+
+[Color2]
+Bold=false
+Color=24,178,24
+Transparency=false
+
+[Color2Intense]
+Bold=false
+Color=84,255,84
+Transparency=false
+
+[Color3]
+Bold=false
+Color=178,104,24
+Transparency=false
+
+[Color3Intense]
+Bold=false
+Color=255,255,84
+Transparency=false
+
+[Color4]
+Bold=false
+Color=92,167,251
+Transparency=false
+
+[Color4Intense]
+Bold=false
+Color=84,84,255
+Transparency=false
+
+[Color5]
+Bold=false
+Color=225,30,225
+Transparency=false
+
+[Color5Intense]
+Bold=false
+Color=255,84,255
+Transparency=false
+
+[Color6]
+Bold=false
+Color=24,178,178
+Transparency=false
+
+[Color6Intense]
+Bold=false
+Color=84,255,255
+Transparency=false
+
+[Color7]
+Bold=false
+Color=178,178,178
+Transparency=false
+
+[Color7Intense]
+Bold=false
+Color=255,255,255
+Transparency=false
+
+[Foreground]
+Bold=false
+Color=24,240,24
+Transparency=false
+
+[ForegroundIntense]
+Bold=true
+Color=24,240,24
+Transparency=false
+
+[General]
+Description=Green on Black
+Opacity=1

=== added file 'assets/color-schemes/Linux.colorscheme'
--- assets/color-schemes/Linux.colorscheme	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/Linux.colorscheme	2017-09-09 05:25:54 +0000
@@ -0,0 +1,100 @@
+[Background]
+Bold=false
+Color=0,0,0
+
+[BackgroundIntense]
+Bold=false
+Color=104,104,104
+
+[Color0]
+Bold=false
+Color=0,0,0
+
+
+[Color0Intense]
+Bold=false
+Color=104,104,104
+
+
+[Color1]
+Bold=false
+Color=178,24,24
+
+
+[Color1Intense]
+Bold=false
+Color=255,84,84
+
+
+[Color2]
+Bold=false
+Color=24,178,24
+
+
+[Color2Intense]
+Bold=false
+Color=84,255,84
+
+
+[Color3]
+Bold=false
+Color=178,104,24
+
+
+[Color3Intense]
+Bold=false
+Color=255,255,84
+
+
+[Color4]
+Bold=false
+Color=24,24,178
+
+
+[Color4Intense]
+Bold=false
+Color=84,84,255
+
+
+[Color5]
+Bold=false
+Color=178,24,178
+
+
+[Color5Intense]
+Bold=false
+Color=255,84,255
+
+
+[Color6]
+Bold=false
+Color=24,178,178
+
+
+[Color6Intense]
+Bold=false
+Color=84,255,255
+
+
+[Color7]
+Bold=false
+Color=178,178,178
+
+
+[Color7Intense]
+Bold=false
+Color=255,255,255
+
+
+[Foreground]
+Bold=false
+Color=178,178,178
+
+
+[ForegroundIntense]
+Bold=false
+Color=255,255,255
+
+
+[General]
+Description=Linux Colors

=== added file 'assets/color-schemes/WhiteOnBlack.schema'
--- assets/color-schemes/WhiteOnBlack.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/WhiteOnBlack.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,42 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title White on Black
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0 255 255 255  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 1  # intensive foreground color
+color 11   0   0   0  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added directory 'assets/color-schemes/historic'
=== added file 'assets/color-schemes/historic/BlackOnLightColor.schema'
--- assets/color-schemes/historic/BlackOnLightColor.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/BlackOnLightColor.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,42 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title Black on Light Color
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+rcolor 1  30 255      1 0  # regular   background color (Light Color)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10   0   0   0  0 1  # intensive foreground color
+color 11 255 255 221  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/DarkPicture.schema'
--- assets/color-schemes/historic/DarkPicture.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/DarkPicture.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,44 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title Marble
+
+image tile Blkmarble.jpg
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0 255 255 255  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 1  # intensive foreground color
+color 11   0   0   0  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/Example.Schema'
--- assets/color-schemes/historic/Example.Schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/Example.Schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,47 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title Ugly 1
+
+# add a wallpaper, if you like. Second word one of { tile,center,full }
+
+image tile /opt/kde/share/wallpapers/dancy_pants.jpg
+                                                    
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+color  1 255 255 255  1 0  # regular   background color (White)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 255   0   0  0 0  # regular   color 1 Red
+color  4   0 255   0  0 0  # regular   color 2 Green
+color  5 255 255   0  0 0  # regular   color 3 Yellow
+color  6   0   0 255  0 0  # regular   color 4 Blue
+color  7 255   0 255  0 0  # regular   color 5 Magenta
+color  8   0 255 255  0 0  # regular   color 6 Cyan
+color  9 255 255 255  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10   0   0   0  0 1  # intensive foreground color
+color 11 255 255 255  1 1  # intensive background color
+
+color 12   0   0   0  0 1  # intensive color 0
+color 13 255   0   0  0 1  # intensive color 1
+color 14   0 255   0  0 1  # intensive color 2
+color 15 255 255   0  0 1  # intensive color 3
+color 16   0   0 255  0 1  # intensive color 4
+color 17 255   0 255  0 1  # intensive color 5
+color 18   0 255 255  0 1  # intensive color 6
+color 19 255 255 255  0 1  # intensive color 7

=== added file 'assets/color-schemes/historic/GreenOnBlack.schema'
--- assets/color-schemes/historic/GreenOnBlack.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/GreenOnBlack.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,42 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title Green on Black
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0  24 240  24  0 0  # regular   foreground color (Green)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10  24 240  24  0 1  # intensive foreground color
+color 11   0   0   0  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/GreenTint.schema'
--- assets/color-schemes/historic/GreenTint.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/GreenTint.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,49 @@
+# linux color schema for konsole
+
+title Green Tint
+
+transparency 0.3 0 150 0
+
+# FIXME
+#
+# The flaw in this schema is that "blick" comes out on the
+# Linux console as intensive background, really.
+# Since this is not used in clients you'll hardly notice
+# it in practice.
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0 178 178 178  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 0  # intensive foreground color
+color 11 104 104 104  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/GreenTint_MC.schema'
--- assets/color-schemes/historic/GreenTint_MC.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/GreenTint_MC.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,49 @@
+# linux color schema for konsole
+
+title Green Tint with Transparent MC
+
+transparency 0.3 0 150 0
+
+# FIXME
+#
+# The flaw in this schema is that "blick" comes out on the
+# Linux console as intensive background, really.
+# Since this is not used in clients you'll hardly notice
+# it in practice.
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0 178 178 178  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6   0   0   0  1 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 0  # intensive foreground color
+color 11 104 104 104  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/LightPicture.schema'
--- assets/color-schemes/historic/LightPicture.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/LightPicture.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,44 @@
+# example scheme for konsole
+
+# the title is to appear in the menu.
+
+title Paper
+
+image tile Paper01.jpg
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+color  1 255 255 255  1 0  # regular   background color (White)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10   0   0   0  0 1  # intensive foreground color
+color 11 255 255 255  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/Linux.schema'
--- assets/color-schemes/historic/Linux.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/Linux.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,47 @@
+# linux color schema for konsole
+
+title Linux Colors
+
+# FIXME
+#
+# The flaw in this schema is that "blick" comes out on the
+# Linux console as intensive background, really.
+# Since this is not used in clients you'll hardly notice
+# it in practice.
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0 178 178 178  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 0  # intensive foreground color
+color 11 104 104 104  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/README.Schema'
--- assets/color-schemes/historic/README.Schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/README.Schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,132 @@
+[README.Schema]
+
+The schemata offered in the Options/Schema menu are
+taken from from configurations files with a *.schema
+pattern either located in $KDEDIR/share/apps/konsole
+or ~/.kde/share/apps/konsole.
+
+Schemata allow to configure the color set that konsole
+uses, together with some more information on rendition
+processing.
+
+Syntax
+
+  File
+  :: { [Line] ['#' Comment] '\n' }
+
+  Line
+  :: "title" Title
+  :: "image" Usage PathToPictureFile
+  :: "transparency" Fade Red Green Blue
+  :: "color" Slot Red Green Blue Transparent Bold
+  :: "rcolor" Slot Saturation Value Transparent Bold
+  :: "sysfg" Slot Transparent Bold
+  :: "sysbg" Slot Transparent Bold
+
+Meaning
+
+  - Title is the text to appear in the Option/Schema menu.
+    It should be unique among all other schemata therefore.
+
+  - The "image" clause allows to place an image on the
+    konsole's background.
+
+    - Usage can be either
+      - "tile"   - the image is tilewise replicated.
+      - "center" - the image is centered.
+      - "full"   - the image is stretched to fit the window size.
+      
+    - The Path of the picture can both be relative
+      (to kde wallpapers) or absolute.
+      
+    When a schema uses a background image (or transparency)
+    one has to make at least one color slot transparent to
+    achive any visible effect. Please read below about the
+    "Transparent" field in color,sysbg,sysfg.
+
+  - The "transparency" clause picks and uses the background
+    of the desktop as if it where an image together with
+    a fade effect. This effect will fade the background
+    to the specified color.
+
+    The "Fade" is a real value between 0 and 1, indicating
+    the strength of the fade. A value of 0 will not change
+    the image, a value of 1 will make it the fade color
+    everywhere, and in between. This will make the "glas"
+    of the window be of the color given in the clause and
+    being more(1) or less(0) intransparent.
+
+  - The remaining clauses (color,sysbg,sysfg) are used
+    to setup konsoles rendition system.
+
+    To this end, konsole offers 20 color slots.
+
+     Slot  Meaning
+    -----  --------------------------
+        0  regular   foreground color
+        1  regular   background color
+      2-9  regular   bgr color 0-7
+       10  intensive foreground color
+       11  intensive background color
+    12-19  intensive bgr color 0-7
+
+    The traditional meaning of the "bgr" color codes
+    has a bitwise interpretation of an additive three
+    primary color scheme inherited from early EGA
+    color terminals.
+
+    Color  Bits  Colors
+    -----  ----  -------
+        0   000  Black
+        1   001  Red
+        2   010  Green
+        3   011  Yellow
+        4   100  Blue
+        5   101  Magenta
+        6   110  Cyan
+        7   111  White
+
+    One may or may not stick to this tradition.
+    Konsole allows to assign colors freely to slots.
+
+    The slots fall apart into two groups, regular
+    and intensive colors. The later are used when
+    BOLD rendition is used by the client.
+
+    Each of the groups have a default fore- and
+    background color and the said bgr colors.
+    Normal terminal processing will simply use
+    the default colors.
+
+    The color desired for a slot is indicated
+    in the Red Green Blue fields of the color
+    clause. Use the sysfg or the sysbg clause
+    to indicate the default fore and background
+    colors of the desktop.
+
+    To specify randomized color for a slot use
+    the clause rcolor. The two parameters to it 
+    being Saturation - the amount of colour, 
+    and Value, the darkness of the colour.
+
+    To use transparency/images and to simulate
+    the behavior of the xterm, one can supply
+    two additional tags to each slot:
+    - Transparent (0/1) meaning to show the
+      background picture, if any.
+    - Bold (0/1) to render characters bold.
+
+
+If you know about the escape codes, you might have
+noticed that intensive and bold rendition are sort
+of confused. This is inherited by the xterm which
+konsole is simulating.
+
+One can use the colortest.sh script supplied
+with the konsole source distribution to test
+a schema.
+
+The schema installed with konsole are more or
+less demonstrations and not really beauty,
+beside the Linux.schema, perhaps, which is
+made after the VGA colors.

=== added file 'assets/color-schemes/historic/README.default.Schema'
--- assets/color-schemes/historic/README.default.Schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/README.default.Schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,44 @@
+# default scheme for konsole (only here for documentation purposes)
+
+# the title is to appear in the menu.
+
+title Konsole Defaults
+
+# image tile /opt/kde/share/wallpapers/gray2.jpg
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+color  1 255 255 255  1 0  # regular   background color (White)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10   0   0   0  0 1  # intensive foreground color
+color 11 255 255 255  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/Transparent.schema'
--- assets/color-schemes/historic/Transparent.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/Transparent.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,49 @@
+# linux color schema for konsole
+
+title Transparent Konsole
+
+transparency 0.35 0 0 0
+
+# FIXME
+#
+# The flaw in this schema is that "blick" comes out on the
+# Linux console as intensive background, really.
+# Since this is not used in clients you'll hardly notice
+# it in practice.
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0 178 178 178  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 0  # intensive foreground color
+color 11 104 104 104  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/Transparent_MC.schema'
--- assets/color-schemes/historic/Transparent_MC.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/Transparent_MC.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,51 @@
+# linux color schema for konsole
+
+title Transparent for MC
+
+transparency 0.35 0 0 0
+
+# FIXME
+#
+# The flaw in this schema is that "blick" comes out on the
+# Linux console as intensive background, really.
+# Since this is not used in clients you'll hardly notice
+# it in practice.
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0 178 178 178  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+#color  6  24  24 178  0 0  # regular   color 4 Blue
+color  6  0  0 0  1 0  # regular   color 4 Blue
+
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 0  # intensive foreground color
+color 11 104 104 104  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/Transparent_darkbg.schema'
--- assets/color-schemes/historic/Transparent_darkbg.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/Transparent_darkbg.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,42 @@
+# linux color schema for konsole
+
+title Transparent, Dark Background
+
+transparency 0.75 0 0 0
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0 255 255 255  0 0  # regular   foreground color (White)
+color  1   0   0   0  1 0  # regular   background color (Black)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 255 255 255  0 0  # intensive foreground color
+color 11 104 104 104  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/Transparent_lightbg.schema'
--- assets/color-schemes/historic/Transparent_lightbg.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/Transparent_lightbg.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,51 @@
+# linux color schema for konsole
+
+title Transparent, Light Background
+
+transparency 0.1 0 0 0
+
+# This is a schema for very light backgrounds. It makes some
+# hacks about the colors to make Midnight Commander transparent
+# and with suitable colors. 
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0  50  50  50  0 0  # regular   foreground color (DarkGray)
+color  1  200 200 200  1 0  # regular   background color (White)
+
+# color  2   0   0   0  0 0  # regular   color 0 Black
+color  2  200 200 200  1 0  # regular   background color (White)
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+#color  6  24  24 178  0 0  # regular   color 4 Blue
+color  6  0  0 0  1 0  # regular   color 4 Blue
+# Blue is transparent, to make MC transparent
+
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+# color  9 178 178 178  0 0  # regular   color 7 White
+color  9  50  50  50  0 0  # regular   foreground color (DarkGray)
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10 0   0   0  0 0  # intensive foreground color
+color 11 255  255  255  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/XTerm.schema'
--- assets/color-schemes/historic/XTerm.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/XTerm.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,46 @@
+# xterm color schema for konsole
+
+# xterm colors can be configured (almost) like
+# konsole colors can. This is the uncustomized
+# xterm schema. 
+# Please refere to your local xterm setup files
+# if this schema differs.
+
+title XTerm Colors
+
+# foreground colors -------------------------------
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+color  1 255 255 255  1 0  # regular   background color (White)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 205   0   0  0 0  # regular   color 1 Red
+color  4   0 205   0  0 0  # regular   color 2 Green
+color  5 205 205   0  0 0  # regular   color 3 Yellow
+color  6   0   0 205  0 0  # regular   color 4 Blue
+color  7 205   0 205  0 0  # regular   color 5 Magenta
+color  8   0 205 205  0 0  # regular   color 6 Cyan
+color  9 229 229 229  0 0  # regular   color 7 White
+
+# intensive colors -------------------------------------------
+
+# for some strange reason, intensive colors are bold, also.
+
+color 10  77  77  77  0 1  # intensive foreground color
+color 11 255 255 255  1 1  # intensive background color
+
+color 12  77  77  77  0 1  # intensive color 0
+color 13 255   0   0  0 1  # intensive color 1
+color 14   0 255   0  0 1  # intensive color 2
+color 15 255 255   0  0 1  # intensive color 3
+color 16   0   0 255  0 1  # intensive color 4
+color 17 255   0 255  0 1  # intensive color 5
+color 18   0 255 255  0 1  # intensive color 6
+color 19 255 255 255  0 1  # intensive color 7

=== added file 'assets/color-schemes/historic/syscolor.schema'
--- assets/color-schemes/historic/syscolor.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/syscolor.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,44 @@
+# schema that uses system colors
+
+# the title is to appear in the menu.
+
+title System Colors
+
+# image none
+
+# foreground colors
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      |              | |
+#      V V--color--V  V V
+
+sysfg  0              0 0  # regular   foreground color (system)
+sysbg  1              1 0  # regular   background color (system)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 178  24  24  0 0  # regular   color 1 Red
+color  4  24 178  24  0 0  # regular   color 2 Green
+color  5 178 104  24  0 0  # regular   color 3 Yellow
+color  6  24  24 178  0 0  # regular   color 4 Blue
+color  7 178  24 178  0 0  # regular   color 5 Magenta
+color  8  24 178 178  0 0  # regular   color 6 Cyan
+color  9 178 178 178  0 0  # regular   color 7 White
+
+# intensive colors
+
+# instead of changing the colors, we've flaged the text to become bold
+
+color 10   0   0   0  0 1  # intensive foreground color
+color 11 255 255 255  1 0  # intensive background color
+
+color 12 104 104 104  0 0  # intensive color 0
+color 13 255  84  84  0 0  # intensive color 1
+color 14  84 255  84  0 0  # intensive color 2
+color 15 255 255  84  0 0  # intensive color 3
+color 16  84  84 255  0 0  # intensive color 4
+color 17 255  84 255  0 0  # intensive color 5
+color 18  84 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added file 'assets/color-schemes/historic/vim.schema'
--- assets/color-schemes/historic/vim.schema	1970-01-01 00:00:00 +0000
+++ assets/color-schemes/historic/vim.schema	2017-09-09 05:25:54 +0000
@@ -0,0 +1,40 @@
+# VIM-recommended color schema for konsole
+
+# VIM (VI improved) in "help xiterm" recommends these colors for xterm.
+
+title VIM Colors
+
+# foreground colors -------------------------------
+
+# note that the default background color is flagged
+# to become transparent when an image is present.
+
+#   slot    transparent bold
+#      | red grn blu  | |
+#      V V--color--V  V V
+
+color  0   0   0   0  0 0  # regular   foreground color (Black)
+color  1 255 255 255  1 0  # regular   background color (White)
+
+color  2   0   0   0  0 0  # regular   color 0 Black
+color  3 192   0   0  0 0  # regular   color 1 Red
+color  4   0 128   0  0 0  # regular   color 2 Green
+color  5 128 128   0  0 0  # regular   color 3 Yellow
+color  6   0   0 192  0 0  # regular   color 4 Blue
+color  7 192   0 192  0 0  # regular   color 5 Magenta
+color  8   0 128 128  0 0  # regular   color 6 Cyan
+color  9 192 192 192  0 0  # regular   color 7 White
+
+# intensive colors -------------------------------------------
+
+color 10  77  77  77  0 1  # intensive foreground color
+color 11 255 255 255  1 1  # intensive background color
+
+color 12 128 128 128  0 0  # intensive color 0
+color 13 255  96  96  0 0  # intensive color 1
+color 14   0 255   0  0 0  # intensive color 2
+color 15 255 255   0  0 0  # intensive color 3
+color 16 128 128 255  0 0  # intensive color 4
+color 17 255  64 255  0 0  # intensive color 5
+color 18   0 255 255  0 0  # intensive color 6
+color 19 255 255 255  0 0  # intensive color 7

=== added directory 'assets/kb-layouts'
=== added file 'assets/kb-layouts/README'
--- assets/kb-layouts/README	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/README	2017-09-09 05:25:54 +0000
@@ -0,0 +1,72 @@
+[README.KeyTab]
+
+The keytabs offered in the Options/Keyboard menu are
+taken from from configurations files with a *.keytab
+pattern either located in $KDEDIR/share/apps/konsole
+or ~/.kde/share/apps/konsole.
+
+Keytabs allow to configure the behavior of konsole
+on keyboard events, especially for functions keys.
+Please have a look into the README.keyboard file, too.
+
+The syntax is that each entry has the form : 
+
+  "key" Keyname { ("+"|"-") Modename } ":" (String|Operation)
+
+Keynames are those defined in <qnamespace.h> with the
+"Qt::Key_" prefix removed.
+
+Mode names are: 
+
+  - Shift   : Shift Key pressed
+  - Alt     : Alt Key pressed
+  - Control : Control Key pressed
+
+  ( The VT100 emulation has modes that can affect the
+    sequences emitted by certain keys. These modes are
+    under control of the client program.
+  
+    - Newline     : effects Return and Enter key.
+    - Application : effects Up and Down key.
+    - Ansi        : effects Up and Down key (This is for VT52, really).
+
+    Since sending a state to a program that has set the state
+    itself is positivly wrong and obsolete design, better forget
+    about this nasty detail. I may well remove this "feature"
+    in a future clean up round. )
+
+  A "+" preceeding a Modename means the Key is pressed.
+  A "-" preceeding a Modename means the Key is not pressed.
+  If no mode is given it means don't care.
+
+  Note that the combination of Key and Modes (set/reset)
+  has to be unique. This means, that
+
+    key A + Shift : "A"
+    key A : "a"
+
+  will not accept the small letter "a" rule as expected,
+  one has to add a "- Shift" to the last clause. Use
+  the stdout/stderr dianostics of konsole when modifying
+  keytabs to find problems like this.
+
+Operations are
+
+  - scrollUpLine   : scroll up   one line in the history log
+  - scrollUpPage   : scroll up   one page in the history log
+  - scrollDownLine : scroll down one line in the history log
+  - scrollDownPage : scroll down one page in the history log
+  - emitClipboard  : "paste" the current clipboard
+  - emitSelection  : "paste" the current selection
+
+Strings have the syntax of C strings,
+one may use the following escapes:
+
+  - \E - escape
+  - \\ - backslash
+  - \" - double quote
+  - \t - tab
+  - \r - return
+  - \n - newline
+  - \b - backspace
+  - \xHH - where HH are two hex digits

=== added file 'assets/kb-layouts/default.keytab'
--- assets/kb-layouts/default.keytab	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/default.keytab	2017-09-09 05:25:54 +0000
@@ -0,0 +1,169 @@
+# [README.default.Keytab] Default Keyboard Table
+#
+# To customize your keyboard, copy this file to something
+# ending with .keytab and change it to meet you needs.
+# Please read the README.KeyTab and the README.keyboard
+# in this case.
+#
+# --------------------------------------------------------------
+
+keyboard "Default (XFree 4)"
+
+# --------------------------------------------------------------
+#
+# Note that this particular table is a "risc" version made to
+# ease customization without bothering with obsolete details.
+# See VT100.keytab for the more hairy stuff.
+#
+# --------------------------------------------------------------
+
+# common keys
+
+key Escape             : "\E"
+
+key Tab   -Shift       : "\t"
+key Tab   +Shift+Ansi  : "\E[Z"
+key Tab   +Shift-Ansi  : "\t"
+key Backtab     +Ansi  : "\E[Z"
+key Backtab     -Ansi  : "\t"
+
+key Return-Shift-NewLine : "\r"
+key Return-Shift+NewLine : "\r\n"
+
+key Return+Shift         : "\EOM"
+
+# Backspace and Delete codes are preserving CTRL-H.
+
+key Backspace      : "\x7f"
+
+# Arrow keys in VT52 mode
+# shift up/down are reserved for scrolling.
+# shift left/right are reserved for switching between tabs (this is hardcoded).
+
+key Up   -Shift-Ansi : "\EA"
+key Down -Shift-Ansi : "\EB"
+key Right-Shift-Ansi : "\EC"
+key Left -Shift-Ansi : "\ED"
+
+# Arrow keys in ANSI mode with Application - and Normal Cursor Mode)
+
+key Up    -Shift-AnyMod+Ansi+AppCuKeys : "\EOA"
+key Down  -Shift-AnyMod+Ansi+AppCuKeys : "\EOB"
+key Right -Shift-AnyMod+Ansi+AppCuKeys : "\EOC"
+key Left  -Shift-AnyMod+Ansi+AppCuKeys : "\EOD"
+
+key Up    -Shift-AnyMod+Ansi-AppCuKeys : "\E[A"
+key Down  -Shift-AnyMod+Ansi-AppCuKeys : "\E[B"
+key Right -Shift-AnyMod+Ansi-AppCuKeys : "\E[C"
+key Left  -Shift-AnyMod+Ansi-AppCuKeys : "\E[D"
+
+key Up    -Shift+AnyMod+Ansi           : "\E[1;*A"
+key Down  -Shift+AnyMod+Ansi           : "\E[1;*B"
+key Right -Shift+AnyMod+Ansi           : "\E[1;*C"
+key Left  -Shift+AnyMod+Ansi           : "\E[1;*D"
+
+# Keypad keys with NumLock ON
+# (see "Numeric Keypad" section at http://www.nw.com/nw/WWW/products/wizcon/vt100.html )
+#
+# Not enabled for now because it breaks the keypad in Vim.
+#
+#key 0 +KeyPad+AppKeyPad : "\EOp"
+#key 1 +KeyPad+AppKeyPad : "\EOq"
+#key 2 +KeyPad+AppKeyPad : "\EOr"
+#key 3 +KeyPad+AppKeyPad : "\EOs"
+#key 4 +KeyPad+AppKeyPad : "\EOt"
+#key 5 +KeyPad+AppKeyPad : "\EOu"
+#key 6 +KeyPad+AppKeyPad : "\EOv"
+#key 7 +KeyPad+AppKeyPad : "\EOw"
+#key 8 +KeyPad+AppKeyPad : "\EOx"
+#key 9 +KeyPad+AppKeyPad : "\EOy"
+#key + +KeyPad+AppKeyPad : "\EOl"
+#key - +KeyPad+AppKeyPad : "\EOm"
+#key . +KeyPad+AppKeyPad : "\EOn"
+#key * +KeyPad+AppKeyPad : "\EOM"
+#key Enter +KeyPad+AppKeyPad : "\r"
+
+# Keypad keys with NumLock Off
+key Up    -Shift+Ansi+AppCuKeys+KeyPad : "\EOA"
+key Down  -Shift+Ansi+AppCuKeys+KeyPad : "\EOB"
+key Right -Shift+Ansi+AppCuKeys+KeyPad : "\EOC"
+key Left  -Shift+Ansi+AppCuKeys+KeyPad : "\EOD"
+
+key Up    -Shift+Ansi-AppCuKeys+KeyPad : "\E[A"
+key Down  -Shift+Ansi-AppCuKeys+KeyPad : "\E[B"
+key Right -Shift+Ansi-AppCuKeys+KeyPad : "\E[C"
+key Left  -Shift+Ansi-AppCuKeys+KeyPad : "\E[D"
+
+key Home        +AppCuKeys+KeyPad : "\EOH"
+key End         +AppCuKeys+KeyPad : "\EOF"
+key Home        -AppCuKeys+KeyPad : "\E[H"
+key End         -AppCuKeys+KeyPad : "\E[F"
+
+key Insert      +KeyPad  : "\E[2~"
+key Delete      +KeyPad  : "\E[3~"
+key Prior -Shift+KeyPad  : "\E[5~"
+key Next  -Shift+KeyPad  : "\E[6~"
+
+# other grey PC keys
+
+key Enter+NewLine : "\r\n"
+key Enter-NewLine : "\r"
+
+key Home        -AnyMod-AppCuKeys : "\E[H"  
+key End         -AnyMod-AppCuKeys : "\E[F"  
+key Home        -AnyMod+AppCuKeys : "\EOH"  
+key End         -AnyMod+AppCuKeys : "\EOF"  
+key Home        +AnyMod           : "\E[1;*H"
+key End         +AnyMod           : "\E[1;*F"
+
+key Insert      -AnyMod  : "\E[2~"
+key Delete      -AnyMod  : "\E[3~"
+key Insert      +AnyMod  : "\E[2;*~"
+key Delete      +AnyMod  : "\E[3;*~"
+
+key Prior -Shift-AnyMod  : "\E[5~"
+key Next  -Shift-AnyMod  : "\E[6~"
+key Prior -Shift+AnyMod  : "\E[5;*~"
+key Next  -Shift+AnyMod  : "\E[6;*~"
+
+# Function keys
+key F1  -AnyMod  : "\EOP"
+key F2  -AnyMod  : "\EOQ"
+key F3  -AnyMod  : "\EOR"
+key F4  -AnyMod  : "\EOS"
+key F5  -AnyMod  : "\E[15~"
+key F6  -AnyMod  : "\E[17~"
+key F7  -AnyMod  : "\E[18~"
+key F8  -AnyMod  : "\E[19~"
+key F9  -AnyMod  : "\E[20~"
+key F10 -AnyMod  : "\E[21~"
+key F11 -AnyMod  : "\E[23~"
+key F12 -AnyMod  : "\E[24~"
+
+key F1  +AnyMod  : "\EO*P"
+key F2  +AnyMod  : "\EO*Q"
+key F3  +AnyMod  : "\EO*R"
+key F4  +AnyMod  : "\EO*S"
+key F5  +AnyMod  : "\E[15;*~"
+key F6  +AnyMod  : "\E[17;*~"
+key F7  +AnyMod  : "\E[18;*~"
+key F8  +AnyMod  : "\E[19;*~"
+key F9  +AnyMod  : "\E[20;*~"
+key F10 +AnyMod  : "\E[21;*~"
+key F11 +AnyMod  : "\E[23;*~"
+key F12 +AnyMod  : "\E[24;*~"
+
+# Work around dead keys
+
+key Space +Control : "\x00"
+
+# Some keys are used by konsole to cause operations.
+# The scroll* operations refer to the history buffer.
+
+key Up    +Shift-AppScreen  : scrollLineUp
+key Prior +Shift-AppScreen  : scrollPageUp
+key Down  +Shift-AppScreen  : scrollLineDown
+key Next  +Shift-AppScreen  : scrollPageDown
+
+key ScrollLock     : scrollLock
+

=== added directory 'assets/kb-layouts/historic'
=== added file 'assets/kb-layouts/historic/vt100.keytab'
--- assets/kb-layouts/historic/vt100.keytab	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/historic/vt100.keytab	2017-09-09 05:25:54 +0000
@@ -0,0 +1,133 @@
+# [vt100.keytab] Konsole Keyboard Table (VT100 keys)
+#
+# --------------------------------------------------------------
+
+keyboard "vt100 (historical)"
+
+# --------------------------------------------------------------
+#
+# This configuration table allows to customize the
+# meaning of the keys.
+#
+# The syntax is that each entry has the form : 
+#
+#   "key" Keyname { ("+"|"-") Modename } ":" (String|Operation)
+#
+# Keynames are those defined in <qnamespace.h> with the
+# "Qt::Key_" removed. (We'd better insert the list here)
+#
+# Mode names are : 
+#
+# - Shift
+# - Alt
+# - Control
+#
+#   The VT100 emulation has two modes that can affect the
+#   sequences emitted by certain keys. These modes are
+#   under control of the client program.
+#   
+# - Newline     : effects Return and Enter key.
+# - Application : effects Up and Down key.
+#
+# - Ansi        : effects Up and Down key (This is for VT52, really).
+#
+# Operations are
+#
+# - scrollUpLine
+# - scrollUpPage
+# - scrollDownLine
+# - scrollDownPage
+#
+# - emitSelection
+#
+# If the key is not found here, the text of the
+# key event as provided by QT is emitted, possibly
+# preceeded by ESC if the Alt key is pressed.
+#
+# --------------------------------------------------------------
+
+key Escape : "\E"
+key Tab    : "\t"
+
+# VT100 can add an extra \n after return.
+# The NewLine mode is set by an escape sequence.
+
+key Return-NewLine : "\r"  
+key Return+NewLine : "\r\n"
+
+# Some desperately try to save the ^H.
+
+key Backspace : "\x7f"
+key Delete    : "\E[3~"
+
+# These codes are for the VT52 mode of VT100
+# The Ansi mode (i.e. VT100 mode) is set by
+# an escape sequence
+
+key Up   -Shift-Ansi : "\EA"
+key Down -Shift-Ansi : "\EB"
+key Right-Shift-Ansi : "\EC"
+key Left -Shift-Ansi : "\ED"
+
+# VT100 emits a mode bit together
+# with the arrow keys.The AppCuKeys
+# mode is set by an escape sequence.
+
+key Up   -Shift+Ansi+AppCuKeys : "\EOA"
+key Down -Shift+Ansi+AppCuKeys : "\EOB"
+key Right-Shift+Ansi+AppCuKeys : "\EOC"
+key Left -Shift+Ansi+AppCuKeys : "\EOD"
+
+key Up   -Shift+Ansi-AppCuKeys : "\E[A"
+key Down -Shift+Ansi-AppCuKeys : "\E[B"
+key Right-Shift+Ansi-AppCuKeys : "\E[C"
+key Left -Shift+Ansi-AppCuKeys : "\E[D"
+
+# function keys (FIXME: make pf1-pf4)
+
+key F1     : "\E[11~"
+key F2     : "\E[12~"
+key F3     : "\E[13~"
+key F4     : "\E[14~"
+key F5     : "\E[15~"
+
+key F6     : "\E[17~" 
+key F7     : "\E[18~" 
+key F8     : "\E[19~" 
+key F9     : "\E[20~" 
+key F10    : "\E[21~" 
+key F11    : "\E[23~" 
+key F12    : "\E[24~" 
+
+key Home   : "\E[H"  
+key End    : "\E[F"  
+
+key Prior -Shift : "\E[5~"  
+key Next  -Shift : "\E[6~"  
+key Insert-Shift : "\E[2~"  
+
+# Keypad-Enter. See comment on Return above.
+
+key Enter+NewLine : "\r\n"
+key Enter-NewLine : "\r"  
+
+key Space +Control : "\x00"
+
+# some of keys are used by konsole.
+
+key Up    +Shift   : scrollLineUp
+key Prior +Shift   : scrollPageUp
+key Down  +Shift   : scrollLineDown
+key Next  +Shift   : scrollPageDown
+
+key ScrollLock     : scrollLock
+
+
+#----------------------------------------------------------
+
+# keypad characters as offered by Qt
+# cannot be recognized as such.
+
+#----------------------------------------------------------
+
+# Following other strings as emitted by konsole.

=== added file 'assets/kb-layouts/historic/x11r5.keytab'
--- assets/kb-layouts/historic/x11r5.keytab	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/historic/x11r5.keytab	2017-09-09 05:25:54 +0000
@@ -0,0 +1,71 @@
+# [x11r5.Keytab] Keyboard Table for X11 R5
+
+keyboard "XTerm (XFree 3.x.x)"
+
+# --------------------------------------------------------------
+#
+# Note that this particular table is a "risc" version made to
+# ease customization without bothering with obsolete details.
+# See VT100.keytab for the more hairy stuff.
+#
+# --------------------------------------------------------------
+
+# common keys
+
+key Escape         : "\E"
+key Tab            : "\t"
+
+key Return         : "\r"
+
+# Backspace and Delete codes are preserving CTRL-H.
+
+key Backspace      : "\x7f"
+
+# cursor keys
+
+key Up    -Shift   : "\EOA"
+key Down  -Shift   : "\EOB"
+key Right -Shift   : "\EOC"
+key Left  -Shift   : "\EOD"
+
+# other grey PC keys
+
+key Enter          : "\r"
+
+key Home           : "\E[1~"
+key Insert-Shift   : "\E[2~"
+key Delete         : "\E[3~"
+key End            : "\E[4~"
+key Prior -Shift   : "\E[5~"
+key Next  -Shift   : "\E[6~"
+
+# function keys
+
+key F1             : "\E[11~"
+key F2             : "\E[12~"
+key F3             : "\E[13~"
+key F4             : "\E[14~"
+key F5             : "\E[15~"
+key F6             : "\E[17~"
+key F7             : "\E[18~"
+key F8             : "\E[19~"
+key F9             : "\E[20~"
+key F10            : "\E[21~"
+key F11            : "\E[23~"
+key F12            : "\E[24~"
+
+# Work around dead keys
+
+key Space +Control : "\x00"
+
+# Some keys are used by konsole to cause operations.
+# The scroll* operations refer to the history buffer.
+
+key Up    +Shift   : scrollLineUp
+key Prior +Shift   : scrollPageUp
+key Down  +Shift   : scrollLineDown
+key Next  +Shift   : scrollPageDown
+
+key ScrollLock     : scrollLock
+
+# keypad characters are not offered differently by Qt.

=== added file 'assets/kb-layouts/linux.keytab'
--- assets/kb-layouts/linux.keytab	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/linux.keytab	2017-09-09 05:25:54 +0000
@@ -0,0 +1,164 @@
+# [linux.keytab] Konsole Keyboard Table (Linux console keys)
+#
+# --------------------------------------------------------------
+
+# NOT TESTED, MAY NEED SOME CLEANUPS
+keyboard "Linux console"
+
+# --------------------------------------------------------------
+#
+# This configuration table allows to customize the
+# meaning of the keys.
+#
+# The syntax is that each entry has the form : 
+#
+#   "key" Keyname { ("+"|"-") Modename } ":" (String|Operation)
+#
+# Keynames are those defined in <qnamespace.h> with the
+# "Qt::Key_" removed. (We'd better insert the list here)
+#
+# Mode names are : 
+#
+# - Shift
+# - Alt
+# - Control
+#
+#   The VT100 emulation has two modes that can affect the
+#   sequences emitted by certain keys. These modes are
+#   under control of the client program.
+#   
+# - Newline     : effects Return and Enter key.
+# - Application : effects Up and Down key.
+#
+# - Ansi        : effects Up and Down key (This is for VT52, really).
+#
+# Operations are
+#
+# - scrollUpLine
+# - scrollUpPage
+# - scrollDownLine
+# - scrollDownPage
+#
+# - emitSelection
+#
+# If the key is not found here, the text of the
+# key event as provided by QT is emitted, possibly
+# preceeded by ESC if the Alt key is pressed.
+#
+# --------------------------------------------------------------
+
+key Escape : "\E"
+key Tab    : "\t"
+
+# VT100 can add an extra \n after return.
+# The NewLine mode is set by an escape sequence.
+
+key Return-NewLine : "\r"  
+key Return+NewLine : "\r\n"
+
+# Some desperately try to save the ^H.
+
+key Backspace : "\x7f"
+key Delete    : "\E[3~"
+
+# These codes are for the VT52 mode of VT100
+# The Ansi mode (i.e. VT100 mode) is set by
+# an escape sequence
+
+key Up   -Shift-Ansi : "\EA"
+key Down -Shift-Ansi : "\EB"
+key Right-Shift-Ansi : "\EC"
+key Left -Shift-Ansi : "\ED"
+
+# VT100 emits a mode bit together
+# with the arrow keys.The AppCuKeys
+# mode is set by an escape sequence.
+
+key Up   -Shift+Ansi+AppCuKeys : "\EOA"
+key Down -Shift+Ansi+AppCuKeys : "\EOB"
+key Right-Shift+Ansi+AppCuKeys : "\EOC"
+key Left -Shift+Ansi+AppCuKeys : "\EOD"
+
+key Up   -Shift+Ansi-AppCuKeys : "\E[A"
+key Down -Shift+Ansi-AppCuKeys : "\E[B"
+key Right-Shift+Ansi-AppCuKeys : "\E[C"
+key Left -Shift+Ansi-AppCuKeys : "\E[D"
+
+# linux functions keys F1-F5 differ from xterm
+
+key F1 : "\E[[A" 
+key F2 : "\E[[B" 
+key F3 : "\E[[C" 
+key F4 : "\E[[D" 
+key F5 : "\E[[E" 
+
+key F6     : "\E[17~" 
+key F7     : "\E[18~" 
+key F8     : "\E[19~" 
+key F9     : "\E[20~" 
+key F10    : "\E[21~" 
+key F11    : "\E[23~" 
+key F12    : "\E[24~" 
+
+key Home   : "\E[1~"  
+key End    : "\E[4~"  
+
+key Prior -Shift : "\E[5~"  
+key Next  -Shift : "\E[6~"  
+key Insert-Shift : "\E[2~"  
+
+# Keypad-Enter. See comment on Return above.
+
+key Enter+NewLine : "\r\n"
+key Enter-NewLine : "\r"  
+
+key Space +Control : "\x00"
+
+# linux term ctrl seq
+
+key A     +Control : "\x01"
+key B     +Control : "\x02"
+key C     +Control : "\x03"
+key D     +Control : "\x04"
+key E     +Control : "\x05"
+key F     +Control : "\x06"
+key G     +Control : "\x07"
+key H     +Control : "\x08"
+key I     +Control : "\x09"
+key J     +Control : "\x0a"
+key K     +Control : "\x0b"
+key L     +Control : "\x0c"
+key M     +Control : "\x0d"
+key N     +Control : "\x0e"
+key O     +Control : "\x0f"
+key P     +Control : "\x10"
+key Q     +Control : "\x11"
+key R     +Control : "\x12"
+key S     +Control : "\x13"
+key T     +Control : "\x14"
+key U     +Control : "\x15"
+key V     +Control : "\x16"
+key W     +Control : "\x17"
+key X     +Control : "\x18"
+key Y     +Control : "\x19"
+key Z     +Control : "\x1a"
+
+
+
+# some of keys are used by konsole.
+
+key Up    +Shift   : scrollLineUp
+key Prior +Shift   : scrollPageUp
+key Down  +Shift   : scrollLineDown
+key Next  +Shift   : scrollPageDown
+
+key ScrollLock     : scrollLock
+
+#----------------------------------------------------------
+
+# keypad characters as offered by Qt
+# cannot be recognized as such.
+
+#----------------------------------------------------------
+
+# Following other strings as emitted by konsole.

=== added file 'assets/kb-layouts/macbook.keytab'
--- assets/kb-layouts/macbook.keytab	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/macbook.keytab	2017-09-09 05:25:54 +0000
@@ -0,0 +1,175 @@
+# [README.default.Keytab] Buildin Keyboard Table
+#
+# To customize your keyboard, copy this file to something
+# ending with .keytab and change it to meet you needs.
+# Please read the README.KeyTab and the README.keyboard
+# in this case.
+#
+# --------------------------------------------------------------
+
+keyboard "Default (XFree 4)"
+
+# --------------------------------------------------------------
+#
+# Note that this particular table is a "risc" version made to
+# ease customization without bothering with obsolete details.
+# See VT100.keytab for the more hairy stuff.
+#
+# --------------------------------------------------------------
+
+# common keys
+
+key Escape             : "\x1b"
+
+#key Control : "^"
+
+key Tab   -Shift       : "\t"
+key Tab   +Shift+Ansi  : "\E[Z"
+key Tab   +Shift-Ansi  : "\t"
+key Backtab     +Ansi  : "\E[Z"
+key Backtab     -Ansi  : "\t"
+
+key Return-Shift-NewLine : "\r"
+key Return-Shift+NewLine : "\r\n"
+
+key Return+Shift         : "\EOM"
+
+# Backspace and Delete codes are preserving CTRL-H.
+
+key Backspace      : "\x7f"
+
+# Arrow keys in VT52 mode
+# shift up/down are reserved for scrolling.
+# shift left/right are reserved for switching between tabs (this is hardcoded).
+
+
+# Command + C
+# on mac - Control=Command, Meta=Ctrl
+# do not use Control+C for interrupt signal - it's used for "Copy to clipboard"
+#key Control +C : "\x03"
+key Meta +C: "\x03"
+
+
+# Arrow keys in ANSI mode with Application - and Normal Cursor Mode)
+
+key Up   -Shift+Ansi-AppCuKeys : "\E[A"
+key Down -Shift+Ansi-AppCuKeys : "\E[B"
+key Right-Shift+Ansi-AppCuKeys : "\E[C"
+key Left -Shift+Ansi-AppCuKeys : "\E[D"
+
+key Up    -Ansi           : "\E[1;*A"
+key Down  -Ansi           : "\E[1;*B"
+key Right -Ansi           : "\E[1;*C"
+key Left  -Ansi           : "\E[1;*D"
+
+#key Up   -Shift-Ansi : "\EA"
+#key Down -Shift-Ansi : "\EB"
+#key Right-Shift-Ansi : "\EC"
+#key Left -Shift-Ansi : "\ED"
+
+#key Up    -Shift-AnyMod+Ansi-AppCuKeys           : "\E[A"
+#key Down  -Shift-AnyMod+Ansi-AppCuKeys           : "\E[B"
+#key Right -Shift-AnyMod+Ansi-AppCuKeys           : "\E[C"
+#key Left  -Shift-AnyMod+Ansi-AppCuKeys           : "\E[D"
+
+#key Up    -Shift-AnyMod+Ansi-AppCuKeys           : "\EOA"
+#key Down  -Shift-AnyMod+Ansi-AppCuKeys           : "\EOB"
+#key Right -Shift-AnyMod+Ansi-AppCuKeys           : "\EOC"
+#key Left  -Shift-AnyMod+Ansi-AppCuKeys           : "\EOD"
+
+#key Up    -Shift-AnyMod+Ansi                     : "\E[1;*A"
+#key Down  -Shift-AnyMod+Ansi                     : "\E[1;*B"
+#key Right -Shift-AnyMod+Ansi                     : "\E[1;*C"
+#key Left  -Shift-AnyMod+Ansi                     : "\E[1;*D"
+
+# other grey PC keys
+
+key Enter+NewLine : "\r\n"
+key Enter-NewLine : "\r"
+
+key Home        -AnyMod     -AppCuKeys           : "\E[H"  
+key End         -AnyMod     -AppCuKeys           : "\E[F"  
+key Home        -AnyMod     +AppCuKeys           : "\EOH"  
+key End         -AnyMod     +AppCuKeys           : "\EOF"  
+key Home        +AnyMod                          : "\E[1;*H"
+key End         +AnyMod                          : "\E[1;*F"
+
+key Insert      -AnyMod                          : "\E[2~"
+key Delete      -AnyMod                          : "\E[3~"
+key Insert      +AnyMod                          : "\E[2;*~"
+key Delete      +AnyMod                          : "\E[3;*~"
+
+key Prior -Shift-AnyMod                          : "\E[5~"
+key Next  -Shift-AnyMod                          : "\E[6~"
+key Prior -Shift+AnyMod                          : "\E[5;*~"
+key Next  -Shift+AnyMod                          : "\E[6;*~"
+
+# Function keys
+#key F1          -AnyMod                          : "\EOP"
+#key F2          -AnyMod                          : "\EOQ"
+#key F3          -AnyMod                          : "\EOR"
+#key F4          -AnyMod                          : "\EOS"
+#define ALT_KP_0		"\033Op"
+#define ALT_KP_1		"\033Oq"
+#define ALT_KP_2		"\033Or"
+#define ALT_KP_3		"\033Os"
+#define ALT_KP_4		"\033Ot"
+#define ALT_KP_5		"\033Ou"
+#define ALT_KP_6		"\033Ov"
+#define ALT_KP_7		"\033Ow"
+#define ALT_KP_8		"\033Ox"
+#define ALT_KP_9		"\033Oy"
+
+key F1          -AnyMod                          : "\EOP"
+key F2          -AnyMod                          : "\EOQ"
+key F3          -AnyMod                          : "\EOR"
+key F4          -AnyMod                          : "\EOS"
+key F5          -AnyMod                          : "\EOT"
+key F6          -AnyMod                          : "\EOU"
+key F7          -AnyMod                          : "\EOV"
+key F8          -AnyMod                          : "\EOW"
+key F9          -AnyMod                          : "\EOX"
+key F10			-AnyMod							 : "\EOY"
+
+#key F5          -AnyMod                          : "\E[15~"
+#key F6          -AnyMod                          : "\E[17~"
+#key F7          -AnyMod                          : "\E[18~"
+#key F8          -AnyMod                          : "\E[19~"
+#key F9          -AnyMod                          : "\E[20~"
+#key F10         -AnyMod                          : "\E[21~"
+#key F11         -AnyMod                          : "\E[23~"
+#key F12         -AnyMod                          : "\E[24~"
+
+#key F1          +AnyMod                          : "\EO*P"
+#key F2          +AnyMod                          : "\EO*Q"
+#key F3          +AnyMod                          : "\EO*R"
+#key F4          +AnyMod                          : "\EO*S"
+#key F5          +AnyMod                          : "\E[15;*~"
+#key F6          +AnyMod                          : "\E[17;*~"
+#key F7          +AnyMod                          : "\E[18;*~"
+#key F8          +AnyMod                          : "\E[19;*~"
+#key F9          +AnyMod                          : "\E[20;*~"
+#key F10         +AnyMod                          : "\E[21;*~"
+#key F11         +AnyMod                          : "\E[23;*~"
+#key F12         +AnyMod                          : "\E[24;*~"
+
+# Work around dead keys
+
+key Space +Control : "\x00"
+
+# Some keys are used by konsole to cause operations.
+# The scroll* operations refer to the history buffer.
+
+key Up    +Shift-AppScreen  : scrollLineUp
+key Prior +Shift-AppScreen  : scrollPageUp
+key Down  +Shift-AppScreen  : scrollLineDown
+key Next  +Shift-AppScreen  : scrollPageDown
+
+#key Up    +Shift  : scrollLineUp
+#key Prior +Shift  : scrollPageUp
+#key Down  +Shift  : scrollLineDown
+#key Next  +Shift  : scrollPageDown
+
+key ScrollLock     : scrollLock
+
+# keypad characters are not offered differently by Qt.

=== added file 'assets/kb-layouts/solaris.keytab'
--- assets/kb-layouts/solaris.keytab	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/solaris.keytab	2017-09-09 05:25:54 +0000
@@ -0,0 +1,108 @@
+# [solaris.keytab] Konsole Keyboard Table 
+# 
+
+keyboard "Solaris console"
+
+# --------------------------------------------------------------
+#
+# This configuration table allows to customize the
+# meaning of the keys.
+#
+# The syntax is that each entry has the form :
+#
+#   "key" Keyname { ("+"|"-") Modename } ":" (String|Operation)
+#
+# Keynames are those defined in <qnamespace.h> with the
+# "Qt::Key_" removed. (We'd better insert the list here)
+#
+# Mode names are :
+#
+# - Shift
+# - Alt
+# - Control
+#
+#   The VT100 emulation has two modes that can affect the
+#   sequences emitted by certain keys. These modes are
+#   under control of the client program.
+#
+#
+# - Newline     : effects Return and Enter key.
+# - Application : effects Up and Down key.
+#
+# - Ansi        : effects Up and Down key (This is for VT52, really).
+#
+# Operations are
+#
+# - scrollUpLine
+# - scrollUpPage
+# - scrollDownLine
+# - scrollDownPage
+#
+# - emitSelection
+#
+# If the key is not found here, the text of the
+# key event as provided by QT is emitted, possibly
+# preceeded by ESC if the Alt key is pressed.
+#
+# --------------------------------------------------------------
+
+key Escape         : "\E" 
+key Tab            : "\t" 
+
+key Return-Alt     : "\r" 
+key Return+Alt     : "\E\r" 
+
+# Backspace and Delete codes are preserving CTRL-H. 
+ 
+key Backspace      : "\x08" 
+#key Delete   : "\x7F" 
+
+# cursor keys 
+
+key Up    -Shift   : "\EOA" 
+key Down  -Shift   : "\EOB" 
+key Right -Shift   : "\EOC" 
+key Left  -Shift   : "\EOD" 
+ 
+# other grey PC keys 
+ 
+key Enter          : "\r" 
+ 
+key Home           : "\E[1~" 
+key Insert-Shift   : "\E[2~" 
+key Delete         : "\E[3~" 
+key End            : "\E[4~" 
+key Prior -Shift   : "\E[5~" 
+key Next  -Shift   : "\E[6~" 
+ 
+# function keys 
+ 
+key F1             : "\E[11~" 
+key F2             : "\E[12~" 
+key F3             : "\E[13~" 
+key F4             : "\E[14~" 
+key F5             : "\E[15~" 
+key F6             : "\E[17~" 
+key F7             : "\E[18~" 
+key F8             : "\E[19~" 
+key F9             : "\E[20~" 
+key F10            : "\E[21~" 
+key F11            : "\E[23~" 
+key F12            : "\E[24~" 
+ 
+# Work around dead keys 
+ 
+key Space +Control : "\x00" 
+ 
+# Some keys are used by konsole to cause operations. 
+# The scroll* operations refer to the history buffer. 
+
+#key Left  +Shift   : prevSession 
+#key Right +Shift   : nextSession 
+key Up    +Shift   : scrollLineUp 
+key Prior +Shift   : scrollPageUp 
+key Down  +Shift   : scrollLineDown 
+key Next  +Shift   : scrollPageDown 
+#key Insert+Shift   : emitSelection 
+
+# keypad characters are not offered differently by Qt.

=== added file 'assets/kb-layouts/vt420pc.keytab'
--- assets/kb-layouts/vt420pc.keytab	1970-01-01 00:00:00 +0000
+++ assets/kb-layouts/vt420pc.keytab	2017-09-09 05:25:54 +0000
@@ -0,0 +1,168 @@
+#
+# NOTE: This keyboard binding is not installed because it
+# apparently doesn't work with actual VT420 systems 
+# (see BUG:170220)
+#
+# [vt420pc.keytab] Konsole Keyboard Table (VT420pc keys)
+# adapted by ferdinand gassauer f.gassauer@xxxxxx
+# Nov 2000
+#
+################################################################
+#
+# The escape sequences emmited by the 
+# keys Shift+F1 to Shift+F12 might not fit your needs
+#
+################# IMPORTANT NOTICE #############################
+# the key bindings (Kcontrol -> look and feel -> keybindgs) 
+# overrule the settings in this file. The key bindings might be 
+# changed by the user WITHOUT notification of the maintainer of
+# the keytab file. Konsole will not work as expected by 
+# the maintainer of the keytab file.
+################################################################
+#
+# --------------------------------------------------------------
+
+keyboard "DEC VT420 Terminal"
+
+# --------------------------------------------------------------
+#
+# This configuration table allows to customize the
+# meaning of the keys.
+#
+# The syntax is that each entry has the form : 
+#
+#   "key" Keyname { ("+"|"-") Modename } ":" (String|Operation)
+#
+# Keynames are those defined in <qnamespace.h> with the
+# "Qt::Key_" removed. (We'd better insert the list here)
+#
+# Mode names are : 
+#
+# - Shift
+# - Alt
+# - Control
+#
+#   The VT100 emulation has two modes that can affect the
+#   sequences emitted by certain keys. These modes are
+#   under control of the client program.
+#   
+# - Newline     : effects Return and Enter key.
+# - Application : effects Up and Down key.
+#
+# - Ansi        : effects Up and Down key (This is for VT52, really).
+#
+# Operations are
+#
+# - scrollUpLine
+# - scrollUpPage
+# - scrollDownLine
+# - scrollDownPage
+#
+# - emitSelection
+#
+# If the key is not found here, the text of the
+# key event as provided by QT is emitted, possibly
+# preceeded by ESC if the Alt key is pressed.
+#
+# --------------------------------------------------------------
+
+key Escape : "\E"
+key Tab    : "\t"
+key Backtab: "\E[Z"
+
+# VT100 can add an extra \n after return.
+# The NewLine mode is set by an escape sequence.
+
+key Return-NewLine : "\r"  
+key Return+NewLine : "\r\n"
+
+# Some desperately try to save the ^H.
+# may be not everyone wants this
+
+key Backspace : "\x08"  # Control H
+key Delete    : "\x7f"
+
+# These codes are for the VT420pc
+# The Ansi mode (i.e. VT100 mode) is set by
+# an escape sequence
+
+key Up   -Shift-Ansi : "\EA"
+key Down -Shift-Ansi : "\EB"
+key Right-Shift-Ansi : "\EC"
+key Left -Shift-Ansi : "\ED"
+
+# VT100 emits a mode bit together
+# with the arrow keys.The AppCuKeys
+# mode is set by an escape sequence.
+
+key Up   -Shift+Ansi+AppCuKeys : "\EOA"
+key Down -Shift+Ansi+AppCuKeys : "\EOB"
+key Right-Shift+Ansi+AppCuKeys : "\EOC"
+key Left -Shift+Ansi+AppCuKeys : "\EOD"
+
+key Up   -Shift+Ansi-AppCuKeys : "\E[A"
+key Down -Shift+Ansi-AppCuKeys : "\E[B"
+key Right-Shift+Ansi-AppCuKeys : "\E[C"
+key Left -Shift+Ansi-AppCuKeys : "\E[D"
+
+# function keys 
+
+key F1 -Shift    : "\E[11~"  
+key F2 -Shift    : "\E[12~"
+key F3 -Shift    : "\E[13~"
+key F4 -Shift    : "\E[14~"
+key F5 -Shift    : "\E[15~"
+key F6 -Shift    : "\E[17~"
+key F7 -Shift    : "\E[18~"
+key F8 -Shift    : "\E[19~"
+key F9 -Shift    : "\E[20~"
+key F10-Shift    : "\E[21~"
+key F11-Shift    : "\E[23~"
+key F12-Shift    : "\E[24~"  
+#
+# Shift F1-F12
+#
+key F1 +Shift    : "\E[11;2~"
+key F2 +Shift    : "\E[12;2~"
+key F3 +Shift    : "\E[13;2~"
+key F4 +Shift    : "\E[14;2~"
+key F5 +Shift    : "\E[15;2~"
+key F6 +Shift    : "\E[17;2~" 
+key F7 +Shift    : "\E[18;2~" 
+key F8 +Shift    : "\E[19;2~" 
+key F9 +Shift    : "\E[20;2~" 
+key F10+Shift    : "\E[21;2~" 
+key F11+Shift    : "\E[23;2~" 
+key F12+Shift    : "\E[24;2~" 
+
+key Home   : "\E[H"  
+key End    : "\E[F"  
+
+key Prior -Shift : "\E[5~"  
+key Next  -Shift : "\E[6~"  
+key Insert-Shift : "\E[2~"  
+
+# Keypad-Enter. See comment on Return above.
+
+key Enter+NewLine : "\r\n"
+key Enter-NewLine : "\r"  
+
+key Space +Control : "\x00"
+
+# some of keys are used by konsole.
+
+key Up    +Shift   : scrollLineUp
+key Prior +Shift   : scrollPageUp
+key Down  +Shift   : scrollLineDown
+key Next  +Shift   : scrollPageDown
+
+key ScrollLock     : scrollLock
+
+#----------------------------------------------------------
+
+# keypad characters as offered by Qt
+# cannot be recognized as such.
+
+#----------------------------------------------------------
+
+# Following other strings as emitted by konsole.

=== added directory 'debian'
=== renamed directory 'debian' => 'debian.moved'
=== added file 'debian/changelog'
--- debian/changelog	1970-01-01 00:00:00 +0000
+++ debian/changelog	2017-09-09 05:25:54 +0000
@@ -0,0 +1,29 @@
+konsole-qml-plugin (0.1.2) raring; urgency=low
+
+  * Fixed text display bug (LP:#1182503)
+
+ -- Dmitry Zagnoyko <hiroshidi@xxxxxxxxx>  Mon, 10 Jun 2013 09:49:02 +0300
+
+konsole-qml-plugin (0.1.1) raring; urgency=low
+
+  * Fixed issue with float values of widget size
+  * Added virtual key event for qml KSession component
+
+ -- Dmitry Zagnoyko <hiroshidi@xxxxxxxxx>  Mon, 06 May 2013 20:11:10 +0300
+
+konsole-qml-plugin (0.1.0ubuntu1~quantal1~test2) quantal; urgency=low
+
+  * Added qml properties for KTerminal
+  * Fixed visibility sope: removed konsole namespace
+  * Added qmltypes
+  * Fixed qml plugin path
+  * Added KSession class
+
+ -- Dmitry Zagnoyko <hiroshidi@xxxxxxxxx>  Sat, 20 Apr 2013 21:44:26 +0300
+
+konsole-qml-plugin (0.1.0ubuntu1~quantal1~test1) quantal; urgency=low
+
+  * Initial release
+  * Ported KDE Konsole
+
+ -- Dmitry Zagnoyko <hiroshidi@xxxxxxxxx>  Fri, 19 Apr 2013 20:22:12 +0300

=== added file 'debian/compat'
--- debian/compat	1970-01-01 00:00:00 +0000
+++ debian/compat	2017-09-09 05:25:54 +0000
@@ -0,0 +1,1 @@
+9

=== added file 'debian/control'
--- debian/control	1970-01-01 00:00:00 +0000
+++ debian/control	2017-09-09 05:25:54 +0000
@@ -0,0 +1,40 @@
+Source: konsole-qml-plugin
+Section: libs
+Priority: optional
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@xxxxxxxxxxxxxxxx>
+Build-Depends: debhelper (>= 9.0.0),
+#               libgl1-mesa-dev | libgl-dev,
+#               libgles2-mesa-dev
+               qtbase5-dev,
+               qtdeclarative5-dev,
+               qt5-default,
+Standards-Version: 3.9.4
+Homepage: http://konsole.kde.org/
+
+Package: qtdeclarative5-konsole-qml-plugin
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${misc:Depends}, ${shlibs:Depends},
+Description: KDE Konsole QML plugin - qml terminal plugin 
+ Originaly, Konsole is a terminal emulator from KDE. This is ported
+ version and do not require KDE.
+ .
+ This package contains the Konsole terminal emulator plugin
+ for Qt Qml, which offers access to terminal by KTerminal and
+ KSession elements. KTerminal is used for displaying information
+ given by KSession.
+
+
+#Package: konsole-qml-plugin-dbg
+#Priority: extra
+#Architecture: any
+#Section: debug
+#Depends: ${misc:Depends}
+#Description: KDE Konsole QML plugin debugging symbols
+# Originaly, Konsole is a terminal emulator from KDE. This is ported
+# version without KDE tails and do not require KDE.
+# .
+# This package contains the debugging symbols for the KDE Konsole
+# QML plugin.
+

=== added file 'debian/copyright'
--- debian/copyright	1970-01-01 00:00:00 +0000
+++ debian/copyright	2017-09-09 05:25:54 +0000
@@ -0,0 +1,50 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/3.0/
+Upstream-Name: konsole-qml-plugin
+Source:
+
+Files: *
+Copyright: 2013          Dmitry Zagnoyko  <hiroshidi@xxxxxxxxx> 
+           2008                      e_k  <e_k@xxxxxxxxxxxxxxxxxxxxx>
+           2006-2008       Robert Knight  <robertknight@xxxxxxxxx>
+           2003-2007  Oswald Buddenhagen  <ossi@xxxxxxx>
+	   2000            Stephan Kulow  <coolo@xxxxxxx>
+           1997-1998         Lars Doelle  <lars.doelle@xxxxxxxxxx>
+License: GPL-3
+
+Files: debian/*
+Copyright: 2013 Dmitry Zagnoyko <hiroshidi@xxxxxxxxx> 
+License: LGPL-3
+
+License: GPL-3
+ This package 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 3 of the License.
+ .
+ This package 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, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU General
+ Public License can be found in "/usr/share/common-licenses/GPL-3".
+
+License: LGPL-3
+ This package is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License.
+ .
+ This package 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
+ Lesser General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ .
+ On Debian systems, the complete text of the GNU Lesser General
+ Public License can be found in "/usr/share/common-licenses/LGPL-3".

=== added file 'debian/rules'
--- debian/rules	1970-01-01 00:00:00 +0000
+++ debian/rules	2017-09-09 05:25:54 +0000
@@ -0,0 +1,21 @@
+#!/usr/bin/make -f
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+#export CFLAGS := $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
+#export CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
+#export LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS) -Wl,--as-needed
+
+override_dh_auto_configure:
+	QT_SELECT=qt5 dh_auto_configure
+
+%:
+	dh $@ --list-missing --parallel 
+# WARN: currently, no pakgage
+# --dbg-package=konsole-qml-plugin-dbg
+
+
+#override_dh_builddeb:
+#	dh_builddeb -- -Zxz
+

=== added directory 'debian/source'
=== added file 'debian/source/format'
--- debian/source/format	1970-01-01 00:00:00 +0000
+++ debian/source/format	2017-09-09 05:25:54 +0000
@@ -0,0 +1,1 @@
+3.0 (native)

=== added file 'konsole-qml-plugin.pro'
--- konsole-qml-plugin.pro	1970-01-01 00:00:00 +0000
+++ konsole-qml-plugin.pro	2017-09-09 05:25:54 +0000
@@ -0,0 +1,97 @@
+#########################################
+##              CONFIGS
+#########################################
+
+TEMPLATE = lib
+CONFIG += qt plugin hide_symbols
+QT += qml quick widgets
+
+DEFINES += HAVE_POSIX_OPENPT HAVE_SYS_TIME_H HAVE_UPDWTMPX
+
+#MANUALY DEFINED PLATFORM
+DEFINES += Q_WS_UBUNTU
+
+TARGET = kdekonsole
+PLUGIN_IMPORT_PATH = org/kde/konsole
+PLUGIN_ASSETS = $$PWD/assets/*
+
+#########################################
+##              SOURCES
+#########################################
+
+SOURCES += \
+        $$PWD/src/plugin.cpp \
+        $$PWD/src/Pty.cpp \
+        $$PWD/src/kptyprocess.cpp \
+        $$PWD/src/kptydevice.cpp \
+        $$PWD/src/kpty.cpp \
+        $$PWD/src/kprocess.cpp \
+        $$PWD/src/ShellCommand.cpp \
+        $$PWD/src/Vt102Emulation.cpp \
+        $$PWD/src/tools.cpp \
+        $$PWD/src/Session.cpp \
+        $$PWD/src/Screen.cpp \
+        $$PWD/src/KeyboardTranslator.cpp \
+        $$PWD/src/Emulation.cpp \
+        $$PWD/src/History.cpp \
+        $$PWD/src/BlockArray.cpp \
+        $$PWD/src/TerminalCharacterDecoder.cpp \
+        $$PWD/src/konsole_wcwidth.cpp \
+        $$PWD/src/ScreenWindow.cpp \
+        $$PWD/src/Filter.cpp \
+        $$PWD/src/ColorScheme.cpp \
+        $$PWD/src/TerminalDisplay.cpp \
+        $$PWD/src/ksession.cpp
+
+HEADERS += \
+        $$PWD/src/plugin.h \
+        $$PWD/src/Pty.h \
+        $$PWD/src/kptyprocess.h \
+        $$PWD/src/kptydevice.h \
+        $$PWD/src/kpty.h \
+        $$PWD/src/kpty_p.h \
+        $$PWD/src/kprocess.h \
+        $$PWD/src/ShellCommand.h \
+        $$PWD/src/Vt102Emulation.h \
+        $$PWD/src/tools.h \
+        $$PWD/src/Session.h \
+        $$PWD/src/Screen.h \
+        $$PWD/src/KeyboardTranslator.h \
+        $$PWD/src/Emulation.h \
+        $$PWD/src/Character.h \
+        $$PWD/src/History.h \
+        $$PWD/src/CharacterColor.h \
+        $$PWD/src/BlockArray.h \
+        $$PWD/src/TerminalCharacterDecoder.h \
+        $$PWD/src/konsole_wcwidth.h \
+        $$PWD/src/ScreenWindow.h \
+        $$PWD/src/DefaultTranslatorText.h \
+        $$PWD/src/LineFont.h \
+        $$PWD/src/Filter.h \
+        $$PWD/src/ExtendedDefaultTranslator.h \
+        $$PWD/src/ColorTables.h \
+        $$PWD/src/ColorScheme.h \
+        $$PWD/src/TerminalDisplay.h \
+        $$PWD/src/ksession.h
+
+OTHER_FILES += \
+    $$PWD/src/qmldir \
+    $$PWD/src/plugins.qmltypes
+
+MOC_DIR = $$PWD/.moc
+OBJECTS_DIR = $$PWD/.obj
+
+#########################################
+##              INTALLS
+#########################################
+
+target.path = $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH
+
+assets.files += $$PLUGIN_ASSETS
+assets.path  += $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH
+
+qmldir.files += $$PWD/src/qmldir \
+                $$PWD/src/plugins.qmltypes
+qmldir.path  += $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH
+
+INSTALLS     += target qmldir assets

=== added directory 'src'
=== renamed directory 'src' => 'src.moved'
=== added file 'src/BlockArray.cpp'
--- src/BlockArray.cpp	1970-01-01 00:00:00 +0000
+++ src/BlockArray.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,377 @@
+/*
+    This file is part of Konsole, an X terminal.
+    Copyright (C) 2000 by Stephan Kulow <coolo@xxxxxxx>
+
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    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.
+
+*/
+
+// Own
+#include "BlockArray.h"
+
+#include <QtCore>
+
+// System
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdio.h>
+
+
+static int blocksize = 0;
+
+BlockArray::BlockArray()
+        : size(0),
+        current(size_t(-1)),
+        index(size_t(-1)),
+        lastmap(0),
+        lastmap_index(size_t(-1)),
+        lastblock(0), ion(-1),
+        length(0)
+{
+    // lastmap_index = index = current = size_t(-1);
+    if (blocksize == 0) {
+        blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();
+    }
+
+}
+
+BlockArray::~BlockArray()
+{
+    setHistorySize(0);
+    assert(!lastblock);
+}
+
+size_t BlockArray::append(Block * block)
+{
+    if (!size) {
+        return size_t(-1);
+    }
+
+    ++current;
+    if (current >= size) {
+        current = 0;
+    }
+
+    int rc;
+    rc = lseek(ion, current * blocksize, SEEK_SET);
+    if (rc < 0) {
+        perror("HistoryBuffer::add.seek");
+        setHistorySize(0);
+        return size_t(-1);
+    }
+    rc = write(ion, block, blocksize);
+    if (rc < 0) {
+        perror("HistoryBuffer::add.write");
+        setHistorySize(0);
+        return size_t(-1);
+    }
+
+    length++;
+    if (length > size) {
+        length = size;
+    }
+
+    ++index;
+
+    delete block;
+    return current;
+}
+
+size_t BlockArray::newBlock()
+{
+    if (!size) {
+        return size_t(-1);
+    }
+    append(lastblock);
+
+    lastblock = new Block();
+    return index + 1;
+}
+
+Block * BlockArray::lastBlock() const
+{
+    return lastblock;
+}
+
+bool BlockArray::has(size_t i) const
+{
+    if (i == index + 1) {
+        return true;
+    }
+
+    if (i > index) {
+        return false;
+    }
+    if (index - i >= length) {
+        return false;
+    }
+    return true;
+}
+
+const Block * BlockArray::at(size_t i)
+{
+    if (i == index + 1) {
+        return lastblock;
+    }
+
+    if (i == lastmap_index) {
+        return lastmap;
+    }
+
+    if (i > index) {
+        qDebug() << "BlockArray::at() i > index\n";
+        return 0;
+    }
+
+//     if (index - i >= length) {
+//         kDebug(1211) << "BlockArray::at() index - i >= length\n";
+//         return 0;
+//     }
+
+    size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
+
+    assert(j < size);
+    unmap();
+
+    Block * block = (Block *)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
+
+    if (block == (Block *)-1) {
+        perror("mmap");
+        return 0;
+    }
+
+    lastmap = block;
+    lastmap_index = i;
+
+    return block;
+}
+
+void BlockArray::unmap()
+{
+    if (lastmap) {
+        int res = munmap((char *)lastmap, blocksize);
+        if (res < 0) {
+            perror("munmap");
+        }
+    }
+    lastmap = 0;
+    lastmap_index = size_t(-1);
+}
+
+bool BlockArray::setSize(size_t newsize)
+{
+    return setHistorySize(newsize * 1024 / blocksize);
+}
+
+bool BlockArray::setHistorySize(size_t newsize)
+{
+//    kDebug(1211) << "setHistorySize " << size << " " << newsize;
+
+    if (size == newsize) {
+        return false;
+    }
+
+    unmap();
+
+    if (!newsize) {
+        delete lastblock;
+        lastblock = 0;
+        if (ion >= 0) {
+            close(ion);
+        }
+        ion = -1;
+        current = size_t(-1);
+        return true;
+    }
+
+    if (!size) {
+        FILE * tmp = tmpfile();
+        if (!tmp) {
+            perror("konsole: cannot open temp file.\n");
+        } else {
+            ion = dup(fileno(tmp));
+            if (ion<0) {
+                perror("konsole: cannot dup temp file.\n");
+                fclose(tmp);
+            }
+        }
+        if (ion < 0) {
+            return false;
+        }
+
+        assert(!lastblock);
+
+        lastblock = new Block();
+        size = newsize;
+        return false;
+    }
+
+    if (newsize > size) {
+        increaseBuffer();
+        size = newsize;
+        return false;
+    } else {
+        decreaseBuffer(newsize);
+        ftruncate(ion, length*blocksize);
+        size = newsize;
+
+        return true;
+    }
+}
+
+void moveBlock(FILE * fion, int cursor, int newpos, char * buffer2)
+{
+    int res = fseek(fion, cursor * blocksize, SEEK_SET);
+    if (res) {
+        perror("fseek");
+    }
+    res = fread(buffer2, blocksize, 1, fion);
+    if (res != 1) {
+        perror("fread");
+    }
+
+    res = fseek(fion, newpos * blocksize, SEEK_SET);
+    if (res) {
+        perror("fseek");
+    }
+    res = fwrite(buffer2, blocksize, 1, fion);
+    if (res != 1) {
+        perror("fwrite");
+    }
+    //    printf("moving block %d to %d\n", cursor, newpos);
+}
+
+void BlockArray::decreaseBuffer(size_t newsize)
+{
+    if (index < newsize) { // still fits in whole
+        return;
+    }
+
+    int offset = (current - (newsize - 1) + size) % size;
+
+    if (!offset) {
+        return;
+    }
+
+    // The Block constructor could do somthing in future...
+    char * buffer1 = new char[blocksize];
+
+    FILE * fion = fdopen(dup(ion), "w+b");
+    if (!fion) {
+        delete [] buffer1;
+        perror("fdopen/dup");
+        return;
+    }
+
+    int firstblock;
+    if (current <= newsize) {
+        firstblock = current + 1;
+    } else {
+        firstblock = 0;
+    }
+
+    size_t oldpos;
+    for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
+        oldpos = (size + cursor + offset) % size;
+        moveBlock(fion, oldpos, cursor, buffer1);
+        if (oldpos < newsize) {
+            cursor = oldpos;
+        } else {
+            cursor++;
+        }
+    }
+
+    current = newsize - 1;
+    length = newsize;
+
+    delete [] buffer1;
+
+    fclose(fion);
+
+}
+
+void BlockArray::increaseBuffer()
+{
+    if (index < size) { // not even wrapped once
+        return;
+    }
+
+    int offset = (current + size + 1) % size;
+    if (!offset) { // no moving needed
+        return;
+    }
+
+    // The Block constructor could do somthing in future...
+    char * buffer1 = new char[blocksize];
+    char * buffer2 = new char[blocksize];
+
+    int runs = 1;
+    int bpr = size; // blocks per run
+
+    if (size % offset == 0) {
+        bpr = size / offset;
+        runs = offset;
+    }
+
+    FILE * fion = fdopen(dup(ion), "w+b");
+    if (!fion) {
+        perror("fdopen/dup");
+        delete [] buffer1;
+        delete [] buffer2;
+        return;
+    }
+
+    int res;
+    for (int i = 0; i < runs; i++) {
+        // free one block in chain
+        int firstblock = (offset + i) % size;
+        res = fseek(fion, firstblock * blocksize, SEEK_SET);
+        if (res) {
+            perror("fseek");
+        }
+        res = fread(buffer1, blocksize, 1, fion);
+        if (res != 1) {
+            perror("fread");
+        }
+        int newpos = 0;
+        for (int j = 1, cursor=firstblock; j < bpr; j++) {
+            cursor = (cursor + offset) % size;
+            newpos = (cursor - offset + size) % size;
+            moveBlock(fion, cursor, newpos, buffer2);
+        }
+        res = fseek(fion, i * blocksize, SEEK_SET);
+        if (res) {
+            perror("fseek");
+        }
+        res = fwrite(buffer1, blocksize, 1, fion);
+        if (res != 1) {
+            perror("fwrite");
+        }
+    }
+    current = size - 1;
+    length = size;
+
+    delete [] buffer1;
+    delete [] buffer2;
+
+    fclose(fion);
+
+}
+

=== added file 'src/BlockArray.h'
--- src/BlockArray.h	1970-01-01 00:00:00 +0000
+++ src/BlockArray.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,126 @@
+/*
+    This file is part of Konsole, an X terminal.
+    Copyright (C) 2000 by Stephan Kulow <coolo@xxxxxxx>
+
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    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.
+*/
+
+#ifndef BLOCKARRAY_H
+#define BLOCKARRAY_H
+
+#include <unistd.h>
+
+//#error Do not use in KDE 2.1
+
+#define BlockSize (1 << 12)
+#define ENTRIES   ((BlockSize - sizeof(size_t) ) / sizeof(unsigned char))
+
+struct Block {
+    Block() {
+        size = 0;
+    }
+    unsigned char data[ENTRIES];
+    size_t size;
+};
+
+// ///////////////////////////////////////////////////////
+
+class BlockArray {
+public:
+    /**
+    * Creates a history file for holding
+    * maximal size blocks. If more blocks
+    * are requested, then it drops earlier
+    * added ones.
+    */
+    BlockArray();
+
+    /// destructor
+    ~BlockArray();
+
+    /**
+    * adds the Block at the end of history.
+    * This may drop other blocks.
+    *
+    * The ownership on the block is transfered.
+    * An unique index number is returned for accessing
+    * it later (if not yet dropped then)
+    *
+    * Note, that the block may be dropped completely
+    * if history is turned off.
+    */
+    size_t append(Block * block);
+
+    /**
+    * gets the block at the index. Function may return
+    * 0 if the block isn't available any more.
+    *
+    * The returned block is strictly readonly as only
+    * maped in memory - and will be invalid on the next
+    * operation on this class.
+    */
+    const Block * at(size_t index);
+
+    /**
+    * reorders blocks as needed. If newsize is null,
+    * the history is emptied completely. The indices
+    * returned on append won't change their semantic,
+    * but they may not be valid after this call.
+    */
+    bool setHistorySize(size_t newsize);
+
+    size_t newBlock();
+
+    Block * lastBlock() const;
+
+    /**
+    * Convenient function to set the size in KBytes
+    * instead of blocks
+    */
+    bool setSize(size_t newsize);
+
+    size_t len() const {
+        return length;
+    }
+
+    bool has(size_t index) const;
+
+    size_t getCurrent() const {
+        return current;
+    }
+
+private:
+    void unmap();
+    void increaseBuffer();
+    void decreaseBuffer(size_t newsize);
+
+    size_t size;
+    // current always shows to the last inserted block
+    size_t current;
+    size_t index;
+
+    Block * lastmap;
+    size_t lastmap_index;
+    Block * lastblock;
+
+    int ion;
+    size_t length;
+
+};
+
+#endif

=== added file 'src/Character.h'
--- src/Character.h	1970-01-01 00:00:00 +0000
+++ src/Character.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,221 @@
+/*
+    This file is part of Konsole, KDE's terminal.
+    
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+#ifndef CHARACTER_H
+#define CHARACTER_H
+
+// Qt
+#include <QtCore/QHash>
+
+// Local
+#include "CharacterColor.h"
+
+typedef unsigned char LineProperty;
+
+static const int LINE_DEFAULT        = 0;
+static const int LINE_WRAPPED          = (1 << 0);
+static const int LINE_DOUBLEWIDTH      = (1 << 1);
+static const int LINE_DOUBLEHEIGHT    = (1 << 2);
+
+#define DEFAULT_RENDITION  0
+#define RE_BOLD            (1 << 0)
+#define RE_BLINK           (1 << 1)
+#define RE_UNDERLINE       (1 << 2)
+#define RE_REVERSE         (1 << 3) // Screen only
+#define RE_INTENSIVE       (1 << 3) // Widget only
+#define RE_CURSOR          (1 << 4)
+#define RE_EXTENDED_CHAR   (1 << 5)
+
+/**
+ * A single character in the terminal which consists of a unicode character
+ * value, foreground and background colors and a set of rendition attributes
+ * which specify how it should be drawn.
+ */
+class Character
+{
+public:
+  /** 
+   * Constructs a new character.
+   *
+   * @param _c The unicode character value of this character.
+   * @param _f The foreground color used to draw the character.
+   * @param _b The color used to draw the character's background.
+   * @param _r A set of rendition flags which specify how this character is to be drawn.
+   */
+  inline Character(quint16 _c = ' ',
+            CharacterColor  _f = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR),
+            CharacterColor  _b = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR),
+            quint8  _r = DEFAULT_RENDITION)
+       : character(_c), rendition(_r), foregroundColor(_f), backgroundColor(_b) {}
+
+  union
+  {
+    /** The unicode character value for this character. */
+    quint16 character;
+    /** 
+     * Experimental addition which allows a single Character instance to contain more than
+     * one unicode character.
+     *
+     * charSequence is a hash code which can be used to look up the unicode
+     * character sequence in the ExtendedCharTable used to create the sequence.
+     */
+    quint16 charSequence; 
+  };
+
+  /** A combination of RENDITION flags which specify options for drawing the character. */
+  quint8  rendition;
+
+  /** The foreground color used to draw this character. */
+  CharacterColor  foregroundColor; 
+  /** The color used to draw this character's background. */
+  CharacterColor  backgroundColor;
+
+  /** 
+   * Returns true if this character has a transparent background when
+   * it is drawn with the specified @p palette.
+   */
+  bool   isTransparent(const ColorEntry* palette) const;
+  /**
+   * Returns true if this character should always be drawn in bold when
+   * it is drawn with the specified @p palette, independent of whether
+   * or not the character has the RE_BOLD rendition flag. 
+   */
+  ColorEntry::FontWeight fontWeight(const ColorEntry* base) const;
+  
+  /** 
+   * returns true if the format (color, rendition flag) of the compared characters is equal
+   */
+  bool equalsFormat(const Character &other) const;
+
+  /** 
+   * Compares two characters and returns true if they have the same unicode character value,
+   * rendition and colors.
+   */
+  friend bool operator == (const Character& a, const Character& b);
+  /**
+   * Compares two characters and returns true if they have different unicode character values,
+   * renditions or colors.
+   */
+  friend bool operator != (const Character& a, const Character& b);
+};
+
+inline bool operator == (const Character& a, const Character& b)
+{ 
+  return a.character == b.character && 
+         a.rendition == b.rendition && 
+         a.foregroundColor == b.foregroundColor && 
+         a.backgroundColor == b.backgroundColor;
+}
+
+inline bool operator != (const Character& a, const Character& b)
+{
+  return    a.character != b.character || 
+            a.rendition != b.rendition || 
+            a.foregroundColor != b.foregroundColor || 
+            a.backgroundColor != b.backgroundColor;
+}
+
+inline bool Character::isTransparent(const ColorEntry* base) const
+{
+  return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) && 
+          base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].transparent)
+      || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) && 
+          base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].transparent);
+}
+
+inline bool Character::equalsFormat(const Character& other) const
+{
+  return 
+    backgroundColor==other.backgroundColor &&
+    foregroundColor==other.foregroundColor &&
+    rendition==other.rendition;
+}	
+
+inline ColorEntry::FontWeight Character::fontWeight(const ColorEntry* base) const
+{
+    if (backgroundColor._colorSpace == COLOR_SPACE_DEFAULT)
+        return base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].fontWeight;
+    else if (backgroundColor._colorSpace == COLOR_SPACE_SYSTEM)
+        return base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].fontWeight;
+    else
+        return ColorEntry::UseCurrentFormat;
+}
+
+extern unsigned short vt100_graphics[32];
+
+
+/**
+ * A table which stores sequences of unicode characters, referenced
+ * by hash keys.  The hash key itself is the same size as a unicode
+ * character ( ushort ) so that it can occupy the same space in
+ * a structure.
+ */
+class ExtendedCharTable
+{
+public:
+    /** Constructs a new character table. */
+    ExtendedCharTable();
+    ~ExtendedCharTable();
+
+    /**
+     * Adds a sequences of unicode characters to the table and returns
+     * a hash code which can be used later to look up the sequence
+     * using lookupExtendedChar()
+     *
+     * If the same sequence already exists in the table, the hash
+     * of the existing sequence will be returned.
+     *
+     * @param unicodePoints An array of unicode character points
+     * @param length Length of @p unicodePoints
+     */
+    ushort createExtendedChar(ushort* unicodePoints , ushort length);
+    /**
+     * Looks up and returns a pointer to a sequence of unicode characters
+     * which was added to the table using createExtendedChar().
+     *
+     * @param hash The hash key returned by createExtendedChar()
+     * @param length This variable is set to the length of the 
+     * character sequence.
+     *
+     * @return A unicode character sequence of size @p length.
+     */
+    ushort* lookupExtendedChar(ushort hash , ushort& length) const;
+
+    /** The global ExtendedCharTable instance. */
+    static ExtendedCharTable instance;
+private:
+    // calculates the hash key of a sequence of unicode points of size 'length'
+    ushort extendedCharHash(ushort* unicodePoints , ushort length) const;
+    // tests whether the entry in the table specified by 'hash' matches the 
+    // character sequence 'unicodePoints' of size 'length'
+    bool extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const;
+    // internal, maps hash keys to character sequence buffers.  The first ushort
+    // in each value is the length of the buffer, followed by the ushorts in the buffer
+    // themselves.
+    QHash<ushort,ushort*> extendedCharTable;
+};
+
+
+Q_DECLARE_TYPEINFO(Character, Q_MOVABLE_TYPE);
+
+#endif // CHARACTER_H
+

=== added file 'src/CharacterColor.h'
--- src/CharacterColor.h	1970-01-01 00:00:00 +0000
+++ src/CharacterColor.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,294 @@
+/*
+    This file is part of Konsole, KDE's terminal.
+    
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+#ifndef CHARACTERCOLOR_H
+#define CHARACTERCOLOR_H
+
+// Qt
+#include <QtGui/QColor>
+
+//#include <kdemacros.h>
+#define KDE_NO_EXPORT
+
+/** 
+ * An entry in a terminal display's color palette. 
+ *
+ * A color palette is an array of 16 ColorEntry instances which map
+ * system color indexes (from 0 to 15) into actual colors.
+ *
+ * Each entry can be set as bold, in which case any text
+ * drawn using the color should be drawn in bold.  
+ *
+ * Each entry can also be transparent, in which case the terminal
+ * display should avoid drawing the background for any characters
+ * using the entry as a background.
+ */
+class ColorEntry
+{
+public:
+  /** Specifies the weight to use when drawing text with this color. */
+  enum FontWeight 
+  {
+    /** Always draw text in this color with a bold weight. */
+    Bold,
+    /** Always draw text in this color with a normal weight. */
+    Normal,
+    /** 
+     * Use the current font weight set by the terminal application.  
+     * This is the default behavior.
+     */
+    UseCurrentFormat
+  };
+
+  /** 
+   * Constructs a new color palette entry.
+   *
+   * @param c The color value for this entry.
+   * @param tr Specifies that the color should be transparent when used as a background color.
+   * @param weight Specifies the font weight to use when drawing text with this color. 
+   */
+  ColorEntry(QColor c, bool tr, FontWeight weight = UseCurrentFormat) 
+          : color(c), transparent(tr), fontWeight(weight) {}
+
+  /**
+   * Constructs a new color palette entry with an undefined color, and
+   * with the transparent and bold flags set to false.
+   */ 
+  ColorEntry() : transparent(false), fontWeight(UseCurrentFormat) {} 
+ 
+  /**
+   * Sets the color, transparency and boldness of this color to those of @p rhs.
+   */ 
+  void operator=(const ColorEntry& rhs) 
+  { 
+       color = rhs.color; 
+       transparent = rhs.transparent; 
+       fontWeight = rhs.fontWeight; 
+  }
+
+  /** The color value of this entry for display. */
+  QColor color;
+
+  /** 
+   * If true character backgrounds using this color should be transparent. 
+   * This is not applicable when the color is used to render text.
+   */
+  bool   transparent;
+  /**
+   * Specifies the font weight to use when drawing text with this color. 
+   * This is not applicable when the color is used to draw a character's background.
+   */
+  FontWeight fontWeight;        
+};
+
+
+// Attributed Character Representations ///////////////////////////////
+
+// Colors
+
+#define BASE_COLORS   (2+8)
+#define INTENSITIES   2
+#define TABLE_COLORS  (INTENSITIES*BASE_COLORS)
+
+#define DEFAULT_FORE_COLOR 0
+#define DEFAULT_BACK_COLOR 1
+
+//a standard set of colors using black text on a white background.
+//defined in TerminalDisplay.cpp
+
+extern const ColorEntry base_color_table[TABLE_COLORS] KDE_NO_EXPORT;
+
+/* CharacterColor is a union of the various color spaces.
+
+   Assignment is as follows:
+
+   Type  - Space        - Values
+
+   0     - Undefined   - u:  0,      v:0        w:0
+   1     - Default     - u:  0..1    v:intense  w:0
+   2     - System      - u:  0..7    v:intense  w:0
+   3     - Index(256)  - u: 16..255  v:0        w:0
+   4     - RGB         - u:  0..255  v:0..256   w:0..256
+
+   Default colour space has two separate colours, namely
+   default foreground and default background colour.
+*/
+
+#define COLOR_SPACE_UNDEFINED   0
+#define COLOR_SPACE_DEFAULT     1
+#define COLOR_SPACE_SYSTEM      2
+#define COLOR_SPACE_256         3
+#define COLOR_SPACE_RGB         4
+
+/**
+ * Describes the color of a single character in the terminal.
+ */
+class CharacterColor
+{
+    friend class Character;
+
+public:
+  /** Constructs a new CharacterColor whoose color and color space are undefined. */
+  CharacterColor() 
+      : _colorSpace(COLOR_SPACE_UNDEFINED), 
+        _u(0), 
+        _v(0), 
+        _w(0) 
+  {}
+
+  /** 
+   * Constructs a new CharacterColor using the specified @p colorSpace and with 
+   * color value @p co
+   *
+   * The meaning of @p co depends on the @p colorSpace used.
+   *
+   * TODO : Document how @p co relates to @p colorSpace
+   *
+   * TODO : Add documentation about available color spaces.
+   */
+  CharacterColor(quint8 colorSpace, int co) 
+      : _colorSpace(colorSpace), 
+        _u(0), 
+        _v(0), 
+        _w(0)
+  {
+    switch (colorSpace)
+    {
+        case COLOR_SPACE_DEFAULT:
+            _u = co & 1;
+            break;
+        case COLOR_SPACE_SYSTEM:
+            _u = co & 7;
+            _v = (co >> 3) & 1;
+            break;
+        case COLOR_SPACE_256:  
+            _u = co & 255;
+            break;
+        case COLOR_SPACE_RGB:
+            _u = co >> 16;
+            _v = co >> 8;
+            _w = co;
+            break;
+        default:
+            _colorSpace = COLOR_SPACE_UNDEFINED;
+    }
+  }
+
+  /** 
+   * Returns true if this character color entry is valid.
+   */
+  bool isValid() 
+  {
+        return _colorSpace != COLOR_SPACE_UNDEFINED;
+  }
+    
+  /** 
+   * Toggles the value of this color between a normal system color and the corresponding intensive
+   * system color.
+   * 
+   * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
+   * color spaces.
+   */
+  void toggleIntensive();
+
+  /** 
+   * Returns the color within the specified color @p palette
+   *
+   * The @p palette is only used if this color is one of the 16 system colors, otherwise
+   * it is ignored.
+   */
+  QColor color(const ColorEntry* palette) const;
+ 
+  /** 
+   * Compares two colors and returns true if they represent the same color value and
+   * use the same color space.
+   */
+  friend bool operator == (const CharacterColor& a, const CharacterColor& b);
+  /**
+   * Compares two colors and returns true if they represent different color values
+   * or use different color spaces.
+   */
+  friend bool operator != (const CharacterColor& a, const CharacterColor& b);
+
+private:
+  quint8 _colorSpace;
+
+  // bytes storing the character color 
+  quint8 _u; 
+  quint8 _v; 
+  quint8 _w; 
+};
+
+inline bool operator == (const CharacterColor& a, const CharacterColor& b)
+{ 
+    return     a._colorSpace == b._colorSpace &&
+            a._u == b._u &&
+            a._v == b._v &&
+            a._w == b._w;
+}
+inline bool operator != (const CharacterColor& a, const CharacterColor& b)
+{
+    return !operator==(a,b);
+}
+
+inline const QColor color256(quint8 u, const ColorEntry* base)
+{
+  //   0.. 16: system colors
+  if (u <   8) return base[u+2            ].color; u -= 8;
+  if (u <   8) return base[u+2+BASE_COLORS].color; u -= 8;
+
+  //  16..231: 6x6x6 rgb color cube
+  if (u < 216) return QColor(((u/36)%6) ? (40*((u/36)%6)+55) : 0,
+                             ((u/ 6)%6) ? (40*((u/ 6)%6)+55) : 0,
+                             ((u/ 1)%6) ? (40*((u/ 1)%6)+55) : 0); u -= 216;
+  
+  // 232..255: gray, leaving out black and white
+  int gray = u*10+8; return QColor(gray,gray,gray);
+}
+
+inline QColor CharacterColor::color(const ColorEntry* base) const
+{
+  switch (_colorSpace)
+  {
+    case COLOR_SPACE_DEFAULT: return base[_u+0+(_v?BASE_COLORS:0)].color;
+    case COLOR_SPACE_SYSTEM: return base[_u+2+(_v?BASE_COLORS:0)].color;
+    case COLOR_SPACE_256: return color256(_u,base);
+    case COLOR_SPACE_RGB: return QColor(_u,_v,_w);
+    case COLOR_SPACE_UNDEFINED: return QColor();
+  }
+
+  Q_ASSERT(false); // invalid color space
+
+  return QColor();
+}
+
+inline void CharacterColor::toggleIntensive()
+{
+  if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT)
+  {
+    _v = !_v;
+  }
+}
+
+
+#endif // CHARACTERCOLOR_H
+

=== added file 'src/ColorScheme.cpp'
--- src/ColorScheme.cpp	1970-01-01 00:00:00 +0000
+++ src/ColorScheme.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,774 @@
+/*
+    This source file is part of Konsole, a terminal emulator.
+
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+// Own
+#include "ColorScheme.h"
+#include "tools.h"
+
+// Qt
+#include <QtGui/QBrush>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtDebug>
+#include <QSettings>
+#include <QDir>
+
+
+// KDE
+//#include <KColorScheme>
+//#include <KConfig>
+//#include <KLocale>
+//#include <KDebug>
+//#include <KConfigGroup>
+//#include <KStandardDirs>
+
+
+const ColorEntry ColorScheme::defaultTable[TABLE_COLORS] =
+ // The following are almost IBM standard color codes, with some slight
+ // gamma correction for the dim colors to compensate for bright X screens.
+ // It contains the 8 ansiterm/xterm colors in 2 intensities.
+{
+    ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
+QColor(0xFF,0xFF,0xFF), 1), // Dfore, Dback
+    ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
+QColor(0xB2,0x18,0x18), 0), // Black, Red
+    ColorEntry( QColor(0x18,0xB2,0x18), 0), ColorEntry(
+QColor(0xB2,0x68,0x18), 0), // Green, Yellow
+    ColorEntry( QColor(0x18,0x18,0xB2), 0), ColorEntry(
+QColor(0xB2,0x18,0xB2), 0), // Blue, Magenta
+    ColorEntry( QColor(0x18,0xB2,0xB2), 0), ColorEntry(
+QColor(0xB2,0xB2,0xB2), 0), // Cyan, White
+    // intensive
+    ColorEntry( QColor(0x00,0x00,0x00), 0), ColorEntry(
+QColor(0xFF,0xFF,0xFF), 1),
+    ColorEntry( QColor(0x68,0x68,0x68), 0), ColorEntry(
+QColor(0xFF,0x54,0x54), 0),
+    ColorEntry( QColor(0x54,0xFF,0x54), 0), ColorEntry(
+QColor(0xFF,0xFF,0x54), 0),
+    ColorEntry( QColor(0x54,0x54,0xFF), 0), ColorEntry(
+QColor(0xFF,0x54,0xFF), 0),
+    ColorEntry( QColor(0x54,0xFF,0xFF), 0), ColorEntry(
+QColor(0xFF,0xFF,0xFF), 0)
+};
+
+const char* const ColorScheme::colorNames[TABLE_COLORS] =
+{
+  "Foreground",
+  "Background",
+  "Color0",
+  "Color1",
+  "Color2",
+  "Color3",
+  "Color4",
+  "Color5",
+  "Color6",
+  "Color7",
+  "ForegroundIntense",
+  "BackgroundIntense",
+  "Color0Intense",
+  "Color1Intense",
+  "Color2Intense",
+  "Color3Intense",
+  "Color4Intense",
+  "Color5Intense",
+  "Color6Intense",
+  "Color7Intense"
+};
+// dummy silently comment out the tr_NOOP
+#define tr_NOOP
+const char* const ColorScheme::translatedColorNames[TABLE_COLORS] =
+{
+    tr_NOOP("Foreground"),
+    tr_NOOP("Background"),
+    tr_NOOP("Color 1"),
+    tr_NOOP("Color 2"),
+    tr_NOOP("Color 3"),
+    tr_NOOP("Color 4"),
+    tr_NOOP("Color 5"),
+    tr_NOOP("Color 6"),
+    tr_NOOP("Color 7"),
+    tr_NOOP("Color 8"),
+    tr_NOOP("Foreground (Intense)"),
+    tr_NOOP("Background (Intense)"),
+    tr_NOOP("Color 1 (Intense)"),
+    tr_NOOP("Color 2 (Intense)"),
+    tr_NOOP("Color 3 (Intense)"),
+    tr_NOOP("Color 4 (Intense)"),
+    tr_NOOP("Color 5 (Intense)"),
+    tr_NOOP("Color 6 (Intense)"),
+    tr_NOOP("Color 7 (Intense)"),
+    tr_NOOP("Color 8 (Intense)")
+};
+
+ColorScheme::ColorScheme()
+{
+    _table = 0;
+    _randomTable = 0;
+    _opacity = 1.0;
+}
+ColorScheme::ColorScheme(const ColorScheme& other)
+      : _opacity(other._opacity)
+       ,_table(0)
+       ,_randomTable(0)
+{
+    setName(other.name());
+    setDescription(other.description());
+
+    if ( other._table != 0 )
+    {
+        for ( int i = 0 ; i < TABLE_COLORS ; i++ )
+            setColorTableEntry(i,other._table[i]);
+    }
+
+    if ( other._randomTable != 0 )
+    {
+        for ( int i = 0 ; i < TABLE_COLORS ; i++ )
+        {
+            const RandomizationRange& range = other._randomTable[i];
+            setRandomizationRange(i,range.hue,range.saturation,range.value);
+        }
+    }
+}
+ColorScheme::~ColorScheme()
+{
+    delete[] _table;
+    delete[] _randomTable;
+}
+
+void ColorScheme::setDescription(const QString& description) { _description = description; }
+QString ColorScheme::description() const { return _description; }
+
+void ColorScheme::setName(const QString& name) { _name = name; }
+QString ColorScheme::name() const { return _name; }
+
+void ColorScheme::setColorTableEntry(int index , const ColorEntry& entry)
+{
+    Q_ASSERT( index >= 0 && index < TABLE_COLORS );
+
+    if ( !_table ) 
+    {
+        _table = new ColorEntry[TABLE_COLORS];
+
+        for (int i=0;i<TABLE_COLORS;i++)
+            _table[i] = defaultTable[i];
+    }
+    
+    _table[index] = entry; 
+}
+ColorEntry ColorScheme::colorEntry(int index , uint randomSeed) const
+{
+    Q_ASSERT( index >= 0 && index < TABLE_COLORS );
+
+    if ( randomSeed != 0 )
+        qsrand(randomSeed);
+
+    ColorEntry entry = colorTable()[index];
+
+    if ( randomSeed != 0 && 
+        _randomTable != 0 && 
+        !_randomTable[index].isNull() )
+    {
+        const RandomizationRange& range = _randomTable[index];
+      
+
+        int hueDifference = range.hue ? (qrand() % range.hue) - range.hue/2 : 0;
+        int saturationDifference = range.saturation ? (qrand() % range.saturation) - range.saturation/2 : 0;
+        int  valueDifference = range.value ? (qrand() % range.value) - range.value/2 : 0;
+
+        QColor& color = entry.color;
+      
+        int newHue = qAbs( (color.hue() + hueDifference) % MAX_HUE );
+        int newValue = qMin( qAbs(color.value() + valueDifference) , 255 );
+        int newSaturation = qMin( qAbs(color.saturation() + saturationDifference) , 255 );
+
+        color.setHsv(newHue,newSaturation,newValue);
+    }
+
+    return entry;
+}
+void ColorScheme::getColorTable(ColorEntry* table , uint randomSeed) const
+{
+    for ( int i = 0 ; i < TABLE_COLORS ; i++ )
+        table[i] = colorEntry(i,randomSeed);
+}
+bool ColorScheme::randomizedBackgroundColor() const
+{
+    return _randomTable == 0 ? false : !_randomTable[1].isNull();
+}
+void ColorScheme::setRandomizedBackgroundColor(bool randomize)
+{
+    // the hue of the background colour is allowed to be randomly 
+    // adjusted as much as possible.
+    //
+    // the value and saturation are left alone to maintain read-ability
+    if ( randomize )
+    {
+        setRandomizationRange( 1 /* background color index */ , MAX_HUE , 255 , 0 ); 
+    }
+    else
+    {
+        if ( _randomTable )
+            setRandomizationRange( 1 /* background color index */ , 0 , 0 , 0 );
+    }
+}
+
+void ColorScheme::setRandomizationRange( int index , quint16 hue , quint8 saturation ,
+                                         quint8 value )
+{
+    Q_ASSERT( hue <= MAX_HUE );
+    Q_ASSERT( index >= 0 && index < TABLE_COLORS );
+
+    if ( _randomTable == 0 )
+        _randomTable = new RandomizationRange[TABLE_COLORS];
+
+    _randomTable[index].hue = hue;
+    _randomTable[index].value = value;
+    _randomTable[index].saturation = saturation;
+}
+
+const ColorEntry* ColorScheme::colorTable() const
+{
+    if ( _table )
+        return _table;
+    else
+        return defaultTable;
+}
+QColor ColorScheme::foregroundColor() const
+{
+    return colorTable()[0].color;
+}
+QColor ColorScheme::backgroundColor() const
+{
+    return colorTable()[1].color;
+}
+bool ColorScheme::hasDarkBackground() const
+{
+    // value can range from 0 - 255, with larger values indicating higher brightness.
+    // so 127 is in the middle, anything less is deemed 'dark'
+    return backgroundColor().value() < 127;
+}
+void ColorScheme::setOpacity(qreal opacity) { _opacity = opacity; }
+qreal ColorScheme::opacity() const { return _opacity; }
+
+void ColorScheme::read(const QString & fileName)
+{
+    QSettings s(fileName, QSettings::IniFormat);
+    s.beginGroup("General");
+
+    _description = s.value("Description", QObject::tr("Un-named Color Scheme")).toString();
+    _opacity = s.value("Opacity",qreal(1.0)).toDouble();
+    s.endGroup();
+
+    for (int i=0 ; i < TABLE_COLORS ; i++)
+    {
+        readColorEntry(&s, i);
+    }
+}
+#if 0
+// implemented upstream - user apps
+void ColorScheme::read(KConfig& config)
+{
+    KConfigGroup configGroup = config.group("General");
+
+    QString description = configGroup.readEntry("Description", QObject::tr("Un-named Color Scheme"));
+
+    _description = tr(description.toUtf8());
+    _opacity = configGroup.readEntry("Opacity",qreal(1.0));
+
+    for (int i=0 ; i < TABLE_COLORS ; i++)
+    {
+        readColorEntry(config,i);
+    }
+}
+void ColorScheme::write(KConfig& config) const
+{
+    KConfigGroup configGroup = config.group("General");
+
+    configGroup.writeEntry("Description",_description);
+    configGroup.writeEntry("Opacity",_opacity);
+    
+    for (int i=0 ; i < TABLE_COLORS ; i++)
+    {
+        RandomizationRange random = _randomTable != 0 ? _randomTable[i] : RandomizationRange();
+        writeColorEntry(config,colorNameForIndex(i),colorTable()[i],random);
+    }
+}
+#endif
+
+QString ColorScheme::colorNameForIndex(int index) 
+{
+    Q_ASSERT( index >= 0 && index < TABLE_COLORS );
+
+    return QString(colorNames[index]);
+}
+QString ColorScheme::translatedColorNameForIndex(int index) 
+{
+    Q_ASSERT( index >= 0 && index < TABLE_COLORS );
+
+    return translatedColorNames[index];
+}
+
+void ColorScheme::readColorEntry(QSettings * s , int index)
+{
+    s->beginGroup(colorNameForIndex(index));
+    
+    ColorEntry entry;
+
+    QStringList rgbList = s->value("Color", QStringList()).toStringList();
+    if (rgbList.count() != 3)
+    {
+        Q_ASSERT(0);
+    }
+    int r, g, b;
+    r = rgbList[0].toInt();
+    g = rgbList[1].toInt();
+    b = rgbList[2].toInt();
+    entry.color = QColor(r, g, b);
+    
+    entry.transparent = s->value("Transparent",false).toBool();
+
+    // Deprecated key from KDE 4.0 which set 'Bold' to true to force
+    // a color to be bold or false to use the current format
+    //
+    // TODO - Add a new tri-state key which allows for bold, normal or
+    // current format
+    if (s->contains("Bold"))
+        entry.fontWeight = s->value("Bold",false).toBool() ? ColorEntry::Bold :
+                                                                 ColorEntry::UseCurrentFormat;
+
+    quint16 hue = s->value("MaxRandomHue",0).toInt();
+    quint8 value = s->value("MaxRandomValue",0).toInt();
+    quint8 saturation = s->value("MaxRandomSaturation",0).toInt();
+
+    setColorTableEntry( index , entry );
+
+    if ( hue != 0 || value != 0 || saturation != 0 )
+       setRandomizationRange( index , hue , saturation , value ); 
+
+    s->endGroup();
+}
+#if 0
+// implemented upstream - user apps
+void ColorScheme::writeColorEntry(KConfig& config , const QString& colorName, const ColorEntry& entry , const RandomizationRange& random) const
+{
+    KConfigGroup configGroup(&config,colorName);
+
+    configGroup.writeEntry("Color",entry.color);
+    configGroup.writeEntry("Transparency",(bool)entry.transparent);
+    if (entry.fontWeight != ColorEntry::UseCurrentFormat)
+    {
+        configGroup.writeEntry("Bold",entry.fontWeight == ColorEntry::Bold);
+    }
+
+    // record randomization if this color has randomization or 
+    // if one of the keys already exists 
+    if ( !random.isNull() || configGroup.hasKey("MaxRandomHue") )
+    {
+        configGroup.writeEntry("MaxRandomHue",(int)random.hue);
+        configGroup.writeEntry("MaxRandomValue",(int)random.value);
+        configGroup.writeEntry("MaxRandomSaturation",(int)random.saturation);
+    }
+}
+#endif
+
+// 
+// Work In Progress - A color scheme for use on KDE setups for users
+// with visual disabilities which means that they may have trouble
+// reading text with the supplied color schemes.
+//
+// This color scheme uses only the 'safe' colors defined by the
+// KColorScheme class.  
+//
+// A complication this introduces is that each color provided by 
+// KColorScheme is defined as a 'background' or 'foreground' color.
+// Only foreground colors are allowed to be used to render text and 
+// only background colors are allowed to be used for backgrounds.
+//
+// The ColorEntry and TerminalDisplay classes do not currently
+// support this restriction.  
+//
+// Requirements:
+//  - A color scheme which uses only colors from the KColorScheme class
+//  - Ability to restrict which colors the TerminalDisplay widget 
+//    uses as foreground and background color
+//  - Make use of KGlobalSettings::allowDefaultBackgroundImages() as
+//    a hint to determine whether this accessible color scheme should 
+//    be used by default.
+//
+//
+// -- Robert Knight <robertknight@xxxxxxxxx> 21/07/2007
+//
+AccessibleColorScheme::AccessibleColorScheme()
+    : ColorScheme()
+{
+#if 0
+// It's not finished in konsole and it breaks Qt4 compilation as well
+    // basic attributes
+    setName("accessible");
+    setDescription(QObject::tr("Accessible Color Scheme"));
+
+    // setup colors
+    const int ColorRoleCount = 8;
+
+    const KColorScheme colorScheme(QPalette::Active);
+
+    QBrush colors[ColorRoleCount] =
+    {
+        colorScheme.foreground( colorScheme.NormalText ),
+        colorScheme.background( colorScheme.NormalBackground ),
+
+        colorScheme.foreground( colorScheme.InactiveText ),
+        colorScheme.foreground( colorScheme.ActiveText ),
+        colorScheme.foreground( colorScheme.LinkText ),
+        colorScheme.foreground( colorScheme.VisitedText ),
+        colorScheme.foreground( colorScheme.NegativeText ),
+        colorScheme.foreground( colorScheme.NeutralText )
+    };
+
+    for ( int i = 0 ; i < TABLE_COLORS ; i++ ) 
+    {
+        ColorEntry entry;
+        entry.color = colors[ i % ColorRoleCount ].color();
+
+        setColorTableEntry( i , entry ); 
+    }   
+#endif
+}
+
+KDE3ColorSchemeReader::KDE3ColorSchemeReader( QIODevice* device ) :
+    _device(device)
+{
+}
+ColorScheme* KDE3ColorSchemeReader::read() 
+{
+    Q_ASSERT( _device->openMode() == QIODevice::ReadOnly ||
+              _device->openMode() == QIODevice::ReadWrite  );
+
+    ColorScheme* scheme = new ColorScheme();
+
+    QRegExp comment("#.*$");
+    while ( !_device->atEnd() )
+    {
+        QString line(_device->readLine());
+        line.remove(comment);
+        line = line.simplified();
+
+        if ( line.isEmpty() )
+            continue;
+
+        if ( line.startsWith(QLatin1String("color")) )
+        {
+            if (!readColorLine(line,scheme))
+                qDebug() << "Failed to read KDE 3 color scheme line" << line;
+        }
+        else if ( line.startsWith(QLatin1String("title")) )
+        {
+            if (!readTitleLine(line,scheme))
+                qDebug() << "Failed to read KDE 3 color scheme title line" << line;
+        }
+        else
+        {
+            qDebug() << "KDE 3 color scheme contains an unsupported feature, '" <<
+                line << "'";
+        } 
+    }
+
+    return scheme;
+}
+bool KDE3ColorSchemeReader::readColorLine(const QString& line,ColorScheme* scheme)
+{
+    QStringList list = line.split(QChar(' '));
+
+    if (list.count() != 7)
+        return false;
+    if (list.first() != "color")
+        return false;
+    
+    int index = list[1].toInt();
+    int red = list[2].toInt();
+    int green = list[3].toInt();
+    int blue = list[4].toInt();
+    int transparent = list[5].toInt();
+    int bold = list[6].toInt();
+
+    const int MAX_COLOR_VALUE = 255;
+
+    if(     (index < 0 || index >= TABLE_COLORS )
+        ||  (red < 0 || red > MAX_COLOR_VALUE )
+        ||  (blue < 0 || blue > MAX_COLOR_VALUE )
+        ||  (green < 0 || green > MAX_COLOR_VALUE )
+        ||  (transparent != 0 && transparent != 1 )
+        ||  (bold != 0 && bold != 1)    )
+        return false;
+
+    ColorEntry entry;
+    entry.color = QColor(red,green,blue);
+    entry.transparent = ( transparent != 0 );
+    entry.fontWeight = ( bold != 0 ) ? ColorEntry::Bold : ColorEntry::UseCurrentFormat;
+
+    scheme->setColorTableEntry(index,entry);
+    return true;
+}
+bool KDE3ColorSchemeReader::readTitleLine(const QString& line,ColorScheme* scheme)
+{
+    if( !line.startsWith(QLatin1String("title")) )
+        return false;
+
+    int spacePos = line.indexOf(' ');
+    if( spacePos == -1 )
+        return false;
+
+    QString description = line.mid(spacePos+1);
+
+    scheme->setDescription(description.toUtf8());
+    return true;
+}
+ColorSchemeManager::ColorSchemeManager()
+    : _haveLoadedAll(false)
+{
+}
+ColorSchemeManager::~ColorSchemeManager()
+{
+    QHashIterator<QString,const ColorScheme*> iter(_colorSchemes);
+    while (iter.hasNext())
+    {
+        iter.next();
+        delete iter.value();
+    }
+}
+void ColorSchemeManager::loadAllColorSchemes()
+{
+    qDebug() << "loadAllColorSchemes";
+    int success = 0;
+    int failed = 0;
+
+    QList<QString> nativeColorSchemes = listColorSchemes();
+
+    QListIterator<QString> nativeIter(nativeColorSchemes);
+    while ( nativeIter.hasNext() )
+    {
+        if ( loadColorScheme( nativeIter.next() ) )
+            success++;
+        else
+            failed++;
+    }
+
+    QList<QString> kde3ColorSchemes = listKDE3ColorSchemes();
+    QListIterator<QString> kde3Iter(kde3ColorSchemes);
+    while ( kde3Iter.hasNext() )
+    {
+        if ( loadKDE3ColorScheme( kde3Iter.next() ) )
+            success++;
+        else
+            failed++;
+    }
+
+    if ( failed > 0 )
+        qDebug() << "failed to load " << failed << " color schemes.";
+
+    _haveLoadedAll = true;
+}
+QList<const ColorScheme*> ColorSchemeManager::allColorSchemes()
+{
+    if ( !_haveLoadedAll )
+    {
+        loadAllColorSchemes();
+    }
+
+    return _colorSchemes.values();
+}
+bool ColorSchemeManager::loadKDE3ColorScheme(const QString& filePath)
+{
+    QFile file(filePath);
+    if (!filePath.endsWith(QLatin1String(".schema")) || !file.open(QIODevice::ReadOnly))
+        return false;
+
+    KDE3ColorSchemeReader reader(&file);
+    ColorScheme* scheme = reader.read();
+    scheme->setName(QFileInfo(file).baseName());
+    file.close();
+
+    if (scheme->name().isEmpty())
+    {
+        qDebug() << "color scheme name is not valid.";
+        delete scheme;
+        return false;
+    }
+    
+    QFileInfo info(filePath);
+
+    if ( !_colorSchemes.contains(info.baseName()) )
+        _colorSchemes.insert(scheme->name(),scheme);
+    else
+    {
+        qDebug() << "color scheme with name" << scheme->name() << "has already been" <<
+            "found, ignoring.";
+        delete scheme;
+    }
+
+    return true;
+}
+#if 0
+void ColorSchemeManager::addColorScheme(ColorScheme* scheme) 
+{
+    _colorSchemes.insert(scheme->name(),scheme);
+
+    // save changes to disk
+    QString path = KGlobal::dirs()->saveLocation("data","konsole/") + scheme->name() + ".colorscheme";
+    KConfig config(path , KConfig::NoGlobals);
+
+    scheme->write(config);
+}
+#endif
+bool ColorSchemeManager::loadColorScheme(const QString& filePath)
+{
+    if ( !filePath.endsWith(QLatin1String(".colorscheme")) || !QFile::exists(filePath) )
+        return false;
+
+    QFileInfo info(filePath);
+    
+    ColorScheme* scheme = new ColorScheme();
+    scheme->setName(info.baseName());
+    scheme->read(filePath);
+
+    if (scheme->name().isEmpty()) 
+    {
+        qDebug() << "Color scheme in" << filePath << "does not have a valid name and was not loaded.";
+        delete scheme;
+        return false;
+    }    
+
+    if ( !_colorSchemes.contains(info.baseName()) )
+    {
+        _colorSchemes.insert(scheme->name(),scheme);
+    }
+    else
+    {
+        qDebug() << "color scheme with name" << scheme->name() << "has already been" <<
+            "found, ignoring.";
+        
+        delete scheme;
+    }
+
+    return true; 
+}
+QList<QString> ColorSchemeManager::listKDE3ColorSchemes()
+{
+    QString dname(get_color_schemes_dir());
+    QDir dir(dname);
+    QStringList filters;
+    filters << "*.schema";
+    dir.setNameFilters(filters);
+    QStringList list = dir.entryList(filters); 
+    QStringList ret;
+    foreach(QString i, list)
+        ret << dname + "/" + i;
+    return ret;
+    //return KGlobal::dirs()->findAllResources("data",
+    //                                         "konsole/*.schema",
+    //                                          KStandardDirs::NoDuplicates);
+    //
+}
+QList<QString> ColorSchemeManager::listColorSchemes()
+{
+    QString dname(get_color_schemes_dir());
+    QDir dir(dname);
+    QStringList filters;
+    filters << "*.colorscheme";
+    dir.setNameFilters(filters);
+    QStringList list = dir.entryList(filters);
+    QStringList ret;
+    foreach(QString i, list)
+        ret << dname + "/" + i;
+    return ret;
+//    return KGlobal::dirs()->findAllResources("data",
+//                                             "konsole/*.colorscheme",
+//                                             KStandardDirs::NoDuplicates);
+}
+const ColorScheme ColorSchemeManager::_defaultColorScheme;
+const ColorScheme* ColorSchemeManager::defaultColorScheme() const
+{
+    return &_defaultColorScheme;
+}
+bool ColorSchemeManager::deleteColorScheme(const QString& name)
+{
+    Q_ASSERT( _colorSchemes.contains(name) );
+
+    // lookup the path and delete 
+    QString path = findColorSchemePath(name);
+    if ( QFile::remove(path) )
+    {
+        _colorSchemes.remove(name);
+        return true;
+    }
+    else
+    {
+        qDebug() << "Failed to remove color scheme -" << path;
+        return false;
+    }
+}
+QString ColorSchemeManager::findColorSchemePath(const QString& name) const
+{
+//    QString path = KStandardDirs::locate("data","konsole/"+name+".colorscheme");
+    QString path(get_color_schemes_dir() + "/"+ name + ".colorscheme");
+    if ( !path.isEmpty() )
+       return path; 
+
+    //path = KStandardDirs::locate("data","konsole/"+name+".schema");
+    path = get_color_schemes_dir() + "/"+ name + ".schema";
+
+    return path;
+}
+const ColorScheme* ColorSchemeManager::findColorScheme(const QString& name) 
+{
+    if ( name.isEmpty() )
+        return defaultColorScheme();
+
+    if ( _colorSchemes.contains(name) )
+        return _colorSchemes[name];
+    else
+    {
+        // look for this color scheme
+        QString path = findColorSchemePath(name); 
+        if ( !path.isEmpty() && loadColorScheme(path) )
+        {
+            return findColorScheme(name); 
+        } 
+        else 
+        {
+            if (!path.isEmpty() && loadKDE3ColorScheme(path))
+                return findColorScheme(name);
+        }
+
+        qDebug() << "Could not find color scheme - " << name;
+
+        return 0; 
+    }
+}
+
+ColorSchemeManager* ColorSchemeManager::theColorSchemeManager = 0;
+//K_GLOBAL_STATIC( ColorSchemeManager , theColorSchemeManager )
+ColorSchemeManager* ColorSchemeManager::instance()
+{
+    if (! theColorSchemeManager)
+        theColorSchemeManager = new ColorSchemeManager();
+    return theColorSchemeManager;
+}

=== added file 'src/ColorScheme.h'
--- src/ColorScheme.h	1970-01-01 00:00:00 +0000
+++ src/ColorScheme.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,342 @@
+/*
+    This source file is part of Konsole, a terminal emulator.
+
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+#ifndef COLORSCHEME_H
+#define COLORSCHEME_H
+
+// Qt
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QMetaType>
+#include <QtCore/QIODevice>
+#include <QtCore/QSet>
+#include <QSettings>
+
+// Konsole
+#include "CharacterColor.h"
+
+class QIODevice;
+//class KConfig;
+
+
+/**
+ * Represents a color scheme for a terminal display.  
+ *
+ * The color scheme includes the palette of colors used to draw the text and character backgrounds
+ * in the display and the opacity level of the display background. 
+ */
+class ColorScheme
+{
+public:
+    /** 
+     * Constructs a new color scheme which is initialised to the default color set 
+     * for Konsole.
+     */
+    ColorScheme();
+    ColorScheme(const ColorScheme& other);
+    ~ColorScheme();
+
+    /** Sets the descriptive name of the color scheme. */
+    void setDescription(const QString& description);
+    /** Returns the descriptive name of the color scheme. */
+    QString description() const;
+
+    /** Sets the name of the color scheme */
+    void setName(const QString& name);
+    /** Returns the name of the color scheme */
+    QString name() const;
+
+#if 0
+// Implemented upstream - in user apps
+    /** Reads the color scheme from the specified configuration source */
+    void read(KConfig& config);
+    /** Writes the color scheme to the specified configuration source */
+    void write(KConfig& config) const;
+#endif
+    void read(const QString & filename);
+
+    /** Sets a single entry within the color palette. */
+    void setColorTableEntry(int index , const ColorEntry& entry);
+
+    /** 
+     * Copies the color entries which form the palette for this color scheme
+     * into @p table.  @p table should be an array with TABLE_COLORS entries.
+     *
+     * @param table Array into which the color entries for this color scheme
+     * are copied.
+     * @param randomSeed Color schemes may allow certain colors in their
+     * palette to be randomized.  The seed is used to pick the random color.
+     */
+    void getColorTable(ColorEntry* table, uint randomSeed = 0) const;
+   
+    /**
+     * Retrieves a single color entry from the table.
+     *
+     * See getColorTable()
+     */
+    ColorEntry colorEntry(int index , uint randomSeed = 0) const;
+
+    /** 
+     * Convenience method.  Returns the 
+     * foreground color for this scheme, 
+     * this is the primary color used to draw the 
+     * text in this scheme.
+     */
+    QColor foregroundColor() const;
+    /**
+     * Convenience method.  Returns the background color for 
+     * this scheme, this is the primary color used to 
+     * draw the terminal background in this scheme.
+     */
+    QColor backgroundColor() const;
+
+    /** 
+     * Returns true if this color scheme has a dark background.
+     * The background color is said to be dark if it has a value of less than 127
+     * in the HSV color space.
+     */
+    bool hasDarkBackground() const;
+
+    /** 
+     * Sets the opacity level of the display background. @p opacity ranges
+     * between 0 (completely transparent background) and 1 (completely
+     * opaque background).
+     *
+     * Defaults to 1.
+     *
+     * TODO: More documentation
+     */
+    void setOpacity(qreal opacity);
+    /** 
+     * Returns the opacity level for this color scheme, see setOpacity()
+     * TODO: More documentation
+     */
+    qreal opacity() const;
+
+    /** 
+     * Enables randomization of the background color.  This will cause
+     * the palette returned by getColorTable() and colorEntry() to
+     * be adjusted depending on the value of the random seed argument
+     * to them.
+     */ 
+    void setRandomizedBackgroundColor(bool randomize);
+
+    /** Returns true if the background color is randomized. */
+    bool randomizedBackgroundColor() const;
+
+    static QString colorNameForIndex(int index);
+    static QString translatedColorNameForIndex(int index);
+
+private:
+    // specifies how much a particular color can be randomized by
+    class RandomizationRange
+    {
+    public:
+        RandomizationRange() : hue(0) , saturation(0) , value(0) {}
+
+        bool isNull() const 
+        {
+            return ( hue == 0 && saturation == 0 && value == 0 );
+        }
+
+        quint16 hue;
+        quint8  saturation;
+        quint8  value;
+    };
+
+    // returns the active color table.  if none has been set specifically,
+    // this is the default color table.
+    const ColorEntry* colorTable() const;
+
+#if 0
+// implemented upstream - user apps
+    // reads a single colour entry from a KConfig source
+    // and sets the palette entry at 'index' to the entry read.
+    void readColorEntry(KConfig& config , int index); 
+    // writes a single colour entry to a KConfig source
+    void writeColorEntry(KConfig& config , const QString& colorName, const ColorEntry& entry,const RandomizationRange& range) const;
+#endif
+    void readColorEntry(QSettings *s, int index);
+
+    // sets the amount of randomization allowed for a particular color 
+    // in the palette.  creates the randomization table if 
+    // it does not already exist
+    void setRandomizationRange( int index , quint16 hue , quint8 saturation , quint8 value );
+
+    QString _description;
+    QString _name;
+    qreal _opacity;
+    ColorEntry* _table; // pointer to custom color table or 0 if the default
+                        // color scheme is being used
+
+
+    static const quint16 MAX_HUE = 340;
+
+    RandomizationRange* _randomTable;   // pointer to randomization table or 0
+                                        // if no colors in the color scheme support
+                                        // randomization
+
+    static const char* const colorNames[TABLE_COLORS];
+    static const char* const translatedColorNames[TABLE_COLORS];
+
+    static const ColorEntry defaultTable[]; // table of default color entries
+};
+
+/** 
+ * A color scheme which uses colors from the standard KDE color palette.
+ *
+ * This is designed primarily for the benefit of users who are using specially
+ * designed colors.
+ *
+ * TODO Implement and make it the default on systems with specialized KDE
+ * color schemes.
+ */
+class AccessibleColorScheme : public ColorScheme
+{
+public:
+    AccessibleColorScheme();
+};
+
+/**
+ * Reads a color scheme stored in the .schema format used in the KDE 3 incarnation
+ * of Konsole
+ *
+ * Only the basic essentials ( title and color palette entries ) are currently
+ * supported.  Additional options such as background image and background
+ * blend colors are ignored.
+ */
+class KDE3ColorSchemeReader
+{
+public:
+    /** 
+     * Constructs a new reader which reads from the specified device. 
+     * The device should be open in read-only mode. 
+     */
+    KDE3ColorSchemeReader( QIODevice* device );
+
+    /** 
+     * Reads and parses the contents of the .schema file from the input
+     * device and returns the ColorScheme defined within it.
+     *
+     * Returns a null pointer if an error occurs whilst parsing
+     * the contents of the file.
+     */
+    ColorScheme* read();
+
+private:
+    // reads a line from the file specifying a colour palette entry
+    // format is: color [index] [red] [green] [blue] [transparent] [bold]
+    bool readColorLine(const QString& line , ColorScheme* scheme);
+    bool readTitleLine(const QString& line , ColorScheme* scheme);
+
+    QIODevice* _device;
+};
+
+/**
+ * Manages the color schemes available for use by terminal displays.
+ * See ColorScheme
+ */
+class ColorSchemeManager
+{
+public:
+
+    /**
+     * Constructs a new ColorSchemeManager and loads the list
+     * of available color schemes.
+     *
+     * The color schemes themselves are not loaded until they are first
+     * requested via a call to findColorScheme()
+     */
+    ColorSchemeManager();
+    /**
+     * Destroys the ColorSchemeManager and saves any modified color schemes to disk.
+     */
+    ~ColorSchemeManager();
+
+    /**
+     * Returns the default color scheme for Konsole
+     */
+    const ColorScheme* defaultColorScheme() const;
+ 
+    /**
+     * Returns the color scheme with the given name or 0 if no
+     * scheme with that name exists.  If @p name is empty, the
+     * default color scheme is returned.
+     *
+     * The first time that a color scheme with a particular name is
+     * requested, the configuration information is loaded from disk.
+     */
+    const ColorScheme* findColorScheme(const QString& name);
+
+#if 0
+    /**
+     * Adds a new color scheme to the manager.  If @p scheme has the same name as
+     * an existing color scheme, it replaces the existing scheme.
+     *
+     * TODO - Ensure the old color scheme gets deleted
+     */
+    void addColorScheme(ColorScheme* scheme);
+#endif
+    /**
+     * Deletes a color scheme.  Returns true on successful deletion or false otherwise. 
+     */
+    bool deleteColorScheme(const QString& name);
+
+    /** 
+     * Returns a list of the all the available color schemes. 
+     * This may be slow when first called because all of the color
+     * scheme resources on disk must be located, read and parsed.
+     *
+     * Subsequent calls will be inexpensive. 
+     */
+    QList<const ColorScheme*> allColorSchemes();    
+
+    /** Returns the global color scheme manager instance. */
+    static ColorSchemeManager* instance();
+
+private:
+    // loads a color scheme from a KDE 4+ .colorscheme file
+    bool loadColorScheme(const QString& path);
+    // loads a color scheme from a KDE 3 .schema file
+    bool loadKDE3ColorScheme(const QString& path);
+    // returns a list of paths of color schemes in the KDE 4+ .colorscheme file format
+    QList<QString> listColorSchemes();
+    // returns a list of paths of color schemes in the .schema file format
+    // used in KDE 3
+    QList<QString> listKDE3ColorSchemes();
+    // loads all of the color schemes
+    void loadAllColorSchemes();
+    // finds the path of a color scheme
+    QString findColorSchemePath(const QString& name) const;
+
+    QHash<QString,const ColorScheme*> _colorSchemes;
+    QSet<ColorScheme*> _modifiedSchemes;
+
+    bool _haveLoadedAll;
+
+    static const ColorScheme _defaultColorScheme;
+
+    static ColorSchemeManager * theColorSchemeManager;
+};
+
+Q_DECLARE_METATYPE(const ColorScheme*)
+
+#endif //COLORSCHEME_H

=== added file 'src/ColorTables.h'
--- src/ColorTables.h	1970-01-01 00:00:00 +0000
+++ src/ColorTables.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,55 @@
+#ifndef _COLOR_TABLE_H
+#define _COLOR_TABLE_H
+
+#include "CharacterColor.h"
+
+//using namespace Konsole;
+#if 0
+static const ColorEntry whiteonblack_color_table[TABLE_COLORS] = {
+    // normal
+    ColorEntry(QColor(0xFF,0xFF,0xFF), false ), ColorEntry( QColor(0x00,0x00,0x00), true ), // Dfore, Dback
+    ColorEntry(QColor(0x00,0x00,0x00), false ), ColorEntry( QColor(0xB2,0x18,0x18), false ), // Black, Red
+    ColorEntry(QColor(0x18,0xB2,0x18), false ), ColorEntry( QColor(0xB2,0x68,0x18), false ), // Green, Yellow
+    ColorEntry(QColor(0x18,0x18,0xB2), false ), ColorEntry( QColor(0xB2,0x18,0xB2), false ), // Blue, Magenta
+    ColorEntry(QColor(0x18,0xB2,0xB2), false ), ColorEntry( QColor(0xB2,0xB2,0xB2), false ), // Cyan, White
+    // intensiv
+    ColorEntry(QColor(0x00,0x00,0x00), false ), ColorEntry( QColor(0xFF,0xFF,0xFF), true ),
+    ColorEntry(QColor(0x68,0x68,0x68), false ), ColorEntry( QColor(0xFF,0x54,0x54), false ),
+    ColorEntry(QColor(0x54,0xFF,0x54), false ), ColorEntry( QColor(0xFF,0xFF,0x54), false ),
+    ColorEntry(QColor(0x54,0x54,0xFF), false ), ColorEntry( QColor(0xFF,0x54,0xFF), false ),
+    ColorEntry(QColor(0x54,0xFF,0xFF), false ), ColorEntry( QColor(0xFF,0xFF,0xFF), false )
+};
+
+static const ColorEntry greenonblack_color_table[TABLE_COLORS] = {
+    ColorEntry(QColor(    24, 240,  24),  false), ColorEntry(QColor(     0,   0,   0),  true),
+    ColorEntry(QColor(     0,   0,   0),  false), ColorEntry(QColor(   178,  24,  24),  false),
+    ColorEntry(QColor(    24, 178,  24),  false), ColorEntry(QColor(   178, 104,  24),  false),
+    ColorEntry(QColor(    24,  24, 178),  false), ColorEntry(QColor(   178,  24, 178),  false),
+    ColorEntry(QColor(    24, 178, 178),  false), ColorEntry(QColor(   178, 178, 178),  false),
+    // intensive colors
+    ColorEntry(QColor(   24, 240,  24),  false ), ColorEntry(QColor(    0,   0,   0),  true ),
+    ColorEntry(QColor(  104, 104, 104),  false ), ColorEntry(QColor(  255,  84,  84),  false ),
+    ColorEntry(QColor(   84, 255,  84),  false ), ColorEntry(QColor(  255, 255,  84),  false ),
+    ColorEntry(QColor(   84,  84, 255),  false ), ColorEntry(QColor(  255,  84, 255),  false ),
+    ColorEntry(QColor(   84, 255, 255),  false ), ColorEntry(QColor(  255, 255, 255),  false )
+};
+
+static const ColorEntry blackonlightyellow_color_table[TABLE_COLORS] = {
+    ColorEntry(QColor(  0,   0,   0),  false),  ColorEntry(QColor( 255, 255, 221),  true),
+    ColorEntry(QColor(  0,   0,   0),  false),  ColorEntry(QColor( 178,  24,  24),  false),
+    ColorEntry(QColor( 24, 178,  24),  false),  ColorEntry(QColor( 178, 104,  24),  false),
+    ColorEntry(QColor( 24,  24, 178),  false),  ColorEntry(QColor( 178,  24, 178),  false),
+    ColorEntry(QColor( 24, 178, 178),  false),  ColorEntry(QColor( 178, 178, 178),  false),
+    ColorEntry(QColor(  0,   0,   0),  false),  ColorEntry(QColor( 255, 255, 221),  true),
+    ColorEntry(QColor(104, 104, 104),  false),  ColorEntry(QColor( 255,  84,  84),  false),
+    ColorEntry(QColor( 84, 255,  84),  false),  ColorEntry(QColor( 255, 255,  84),  false),
+    ColorEntry(QColor( 84,  84, 255),  false),  ColorEntry(QColor( 255,  84, 255),  false),
+    ColorEntry(QColor( 84, 255, 255),  false),  ColorEntry(QColor( 255, 255, 255),  false)
+};
+
+
+#endif
+
+
+#endif
+

=== added file 'src/DefaultTranslatorText.h'
--- src/DefaultTranslatorText.h	1970-01-01 00:00:00 +0000
+++ src/DefaultTranslatorText.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,2 @@
+"keyboard \"Fallback Key Translator\"\n"
+"key Tab : \"\\t\" \0"

=== added file 'src/Emulation.cpp'
--- src/Emulation.cpp	1970-01-01 00:00:00 +0000
+++ src/Emulation.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,458 @@
+/*
+    Copyright 2007-2008 Robert Knight <robertknight@xxxxxxxxx> 
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+    Copyright 1996 by Matthias Ettrich <ettrich@xxxxxxx>
+
+    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.
+*/
+
+// Own
+#include "Emulation.h"
+
+// System
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// Qt
+#include <QGuiApplication>
+#include <QtGui/QClipboard>
+#include <QtCore/QHash>
+#include <QtGui/QKeyEvent>
+#include <QtCore/QRegExp>
+#include <QtCore/QTextStream>
+#include <QtCore/QThread>
+
+#include <QtCore/QTime>
+
+// KDE
+//#include <kdebug.h>
+
+// Konsole
+#include "KeyboardTranslator.h"
+#include "Screen.h"
+#include "TerminalCharacterDecoder.h"
+#include "ScreenWindow.h"
+
+Emulation::Emulation() :
+  _currentScreen(0),
+  _codec(0),
+  _decoder(0),
+  _keyTranslator(0),
+  _usesMouse(false)
+{
+  // create screens with a default size
+  _screen[0] = new Screen(40,80);
+  _screen[1] = new Screen(40,80);
+  _currentScreen = _screen[0];
+
+  QObject::connect(&_bulkTimer1, SIGNAL(timeout()), this, SLOT(showBulk()) );
+  QObject::connect(&_bulkTimer2, SIGNAL(timeout()), this, SLOT(showBulk()) );
+   
+  // listen for mouse status changes
+  connect( this , SIGNAL(programUsesMouseChanged(bool)) , 
+           SLOT(usesMouseChanged(bool)) );
+}
+
+bool Emulation::programUsesMouse() const
+{
+    return _usesMouse;
+}
+
+void Emulation::usesMouseChanged(bool usesMouse)
+{
+    _usesMouse = usesMouse;
+}
+
+ScreenWindow* Emulation::createWindow()
+{
+    ScreenWindow* window = new ScreenWindow();
+    window->setScreen(_currentScreen);
+    _windows << window;
+
+    connect(window , SIGNAL(selectionChanged()),
+            this , SLOT(bufferedUpdate()));
+
+    connect(this , SIGNAL(outputChanged()),
+            window , SLOT(notifyOutputChanged()) );
+    return window;
+}
+
+Emulation::~Emulation()
+{
+  QListIterator<ScreenWindow*> windowIter(_windows);
+
+  while (windowIter.hasNext())
+  {
+    delete windowIter.next();
+  }
+
+  delete _screen[0];
+  delete _screen[1];
+  delete _decoder;
+}
+
+void Emulation::setScreen(int n)
+{
+  Screen *old = _currentScreen;
+  _currentScreen = _screen[n & 1];
+  if (_currentScreen != old) 
+  {
+     // tell all windows onto this emulation to switch to the newly active screen
+     foreach(ScreenWindow* window,_windows)
+         window->setScreen(_currentScreen);
+  }
+}
+
+void Emulation::clearHistory()
+{
+    _screen[0]->setScroll( _screen[0]->getScroll() , false );
+}
+void Emulation::setHistory(const HistoryType& t)
+{
+  _screen[0]->setScroll(t);
+
+  showBulk();
+}
+
+const HistoryType& Emulation::history() const
+{
+  return _screen[0]->getScroll();
+}
+
+void Emulation::setCodec(const QTextCodec * qtc)
+{
+  if (qtc)
+      _codec = qtc;
+  else
+     setCodec(LocaleCodec);
+
+  delete _decoder;
+  _decoder = _codec->makeDecoder();
+
+  emit useUtf8Request(utf8());
+}
+
+void Emulation::setCodec(EmulationCodec codec)
+{
+    if ( codec == Utf8Codec )
+        setCodec( QTextCodec::codecForName("utf8") );
+    else if ( codec == LocaleCodec )
+        setCodec( QTextCodec::codecForLocale() );
+}
+
+void Emulation::setKeyBindings(const QString& name)
+{
+  _keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name);
+  if (!_keyTranslator)
+  {
+      _keyTranslator = KeyboardTranslatorManager::instance()->defaultTranslator();
+  }
+}
+
+QString Emulation::keyBindings() const
+{
+  return _keyTranslator->name();
+}
+
+void Emulation::receiveChar(int c)
+// process application unicode input to terminal
+// this is a trivial scanner
+{
+  c &= 0xff;
+  switch (c)
+  {
+    case '\b'      : _currentScreen->backspace();                 break;
+    case '\t'      : _currentScreen->tab();                       break;
+    case '\n'      : _currentScreen->newLine();                   break;
+    case '\r'      : _currentScreen->toStartOfLine();             break;
+    case 0x07      : emit stateSet(NOTIFYBELL);
+                     break;
+    default        : _currentScreen->displayCharacter(c);         break;
+  };
+}
+
+void Emulation::sendKeyEvent( QKeyEvent* ev )
+{
+  emit stateSet(NOTIFYNORMAL);
+  
+  if (!ev->text().isEmpty())
+  { // A block of text
+    // Note that the text is proper unicode.
+    // We should do a conversion here
+    emit sendData(ev->text().toUtf8(),ev->text().length());
+  }
+}
+
+void Emulation::sendString(const char*,int)
+{
+    // default implementation does nothing
+}
+
+void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int /*eventType*/)
+{
+    // default implementation does nothing
+}
+
+/*
+   We are doing code conversion from locale to unicode first.
+TODO: Character composition from the old code.  See #96536
+*/
+
+void Emulation::receiveData(const char* text, int length)
+{
+    emit stateSet(NOTIFYACTIVITY);
+
+    bufferedUpdate();
+        
+    QString unicodeText = _decoder->toUnicode(text,length);
+
+    //send characters to terminal emulator
+    for (int i=0;i<unicodeText.length();i++)
+        receiveChar(unicodeText[i].unicode());
+
+    //look for z-modem indicator
+    //-- someone who understands more about z-modems that I do may be able to move
+    //this check into the above for loop?
+    for (int i=0;i<length;i++)
+    {
+        if (text[i] == '\030')
+        {
+            if ((length-i-1 > 3) && (strncmp(text+i+1, "B00", 3) == 0))
+                emit zmodemDetected();
+        }
+    }
+}
+
+//OLDER VERSION
+//This version of onRcvBlock was commented out because
+//    a)  It decoded incoming characters one-by-one, which is slow in the current version of Qt (4.2 tech preview)
+//    b)  It messed up decoding of non-ASCII characters, with the result that (for example) chinese characters
+//        were not printed properly.
+//
+//There is something about stopping the _decoder if "we get a control code halfway a multi-byte sequence" (see below)
+//which hasn't been ported into the newer function (above).  Hopefully someone who understands this better
+//can find an alternative way of handling the check.  
+
+
+/*void Emulation::onRcvBlock(const char *s, int len)
+{
+  emit notifySessionState(NOTIFYACTIVITY);
+  
+  bufferedUpdate();
+  for (int i = 0; i < len; i++)
+  {
+
+    QString result = _decoder->toUnicode(&s[i],1);
+    int reslen = result.length();
+
+    // If we get a control code halfway a multi-byte sequence
+    // we flush the _decoder and continue with the control code.
+    if ((s[i] < 32) && (s[i] > 0))
+    {
+       // Flush _decoder
+       while(!result.length())
+          result = _decoder->toUnicode(&s[i],1);
+       reslen = 1;
+       result.resize(reslen);
+       result[0] = QChar(s[i]);
+    }
+
+    for (int j = 0; j < reslen; j++)
+    {
+      if (result[j].characterategory() == QChar::Mark_NonSpacing)
+         _currentScreen->compose(result.mid(j,1));
+      else
+         onRcvChar(result[j].unicode());
+    }
+    if (s[i] == '\030')
+    {
+      if ((len-i-1 > 3) && (strncmp(s+i+1, "B00", 3) == 0))
+          emit zmodemDetected();
+    }
+  }
+}*/
+
+void Emulation::writeToStream( TerminalCharacterDecoder* _decoder , 
+                               int startLine ,
+                               int endLine) 
+{
+  _currentScreen->writeLinesToStream(_decoder,startLine,endLine);
+}
+
+int Emulation::lineCount() const
+{
+    // sum number of lines currently on _screen plus number of lines in history
+    return _currentScreen->getLines() + _currentScreen->getHistLines();
+}
+
+#define BULK_TIMEOUT1 10
+#define BULK_TIMEOUT2 40
+
+void Emulation::showBulk()
+{
+    _bulkTimer1.stop();
+    _bulkTimer2.stop();
+
+    emit outputChanged();
+
+    _currentScreen->resetScrolledLines();
+    _currentScreen->resetDroppedLines();
+}
+
+void Emulation::bufferedUpdate()
+{
+   _bulkTimer1.setSingleShot(true);
+   _bulkTimer1.start(BULK_TIMEOUT1);
+   if (!_bulkTimer2.isActive())
+   {
+      _bulkTimer2.setSingleShot(true);
+      _bulkTimer2.start(BULK_TIMEOUT2);
+   }
+}
+
+char Emulation::eraseChar() const
+{
+  return '\b';
+}
+
+void Emulation::setImageSize(int lines, int columns)
+{
+  if ((lines < 1) || (columns < 1)) 
+    return;
+
+  QSize screenSize[2] = { QSize(_screen[0]->getColumns(),
+                                _screen[0]->getLines()),
+                          QSize(_screen[1]->getColumns(),
+                                _screen[1]->getLines()) };
+  QSize newSize(columns,lines);
+
+  if (newSize == screenSize[0] && newSize == screenSize[1])
+    return;    
+
+  _screen[0]->resizeImage(lines,columns);
+  _screen[1]->resizeImage(lines,columns);
+
+  emit imageSizeChanged(lines,columns);
+
+  bufferedUpdate();
+}
+
+QSize Emulation::imageSize() const
+{
+  return QSize(_currentScreen->getColumns(), _currentScreen->getLines());
+}
+
+ushort ExtendedCharTable::extendedCharHash(ushort* unicodePoints , ushort length) const
+{
+    ushort hash = 0;
+    for ( ushort i = 0 ; i < length ; i++ )
+    {
+        hash = 31*hash + unicodePoints[i];
+    }
+    return hash;
+}
+bool ExtendedCharTable::extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const
+{
+    ushort* entry = extendedCharTable[hash];
+
+    // compare given length with stored sequence length ( given as the first ushort in the 
+    // stored buffer ) 
+    if ( entry == 0 || entry[0] != length ) 
+       return false;
+    // if the lengths match, each character must be checked.  the stored buffer starts at
+    // entry[1]
+    for ( int i = 0 ; i < length ; i++ )
+    {
+        if ( entry[i+1] != unicodePoints[i] )
+           return false; 
+    } 
+    return true;
+}
+ushort ExtendedCharTable::createExtendedChar(ushort* unicodePoints , ushort length)
+{
+    // look for this sequence of points in the table
+    ushort hash = extendedCharHash(unicodePoints,length);
+
+    // check existing entry for match
+    while ( extendedCharTable.contains(hash) )
+    {
+        if ( extendedCharMatch(hash,unicodePoints,length) )
+        {
+            // this sequence already has an entry in the table, 
+            // return its hash
+            return hash;
+        }
+        else
+        {
+            // if hash is already used by another, different sequence of unicode character
+            // points then try next hash
+            hash++;
+        }
+    }    
+
+    
+     // add the new sequence to the table and
+     // return that index
+    ushort* buffer = new ushort[length+1];
+    buffer[0] = length;
+    for ( int i = 0 ; i < length ; i++ )
+       buffer[i+1] = unicodePoints[i]; 
+    
+    extendedCharTable.insert(hash,buffer);
+
+    return hash;
+}
+
+ushort* ExtendedCharTable::lookupExtendedChar(ushort hash , ushort& length) const
+{
+    // lookup index in table and if found, set the length
+    // argument and return a pointer to the character sequence
+
+    ushort* buffer = extendedCharTable[hash];
+    if ( buffer )
+    {
+        length = buffer[0];
+        return buffer+1;
+    }
+    else
+    {
+        length = 0;
+        return 0;
+    }
+}
+
+ExtendedCharTable::ExtendedCharTable()
+{
+}
+ExtendedCharTable::~ExtendedCharTable()
+{
+    // free all allocated character buffers
+    QHashIterator<ushort,ushort*> iter(extendedCharTable);
+    while ( iter.hasNext() )
+    {
+        iter.next();
+        delete[] iter.value();
+    }
+}
+
+// global instance
+ExtendedCharTable ExtendedCharTable::instance;
+
+
+//#include "Emulation.moc"
+

=== added file 'src/Emulation.h'
--- src/Emulation.h	1970-01-01 00:00:00 +0000
+++ src/Emulation.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,467 @@
+/*
+    This file is part of Konsole, an X terminal.
+    
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+#ifndef EMULATION_H
+#define EMULATION_H
+
+// System
+#include <stdio.h>
+
+// Qt 
+#include <QtGui/QKeyEvent>
+//#include <QPointer>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+#include <QtCore/QTimer>
+
+// Konsole
+//#include "konsole_export.h"
+#define KONSOLEPRIVATE_EXPORT
+
+class KeyboardTranslator;
+class HistoryType;
+class Screen;
+class ScreenWindow;
+class TerminalCharacterDecoder;
+
+/** 
+ * This enum describes the available states which 
+ * the terminal emulation may be set to.
+ *
+ * These are the values used by Emulation::stateChanged() 
+ */
+enum 
+{ 
+    /** The emulation is currently receiving user input. */
+    NOTIFYNORMAL=0, 
+    /** 
+     * The terminal program has triggered a bell event
+     * to get the user's attention.
+     */
+    NOTIFYBELL=1, 
+    /** 
+     * The emulation is currently receiving data from its 
+     * terminal input.
+     */
+    NOTIFYACTIVITY=2,
+
+    // unused here? 
+    NOTIFYSILENCE=3 
+};
+
+/**
+ * Base class for terminal emulation back-ends.
+ *
+ * The back-end is responsible for decoding an incoming character stream and 
+ * producing an output image of characters.
+ *
+ * When input from the terminal is received, the receiveData() slot should be called with
+ * the data which has arrived.  The emulation will process the data and update the 
+ * screen image accordingly.  The codec used to decode the incoming character stream
+ * into the unicode characters used internally can be specified using setCodec() 
+ *
+ * The size of the screen image can be specified by calling setImageSize() with the 
+ * desired number of lines and columns.  When new lines are added, old content
+ * is moved into a history store, which can be set by calling setHistory(). 
+ *
+ * The screen image can be accessed by creating a ScreenWindow onto this emulation 
+ * by calling createWindow().  Screen windows provide access to a section of the 
+ * output.  Each screen window covers the same number of lines and columns as the 
+ * image size returned by imageSize().  The screen window can be moved up and down
+ * and provides transparent access to both the current on-screen image and the 
+ * previous output.  The screen windows emit an outputChanged signal
+ * when the section of the image they are looking at changes.
+ * Graphical views can then render the contents of a screen window, listening for notifications
+ * of output changes from the screen window which they are associated with and updating 
+ * accordingly. 
+ *
+ * The emulation also is also responsible for converting input from the connected views such
+ * as keypresses and mouse activity into a character string which can be sent
+ * to the terminal program.  Key presses can be processed by calling the sendKeyEvent() slot,
+ * while mouse events can be processed using the sendMouseEvent() slot.  When the character
+ * stream has been produced, the emulation will emit a sendData() signal with a pointer
+ * to the character buffer.  This data should be fed to the standard input of the terminal
+ * process.  The translation of key presses into an output character stream is performed
+ * using a lookup in a set of key bindings which map key sequences to output
+ * character sequences.  The name of the key bindings set used can be specified using
+ * setKeyBindings()
+ *
+ * The emulation maintains certain state information which changes depending on the 
+ * input received.  The emulation can be reset back to its starting state by calling 
+ * reset().  
+ *
+ * The emulation also maintains an activity state, which specifies whether
+ * terminal is currently active ( when data is received ), normal
+ * ( when the terminal is idle or receiving user input ) or trying
+ * to alert the user ( also known as a "Bell" event ).  The stateSet() signal
+ * is emitted whenever the activity state is set.  This can be used to determine
+ * how long the emulation has been active/idle for and also respond to
+ * a 'bell' event in different ways.
+ */
+class KONSOLEPRIVATE_EXPORT Emulation : public QObject
+{ 
+Q_OBJECT
+
+public:
+ 
+   /** Constructs a new terminal emulation */ 
+   Emulation();
+  ~Emulation();
+
+  /**
+   * Creates a new window onto the output from this emulation.  The contents
+   * of the window are then rendered by views which are set to use this window using the
+   * TerminalDisplay::setScreenWindow() method.
+   */
+  ScreenWindow* createWindow();
+
+  /** Returns the size of the screen image which the emulation produces */
+  QSize imageSize() const;
+
+  /**
+   * Returns the total number of lines, including those stored in the history.
+   */ 
+  int lineCount() const;
+
+  /** 
+   * Sets the history store used by this emulation.  When new lines
+   * are added to the output, older lines at the top of the screen are transferred to a history
+   * store.   
+   *
+   * The number of lines which are kept and the storage location depend on the 
+   * type of store.
+   */
+  void setHistory(const HistoryType&);
+  /** Returns the history store used by this emulation.  See setHistory() */
+  const HistoryType& history() const;
+  /** Clears the history scroll. */
+  void clearHistory();
+
+  /** 
+   * Copies the output history from @p startLine to @p endLine 
+   * into @p stream, using @p decoder to convert the terminal
+   * characters into text. 
+   *
+   * @param decoder A decoder which converts lines of terminal characters with 
+   * appearance attributes into output text.  PlainTextDecoder is the most commonly
+   * used decoder.
+   * @param startLine Index of first line to copy
+   * @param endLine Index of last line to copy
+   */
+  virtual void writeToStream(TerminalCharacterDecoder* decoder,int startLine,int endLine);
+  
+  /** Returns the codec used to decode incoming characters.  See setCodec() */
+  const QTextCodec* codec() const { return _codec; }
+  /** Sets the codec used to decode incoming characters.  */
+  void setCodec(const QTextCodec*);
+
+  /** 
+   * Convenience method.  
+   * Returns true if the current codec used to decode incoming
+   * characters is UTF-8
+   */
+  bool utf8() const
+  { Q_ASSERT(_codec); return _codec->mibEnum() == 106; }
+  
+
+  /** TODO Document me */
+  virtual char eraseChar() const;
+
+  /** 
+   * Sets the key bindings used to key events
+   * ( received through sendKeyEvent() ) into character
+   * streams to send to the terminal.
+   */
+  void setKeyBindings(const QString& name);
+  /** 
+   * Returns the name of the emulation's current key bindings.
+   * See setKeyBindings()
+   */
+  QString keyBindings() const;
+
+  /** 
+   * Copies the current image into the history and clears the screen.
+   */
+  virtual void clearEntireScreen() =0;
+
+  /** Resets the state of the terminal. */
+  virtual void reset() =0;
+
+  /** 
+   * Returns true if the active terminal program wants
+   * mouse input events.
+   *
+   * The programUsesMouseChanged() signal is emitted when this
+   * changes.
+   */
+  bool programUsesMouse() const;
+
+public slots: 
+
+  /** Change the size of the emulation's image */
+  virtual void setImageSize(int lines, int columns);
+  
+  /** 
+   * Interprets a sequence of characters and sends the result to the terminal.
+   * This is equivalent to calling sendKeyEvent() for each character in @p text in succession.
+   */
+  virtual void sendText(const QString& text) = 0;
+
+  /** 
+   * Interprets a key press event and emits the sendData() signal with
+   * the resulting character stream. 
+   */
+  virtual void sendKeyEvent(QKeyEvent*);
+ 
+  /** 
+   * Converts information about a mouse event into an xterm-compatible escape
+   * sequence and emits the character sequence via sendData()
+   */
+  virtual void sendMouseEvent(int buttons, int column, int line, int eventType);
+  
+  /**
+   * Sends a string of characters to the foreground terminal process. 
+   *
+   * @param string The characters to send.  
+   * @param length Length of @p string or if set to a negative value, @p string will
+   * be treated as a null-terminated string and its length will be determined automatically.
+   */
+  virtual void sendString(const char* string, int length = -1) = 0;
+
+  /** 
+   * Processes an incoming stream of characters.  receiveData() decodes the incoming
+   * character buffer using the current codec(), and then calls receiveChar() for
+   * each unicode character in the resulting buffer.  
+   *
+   * receiveData() also starts a timer which causes the outputChanged() signal
+   * to be emitted when it expires.  The timer allows multiple updates in quick
+   * succession to be buffered into a single outputChanged() signal emission.
+   *
+   * @param buffer A string of characters received from the terminal program.
+   * @param len The length of @p buffer
+   */
+  void receiveData(const char* buffer,int len);
+
+signals:
+
+  /** 
+   * Emitted when a buffer of data is ready to send to the 
+   * standard input of the terminal.
+   *
+   * @param data The buffer of data ready to be sent
+   * @param len The length of @p data in bytes
+   */
+  void sendData(const char* data,int len);
+
+  /** 
+   * Requests that sending of input to the emulation
+   * from the terminal process be suspended or resumed.
+   *
+   * @param suspend If true, requests that sending of 
+   * input from the terminal process' stdout be 
+   * suspended.  Otherwise requests that sending of
+   * input be resumed. 
+   */
+  void lockPtyRequest(bool suspend);
+
+  /**
+   * Requests that the pty used by the terminal process
+   * be set to UTF 8 mode.  
+   *
+   * TODO: More documentation
+   */
+  void useUtf8Request(bool);
+
+  /**
+   * Emitted when the activity state of the emulation is set.
+   *
+   * @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY
+   * or NOTIFYBELL
+   */
+  void stateSet(int state);
+
+  /** TODO Document me */
+  void zmodemDetected();
+
+
+  /**
+   * Requests that the color of the text used
+   * to represent the tabs associated with this
+   * emulation be changed.  This is a Konsole-specific
+   * extension from pre-KDE 4 times.
+   *
+   * TODO: Document how the parameter works.
+   */
+  void changeTabTextColorRequest(int color);
+
+  /** 
+   * This is emitted when the program running in the shell indicates whether or
+   * not it is interested in mouse events.
+   *
+   * @param usesMouse This will be true if the program wants to be informed about
+   * mouse events or false otherwise.
+   */
+  void programUsesMouseChanged(bool usesMouse);
+
+  /** 
+   * Emitted when the contents of the screen image change.
+   * The emulation buffers the updates from successive image changes,
+   * and only emits outputChanged() at sensible intervals when
+   * there is a lot of terminal activity.
+   *
+   * Normally there is no need for objects other than the screen windows
+   * created with createWindow() to listen for this signal.
+   *
+   * ScreenWindow objects created using createWindow() will emit their
+   * own outputChanged() signal in response to this signal. 
+   */
+  void outputChanged();
+
+  /**
+   * Emitted when the program running in the terminal wishes to update the 
+   * session's title.  This also allows terminal programs to customize other
+   * aspects of the terminal emulation display. 
+   *
+   * This signal is emitted when the escape sequence "\033]ARG;VALUE\007"
+   * is received in the input string, where ARG is a number specifying what
+   * should change and VALUE is a string specifying the new value.
+   *
+   * TODO:  The name of this method is not very accurate since this method
+   * is used to perform a whole range of tasks besides just setting
+   * the user-title of the session.    
+   *
+   * @param title Specifies what to change.
+   * <ul>
+   * <li>0 - Set window icon text and session title to @p newTitle</li>
+   * <li>1 - Set window icon text to @p newTitle</li>
+   * <li>2 - Set session title to @p newTitle</li>
+   * <li>11 - Set the session's default background color to @p newTitle,
+   *         where @p newTitle can be an HTML-style string ("#RRGGBB") or a named
+   *         color (eg 'red', 'blue').  
+   *         See http://doc.trolltech.com/4.2/qcolor.html#setNamedColor for more
+   *         details.
+   * </li>
+   * <li>31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)</li>
+   * <li>32 - Sets the icon associated with the session.  @p newTitle is the name 
+   *    of the icon to use, which can be the name of any icon in the current KDE icon
+   *    theme (eg: 'konsole', 'kate', 'folder_home')</li>
+   * </ul>
+   * @param newTitle Specifies the new title 
+   */
+
+  void titleChanged(int title,const QString& newTitle);
+
+  /**
+   * Emitted when the program running in the terminal changes the
+   * screen size.
+   */
+  void imageSizeChanged(int lineCount , int columnCount);
+
+  /** 
+   * Emitted when the terminal program requests to change various properties
+   * of the terminal display.  
+   *
+   * A profile change command occurs when a special escape sequence, followed
+   * by a string containing a series of name and value pairs is received.
+   * This string can be parsed using a ProfileCommandParser instance.
+   *
+   * @param text A string expected to contain a series of key and value pairs in
+   * the form:  name=value;name2=value2 ...
+   */
+  void profileChangeCommandReceived(const QString& text);
+
+  /** 
+   * Emitted when a flow control key combination ( Ctrl+S or Ctrl+Q ) is pressed.
+   * @param suspendKeyPressed True if Ctrl+S was pressed to suspend output or Ctrl+Q to
+   * resume output.
+   */
+  void flowControlKeyPressed(bool suspendKeyPressed);
+
+protected:
+  virtual void setMode(int mode) = 0;
+  virtual void resetMode(int mode) = 0;
+   
+  /** 
+   * Processes an incoming character.  See receiveData()
+   * @p ch A unicode character code. 
+   */
+  virtual void receiveChar(int ch);
+
+  /** 
+   * Sets the active screen.  The terminal has two screens, primary and alternate.
+   * The primary screen is used by default.  When certain interactive programs such
+   * as Vim are run, they trigger a switch to the alternate screen.
+   *
+   * @param index 0 to switch to the primary screen, or 1 to switch to the alternate screen
+   */
+  void setScreen(int index); 
+
+  enum EmulationCodec
+  {
+      LocaleCodec = 0,
+      Utf8Codec   = 1
+  };
+  void setCodec(EmulationCodec codec); // codec number, 0 = locale, 1=utf8
+
+
+  QList<ScreenWindow*> _windows;
+  
+  Screen* _currentScreen;  // pointer to the screen which is currently active, 
+                            // this is one of the elements in the screen[] array
+
+  Screen* _screen[2];      // 0 = primary screen ( used by most programs, including the shell
+                            //                      scrollbars are enabled in this mode )
+                            // 1 = alternate      ( used by vi , emacs etc.
+                            //                      scrollbars are not enabled in this mode )
+                            
+  
+  //decodes an incoming C-style character stream into a unicode QString using 
+  //the current text codec.  (this allows for rendering of non-ASCII characters in text files etc.)
+  const QTextCodec* _codec;
+  QTextDecoder* _decoder;
+  const KeyboardTranslator* _keyTranslator; // the keyboard layout
+
+protected slots:
+  /** 
+   * Schedules an update of attached views.
+   * Repeated calls to bufferedUpdate() in close succession will result in only a single update,
+   * much like the Qt buffered update of widgets. 
+   */
+  void bufferedUpdate();
+
+private slots: 
+
+  // triggered by timer, causes the emulation to send an updated screen image to each
+  // view
+  void showBulk(); 
+
+  void usesMouseChanged(bool usesMouse);
+
+private:
+  bool _usesMouse;
+  QTimer _bulkTimer1;
+  QTimer _bulkTimer2;
+  
+};
+
+
+#endif // ifndef EMULATION_H

=== added file 'src/ExtendedDefaultTranslator.h'
--- src/ExtendedDefaultTranslator.h	1970-01-01 00:00:00 +0000
+++ src/ExtendedDefaultTranslator.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,74 @@
+"keyboard \"Default (XFree 4)\""
+"key Escape             : \"\\E\""
+"key Tab   -Shift       : \"\\t\"\n"
+"key Tab   +Shift+Ansi  : \"\\E[Z\"\n"
+"key Tab   +Shift-Ansi  : \"\\t\"\n"
+"key Backtab     +Ansi  : \"\\E[Z\"\n"
+"key Backtab     -Ansi  : \"\\t\"\n"
+"key Return-Shift-NewLine : \"\\r\"\n"
+"key Return-Shift+NewLine : \"\\r\\n\"\n"
+"key Return+Shift         : \"\\EOM\"\n"
+"key Backspace      : \"\\x7f\"\n"
+"key Up   -Shift-Ansi : \"\\EA\"\n"
+"key Down -Shift-Ansi : \"\\EB\"\n"
+"key Right-Shift-Ansi : \"\\EC\"\n"
+"key Left -Shift-Ansi : \"\\ED\"\n"
+"key Up    -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOA\"\n"
+"key Down  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOB\"\n"
+"key Right -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOC\"\n"
+"key Left  -Shift-AnyMod+Ansi+AppCuKeys           : \"\\EOD\"\n"
+"key Up    -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[A\"\n"
+"key Down  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[B\"\n"
+"key Right -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[C\"\n"
+"key Left  -Shift-AnyMod+Ansi-AppCuKeys           : \"\\E[D\"\n"
+"key Up    -Shift+AnyMod+Ansi                     : \"\\E[1;*A\"\n"
+"key Down  -Shift+AnyMod+Ansi                     : \"\\E[1;*B\"\n"
+"key Right -Shift+AnyMod+Ansi                     : \"\\E[1;*C\"\n"
+"key Left  -Shift+AnyMod+Ansi                     : \"\\E[1;*D\"\n"
+"key Enter+NewLine : \"\\r\\n\"\n"
+"key Enter-NewLine : \"\\r\"\n"
+"key Home        -AnyMod     -AppCuKeys           : \"\\E[H\"  \n"
+"key End         -AnyMod     -AppCuKeys           : \"\\E[F\"  \n"
+"key Home        -AnyMod     +AppCuKeys           : \"\\EOH\"  \n"
+"key End         -AnyMod     +AppCuKeys           : \"\\EOF\"  \n"
+"key Home        +AnyMod                          : \"\\E[1;*H\"\n"
+"key End         +AnyMod                          : \"\\E[1;*F\"\n"
+"key Insert      -AnyMod                          : \"\\E[2~\"\n"
+"key Delete      -AnyMod                          : \"\\E[3~\"\n"
+"key Insert      +AnyMod                          : \"\\E[2;*~\"\n"
+"key Delete      +AnyMod                          : \"\\E[3;*~\"\n"
+"key Prior -Shift-AnyMod                          : \"\\E[5~\"\n"
+"key Next  -Shift-AnyMod                          : \"\\E[6~\"\n"
+"key Prior -Shift+AnyMod                          : \"\\E[5;*~\"\n"
+"key Next  -Shift+AnyMod                          : \"\\E[6;*~\"\n"
+"key F1          -AnyMod                          : \"\\EOP\"\n"
+"key F2          -AnyMod                          : \"\\EOQ\"\n"
+"key F3          -AnyMod                          : \"\\EOR\"\n"
+"key F4          -AnyMod                          : \"\\EOS\"\n"
+"key F5          -AnyMod                          : \"\\E[15~\"\n"
+"key F6          -AnyMod                          : \"\\E[17~\"\n"
+"key F7          -AnyMod                          : \"\\E[18~\"\n"
+"key F8          -AnyMod                          : \"\\E[19~\"\n"
+"key F9          -AnyMod                          : \"\\E[20~\"\n"
+"key F10         -AnyMod                          : \"\\E[21~\"\n"
+"key F11         -AnyMod                          : \"\\E[23~\"\n"
+"key F12         -AnyMod                          : \"\\E[24~\"\n"
+"key F1          +AnyMod                          : \"\\EO*P\"\n"
+"key F2          +AnyMod                          : \"\\EO*Q\"\n"
+"key F3          +AnyMod                          : \"\\EO*R\"\n"
+"key F4          +AnyMod                          : \"\\EO*S\"\n"
+"key F5          +AnyMod                          : \"\\E[15;*~\"\n"
+"key F6          +AnyMod                          : \"\\E[17;*~\"\n"
+"key F7          +AnyMod                          : \"\\E[18;*~\"\n"
+"key F8          +AnyMod                          : \"\\E[19;*~\"\n"
+"key F9          +AnyMod                          : \"\\E[20;*~\"\n"
+"key F10         +AnyMod                          : \"\\E[21;*~\"\n"
+"key F11         +AnyMod                          : \"\\E[23;*~\"\n"
+"key F12         +AnyMod                          : \"\\E[24;*~\"\n"
+"key Space +Control : \"\\x00\"\n"
+"key Up    +Shift-AppScreen  : scrollLineUp\n"
+"key Prior +Shift-AppScreen  : scrollPageUp\n"
+"key Down  +Shift-AppScreen  : scrollLineDown\n"
+"key Next  +Shift-AppScreen  : scrollPageDown\n"
+"key ScrollLock     : scrollLock\n"
+"\0"

=== added file 'src/Filter.cpp'
--- src/Filter.cpp	1970-01-01 00:00:00 +0000
+++ src/Filter.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,542 @@
+/*
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+// Own
+#include "Filter.h"
+
+// System
+#include <iostream>
+
+// Qt
+#include <QtWidgets/QAction>
+#include <QtWidgets/QApplication>
+#include <QtGui/QClipboard>
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+#include <QtCore/QSharedData>
+#include <QtCore/QFile>
+#include <QDesktopServices>
+#include <QUrl>
+
+// KDE
+//#include <KLocale>
+//#include <KRun>
+
+// Konsole
+#include "TerminalCharacterDecoder.h"
+#include "konsole_wcwidth.h"
+
+
+FilterChain::~FilterChain()
+{
+    QMutableListIterator<Filter*> iter(*this);
+    
+    while ( iter.hasNext() )
+    {
+        Filter* filter = iter.next();
+        iter.remove();
+        delete filter;
+    }
+}
+
+void FilterChain::addFilter(Filter* filter)
+{
+    append(filter);
+}
+void FilterChain::removeFilter(Filter* filter)
+{
+    removeAll(filter);
+}
+bool FilterChain::containsFilter(Filter* filter)
+{
+    return contains(filter);
+}
+void FilterChain::reset()
+{
+    QListIterator<Filter*> iter(*this);
+    while (iter.hasNext())
+        iter.next()->reset();
+}
+void FilterChain::setBuffer(const QString* buffer , const QList<int>* linePositions)
+{
+    QListIterator<Filter*> iter(*this);
+    while (iter.hasNext())
+        iter.next()->setBuffer(buffer,linePositions);
+}
+void FilterChain::process()
+{
+    QListIterator<Filter*> iter(*this);
+    while (iter.hasNext())
+        iter.next()->process();
+}
+void FilterChain::clear()
+{
+    QList<Filter*>::clear();
+}
+Filter::HotSpot* FilterChain::hotSpotAt(int line , int column) const
+{
+    QListIterator<Filter*> iter(*this);
+    while (iter.hasNext())
+    {
+        Filter* filter = iter.next();
+        Filter::HotSpot* spot = filter->hotSpotAt(line,column);
+        if ( spot != 0 )
+        {
+            return spot;
+        }
+    }
+
+    return 0;
+}
+
+QList<Filter::HotSpot*> FilterChain::hotSpots() const
+{
+    QList<Filter::HotSpot*> list;
+    QListIterator<Filter*> iter(*this);
+    while (iter.hasNext())
+    {
+        Filter* filter = iter.next();
+        list << filter->hotSpots();
+    }
+    return list;
+}
+//QList<Filter::HotSpot*> FilterChain::hotSpotsAtLine(int line) const;
+
+TerminalImageFilterChain::TerminalImageFilterChain()
+: _buffer(0)
+, _linePositions(0)
+{
+}
+
+TerminalImageFilterChain::~TerminalImageFilterChain()
+{
+    delete _buffer;
+    delete _linePositions;
+}
+
+void TerminalImageFilterChain::setImage(const Character* const image , int lines , int columns, const QVector<LineProperty>& lineProperties)
+{
+    if (empty())
+        return;
+
+    // reset all filters and hotspots
+    reset();
+
+    PlainTextDecoder decoder;
+    decoder.setTrailingWhitespace(false);
+    
+    // setup new shared buffers for the filters to process on
+    QString* newBuffer = new QString();
+    QList<int>* newLinePositions = new QList<int>();
+    setBuffer( newBuffer , newLinePositions );
+
+    // free the old buffers
+    delete _buffer;
+    delete _linePositions;
+
+    _buffer = newBuffer;
+    _linePositions = newLinePositions;
+
+    QTextStream lineStream(_buffer);
+    decoder.begin(&lineStream);
+
+    for (int i=0 ; i < lines ; i++)
+    {
+        _linePositions->append(_buffer->length());
+        decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT);
+
+        // pretend that each line ends with a newline character.
+        // this prevents a link that occurs at the end of one line
+        // being treated as part of a link that occurs at the start of the next line
+        //
+        // the downside is that links which are spread over more than one line are not
+        // highlighted.  
+        //
+        // TODO - Use the "line wrapped" attribute associated with lines in a
+        // terminal image to avoid adding this imaginary character for wrapped
+        // lines
+        if ( !(lineProperties.value(i,LINE_DEFAULT) & LINE_WRAPPED) )
+            lineStream << QChar('\n');
+    }
+    decoder.end();
+}
+
+Filter::Filter() :
+_linePositions(0),
+_buffer(0)
+{
+}
+
+Filter::~Filter()
+{
+    QListIterator<HotSpot*> iter(_hotspotList);
+    while (iter.hasNext())
+    {
+        delete iter.next();
+    }
+}
+void Filter::reset()
+{
+    _hotspots.clear();
+    _hotspotList.clear();
+}
+
+void Filter::setBuffer(const QString* buffer , const QList<int>* linePositions)
+{
+    _buffer = buffer;
+    _linePositions = linePositions;
+}
+
+void Filter::getLineColumn(int position , int& startLine , int& startColumn)
+{
+    Q_ASSERT( _linePositions );
+    Q_ASSERT( _buffer );
+
+
+    for (int i = 0 ; i < _linePositions->count() ; i++)
+    {
+        int nextLine = 0;
+
+        if ( i == _linePositions->count()-1 )
+            nextLine = _buffer->length() + 1;
+        else
+            nextLine = _linePositions->value(i+1);
+
+        if ( _linePositions->value(i) <= position && position < nextLine ) 
+        {
+            startLine = i;
+            startColumn = string_width(buffer()->mid(_linePositions->value(i),position - _linePositions->value(i)));
+            return;
+        }
+    }
+}
+    
+
+/*void Filter::addLine(const QString& text)
+{
+    _linePositions << _buffer.length();
+    _buffer.append(text);
+}*/
+
+const QString* Filter::buffer()
+{
+    return _buffer;
+}
+Filter::HotSpot::~HotSpot()
+{
+}
+void Filter::addHotSpot(HotSpot* spot)
+{
+    _hotspotList << spot;
+
+    for (int line = spot->startLine() ; line <= spot->endLine() ; line++)
+    {
+        _hotspots.insert(line,spot);
+    }    
+}
+QList<Filter::HotSpot*> Filter::hotSpots() const
+{
+    return _hotspotList;
+}
+QList<Filter::HotSpot*> Filter::hotSpotsAtLine(int line) const
+{
+    return _hotspots.values(line);
+}
+
+Filter::HotSpot* Filter::hotSpotAt(int line , int column) const
+{
+    QListIterator<HotSpot*> spotIter(_hotspots.values(line));
+
+    while (spotIter.hasNext())
+    {
+        HotSpot* spot = spotIter.next();
+        
+        if ( spot->startLine() == line && spot->startColumn() > column )
+            continue;
+        if ( spot->endLine() == line && spot->endColumn() < column )
+            continue;
+       
+        return spot;
+    }
+
+    return 0;
+}
+
+Filter::HotSpot::HotSpot(int startLine , int startColumn , int endLine , int endColumn)
+    : _startLine(startLine)
+    , _startColumn(startColumn)
+    , _endLine(endLine)
+    , _endColumn(endColumn)
+    , _type(NotSpecified)
+{
+}
+QString Filter::HotSpot::tooltip() const
+{
+    return QString();
+}
+QList<QAction*> Filter::HotSpot::actions()
+{
+    return QList<QAction*>();
+}
+int Filter::HotSpot::startLine() const
+{
+    return _startLine;
+}
+int Filter::HotSpot::endLine() const
+{
+    return _endLine;
+}
+int Filter::HotSpot::startColumn() const
+{
+    return _startColumn;
+}
+int Filter::HotSpot::endColumn() const
+{
+    return _endColumn;
+}
+Filter::HotSpot::Type Filter::HotSpot::type() const
+{
+    return _type;
+}
+void Filter::HotSpot::setType(Type type)
+{
+    _type = type;
+}
+
+RegExpFilter::RegExpFilter()
+{
+}
+
+RegExpFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
+    : Filter::HotSpot(startLine,startColumn,endLine,endColumn)
+{
+    setType(Marker);
+}
+
+void RegExpFilter::HotSpot::activate(QObject*)
+{
+}
+
+void RegExpFilter::HotSpot::setCapturedTexts(const QStringList& texts)
+{
+    _capturedTexts = texts;
+}
+QStringList RegExpFilter::HotSpot::capturedTexts() const
+{
+    return _capturedTexts;
+}
+
+void RegExpFilter::setRegExp(const QRegExp& regExp) 
+{
+    _searchText = regExp;
+}
+QRegExp RegExpFilter::regExp() const
+{
+    return _searchText;
+}
+/*void RegExpFilter::reset(int)
+{
+    _buffer = QString();
+}*/
+void RegExpFilter::process()
+{
+    int pos = 0;
+    const QString* text = buffer();
+
+    Q_ASSERT( text );
+
+    // ignore any regular expressions which match an empty string.
+    // otherwise the while loop below will run indefinitely
+    static const QString emptyString("");
+    if ( _searchText.exactMatch(emptyString) )
+        return;
+
+    while(pos >= 0)
+    {
+        pos = _searchText.indexIn(*text,pos);
+
+        if ( pos >= 0 )
+        {
+            int startLine = 0;
+            int endLine = 0;
+            int startColumn = 0;
+            int endColumn = 0;
+
+            getLineColumn(pos,startLine,startColumn);
+            getLineColumn(pos + _searchText.matchedLength(),endLine,endColumn);
+
+            RegExpFilter::HotSpot* spot = newHotSpot(startLine,startColumn,
+                                           endLine,endColumn);
+            spot->setCapturedTexts(_searchText.capturedTexts());
+
+            addHotSpot( spot );  
+            pos += _searchText.matchedLength();
+
+            // if matchedLength == 0, the program will get stuck in an infinite loop
+            if ( _searchText.matchedLength() == 0 )
+                pos = -1;
+        }
+    }    
+}
+
+RegExpFilter::HotSpot* RegExpFilter::newHotSpot(int startLine,int startColumn,
+                                                int endLine,int endColumn)
+{
+    return new RegExpFilter::HotSpot(startLine,startColumn,
+                                                  endLine,endColumn);
+}
+RegExpFilter::HotSpot* UrlFilter::newHotSpot(int startLine,int startColumn,int endLine,
+                                                    int endColumn)
+{
+    return new UrlFilter::HotSpot(startLine,startColumn,
+                                               endLine,endColumn);
+}
+UrlFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
+: RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn)
+, _urlObject(new FilterObject(this))
+{
+    setType(Link);
+}
+QString UrlFilter::HotSpot::tooltip() const
+{
+    QString url = capturedTexts().first();
+
+    const UrlType kind = urlType();
+
+    if ( kind == StandardUrl )
+        return QString(); 
+    else if ( kind == Email )
+        return QString(); 
+    else
+        return QString();
+}
+UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const
+{
+    QString url = capturedTexts().first();
+    
+    if ( FullUrlRegExp.exactMatch(url) )
+        return StandardUrl;
+    else if ( EmailAddressRegExp.exactMatch(url) )
+        return Email;
+    else
+        return Unknown;
+}
+
+void UrlFilter::HotSpot::activate(QObject* object)
+{
+    QString url = capturedTexts().first();
+
+    const UrlType kind = urlType();
+
+    const QString& actionName = object ? object->objectName() : QString();
+
+    if ( actionName == "copy-action" )
+    {
+        QApplication::clipboard()->setText(url);
+        return;
+    }
+
+    if ( !object || actionName == "open-action" )
+    {
+        if ( kind == StandardUrl )
+        {
+            // if the URL path does not include the protocol ( eg. "www.kde.org" ) then
+            // prepend http:// ( eg. "www.kde.org" --> "http://www.kde.org"; )
+            if (!url.contains("://"))
+            {
+                url.prepend("http://";);
+            }
+        } 
+        else if ( kind == Email )
+        {
+            url.prepend("mailto:";);
+        }
+    
+        QDesktopServices::openUrl(QUrl(url));
+        //new KRun(url,QApplication::activeWindow());
+    }
+}
+
+// Note:  Altering these regular expressions can have a major effect on the performance of the filters 
+// used for finding URLs in the text, especially if they are very general and could match very long
+// pieces of text.
+// Please be careful when altering them.
+
+//regexp matches:
+// full url:  
+// protocolname:// or www. followed by anything other than whitespaces, <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, comma and dot
+const QRegExp UrlFilter::FullUrlRegExp("(www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]]");
+// email address:
+// [word chars, dots or dashes]@[word chars, dots or dashes].[word chars]
+const QRegExp UrlFilter::EmailAddressRegExp("\\b(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+\\b");
+
+// matches full url or email address
+const QRegExp UrlFilter::CompleteUrlRegExp('('+FullUrlRegExp.pattern()+'|'+
+                                            EmailAddressRegExp.pattern()+')');
+
+UrlFilter::UrlFilter()
+{
+    setRegExp( CompleteUrlRegExp );
+}
+UrlFilter::HotSpot::~HotSpot()
+{
+    delete _urlObject;
+}
+void FilterObject::activated()
+{
+    _filter->activate(sender());
+}
+QList<QAction*> UrlFilter::HotSpot::actions()
+{
+    QList<QAction*> list;
+
+    const UrlType kind = urlType();
+
+    QAction* openAction = new QAction(_urlObject);
+    QAction* copyAction = new QAction(_urlObject);;
+
+    Q_ASSERT( kind == StandardUrl || kind == Email );
+
+    if ( kind == StandardUrl )
+    {
+        openAction->setText(QObject::tr("Open Link"));
+        copyAction->setText(QObject::tr("Copy Link Address"));
+    }
+    else if ( kind == Email )
+    {
+        openAction->setText(QObject::tr("Send Email To..."));
+        copyAction->setText(QObject::tr("Copy Email Address"));
+    }
+
+    // object names are set here so that the hotspot performs the
+    // correct action when activated() is called with the triggered
+    // action passed as a parameter.
+    openAction->setObjectName( QLatin1String("open-action" ));
+    copyAction->setObjectName( QLatin1String("copy-action" ));
+
+    QObject::connect( openAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
+    QObject::connect( copyAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
+
+    list << openAction;
+    list << copyAction;
+
+    return list; 
+}
+
+//#include "Filter.moc"

=== added file 'src/Filter.h'
--- src/Filter.h	1970-01-01 00:00:00 +0000
+++ src/Filter.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,380 @@
+/*
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+#ifndef FILTER_H
+#define FILTER_H
+
+// Qt
+#include <QtWidgets/QAction>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+#include <QtCore/QRegExp>
+
+// Local
+#include "Character.h"
+
+
+/**
+ * A filter processes blocks of text looking for certain patterns (such as URLs or keywords from a list)
+ * and marks the areas which match the filter's patterns as 'hotspots'.
+ *
+ * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
+ * and an action.  When the user performs some activity such as a mouse-click in a hotspot area ( the exact
+ * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
+ * activate() method should be called.  Depending on the type of hotspot this will trigger a suitable response.
+ *
+ * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.
+ * Hotspots may have more than one action, in which case the list of actions can be obtained using the 
+ * actions() method.
+ *
+ * Different subclasses of filter will return different types of hotspot.
+ * Subclasses must reimplement the process() method to examine a block of text and identify sections of interest.
+ * When processing the text they should create instances of Filter::HotSpot subclasses for sections of interest
+ * and add them to the filter's list of hotspots using addHotSpot()
+ */
+class Filter
+{
+public:
+    /**
+    * Represents an area of text which matched the pattern a particular filter has been looking for.
+    *
+    * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
+    * and an action.  When the user performs some activity such as a mouse-click in a hotspot area ( the exact
+    * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
+    * activate() method should be called.  Depending on the type of hotspot this will trigger a suitable response.
+    *
+    * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.
+    * Hotspots may have more than one action, in which case the list of actions can be obtained using the 
+    * actions() method.  These actions may then be displayed in a popup menu or toolbar for example. 
+    */
+    class HotSpot
+    {
+    public:
+       /** 
+        * Constructs a new hotspot which covers the area from (@p startLine,@p startColumn) to (@p endLine,@p endColumn)
+        * in a block of text.
+        */
+       HotSpot(int startLine , int startColumn , int endLine , int endColumn);
+       virtual ~HotSpot();
+
+       enum Type
+       {
+            // the type of the hotspot is not specified
+            NotSpecified,
+            // this hotspot represents a clickable link
+            Link,
+            // this hotspot represents a marker
+            Marker
+       }; 
+
+       /** Returns the line when the hotspot area starts */
+       int startLine() const;
+       /** Returns the line where the hotspot area ends */
+       int endLine() const;
+       /** Returns the column on startLine() where the hotspot area starts */
+       int startColumn() const;
+       /** Returns the column on endLine() where the hotspot area ends */
+       int endColumn() const;
+       /** 
+        * Returns the type of the hotspot.  This is usually used as a hint for views on how to represent
+        * the hotspot graphically.  eg.  Link hotspots are typically underlined when the user mouses over them
+        */
+       Type type() const;
+       /** 
+        * Causes the an action associated with a hotspot to be triggered. 
+        *
+        * @param object The object which caused the hotspot to be triggered.  This is
+        * typically null ( in which case the default action should be performed ) or
+        * one of the objects from the actions() list.  In which case the associated
+        * action should be performed. 
+        */
+       virtual void activate(QObject* object = 0) = 0; 
+       /** 
+        * Returns a list of actions associated with the hotspot which can be used in a 
+        * menu or toolbar 
+        */
+       virtual QList<QAction*> actions();
+
+       /** 
+        * Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or
+        * an empty string if there is no tooltip associated with this hotspot.
+        *
+        * The default implementation returns an empty string. 
+        */
+       virtual QString tooltip() const;
+
+    protected:
+       /** Sets the type of a hotspot.  This should only be set once */
+       void setType(Type type);
+
+    private:
+       int    _startLine;
+       int    _startColumn;
+       int    _endLine;
+       int    _endColumn;
+       Type _type;
+    
+    };
+
+    /** Constructs a new filter. */
+    Filter();
+    virtual ~Filter();
+
+    /** Causes the filter to process the block of text currently in its internal buffer */
+    virtual void process() = 0;
+
+    /** 
+     * Empties the filters internal buffer and resets the line count back to 0.
+     * All hotspots are deleted. 
+     */
+    void reset();
+
+    /** Adds a new line of text to the filter and increments the line count */
+    //void addLine(const QString& string);
+
+    /** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */
+    HotSpot* hotSpotAt(int line , int column) const;
+
+    /** Returns the list of hotspots identified by the filter */
+    QList<HotSpot*> hotSpots() const;
+
+    /** Returns the list of hotspots identified by the filter which occur on a given line */
+    QList<HotSpot*> hotSpotsAtLine(int line) const;
+
+    /** 
+     * TODO: Document me
+     */
+    void setBuffer(const QString* buffer , const QList<int>* linePositions);
+
+protected:
+    /** Adds a new hotspot to the list */
+    void addHotSpot(HotSpot*);
+    /** Returns the internal buffer */
+    const QString* buffer();
+    /** Converts a character position within buffer() to a line and column */
+    void getLineColumn(int position , int& startLine , int& startColumn);
+
+private:
+    QMultiHash<int,HotSpot*> _hotspots;
+    QList<HotSpot*> _hotspotList;
+    
+    const QList<int>* _linePositions;
+    const QString* _buffer;
+};
+
+/** 
+ * A filter which searches for sections of text matching a regular expression and creates a new RegExpFilter::HotSpot 
+ * instance for them.
+ *
+ * Subclasses can reimplement newHotSpot() to return custom hotspot types when matches for the regular expression
+ * are found. 
+ */
+class RegExpFilter : public Filter
+{
+public:
+    /** 
+     * Type of hotspot created by RegExpFilter.  The capturedTexts() method can be used to find the text
+     * matched by the filter's regular expression.
+     */
+    class HotSpot : public Filter::HotSpot
+    {
+    public:
+        HotSpot(int startLine, int startColumn, int endLine , int endColumn);
+        virtual void activate(QObject* object = 0);
+
+        /** Sets the captured texts associated with this hotspot */
+        void setCapturedTexts(const QStringList& texts);
+        /** Returns the texts found by the filter when matching the filter's regular expression */
+        QStringList capturedTexts() const;
+    private:
+        QStringList _capturedTexts;
+    };
+
+    /** Constructs a new regular expression filter */
+    RegExpFilter();
+
+    /** 
+     * Sets the regular expression which the filter searches for in blocks of text. 
+     *
+     * Regular expressions which match the empty string are treated as not matching
+     * anything. 
+     */
+    void setRegExp(const QRegExp& text);
+    /** Returns the regular expression which the filter searches for in blocks of text */
+    QRegExp regExp() const;
+
+    /** 
+     * Reimplemented to search the filter's text buffer for text matching regExp() 
+     *
+     * If regexp matches the empty string, then process() will return immediately
+     * without finding results. 
+     */
+    virtual void process();
+
+protected:
+    /** 
+     * Called when a match for the regular expression is encountered.  Subclasses should reimplement this
+     * to return custom hotspot types
+     */
+    virtual RegExpFilter::HotSpot* newHotSpot(int startLine,int startColumn,
+                                    int endLine,int endColumn);
+
+private:
+    QRegExp _searchText;
+};
+
+class FilterObject;
+
+/** A filter which matches URLs in blocks of text */
+class UrlFilter : public RegExpFilter 
+{
+public:
+    /** 
+     * Hotspot type created by UrlFilter instances.  The activate() method opens a web browser 
+     * at the given URL when called.
+     */
+    class HotSpot : public RegExpFilter::HotSpot 
+    {
+    public:
+        HotSpot(int startLine,int startColumn,int endLine,int endColumn);
+        virtual ~HotSpot();
+
+        virtual QList<QAction*> actions();
+
+        /** 
+         * Open a web browser at the current URL.  The url itself can be determined using
+         * the capturedTexts() method.
+         */
+        virtual void activate(QObject* object = 0);
+
+        virtual QString tooltip() const;
+    private:
+        enum UrlType
+        {
+            StandardUrl,
+            Email,
+            Unknown
+        };
+        UrlType urlType() const;
+
+        FilterObject* _urlObject;
+    };
+
+    UrlFilter();
+
+protected:
+    virtual RegExpFilter::HotSpot* newHotSpot(int,int,int,int);
+
+private:
+    
+    static const QRegExp FullUrlRegExp;
+    static const QRegExp EmailAddressRegExp;
+
+    // combined OR of FullUrlRegExp and EmailAddressRegExp
+    static const QRegExp CompleteUrlRegExp; 
+};
+
+class FilterObject : public QObject
+{
+Q_OBJECT
+public:
+    FilterObject(Filter::HotSpot* filter) : _filter(filter) {}
+private slots:
+    void activated();
+private:
+    Filter::HotSpot* _filter;
+};
+
+/** 
+ * A chain which allows a group of filters to be processed as one. 
+ * The chain owns the filters added to it and deletes them when the chain itself is destroyed.
+ *
+ * Use addFilter() to add a new filter to the chain.  
+ * When new text to be filtered arrives, use addLine() to add each additional
+ * line of text which needs to be processed and then after adding the last line, use
+ * process() to cause each filter in the chain to process the text.
+ *
+ * After processing a block of text, the reset() method can be used to set the filter chain's
+ * internal cursor back to the first line.
+ *
+ * The hotSpotAt() method will return the first hotspot which covers a given position.
+ *
+ * The hotSpots() and hotSpotsAtLine() method return all of the hotspots in the text and on
+ * a given line respectively.
+ */
+class FilterChain : protected QList<Filter*>
+{
+public:
+    virtual ~FilterChain();
+
+    /** Adds a new filter to the chain.  The chain will delete this filter when it is destroyed */
+    void addFilter(Filter* filter);
+    /** Removes a filter from the chain.  The chain will no longer delete the filter when destroyed */
+    void removeFilter(Filter* filter);
+    /** Returns true if the chain contains @p filter */
+    bool containsFilter(Filter* filter);
+    /** Removes all filters from the chain */
+    void clear();
+
+    /** Resets each filter in the chain */
+    void reset();
+    /**
+     * Processes each filter in the chain 
+     */
+    void process();
+
+    /** Sets the buffer for each filter in the chain to process. */
+    void setBuffer(const QString* buffer , const QList<int>* linePositions); 
+
+    /** Returns the first hotspot which occurs at @p line, @p column or 0 if no hotspot was found */
+    Filter::HotSpot* hotSpotAt(int line , int column) const;
+    /** Returns a list of all the hotspots in all the chain's filters */
+    QList<Filter::HotSpot*> hotSpots() const;
+    /** Returns a list of all hotspots at the given line in all the chain's filters */
+    QList<Filter::HotSpot> hotSpotsAtLine(int line) const;
+
+};
+
+/** A filter chain which processes character images from terminal displays */
+class TerminalImageFilterChain : public FilterChain
+{
+public:
+    TerminalImageFilterChain();
+    virtual ~TerminalImageFilterChain();
+
+    /**
+     * Set the current terminal image to @p image.
+     *
+     * @param image The terminal image
+     * @param lines The number of lines in the terminal image
+     * @param columns The number of columns in the terminal image
+     * @param lineProperties The line properties to set for image
+     */
+    void setImage(const Character* const image , int lines , int columns,
+                  const QVector<LineProperty>& lineProperties);  
+
+private:
+    QString* _buffer;
+    QList<int>* _linePositions;
+};
+
+
+#endif //FILTER_H

=== added file 'src/History.cpp'
--- src/History.cpp	1970-01-01 00:00:00 +0000
+++ src/History.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,986 @@
+/*
+    This file is part of Konsole, an X terminal.
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+// Own
+#include "History.h"
+
+// System
+#include <iostream>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <QtDebug>
+
+// KDE
+//#include <kde_file.h>
+//#include <kdebug.h>
+
+// Reasonable line size
+#define LINE_SIZE    1024
+#define KDE_lseek lseek
+
+
+/*
+   An arbitrary long scroll.
+
+   One can modify the scroll only by adding either cells
+   or newlines, but access it randomly.
+
+   The model is that of an arbitrary wide typewriter scroll
+   in that the scroll is a serie of lines and each line is
+   a serie of cells with no overwriting permitted.
+
+   The implementation provides arbitrary length and numbers
+   of cells and line/column indexed read access to the scroll
+   at constant costs.
+
+KDE4: Can we use QTemporaryFile here, instead of KTempFile?
+
+FIXME: some complain about the history buffer comsuming the
+       memory of their machines. This problem is critical
+       since the history does not behave gracefully in cases
+       where the memory is used up completely.
+
+       I put in a workaround that should handle it problem
+       now gracefully. I'm not satisfied with the solution.
+
+FIXME: Terminating the history is not properly indicated
+       in the menu. We should throw a signal.
+
+FIXME: There is noticeable decrease in speed, also. Perhaps,
+       there whole feature needs to be revisited therefore.
+       Disadvantage of a more elaborated, say block-oriented
+       scheme with wrap around would be it's complexity.
+*/
+
+//FIXME: tempory replacement for tmpfile
+//       this is here one for debugging purpose.
+
+//#define tmpfile xTmpFile
+
+// History File ///////////////////////////////////////////
+
+/*
+  A Row(X) data type which allows adding elements to the end.
+*/
+
+HistoryFile::HistoryFile()
+  : ion(-1),
+    length(0),
+    fileMap(0)
+{
+  if (tmpFile.open())
+  { 
+    tmpFile.setAutoRemove(true);
+    ion = tmpFile.handle();
+  }
+}
+
+HistoryFile::~HistoryFile()
+{
+    if (fileMap)
+        unmap();
+}
+
+//TODO:  Mapping the entire file in will cause problems if the history file becomes exceedingly large,
+//(ie. larger than available memory).  HistoryFile::map() should only map in sections of the file at a time,
+//to avoid this.
+void HistoryFile::map()
+{
+    assert( fileMap == 0 );
+
+    fileMap = (char*)mmap( 0 , length , PROT_READ , MAP_PRIVATE , ion , 0 );
+
+    //if mmap'ing fails, fall back to the read-lseek combination
+    if ( fileMap == MAP_FAILED )
+    {
+            readWriteBalance = 0; 
+            fileMap = 0;
+            qDebug() << __FILE__ << __LINE__ << ": mmap'ing history failed.  errno = " << errno;
+    }
+}
+
+void HistoryFile::unmap()
+{
+    int result = munmap( fileMap , length );
+    assert( result == 0 ); Q_UNUSED( result );
+
+    fileMap = 0;
+}
+
+bool HistoryFile::isMapped()
+{
+    return (fileMap != 0);
+}
+
+void HistoryFile::add(const unsigned char* bytes, int len)
+{
+  if ( fileMap )
+          unmap();
+        
+  readWriteBalance++;
+
+  int rc = 0;
+
+  rc = KDE_lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryFile::add.seek"); return; }
+  rc = write(ion,bytes,len);       if (rc < 0) { perror("HistoryFile::add.write"); return; }
+  length += rc;
+}
+
+void HistoryFile::get(unsigned char* bytes, int len, int loc)
+{
+  //count number of get() calls vs. number of add() calls.  
+  //If there are many more get() calls compared with add() 
+  //calls (decided by using MAP_THRESHOLD) then mmap the log
+  //file to improve performance.
+  readWriteBalance--;
+  if ( !fileMap && readWriteBalance < MAP_THRESHOLD )
+          map();
+
+  if ( fileMap )
+  {
+    for (int i=0;i<len;i++)
+            bytes[i]=fileMap[loc+i];
+  }
+  else
+  {    
+      int rc = 0;
+
+      if (loc < 0 || len < 0 || loc + len > length)
+        fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
+      rc = KDE_lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryFile::get.seek"); return; }
+      rc = read(ion,bytes,len);     if (rc < 0) { perror("HistoryFile::get.read"); return; }
+  }
+}
+
+int HistoryFile::len()
+{
+  return length;
+}
+
+
+// History Scroll abstract base class //////////////////////////////////////
+
+
+HistoryScroll::HistoryScroll(HistoryType* t)
+  : m_histType(t)
+{
+}
+
+HistoryScroll::~HistoryScroll()
+{
+  delete m_histType;
+}
+
+bool HistoryScroll::hasScroll()
+{
+  return true;
+}
+
+// History Scroll File //////////////////////////////////////
+
+/* 
+   The history scroll makes a Row(Row(Cell)) from
+   two history buffers. The index buffer contains
+   start of line positions which refere to the cells
+   buffer.
+
+   Note that index[0] addresses the second line
+   (line #1), while the first line (line #0) starts
+   at 0 in cells.
+*/
+
+HistoryScrollFile::HistoryScrollFile(const QString &logFileName)
+  : HistoryScroll(new HistoryTypeFile(logFileName)),
+  m_logFileName(logFileName)
+{
+}
+
+HistoryScrollFile::~HistoryScrollFile()
+{
+}
+ 
+int HistoryScrollFile::getLines()
+{
+  return index.len() / sizeof(int);
+}
+
+int HistoryScrollFile::getLineLen(int lineno)
+{
+  return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character);
+}
+
+bool HistoryScrollFile::isWrappedLine(int lineno)
+{
+  if (lineno>=0 && lineno <= getLines()) {
+    unsigned char flag;
+    lineflags.get((unsigned char*)&flag,sizeof(unsigned char),(lineno)*sizeof(unsigned char));
+    return flag;
+  }
+  return false;
+}
+
+int HistoryScrollFile::startOfLine(int lineno)
+{
+  if (lineno <= 0) return 0;
+  if (lineno <= getLines())
+    { 
+    
+    if (!index.isMapped())
+            index.map();
+    
+    int res;
+    index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
+    return res;
+    }
+  return cells.len();
+}
+
+void HistoryScrollFile::getCells(int lineno, int colno, int count, Character res[])
+{
+  cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character));
+}
+
+void HistoryScrollFile::addCells(const Character text[], int count)
+{
+  cells.add((unsigned char*)text,count*sizeof(Character));
+}
+
+void HistoryScrollFile::addLine(bool previousWrapped)
+{
+  if (index.isMapped())
+          index.unmap();
+
+  int locn = cells.len();
+  index.add((unsigned char*)&locn,sizeof(int));
+  unsigned char flags = previousWrapped ? 0x01 : 0x00;
+  lineflags.add((unsigned char*)&flags,sizeof(unsigned char));
+}
+
+
+// History Scroll Buffer //////////////////////////////////////
+HistoryScrollBuffer::HistoryScrollBuffer(unsigned int maxLineCount)
+  : HistoryScroll(new HistoryTypeBuffer(maxLineCount))
+   ,_historyBuffer()
+   ,_maxLineCount(0)
+   ,_usedLines(0)
+   ,_head(0)
+{
+  setMaxNbLines(maxLineCount);
+}
+
+HistoryScrollBuffer::~HistoryScrollBuffer()
+{
+    delete[] _historyBuffer;
+}
+
+void HistoryScrollBuffer::addCellsVector(const QVector<Character>& cells)
+{
+    _head++;
+    if ( _usedLines < _maxLineCount )
+        _usedLines++;
+
+    if ( _head >= _maxLineCount )
+    {
+        _head = 0;
+    }
+
+    _historyBuffer[bufferIndex(_usedLines-1)] = cells;
+    _wrappedLine[bufferIndex(_usedLines-1)] = false;
+}
+void HistoryScrollBuffer::addCells(const Character a[], int count)
+{
+  HistoryLine newLine(count);
+  qCopy(a,a+count,newLine.begin());
+
+  addCellsVector(newLine);
+}
+
+void HistoryScrollBuffer::addLine(bool previousWrapped)
+{
+    _wrappedLine[bufferIndex(_usedLines-1)] = previousWrapped;
+}
+
+int HistoryScrollBuffer::getLines()
+{
+    return _usedLines;
+}
+
+int HistoryScrollBuffer::getLineLen(int lineNumber)
+{
+  Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount );
+
+  if ( lineNumber < _usedLines )
+  {
+    return _historyBuffer[bufferIndex(lineNumber)].size();
+  }
+  else
+  {
+    return 0;
+  }
+}
+
+bool HistoryScrollBuffer::isWrappedLine(int lineNumber)
+{
+  Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount );
+    
+  if (lineNumber < _usedLines)
+  {
+    //kDebug() << "Line" << lineNumber << "wrapped is" << _wrappedLine[bufferIndex(lineNumber)];
+    return _wrappedLine[bufferIndex(lineNumber)];
+  }
+  else
+    return false;
+}
+
+void HistoryScrollBuffer::getCells(int lineNumber, int startColumn, int count, Character buffer[])
+{
+  if ( count == 0 ) return;
+
+  Q_ASSERT( lineNumber < _maxLineCount );
+
+  if (lineNumber >= _usedLines) 
+  {
+    memset(buffer, 0, count * sizeof(Character));
+    return;
+  }
+  
+  const HistoryLine& line = _historyBuffer[bufferIndex(lineNumber)];
+
+  //kDebug() << "startCol " << startColumn;
+  //kDebug() << "line.size() " << line.size();
+  //kDebug() << "count " << count;
+
+  Q_ASSERT( startColumn <= line.size() - count );
+    
+  memcpy(buffer, line.constData() + startColumn , count * sizeof(Character));
+}
+
+void HistoryScrollBuffer::setMaxNbLines(unsigned int lineCount)
+{
+    HistoryLine* oldBuffer = _historyBuffer;
+    HistoryLine* newBuffer = new HistoryLine[lineCount];
+    
+    for ( int i = 0 ; i < qMin(_usedLines,(int)lineCount) ; i++ )
+    {
+        newBuffer[i] = oldBuffer[bufferIndex(i)];
+    }
+    
+    _usedLines = qMin(_usedLines,(int)lineCount);
+    _maxLineCount = lineCount;
+    _head = ( _usedLines == _maxLineCount ) ? 0 : _usedLines-1;
+
+    _historyBuffer = newBuffer;
+    delete[] oldBuffer;
+
+    _wrappedLine.resize(lineCount);
+    dynamic_cast<HistoryTypeBuffer*>(m_histType)->m_nbLines = lineCount;
+}
+
+int HistoryScrollBuffer::bufferIndex(int lineNumber)
+{
+    Q_ASSERT( lineNumber >= 0 );
+    Q_ASSERT( lineNumber < _maxLineCount );
+    Q_ASSERT( (_usedLines == _maxLineCount) || lineNumber <= _head );
+
+    if ( _usedLines == _maxLineCount )
+    {
+        return (_head+lineNumber+1) % _maxLineCount;
+    }
+    else
+    {   
+        return lineNumber;
+    }
+}
+
+
+// History Scroll None //////////////////////////////////////
+
+HistoryScrollNone::HistoryScrollNone()
+  : HistoryScroll(new HistoryTypeNone())
+{
+}
+
+HistoryScrollNone::~HistoryScrollNone()
+{
+}
+
+bool HistoryScrollNone::hasScroll()
+{
+  return false;
+}
+
+int  HistoryScrollNone::getLines()
+{
+  return 0;
+}
+
+int  HistoryScrollNone::getLineLen(int)
+{
+  return 0;
+}
+
+bool HistoryScrollNone::isWrappedLine(int /*lineno*/)
+{
+  return false;
+}
+
+void HistoryScrollNone::getCells(int, int, int, Character [])
+{
+}
+
+void HistoryScrollNone::addCells(const Character [], int)
+{
+}
+
+void HistoryScrollNone::addLine(bool)
+{
+}
+
+// History Scroll BlockArray //////////////////////////////////////
+
+HistoryScrollBlockArray::HistoryScrollBlockArray(size_t size)
+  : HistoryScroll(new HistoryTypeBlockArray(size))
+{
+  m_blockArray.setHistorySize(size); // nb. of lines.
+}
+
+HistoryScrollBlockArray::~HistoryScrollBlockArray()
+{
+}
+
+int  HistoryScrollBlockArray::getLines()
+{
+  return m_lineLengths.count();
+}
+
+int  HistoryScrollBlockArray::getLineLen(int lineno)
+{
+    if ( m_lineLengths.contains(lineno) )
+        return m_lineLengths[lineno];
+    else
+        return 0;
+}
+
+bool HistoryScrollBlockArray::isWrappedLine(int /*lineno*/)
+{
+  return false;
+}
+
+void HistoryScrollBlockArray::getCells(int lineno, int colno,
+                                       int count, Character res[])
+{
+  if (!count) return;
+
+  const Block *b = m_blockArray.at(lineno);
+
+  if (!b) {
+    memset(res, 0, count * sizeof(Character)); // still better than random data
+    return;
+  }
+
+  assert(((colno + count) * sizeof(Character)) < ENTRIES);
+  memcpy(res, b->data + (colno * sizeof(Character)), count * sizeof(Character));
+}
+
+void HistoryScrollBlockArray::addCells(const Character a[], int count)
+{
+  Block *b = m_blockArray.lastBlock();
+  
+  if (!b) return;
+
+  // put cells in block's data
+  assert((count * sizeof(Character)) < ENTRIES);
+
+  memset(b->data, 0, ENTRIES);
+
+  memcpy(b->data, a, count * sizeof(Character));
+  b->size = count * sizeof(Character);
+
+  size_t res = m_blockArray.newBlock();
+  assert (res > 0);
+  Q_UNUSED( res );
+
+  m_lineLengths.insert(m_blockArray.getCurrent(), count);
+}
+
+void HistoryScrollBlockArray::addLine(bool)
+{
+}
+
+////////////////////////////////////////////////////////////////
+// Compact History Scroll //////////////////////////////////////
+////////////////////////////////////////////////////////////////
+void* CompactHistoryBlock::allocate ( size_t length )
+{
+ Q_ASSERT ( length > 0 );
+  if ( tail-blockStart+length > blockLength )
+    return NULL;
+
+  void* block = tail;
+  tail += length;
+  //kDebug() << "allocated " << length << " bytes at address " << block;
+  allocCount++;
+  return block;
+}
+
+void CompactHistoryBlock::deallocate ( )
+{
+  allocCount--;
+  Q_ASSERT ( allocCount >= 0 );
+}
+
+void* CompactHistoryBlockList::allocate(size_t size)
+{
+  CompactHistoryBlock* block;
+  if ( list.isEmpty() || list.last()->remaining() < size)
+  {
+    block = new CompactHistoryBlock();
+    list.append ( block );
+    //kDebug() << "new block created, remaining " << block->remaining() << "number of blocks=" << list.size();
+  }
+  else
+  {
+    block = list.last();
+    //kDebug() << "old block used, remaining " << block->remaining();
+  }
+  return block->allocate(size);
+}
+
+void CompactHistoryBlockList::deallocate(void* ptr)
+{
+  Q_ASSERT( !list.isEmpty());
+  
+  int i=0;  
+  CompactHistoryBlock *block = list.at(i);
+  while ( i<list.size() && !block->contains(ptr) )
+  { 
+    i++;
+    block=list.at(i);
+  }
+
+  Q_ASSERT( i<list.size() );
+  
+  block->deallocate();
+
+  if (!block->isInUse())
+  {
+    list.removeAt(i);
+    delete block;
+    //kDebug() << "block deleted, new size = " << list.size();
+  }
+}
+
+CompactHistoryBlockList::~CompactHistoryBlockList()
+{
+  qDeleteAll ( list.begin(), list.end() );
+  list.clear();
+}
+
+void* CompactHistoryLine::operator new (size_t size, CompactHistoryBlockList& blockList)
+{
+  return blockList.allocate(size);
+}
+
+CompactHistoryLine::CompactHistoryLine ( const TextLine& line, CompactHistoryBlockList& bList ) 
+  : blockList(bList),
+    formatLength(0)
+{
+  length=line.size();
+      
+  if (line.size() > 0) {
+    formatLength=1;
+    int k=1;
+  
+    // count number of different formats in this text line
+    Character c = line[0];
+    while ( k<length )
+    {
+      if ( !(line[k].equalsFormat(c)))
+      {
+        formatLength++; // format change detected
+        c=line[k];
+      }
+      k++;
+    }
+  
+    //kDebug() << "number of different formats in string: " << formatLength;
+    formatArray = (CharacterFormat*) blockList.allocate(sizeof(CharacterFormat)*formatLength);
+    Q_ASSERT (formatArray!=NULL);
+    text = (quint16*) blockList.allocate(sizeof(quint16)*line.size());
+    Q_ASSERT (text!=NULL);
+  
+    length=line.size();
+    formatLength=formatLength;
+    wrapped=false;
+  
+    // record formats and their positions in the format array
+    c=line[0];
+    formatArray[0].setFormat ( c );
+    formatArray[0].startPos=0;                        // there's always at least 1 format (for the entire line, unless a change happens)
+  
+    k=1;                                              // look for possible format changes
+    int j=1;
+    while ( k<length && j<formatLength )
+    {
+      if (!(line[k].equalsFormat(c)))
+      {
+        c=line[k];
+        formatArray[j].setFormat(c);
+        formatArray[j].startPos=k;
+        //kDebug() << "format entry " << j << " at pos " << formatArray[j].startPos << " " << &(formatArray[j].startPos) ;
+        j++;
+      }
+      k++;
+    }
+  
+    // copy character values
+    for ( int i=0; i<line.size(); i++ )
+    {
+      text[i]=line[i].character;
+      //kDebug() << "char " << i << " at mem " << &(text[i]);
+    }
+  }
+  //kDebug() << "line created, length " << length << " at " << &(length);
+}
+
+CompactHistoryLine::~CompactHistoryLine()
+{
+  //kDebug() << "~CHL";
+  if (length>0) {
+    blockList.deallocate(text);
+    blockList.deallocate(formatArray);
+  }
+  blockList.deallocate(this);  
+}
+
+void CompactHistoryLine::getCharacter ( int index, Character &r )
+{
+  Q_ASSERT ( index < length );
+  int formatPos=0;
+  while ( ( formatPos+1 ) < formatLength && index >= formatArray[formatPos+1].startPos )
+    formatPos++;
+
+  r.character=text[index];
+  r.rendition = formatArray[formatPos].rendition;
+  r.foregroundColor = formatArray[formatPos].fgColor;
+  r.backgroundColor = formatArray[formatPos].bgColor;
+}
+
+void CompactHistoryLine::getCharacters ( Character* array, int length, int startColumn )
+{
+  Q_ASSERT ( startColumn >= 0 && length >= 0 );
+  Q_ASSERT ( startColumn+length <= ( int ) getLength() );
+
+  for ( int i=startColumn; i<length+startColumn; i++ )
+  {
+    getCharacter ( i, array[i-startColumn] );
+  }
+}
+
+CompactHistoryScroll::CompactHistoryScroll ( unsigned int maxLineCount )
+    : HistoryScroll ( new CompactHistoryType ( maxLineCount ) )
+    ,lines()
+    ,blockList()
+{
+  //kDebug() << "scroll of length " << maxLineCount << " created";
+  setMaxNbLines ( maxLineCount );
+}
+
+CompactHistoryScroll::~CompactHistoryScroll()
+{
+  qDeleteAll ( lines.begin(), lines.end() );
+  lines.clear();
+}
+
+void CompactHistoryScroll::addCellsVector ( const TextLine& cells )
+{
+  CompactHistoryLine *line;
+  line = new(blockList) CompactHistoryLine ( cells, blockList );
+
+  if ( lines.size() > ( int ) _maxLineCount )
+  {
+    delete lines.takeAt ( 0 );
+  }
+  lines.append ( line );
+}
+
+void CompactHistoryScroll::addCells ( const Character a[], int count )
+{
+  TextLine newLine ( count );
+  qCopy ( a,a+count,newLine.begin() );
+  addCellsVector ( newLine );
+}
+
+void CompactHistoryScroll::addLine ( bool previousWrapped )
+{
+  CompactHistoryLine *line = lines.last();
+  //kDebug() << "last line at address " << line;
+  line->setWrapped(previousWrapped);
+}
+
+int CompactHistoryScroll::getLines()
+{
+  return lines.size();
+}
+
+int CompactHistoryScroll::getLineLen ( int lineNumber )
+{
+  Q_ASSERT ( lineNumber >= 0 && lineNumber < lines.size() );
+  CompactHistoryLine* line = lines[lineNumber];
+  //kDebug() << "request for line at address " << line;
+  return line->getLength();
+}
+
+
+void CompactHistoryScroll::getCells ( int lineNumber, int startColumn, int count, Character buffer[] )
+{
+  if ( count == 0 ) return;
+  Q_ASSERT ( lineNumber < lines.size() );
+  CompactHistoryLine* line = lines[lineNumber];
+  Q_ASSERT ( startColumn >= 0 );
+  Q_ASSERT ( (unsigned int)startColumn <= line->getLength() - count );
+  line->getCharacters ( buffer, count, startColumn );
+}
+
+void CompactHistoryScroll::setMaxNbLines ( unsigned int lineCount )
+{
+  _maxLineCount = lineCount;
+
+  while (lines.size() > (int) lineCount) {
+    delete lines.takeAt(0);
+  }
+  //kDebug() << "set max lines to: " << _maxLineCount;
+}
+
+bool CompactHistoryScroll::isWrappedLine ( int lineNumber )
+{
+  Q_ASSERT ( lineNumber < lines.size() );
+  return lines[lineNumber]->isWrapped();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// History Types
+//////////////////////////////////////////////////////////////////////
+
+HistoryType::HistoryType()
+{
+}
+
+HistoryType::~HistoryType()
+{
+}
+
+//////////////////////////////
+
+HistoryTypeNone::HistoryTypeNone()
+{
+}
+
+bool HistoryTypeNone::isEnabled() const
+{
+  return false;
+}
+
+HistoryScroll* HistoryTypeNone::scroll(HistoryScroll *old) const
+{
+  delete old;
+  return new HistoryScrollNone();
+}
+
+int HistoryTypeNone::maximumLineCount() const
+{
+  return 0;
+}
+
+//////////////////////////////
+
+HistoryTypeBlockArray::HistoryTypeBlockArray(size_t size)
+  : m_size(size)
+{
+}
+
+bool HistoryTypeBlockArray::isEnabled() const
+{
+  return true;
+}
+
+int HistoryTypeBlockArray::maximumLineCount() const
+{
+  return m_size;
+}
+
+HistoryScroll* HistoryTypeBlockArray::scroll(HistoryScroll *old) const
+{
+  delete old;
+  return new HistoryScrollBlockArray(m_size);
+}
+
+
+//////////////////////////////
+
+HistoryTypeBuffer::HistoryTypeBuffer(unsigned int nbLines)
+  : m_nbLines(nbLines)
+{
+}
+
+bool HistoryTypeBuffer::isEnabled() const
+{
+  return true;
+}
+
+int HistoryTypeBuffer::maximumLineCount() const
+{
+  return m_nbLines;
+}
+
+HistoryScroll* HistoryTypeBuffer::scroll(HistoryScroll *old) const
+{
+  if (old)
+  {
+    HistoryScrollBuffer *oldBuffer = dynamic_cast<HistoryScrollBuffer*>(old);
+    if (oldBuffer)
+    {
+       oldBuffer->setMaxNbLines(m_nbLines);
+       return oldBuffer;
+    }
+
+    HistoryScroll *newScroll = new HistoryScrollBuffer(m_nbLines);
+    int lines = old->getLines();
+    int startLine = 0;
+    if (lines > (int) m_nbLines)
+       startLine = lines - m_nbLines;
+
+    Character line[LINE_SIZE];
+    for(int i = startLine; i < lines; i++)
+    {
+       int size = old->getLineLen(i);
+       if (size > LINE_SIZE)
+       {
+          Character *tmp_line = new Character[size];
+          old->getCells(i, 0, size, tmp_line);
+          newScroll->addCells(tmp_line, size);
+          newScroll->addLine(old->isWrappedLine(i));
+          delete [] tmp_line;
+       }
+       else
+       {
+          old->getCells(i, 0, size, line);
+          newScroll->addCells(line, size);
+          newScroll->addLine(old->isWrappedLine(i));
+       }
+    }
+    delete old;
+    return newScroll;
+  }
+  return new HistoryScrollBuffer(m_nbLines);
+}
+
+//////////////////////////////
+
+HistoryTypeFile::HistoryTypeFile(const QString& fileName)
+  : m_fileName(fileName)
+{
+}
+
+bool HistoryTypeFile::isEnabled() const
+{
+  return true;
+}
+
+const QString& HistoryTypeFile::getFileName() const
+{
+  return m_fileName;
+}
+
+HistoryScroll* HistoryTypeFile::scroll(HistoryScroll *old) const
+{
+  if (dynamic_cast<HistoryFile *>(old)) 
+     return old; // Unchanged.
+
+  HistoryScroll *newScroll = new HistoryScrollFile(m_fileName);
+
+  Character line[LINE_SIZE];
+  int lines = (old != 0) ? old->getLines() : 0;
+  for(int i = 0; i < lines; i++)
+  {
+     int size = old->getLineLen(i);
+     if (size > LINE_SIZE)
+     {
+        Character *tmp_line = new Character[size];
+        old->getCells(i, 0, size, tmp_line);
+        newScroll->addCells(tmp_line, size);
+        newScroll->addLine(old->isWrappedLine(i));
+        delete [] tmp_line;
+     }
+     else
+     {
+        old->getCells(i, 0, size, line);
+        newScroll->addCells(line, size);
+        newScroll->addLine(old->isWrappedLine(i));
+     }
+  }
+
+  delete old;
+  return newScroll; 
+}
+
+int HistoryTypeFile::maximumLineCount() const
+{
+  return 0;
+}
+
+//////////////////////////////
+
+CompactHistoryType::CompactHistoryType ( unsigned int nbLines )
+    : m_nbLines ( nbLines )
+{
+}
+
+bool CompactHistoryType::isEnabled() const
+{
+  return true;
+}
+
+int CompactHistoryType::maximumLineCount() const
+{
+  return m_nbLines;
+}
+
+HistoryScroll* CompactHistoryType::scroll ( HistoryScroll *old ) const
+{
+  if ( old )
+  {
+    CompactHistoryScroll *oldBuffer = dynamic_cast<CompactHistoryScroll*> ( old );
+    if ( oldBuffer )
+    {
+      oldBuffer->setMaxNbLines ( m_nbLines );
+      return oldBuffer;
+    }
+    delete old;
+  }
+  return new CompactHistoryScroll ( m_nbLines );
+}

=== added file 'src/History.h'
--- src/History.h	1970-01-01 00:00:00 +0000
+++ src/History.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,490 @@
+/*
+    This file is part of Konsole, an X terminal.
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+#ifndef TEHISTORY_H
+#define TEHISTORY_H
+
+// Qt
+#include <QtCore/QBitRef>
+#include <QtCore/QHash>
+#include <QtCore/QVector>
+#include <QTemporaryFile>
+
+// KDE
+//#include <ktemporaryfile.h>
+
+// Konsole
+#include "BlockArray.h"
+#include "Character.h"
+
+// map
+#include <sys/mman.h>
+
+
+#if 1
+/*
+   An extendable tmpfile(1) based buffer.
+*/
+
+class HistoryFile
+{
+public:
+  HistoryFile();
+  virtual ~HistoryFile();
+
+  virtual void add(const unsigned char* bytes, int len);
+  virtual void get(unsigned char* bytes, int len, int loc);
+  virtual int  len();
+
+  //mmaps the file in read-only mode
+  void map();
+  //un-mmaps the file
+  void unmap();
+  //returns true if the file is mmap'ed
+  bool isMapped();
+
+
+private:
+  int  ion;
+  int  length;
+  QTemporaryFile tmpFile;
+
+  //pointer to start of mmap'ed file data, or 0 if the file is not mmap'ed
+  char* fileMap;
+ 
+  //incremented whenver 'add' is called and decremented whenever
+  //'get' is called.
+  //this is used to detect when a large number of lines are being read and processed from the history
+  //and automatically mmap the file for better performance (saves the overhead of many lseek-read calls).
+  int readWriteBalance;
+
+  //when readWriteBalance goes below this threshold, the file will be mmap'ed automatically
+  static const int MAP_THRESHOLD = -1000;
+};
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+// Abstract base class for file and buffer versions
+//////////////////////////////////////////////////////////////////////
+class HistoryType;
+
+class HistoryScroll
+{
+public:
+  HistoryScroll(HistoryType*);
+ virtual ~HistoryScroll();
+
+  virtual bool hasScroll();
+
+  // access to history
+  virtual int  getLines() = 0;
+  virtual int  getLineLen(int lineno) = 0;
+  virtual void getCells(int lineno, int colno, int count, Character res[]) = 0;
+  virtual bool isWrappedLine(int lineno) = 0;
+
+  // backward compatibility (obsolete)
+  Character   getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; }
+
+  // adding lines.
+  virtual void addCells(const Character a[], int count) = 0;
+  // convenience method - this is virtual so that subclasses can take advantage
+  // of QVector's implicit copying
+  virtual void addCellsVector(const QVector<Character>& cells)
+  {
+    addCells(cells.data(),cells.size());
+  }
+
+  virtual void addLine(bool previousWrapped=false) = 0;
+
+  //
+  // FIXME:  Passing around constant references to HistoryType instances
+  // is very unsafe, because those references will no longer
+  // be valid if the history scroll is deleted.
+  //
+  const HistoryType& getType() { return *m_histType; }
+
+protected:
+  HistoryType* m_histType;
+
+};
+
+#if 1
+
+//////////////////////////////////////////////////////////////////////
+// File-based history (e.g. file log, no limitation in length)
+//////////////////////////////////////////////////////////////////////
+
+class HistoryScrollFile : public HistoryScroll
+{
+public:
+  HistoryScrollFile(const QString &logFileName);
+  virtual ~HistoryScrollFile();
+
+  virtual int  getLines();
+  virtual int  getLineLen(int lineno);
+  virtual void getCells(int lineno, int colno, int count, Character res[]);
+  virtual bool isWrappedLine(int lineno);
+
+  virtual void addCells(const Character a[], int count);
+  virtual void addLine(bool previousWrapped=false);
+
+private:
+  int startOfLine(int lineno);
+
+  QString m_logFileName;
+  HistoryFile index; // lines Row(int)
+  HistoryFile cells; // text  Row(Character)
+  HistoryFile lineflags; // flags Row(unsigned char)
+};
+
+
+//////////////////////////////////////////////////////////////////////
+// Buffer-based history (limited to a fixed nb of lines)
+//////////////////////////////////////////////////////////////////////
+class HistoryScrollBuffer : public HistoryScroll
+{
+public:
+  typedef QVector<Character> HistoryLine;
+
+  HistoryScrollBuffer(unsigned int maxNbLines = 1000);
+  virtual ~HistoryScrollBuffer();
+
+  virtual int  getLines();
+  virtual int  getLineLen(int lineno);
+  virtual void getCells(int lineno, int colno, int count, Character res[]);
+  virtual bool isWrappedLine(int lineno);
+
+  virtual void addCells(const Character a[], int count);
+  virtual void addCellsVector(const QVector<Character>& cells);
+  virtual void addLine(bool previousWrapped=false);
+
+  void setMaxNbLines(unsigned int nbLines);
+  unsigned int maxNbLines() { return _maxLineCount; }
+  
+
+private:
+  int bufferIndex(int lineNumber);
+
+  HistoryLine* _historyBuffer;
+  QBitArray _wrappedLine;
+  int _maxLineCount;
+  int _usedLines;  
+  int _head;
+  
+  //QVector<histline*> m_histBuffer;
+  //QBitArray m_wrappedLine;
+  //unsigned int m_maxNbLines;
+  //unsigned int m_nbLines;
+  //unsigned int m_arrayIndex;
+  //bool         m_buffFilled;
+};
+
+/*class HistoryScrollBufferV2 : public HistoryScroll
+{
+public:
+  virtual int  getLines();
+  virtual int  getLineLen(int lineno);
+  virtual void getCells(int lineno, int colno, int count, Character res[]);
+  virtual bool isWrappedLine(int lineno);
+
+  virtual void addCells(const Character a[], int count);
+  virtual void addCells(const QVector<Character>& cells);
+  virtual void addLine(bool previousWrapped=false);
+
+};*/
+
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Nothing-based history (no history :-)
+//////////////////////////////////////////////////////////////////////
+class HistoryScrollNone : public HistoryScroll
+{
+public:
+  HistoryScrollNone();
+  virtual ~HistoryScrollNone();
+
+  virtual bool hasScroll();
+
+  virtual int  getLines();
+  virtual int  getLineLen(int lineno);
+  virtual void getCells(int lineno, int colno, int count, Character res[]);
+  virtual bool isWrappedLine(int lineno);
+
+  virtual void addCells(const Character a[], int count);
+  virtual void addLine(bool previousWrapped=false);
+};
+
+//////////////////////////////////////////////////////////////////////
+// BlockArray-based history
+//////////////////////////////////////////////////////////////////////
+class HistoryScrollBlockArray : public HistoryScroll
+{
+public:
+  HistoryScrollBlockArray(size_t size);
+  virtual ~HistoryScrollBlockArray();
+
+  virtual int  getLines();
+  virtual int  getLineLen(int lineno);
+  virtual void getCells(int lineno, int colno, int count, Character res[]);
+  virtual bool isWrappedLine(int lineno);
+
+  virtual void addCells(const Character a[], int count);
+  virtual void addLine(bool previousWrapped=false);
+
+protected:
+  BlockArray m_blockArray;
+  QHash<int,size_t> m_lineLengths;
+};
+
+//////////////////////////////////////////////////////////////////////
+// History using compact storage
+// This implementation uses a list of fixed-sized blocks
+// where history lines are allocated in (avoids heap fragmentation)
+//////////////////////////////////////////////////////////////////////
+typedef QVector<Character> TextLine;
+
+class CharacterFormat
+{
+public:
+  bool equalsFormat(const CharacterFormat &other) const {
+    return other.rendition==rendition && other.fgColor==fgColor && other.bgColor==bgColor;
+  }
+
+  bool equalsFormat(const Character &c) const {
+    return c.rendition==rendition && c.foregroundColor==fgColor && c.backgroundColor==bgColor;
+  }
+
+  void setFormat(const Character& c) {
+    rendition=c.rendition;
+    fgColor=c.foregroundColor;
+    bgColor=c.backgroundColor;
+  }
+
+  CharacterColor fgColor, bgColor;
+  quint16 startPos;
+  quint8 rendition;
+};
+
+class CompactHistoryBlock
+{
+public:
+  
+  CompactHistoryBlock(){
+    blockLength = 4096*64; // 256kb
+    head = (quint8*) mmap(0, blockLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+    //head = (quint8*) malloc(blockLength);
+    Q_ASSERT(head != MAP_FAILED);
+    tail = blockStart = head;
+    allocCount=0;
+  }
+  
+  virtual ~CompactHistoryBlock(){
+    //free(blockStart);
+    munmap(blockStart, blockLength);
+  }
+  
+  virtual unsigned int remaining(){ return blockStart+blockLength-tail;}
+  virtual unsigned  length() { return blockLength; }
+  virtual void* allocate(size_t length);
+  virtual bool contains(void *addr) {return addr>=blockStart && addr<(blockStart+blockLength);}
+  virtual void deallocate();
+  virtual bool isInUse(){ return allocCount!=0; } ;
+
+private:
+  size_t blockLength;
+  quint8* head;
+  quint8* tail;
+  quint8* blockStart;
+  int allocCount;
+};
+
+class CompactHistoryBlockList {
+public:
+  CompactHistoryBlockList() {};
+  ~CompactHistoryBlockList();
+
+  void *allocate( size_t size );
+  void deallocate(void *);
+  int length() {return list.size();}
+private:
+  QList<CompactHistoryBlock*> list;
+};
+
+class CompactHistoryLine
+{
+public:
+  CompactHistoryLine(const TextLine&, CompactHistoryBlockList& blockList);
+  virtual ~CompactHistoryLine();
+
+  // custom new operator to allocate memory from custom pool instead of heap
+  static void *operator new( size_t size, CompactHistoryBlockList& blockList);
+  static void operator delete( void *) { /* do nothing, deallocation from pool is done in destructor*/ } ;
+
+  virtual void getCharacters(Character* array, int length, int startColumn) ;
+  virtual void getCharacter(int index, Character &r) ;
+  virtual bool isWrapped() const {return wrapped;};
+  virtual void setWrapped(bool isWrapped) { wrapped=isWrapped;};
+  virtual unsigned int getLength() const {return length;};
+
+protected:
+  CompactHistoryBlockList& blockList;
+  CharacterFormat* formatArray;
+  quint16 length;
+  quint16* text;
+  quint16 formatLength;
+  bool wrapped;
+};
+
+class CompactHistoryScroll : public HistoryScroll
+{
+  typedef QList<CompactHistoryLine*> HistoryArray;
+
+public:
+  CompactHistoryScroll(unsigned int maxNbLines = 1000);
+  virtual ~CompactHistoryScroll();
+
+  virtual int  getLines();
+  virtual int  getLineLen(int lineno);
+  virtual void getCells(int lineno, int colno, int count, Character res[]);
+  virtual bool isWrappedLine(int lineno);
+
+  virtual void addCells(const Character a[], int count);
+  virtual void addCellsVector(const TextLine& cells);
+  virtual void addLine(bool previousWrapped=false);
+
+  void setMaxNbLines(unsigned int nbLines);
+  unsigned int maxNbLines() const { return _maxLineCount; }
+
+private:
+  bool hasDifferentColors(const TextLine& line) const;
+  HistoryArray lines;
+  CompactHistoryBlockList blockList;
+  
+  unsigned int _maxLineCount;
+};
+
+//////////////////////////////////////////////////////////////////////
+// History type
+//////////////////////////////////////////////////////////////////////
+
+class HistoryType
+{
+public:
+  HistoryType();
+  virtual ~HistoryType();
+
+  /**
+   * Returns true if the history is enabled ( can store lines of output )
+   * or false otherwise. 
+   */
+  virtual bool isEnabled()           const = 0;
+  /**
+   * Returns true if the history size is unlimited.
+   */
+  bool isUnlimited() const { return maximumLineCount() == 0; }
+  /**
+   * Returns the maximum number of lines which this history type
+   * can store or 0 if the history can store an unlimited number of lines.
+   */
+  virtual int maximumLineCount()    const = 0;
+
+  virtual HistoryScroll* scroll(HistoryScroll *) const = 0;
+};
+
+class HistoryTypeNone : public HistoryType
+{
+public:
+  HistoryTypeNone();
+
+  virtual bool isEnabled() const;
+  virtual int maximumLineCount() const;
+
+  virtual HistoryScroll* scroll(HistoryScroll *) const;
+};
+
+class HistoryTypeBlockArray : public HistoryType
+{
+public:
+  HistoryTypeBlockArray(size_t size);
+  
+  virtual bool isEnabled() const;
+  virtual int maximumLineCount() const;
+
+  virtual HistoryScroll* scroll(HistoryScroll *) const;
+
+protected:
+  size_t m_size;
+};
+
+#if 1 
+class HistoryTypeFile : public HistoryType
+{
+public:
+  HistoryTypeFile(const QString& fileName=QString());
+
+  virtual bool isEnabled() const;
+  virtual const QString& getFileName() const;
+  virtual int maximumLineCount() const;
+
+  virtual HistoryScroll* scroll(HistoryScroll *) const;
+
+protected:
+  QString m_fileName;
+};
+
+
+class HistoryTypeBuffer : public HistoryType
+{
+    friend class HistoryScrollBuffer;
+
+public:
+  HistoryTypeBuffer(unsigned int nbLines);
+   
+  virtual bool isEnabled() const;
+  virtual int maximumLineCount() const;
+  
+  virtual HistoryScroll* scroll(HistoryScroll *) const;
+
+protected:
+  unsigned int m_nbLines;
+};
+
+class CompactHistoryType : public HistoryType
+{
+public:
+  CompactHistoryType(unsigned int size);
+  
+  virtual bool isEnabled() const;
+  virtual int maximumLineCount() const;
+
+  virtual HistoryScroll* scroll(HistoryScroll *) const;
+
+protected:
+  unsigned int m_nbLines;
+};
+
+
+#endif
+
+
+#endif // TEHISTORY_H

=== added file 'src/KeyboardTranslator.cpp'
--- src/KeyboardTranslator.cpp	1970-01-01 00:00:00 +0000
+++ src/KeyboardTranslator.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,892 @@
+/*
+    This source file is part of Konsole, a terminal emulator.
+
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+// Own
+#include "KeyboardTranslator.h"
+
+// System
+#include <ctype.h>
+#include <stdio.h>
+
+// Qt
+#include <QtCore/QBuffer>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextStream>
+#include <QtGui/QKeySequence>
+#include <QDir>
+#include <QtDebug>
+
+#include "tools.h"
+
+// KDE
+//#include <KDebug>
+//#include <KLocale>
+//#include <KStandardDirs>
+
+
+const QByteArray KeyboardTranslatorManager::defaultTranslatorText(
+"keyboard \"Fallback Key Translator\"\n"
+"key Tab : \"\\t\""
+);
+
+KeyboardTranslatorManager::KeyboardTranslatorManager()
+    : _haveLoadedAll(false)
+{
+}
+KeyboardTranslatorManager::~KeyboardTranslatorManager()
+{
+    qDeleteAll(_translators);
+}
+QString KeyboardTranslatorManager::findTranslatorPath(const QString& name)
+{
+    return QString(get_kb_layout_dir() + name + ".keytab");
+    //return KGlobal::dirs()->findResource("data","konsole/"+name+".keytab");
+}
+
+void KeyboardTranslatorManager::findTranslators()
+{
+    QDir dir(get_kb_layout_dir());
+    QStringList filters;
+    filters << "*.keytab";
+    dir.setNameFilters(filters);
+    QStringList list = dir.entryList(filters);
+    list = dir.entryList(filters);
+//    QStringList list = KGlobal::dirs()->findAllResources("data",
+//                                                         "konsole/*.keytab",
+//                                                        KStandardDirs::NoDuplicates);
+
+    // add the name of each translator to the list and associated
+    // the name with a null pointer to indicate that the translator
+    // has not yet been loaded from disk
+    QStringListIterator listIter(list);
+    while (listIter.hasNext())
+    {
+        QString translatorPath = listIter.next();
+
+        QString name = QFileInfo(translatorPath).baseName();
+       
+        if ( !_translators.contains(name) ) 
+            _translators.insert(name,0);
+    }
+
+    _haveLoadedAll = true;
+}
+
+const KeyboardTranslator* KeyboardTranslatorManager::findTranslator(const QString& name)
+{
+    if ( name.isEmpty() )
+        return defaultTranslator();
+
+    if ( _translators.contains(name) && _translators[name] != 0 )
+        return _translators[name];
+
+    KeyboardTranslator* translator = loadTranslator(name);
+
+    if ( translator != 0 )
+        _translators[name] = translator;
+    else if ( !name.isEmpty() )
+        qDebug() << "Unable to load translator" << name;
+
+    return translator;
+}
+
+bool KeyboardTranslatorManager::saveTranslator(const KeyboardTranslator* translator)
+{
+qDebug() << "KeyboardTranslatorManager::saveTranslator" << "unimplemented";
+Q_UNUSED(translator);
+#if 0
+    const QString path = KGlobal::dirs()->saveLocation("data","konsole/")+translator->name()
+           +".keytab";
+
+    //kDebug() << "Saving translator to" << path;
+
+    QFile destination(path);
+    if (!destination.open(QIODevice::WriteOnly | QIODevice::Text))
+    {
+        qDebug() << "Unable to save keyboard translation:" 
+                   << destination.errorString();
+        return false;
+    }
+
+    {
+        KeyboardTranslatorWriter writer(&destination);
+        writer.writeHeader(translator->description());
+    
+        QListIterator<KeyboardTranslator::Entry> iter(translator->entries());
+        while ( iter.hasNext() )
+            writer.writeEntry(iter.next());
+    }
+
+    destination.close();
+#endif
+    return true;
+}
+
+KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& name)
+{
+    const QString& path = findTranslatorPath(name);
+
+    QFile source(path); 
+    if (name.isEmpty() || !source.open(QIODevice::ReadOnly | QIODevice::Text))
+        return 0;
+
+    return loadTranslator(&source,name);
+}
+
+const KeyboardTranslator* KeyboardTranslatorManager::defaultTranslator()
+{
+    // Try to find the default.keytab file if it exists, otherwise
+    // fall back to the hard-coded one
+    const KeyboardTranslator* translator = findTranslator("default");
+    if (!translator)
+    {
+        QBuffer textBuffer;
+        textBuffer.setData(defaultTranslatorText);
+        textBuffer.open(QIODevice::ReadOnly);
+        translator = loadTranslator(&textBuffer,"fallback");
+    }
+    return translator;
+}
+
+KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(QIODevice* source,const QString& name)
+{
+    KeyboardTranslator* translator = new KeyboardTranslator(name);
+    KeyboardTranslatorReader reader(source);
+    translator->setDescription( reader.description() );
+    while ( reader.hasNextEntry() )
+        translator->addEntry(reader.nextEntry());
+
+    source->close();
+
+    if ( !reader.parseError() )
+    {
+        return translator;
+    }
+    else
+    {
+        delete translator;
+        return 0;
+    }
+}
+
+KeyboardTranslatorWriter::KeyboardTranslatorWriter(QIODevice* destination)
+: _destination(destination)
+{
+    Q_ASSERT( destination && destination->isWritable() );
+
+    _writer = new QTextStream(_destination);
+}
+KeyboardTranslatorWriter::~KeyboardTranslatorWriter()
+{
+    delete _writer;
+}
+void KeyboardTranslatorWriter::writeHeader( const QString& description )
+{
+    *_writer << "keyboard \"" << description << '\"' << '\n';
+}
+void KeyboardTranslatorWriter::writeEntry( const KeyboardTranslator::Entry& entry )
+{
+    QString result;
+    if ( entry.command() != KeyboardTranslator::NoCommand )
+        result = entry.resultToString();
+    else
+        result = '\"' + entry.resultToString() + '\"';
+
+    *_writer << "key " << entry.conditionToString() << " : " << result << '\n';
+}
+
+
+// each line of the keyboard translation file is one of:
+//
+// - keyboard "name"
+// - key KeySequence : "characters"
+// - key KeySequence : CommandName
+//
+// KeySequence begins with the name of the key ( taken from the Qt::Key enum )
+// and is followed by the keyboard modifiers and state flags ( with + or - in front
+// of each modifier or flag to indicate whether it is required ).  All keyboard modifiers
+// and flags are optional, if a particular modifier or state is not specified it is 
+// assumed not to be a part of the sequence.  The key sequence may contain whitespace
+//
+// eg:  "key Up+Shift : scrollLineUp"
+//      "key Next-Shift : "\E[6~"
+//
+// (lines containing only whitespace are ignored, parseLine assumes that comments have
+// already been removed)
+//
+
+KeyboardTranslatorReader::KeyboardTranslatorReader( QIODevice* source )
+    : _source(source)
+    , _hasNext(false)
+{
+   // read input until we find the description
+   while ( _description.isEmpty() && !source->atEnd() )
+   {
+        QList<Token> tokens = tokenize( QString(source->readLine()) );
+        if ( !tokens.isEmpty() && tokens.first().type == Token::TitleKeyword )
+            _description = tokens[1].text.toUtf8();
+   }
+   // read first entry (if any)
+   readNext();
+}
+void KeyboardTranslatorReader::readNext() 
+{
+    // find next entry
+    while ( !_source->atEnd() )
+    {
+        const QList<Token>& tokens = tokenize( QString(_source->readLine()) );
+        if ( !tokens.isEmpty() && tokens.first().type == Token::KeyKeyword )
+        {
+            KeyboardTranslator::States flags = KeyboardTranslator::NoState;
+            KeyboardTranslator::States flagMask = KeyboardTranslator::NoState;
+            Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+            Qt::KeyboardModifiers modifierMask = Qt::NoModifier;
+
+            int keyCode = Qt::Key_unknown;
+
+            decodeSequence(tokens[1].text.toLower(),
+                           keyCode,
+                           modifiers,
+                           modifierMask,
+                           flags,
+                           flagMask); 
+
+            KeyboardTranslator::Command command = KeyboardTranslator::NoCommand;
+            QByteArray text;
+
+            // get text or command
+            if ( tokens[2].type == Token::OutputText )
+            {
+                text = tokens[2].text.toLocal8Bit();
+            }
+            else if ( tokens[2].type == Token::Command )
+            {
+                // identify command
+                if (!parseAsCommand(tokens[2].text,command))
+                    qDebug() << "Command" << tokens[2].text << "not understood.";
+            }
+
+            KeyboardTranslator::Entry newEntry;
+            newEntry.setKeyCode( keyCode );
+            newEntry.setState( flags );
+            newEntry.setStateMask( flagMask );
+            newEntry.setModifiers( modifiers );
+            newEntry.setModifierMask( modifierMask );
+            newEntry.setText( text );
+            newEntry.setCommand( command );
+
+            _nextEntry = newEntry;
+
+            _hasNext = true;
+
+            return;
+        }
+    } 
+
+    _hasNext = false;
+}
+
+bool KeyboardTranslatorReader::parseAsCommand(const QString& text,KeyboardTranslator::Command& command) 
+{
+    if ( text.compare("erase",Qt::CaseInsensitive) == 0 )
+        command = KeyboardTranslator::EraseCommand;
+    else if ( text.compare("scrollpageup",Qt::CaseInsensitive) == 0 )
+        command = KeyboardTranslator::ScrollPageUpCommand;
+    else if ( text.compare("scrollpagedown",Qt::CaseInsensitive) == 0 )
+        command = KeyboardTranslator::ScrollPageDownCommand;
+    else if ( text.compare("scrolllineup",Qt::CaseInsensitive) == 0 )
+        command = KeyboardTranslator::ScrollLineUpCommand;
+    else if ( text.compare("scrolllinedown",Qt::CaseInsensitive) == 0 )
+        command = KeyboardTranslator::ScrollLineDownCommand;
+    else if ( text.compare("scrolllock",Qt::CaseInsensitive) == 0 )
+        command = KeyboardTranslator::ScrollLockCommand;
+    else
+        return false;
+
+    return true;
+}
+
+bool KeyboardTranslatorReader::decodeSequence(const QString& text,
+                                              int& keyCode,
+                                              Qt::KeyboardModifiers& modifiers,
+                                              Qt::KeyboardModifiers& modifierMask,
+                                              KeyboardTranslator::States& flags,
+                                              KeyboardTranslator::States& flagMask)
+{
+    bool isWanted = true; 
+    bool endOfItem = false;
+    QString buffer;
+
+    Qt::KeyboardModifiers tempModifiers = modifiers;
+    Qt::KeyboardModifiers tempModifierMask = modifierMask;
+    KeyboardTranslator::States tempFlags = flags;
+    KeyboardTranslator::States tempFlagMask = flagMask;
+
+    for ( int i = 0 ; i < text.count() ; i++ )
+    {
+        const QChar& ch = text[i];
+        bool isFirstLetter = i == 0;
+        bool isLastLetter = ( i == text.count()-1 );
+        endOfItem = true;
+        if ( ch.isLetterOrNumber() )
+        {
+            endOfItem = false;
+            buffer.append(ch);
+        } else if ( isFirstLetter )
+        {
+            buffer.append(ch);
+        }
+
+        if ( (endOfItem || isLastLetter) && !buffer.isEmpty() )
+        {
+            Qt::KeyboardModifier itemModifier = Qt::NoModifier;
+            int itemKeyCode = 0;
+            KeyboardTranslator::State itemFlag = KeyboardTranslator::NoState;
+
+            if ( parseAsModifier(buffer,itemModifier) )
+            {
+                tempModifierMask |= itemModifier;
+
+                if ( isWanted )
+                    tempModifiers |= itemModifier;
+            }
+            else if ( parseAsStateFlag(buffer,itemFlag) )
+            {
+                tempFlagMask |= itemFlag;
+
+                if ( isWanted )
+                    tempFlags |= itemFlag;
+            }
+            else if ( parseAsKeyCode(buffer,itemKeyCode) )
+                keyCode = itemKeyCode;
+            else
+                qDebug() << "Unable to parse key binding item:" << buffer;
+
+            buffer.clear();
+        }
+
+        // check if this is a wanted / not-wanted flag and update the 
+        // state ready for the next item
+        if ( ch == '+' )
+           isWanted = true;
+        else if ( ch == '-' )
+           isWanted = false; 
+    } 
+
+    modifiers = tempModifiers;
+    modifierMask = tempModifierMask;
+    flags = tempFlags;
+    flagMask = tempFlagMask;
+
+    return true;
+}
+
+bool KeyboardTranslatorReader::parseAsModifier(const QString& item , Qt::KeyboardModifier& modifier)
+{
+    if ( item == "shift" )
+        modifier = Qt::ShiftModifier;
+    else if ( item == "ctrl" || item == "control" )
+        modifier = Qt::ControlModifier;
+    else if ( item == "alt" )
+        modifier = Qt::AltModifier;
+    else if ( item == "meta" )
+        modifier = Qt::MetaModifier;
+    else if ( item == "keypad" )
+        modifier = Qt::KeypadModifier;
+    else
+        return false;
+
+    return true;
+}
+bool KeyboardTranslatorReader::parseAsStateFlag(const QString& item , KeyboardTranslator::State& flag)
+{
+    if ( item == "appcukeys" || item == "appcursorkeys" )
+        flag = KeyboardTranslator::CursorKeysState;
+    else if ( item == "ansi" )
+        flag = KeyboardTranslator::AnsiState;
+    else if ( item == "newline" )
+        flag = KeyboardTranslator::NewLineState;
+    else if ( item == "appscreen" )
+        flag = KeyboardTranslator::AlternateScreenState;
+    else if ( item == "anymod" || item == "anymodifier" )
+        flag = KeyboardTranslator::AnyModifierState;
+    else if ( item == "appkeypad" )
+        flag = KeyboardTranslator::ApplicationKeypadState;
+    else
+        return false;
+
+    return true;
+}
+bool KeyboardTranslatorReader::parseAsKeyCode(const QString& item , int& keyCode)
+{
+    QKeySequence sequence = QKeySequence::fromString(item);
+    if ( !sequence.isEmpty() )
+    {
+        keyCode = sequence[0];
+
+        if ( sequence.count() > 1 )
+        {
+            qDebug() << "Unhandled key codes in sequence: " << item;
+        }
+    }
+    // additional cases implemented for backwards compatibility with KDE 3
+    else if ( item == "prior" )
+        keyCode = Qt::Key_PageUp;
+    else if ( item == "next" )
+        keyCode = Qt::Key_PageDown;
+    else
+        return false;
+
+    return true;
+}
+
+QString KeyboardTranslatorReader::description() const
+{
+    return _description;
+}
+bool KeyboardTranslatorReader::hasNextEntry()
+{
+    return _hasNext;
+}
+KeyboardTranslator::Entry KeyboardTranslatorReader::createEntry( const QString& condition , 
+                                                                 const QString& result )
+{
+    QString entryString("keyboard \"temporary\"\nkey ");
+    entryString.append(condition);
+    entryString.append(" : ");
+
+    // if 'result' is the name of a command then the entry result will be that command,
+    // otherwise the result will be treated as a string to echo when the key sequence
+    // specified by 'condition' is pressed
+    KeyboardTranslator::Command command;
+    if (parseAsCommand(result,command))
+        entryString.append(result);
+    else
+        entryString.append('\"' + result + '\"');
+
+    QByteArray array = entryString.toUtf8();
+    QBuffer buffer(&array);
+    buffer.open(QIODevice::ReadOnly);
+    KeyboardTranslatorReader reader(&buffer);
+
+    KeyboardTranslator::Entry entry;
+    if ( reader.hasNextEntry() )
+        entry = reader.nextEntry();
+
+    return entry;
+}
+
+KeyboardTranslator::Entry KeyboardTranslatorReader::nextEntry() 
+{
+    Q_ASSERT( _hasNext );
+    KeyboardTranslator::Entry entry = _nextEntry;
+    readNext();
+    return entry;
+}
+bool KeyboardTranslatorReader::parseError()
+{
+    return false;
+}
+QList<KeyboardTranslatorReader::Token> KeyboardTranslatorReader::tokenize(const QString& line)
+{
+    QString text = line;
+
+    // remove comments 
+    bool inQuotes = false;
+    int commentPos = -1;
+    for (int i=text.length()-1;i>=0;i--)
+    {
+        QChar ch = text[i];
+        if (ch == '\"')
+            inQuotes = !inQuotes;
+        else if (ch == '#' && !inQuotes)
+            commentPos = i;
+    }
+    if (commentPos != -1)
+        text.remove(commentPos,text.length());
+
+    text = text.simplified();
+   
+    // title line: keyboard "title"
+    static QRegExp title("keyboard\\s+\"(.*)\"");
+    // key line: key KeySequence : "output"
+    // key line: key KeySequence : command
+    static QRegExp key("key\\s+([\\w\\+\\s\\-\\*\\.]+)\\s*:\\s*(\"(.*)\"|\\w+)");
+
+    QList<Token> list;
+    if ( text.isEmpty() ) 
+    {
+        return list;
+    }
+
+    if ( title.exactMatch(text) )
+    {
+        Token titleToken = { Token::TitleKeyword , QString() };
+        Token textToken = { Token::TitleText , title.capturedTexts()[1] };
+    
+        list << titleToken << textToken;
+    }
+    else if  ( key.exactMatch(text) )
+    {
+        Token keyToken = { Token::KeyKeyword , QString() };
+        Token sequenceToken = { Token::KeySequence , key.capturedTexts()[1].remove(' ') };
+
+        list << keyToken << sequenceToken;
+
+        if ( key.capturedTexts()[3].isEmpty() )
+        {
+            // capturedTexts()[2] is a command
+            Token commandToken = { Token::Command , key.capturedTexts()[2] };
+            list << commandToken;    
+        }   
+        else
+        {
+            // capturedTexts()[3] is the output string
+           Token outputToken = { Token::OutputText , key.capturedTexts()[3] };
+           list << outputToken;
+        }    
+    }
+    else
+    {
+        qDebug() << "Line in keyboard translator file could not be understood:" << text;
+    }
+
+    return list;
+}
+
+QList<QString> KeyboardTranslatorManager::allTranslators() 
+{
+    if ( !_haveLoadedAll )
+    {
+        findTranslators();
+    }
+
+    return _translators.keys();
+}
+
+KeyboardTranslator::Entry::Entry()
+: _keyCode(0)
+, _modifiers(Qt::NoModifier)
+, _modifierMask(Qt::NoModifier)
+, _state(NoState)
+, _stateMask(NoState)
+, _command(NoCommand)
+{
+}
+
+bool KeyboardTranslator::Entry::operator==(const Entry& rhs) const
+{
+    return _keyCode == rhs._keyCode &&
+           _modifiers == rhs._modifiers &&
+           _modifierMask == rhs._modifierMask &&
+           _state == rhs._state &&
+           _stateMask == rhs._stateMask &&
+           _command == rhs._command &&
+           _text == rhs._text;
+}
+
+bool KeyboardTranslator::Entry::matches(int keyCode , 
+                                        Qt::KeyboardModifiers modifiers,
+                                        States testState) const
+{
+    if ( _keyCode != keyCode )
+        return false;
+
+    if ( (modifiers & _modifierMask) != (_modifiers & _modifierMask) ) 
+        return false;
+
+    // if modifiers is non-zero, the 'any modifier' state is implicit
+    if ( modifiers != 0 )
+        testState |= AnyModifierState;
+
+    if ( (testState & _stateMask) != (_state & _stateMask) )
+        return false;
+
+    // special handling for the 'Any Modifier' state, which checks for the presence of 
+    // any or no modifiers.  In this context, the 'keypad' modifier does not count.
+    bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier;
+    bool wantAnyModifier = _state & KeyboardTranslator::AnyModifierState;
+    if ( _stateMask & KeyboardTranslator::AnyModifierState )
+    {
+        if ( wantAnyModifier != anyModifiersSet )
+           return false;
+    }
+    
+    return true;
+}
+QByteArray KeyboardTranslator::Entry::escapedText(bool expandWildCards,Qt::KeyboardModifiers modifiers) const
+{
+    QByteArray result(text(expandWildCards,modifiers));
+
+    for ( int i = 0 ; i < result.count() ; i++ )
+    {
+        char ch = result[i];
+        char replacement = 0;
+
+        switch ( ch )
+        {
+            case 27 : replacement = 'E'; break;
+            case 8  : replacement = 'b'; break;
+            case 12 : replacement = 'f'; break;
+            case 9  : replacement = 't'; break;
+            case 13 : replacement = 'r'; break;
+            case 10 : replacement = 'n'; break;
+            default:
+                // any character which is not printable is replaced by an equivalent
+                // \xhh escape sequence (where 'hh' are the corresponding hex digits)
+                if ( !QChar(ch).isPrint() )
+                    replacement = 'x';
+        }
+
+        if ( replacement == 'x' )
+        {
+            result.replace(i,1,"\\x"+QByteArray(1,ch).toHex()); 
+        } else if ( replacement != 0 )
+        {
+            result.remove(i,1);
+            result.insert(i,'\\');
+            result.insert(i+1,replacement);
+        }
+    }
+
+    return result;
+}
+QByteArray KeyboardTranslator::Entry::unescape(const QByteArray& input) const
+{
+    QByteArray result(input);
+
+    for ( int i = 0 ; i < result.count()-1 ; i++ )
+    {
+
+        QByteRef ch = result[i];
+        if ( ch == '\\' )
+        {
+           char replacement[2] = {0,0};
+           int charsToRemove = 2;
+           bool escapedChar = true;
+
+           switch ( result[i+1] )
+           {
+              case 'E' : replacement[0] = 27; break;
+              case 'b' : replacement[0] = 8 ; break;
+              case 'f' : replacement[0] = 12; break;
+              case 't' : replacement[0] = 9 ; break;
+              case 'r' : replacement[0] = 13; break;
+              case 'n' : replacement[0] = 10; break;
+              case 'x' :
+                 {
+                    // format is \xh or \xhh where 'h' is a hexadecimal
+                    // digit from 0-9 or A-F which should be replaced
+                    // with the corresponding character value
+                    char hexDigits[3] = {0};
+
+                    if ( (i < result.count()-2) && isxdigit(result[i+2]) )
+                            hexDigits[0] = result[i+2];
+                    if ( (i < result.count()-3) && isxdigit(result[i+3]) )
+                            hexDigits[1] = result[i+3];
+
+                    unsigned charValue = 0;
+                    sscanf(hexDigits,"%x",&charValue);
+
+                    replacement[0] = (char)charValue; 
+                    charsToRemove = 2 + strlen(hexDigits);
+                  }
+              break;
+              default:
+                  escapedChar = false;
+           }
+
+           if ( escapedChar )
+               result.replace(i,charsToRemove,replacement);
+        }
+    }
+
+    return result;
+}
+
+void KeyboardTranslator::Entry::insertModifier( QString& item , int modifier ) const
+{
+    if ( !(modifier & _modifierMask) )
+        return;
+
+    if ( modifier & _modifiers )
+        item += '+';
+    else
+        item += '-';
+
+    if ( modifier == Qt::ShiftModifier )
+        item += "Shift";
+    else if ( modifier == Qt::ControlModifier )
+        item += "Ctrl";
+    else if ( modifier == Qt::AltModifier )
+        item += "Alt";
+    else if ( modifier == Qt::MetaModifier )
+        item += "Meta";
+    else if ( modifier == Qt::KeypadModifier )
+        item += "KeyPad";
+}
+void KeyboardTranslator::Entry::insertState( QString& item , int state ) const
+{
+    if ( !(state & _stateMask) )
+        return;
+
+    if ( state & _state )
+        item += '+' ;
+    else
+        item += '-' ;
+
+    if ( state == KeyboardTranslator::AlternateScreenState )
+        item += "AppScreen";
+    else if ( state == KeyboardTranslator::NewLineState )
+        item += "NewLine";
+    else if ( state == KeyboardTranslator::AnsiState )
+        item += "Ansi";
+    else if ( state == KeyboardTranslator::CursorKeysState )
+        item += "AppCursorKeys";
+    else if ( state == KeyboardTranslator::AnyModifierState )
+        item += "AnyModifier";
+    else if ( state == KeyboardTranslator::ApplicationKeypadState )
+        item += "AppKeypad";
+}
+QString KeyboardTranslator::Entry::resultToString(bool expandWildCards,Qt::KeyboardModifiers modifiers) const
+{
+    if ( !_text.isEmpty() )
+        return escapedText(expandWildCards,modifiers);
+    else if ( _command == EraseCommand )
+        return "Erase";
+    else if ( _command == ScrollPageUpCommand )
+        return "ScrollPageUp";
+    else if ( _command == ScrollPageDownCommand )
+        return "ScrollPageDown";
+    else if ( _command == ScrollLineUpCommand )
+        return "ScrollLineUp";
+    else if ( _command == ScrollLineDownCommand )
+        return "ScrollLineDown";
+    else if ( _command == ScrollLockCommand )
+        return "ScrollLock";
+
+    return QString();
+}
+QString KeyboardTranslator::Entry::conditionToString() const
+{
+    QString result = QKeySequence(_keyCode).toString();
+
+    insertModifier( result , Qt::ShiftModifier );
+    insertModifier( result , Qt::ControlModifier );
+    insertModifier( result , Qt::AltModifier );
+    insertModifier( result , Qt::MetaModifier );
+    insertModifier( result , Qt::KeypadModifier );
+
+    insertState( result , KeyboardTranslator::AlternateScreenState );
+    insertState( result , KeyboardTranslator::NewLineState );
+    insertState( result , KeyboardTranslator::AnsiState );
+    insertState( result , KeyboardTranslator::CursorKeysState );
+    insertState( result , KeyboardTranslator::AnyModifierState );
+    insertState( result , KeyboardTranslator::ApplicationKeypadState );
+
+    return result;
+}
+
+KeyboardTranslator::KeyboardTranslator(const QString& name)
+: _name(name)
+{
+}
+
+void KeyboardTranslator::setDescription(const QString& description) 
+{
+    _description = description;
+}
+QString KeyboardTranslator::description() const
+{
+    return _description;
+}
+void KeyboardTranslator::setName(const QString& name)
+{
+    _name = name;
+}
+QString KeyboardTranslator::name() const
+{
+    return _name;
+}
+
+QList<KeyboardTranslator::Entry> KeyboardTranslator::entries() const
+{
+    return _entries.values();
+}
+
+void KeyboardTranslator::addEntry(const Entry& entry)
+{
+    const int keyCode = entry.keyCode();
+    _entries.insert(keyCode,entry);
+}
+void KeyboardTranslator::replaceEntry(const Entry& existing , const Entry& replacement)
+{
+    if ( !existing.isNull() )
+        _entries.remove(existing.keyCode(),existing);
+    _entries.insert(replacement.keyCode(),replacement);
+}
+void KeyboardTranslator::removeEntry(const Entry& entry)
+{
+    _entries.remove(entry.keyCode(),entry);
+}
+KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state) const
+{
+    foreach(const Entry& entry, _entries.values(keyCode))
+    {
+        if ( entry.matches(keyCode,modifiers,state) )
+            return entry;
+    }
+    return Entry(); // entry not found
+}
+void KeyboardTranslatorManager::addTranslator(KeyboardTranslator* translator)
+{
+    _translators.insert(translator->name(),translator);
+
+    if ( !saveTranslator(translator) )
+        qDebug() << "Unable to save translator" << translator->name()
+                   << "to disk.";
+}
+bool KeyboardTranslatorManager::deleteTranslator(const QString& name)
+{
+    Q_ASSERT( _translators.contains(name) );
+
+    // locate and delete
+    QString path = findTranslatorPath(name);
+    if ( QFile::remove(path) )
+    {
+        _translators.remove(name);
+        return true; 
+    }
+    else
+    {
+        qDebug() << "Failed to remove translator - " << path;
+        return false;
+    }
+}
+//K_GLOBAL_STATIC( KeyboardTranslatorManager , theKeyboardTranslatorManager )
+KeyboardTranslatorManager* KeyboardTranslatorManager::theKeyboardTranslatorManager = 0;
+KeyboardTranslatorManager* KeyboardTranslatorManager::instance()
+{
+    if (! theKeyboardTranslatorManager)
+        theKeyboardTranslatorManager = new KeyboardTranslatorManager();
+    return theKeyboardTranslatorManager;
+}

=== added file 'src/KeyboardTranslator.h'
--- src/KeyboardTranslator.h	1970-01-01 00:00:00 +0000
+++ src/KeyboardTranslator.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,584 @@
+/*
+    This source file is part of Konsole, a terminal emulator.
+
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+#ifndef KEYBOARDTRANSLATOR_H
+#define KEYBOARDTRANSLATOR_H
+
+// Qt
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtGui/QKeySequence>
+#include <QtCore/QMetaType>
+#include <QtCore/QVarLengthArray>
+
+// Konsole
+//#include "konsole_export.h"
+#define KONSOLEPRIVATE_EXPORT
+
+class QIODevice;
+class QTextStream;
+
+
+/** 
+ * A convertor which maps between key sequences pressed by the user and the
+ * character strings which should be sent to the terminal and commands
+ * which should be invoked when those character sequences are pressed.
+ *
+ * Konsole supports multiple keyboard translators, allowing the user to
+ * specify the character sequences which are sent to the terminal
+ * when particular key sequences are pressed.
+ *
+ * A key sequence is defined as a key code, associated keyboard modifiers
+ * (Shift,Ctrl,Alt,Meta etc.) and state flags which indicate the state
+ * which the terminal must be in for the key sequence to apply.
+ */
+class KeyboardTranslator
+{
+public:
+    /** 
+     * The meaning of a particular key sequence may depend upon the state which
+     * the terminal emulation is in.  Therefore findEntry() may return a different
+     * Entry depending upon the state flags supplied.
+     *
+     * This enum describes the states which may be associated with with a particular
+     * entry in the keyboard translation entry.
+     */
+    enum State
+    {
+        /** Indicates that no special state is active */
+        NoState = 0,
+        /**
+         * TODO More documentation
+         */
+        NewLineState = 1,
+        /** 
+         * Indicates that the terminal is in 'Ansi' mode.
+         * TODO: More documentation
+         */
+        AnsiState = 2,
+        /**
+         * TODO More documentation
+         */
+        CursorKeysState = 4,
+        /**
+         * Indicates that the alternate screen ( typically used by interactive programs
+         * such as screen or vim ) is active 
+         */
+        AlternateScreenState = 8,
+        /** Indicates that any of the modifier keys is active. */ 
+        AnyModifierState = 16,
+        /** Indicates that the numpad is in application mode. */
+        ApplicationKeypadState = 32
+    };
+    Q_DECLARE_FLAGS(States,State)
+
+    /**
+     * This enum describes commands which are associated with particular key sequences.
+     */
+    enum Command
+    {
+        /** Indicates that no command is associated with this command sequence */
+        NoCommand = 0,
+        /** TODO Document me */
+        SendCommand = 1,
+        /** Scroll the terminal display up one page */
+        ScrollPageUpCommand = 2,
+        /** Scroll the terminal display down one page */
+        ScrollPageDownCommand = 4,
+        /** Scroll the terminal display up one line */
+        ScrollLineUpCommand = 8,
+        /** Scroll the terminal display down one line */
+        ScrollLineDownCommand = 16,
+        /** Toggles scroll lock mode */
+        ScrollLockCommand = 32,
+        /** Echos the operating system specific erase character. */
+        EraseCommand = 64
+    };
+    Q_DECLARE_FLAGS(Commands,Command)
+
+    /**
+     * Represents an association between a key sequence pressed by the user
+     * and the character sequence and commands associated with it for a particular
+     * KeyboardTranslator.
+     */
+    class Entry
+    {
+    public:
+        /** 
+         * Constructs a new entry for a keyboard translator.
+         */
+        Entry();
+
+        /** 
+         * Returns true if this entry is null.
+         * This is true for newly constructed entries which have no properties set. 
+         */
+        bool isNull() const;
+
+        /** Returns the commands associated with this entry */
+        Command command() const;
+        /** Sets the command associated with this entry. */
+        void setCommand(Command command);
+
+        /** 
+         * Returns the character sequence associated with this entry, optionally replacing 
+         * wildcard '*' characters with numbers to indicate the keyboard modifiers being pressed.
+         *
+         * TODO: The numbers used to replace '*' characters are taken from the Konsole/KDE 3 code.
+         * Document them. 
+         *
+         * @param expandWildCards Specifies whether wild cards (occurrences of the '*' character) in
+         * the entry should be replaced with a number to indicate the modifier keys being pressed. 
+         *
+         * @param modifiers The keyboard modifiers being pressed.
+         */
+        QByteArray text(bool expandWildCards = false,
+                        Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
+
+        /** Sets the character sequence associated with this entry */
+        void setText(const QByteArray& text);
+
+        /** 
+         * Returns the character sequence associated with this entry,
+         * with any non-printable characters replaced with escape sequences.
+         *
+         * eg. \\E for Escape, \\t for tab, \\n for new line.
+         *
+         * @param expandWildCards See text()
+         * @param modifiers See text()
+         */
+        QByteArray escapedText(bool expandWildCards = false,
+                               Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
+
+        /** Returns the character code ( from the Qt::Key enum ) associated with this entry */
+        int keyCode() const;
+        /** Sets the character code associated with this entry */
+        void setKeyCode(int keyCode);
+
+        /** 
+         * Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry. 
+         * If a modifier is set in modifierMask() but not in modifiers(), this means that the entry
+         * only matches when that modifier is NOT pressed.
+         *
+         * If a modifier is not set in modifierMask() then the entry matches whether the modifier
+         * is pressed or not. 
+         */
+        Qt::KeyboardModifiers modifiers() const;
+
+        /** Returns the keyboard modifiers which are valid in this entry.  See modifiers() */
+        Qt::KeyboardModifiers modifierMask() const;
+
+        /** See modifiers() */
+        void setModifiers( Qt::KeyboardModifiers modifiers );
+        /** See modifierMask() and modifiers() */
+        void setModifierMask( Qt::KeyboardModifiers modifiers );
+
+        /** 
+         * Returns a bitwise-OR of the enabled state flags associated with this entry. 
+         * If flag is set in stateMask() but not in state(), this means that the entry only 
+         * matches when the terminal is NOT in that state.
+         *
+         * If a state is not set in stateMask() then the entry matches whether the terminal
+         * is in that state or not. 
+         */
+        States state() const;
+
+        /** Returns the state flags which are valid in this entry.  See state() */
+        States stateMask() const;
+
+        /** See state() */
+        void setState( States state );
+        /** See stateMask() */
+        void setStateMask( States mask );
+
+        /** 
+         * Returns the key code and modifiers associated with this entry 
+         * as a QKeySequence
+         */
+        //QKeySequence keySequence() const;
+
+        /** 
+         * Returns this entry's conditions ( ie. its key code, modifier and state criteria )
+         * as a string.
+         */
+        QString conditionToString() const;
+
+        /**
+         * Returns this entry's result ( ie. its command or character sequence )
+         * as a string.
+         *
+         * @param expandWildCards See text()
+         * @param modifiers See text()
+         */
+        QString resultToString(bool expandWildCards = false,
+                               Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
+
+        /** 
+         * Returns true if this entry matches the given key sequence, specified
+         * as a combination of @p keyCode , @p modifiers and @p state.
+         */
+        bool matches( int keyCode , 
+                      Qt::KeyboardModifiers modifiers , 
+                      States flags ) const;
+
+        bool operator==(const Entry& rhs) const;
+       
+    private:
+        void insertModifier( QString& item , int modifier ) const;
+        void insertState( QString& item , int state ) const;
+        QByteArray unescape(const QByteArray& text) const;
+
+        int _keyCode;
+        Qt::KeyboardModifiers _modifiers;
+        Qt::KeyboardModifiers _modifierMask;
+        States _state;
+        States _stateMask;
+
+        Command _command;
+        QByteArray _text;
+    };
+
+    /** Constructs a new keyboard translator with the given @p name */
+    KeyboardTranslator(const QString& name);
+   
+    //KeyboardTranslator(const KeyboardTranslator& other);
+
+    /** Returns the name of this keyboard translator */
+    QString name() const;
+
+    /** Sets the name of this keyboard translator */
+    void setName(const QString& name);
+
+    /** Returns the descriptive name of this keyboard translator */
+    QString description() const;
+
+    /** Sets the descriptive name of this keyboard translator */
+    void setDescription(const QString& description);
+
+    /**
+     * Looks for an entry in this keyboard translator which matches the given
+     * key code, keyboard modifiers and state flags.
+     * 
+     * Returns the matching entry if found or a null Entry otherwise ( ie.
+     * entry.isNull() will return true )
+     *
+     * @param keyCode A key code from the Qt::Key enum
+     * @param modifiers A combination of modifiers
+     * @param state Optional flags which specify the current state of the terminal
+     */
+    Entry findEntry(int keyCode , 
+                    Qt::KeyboardModifiers modifiers , 
+                    States state = NoState) const;
+
+    /** 
+     * Adds an entry to this keyboard translator's table.  Entries can be looked up according
+     * to their key sequence using findEntry()
+     */
+    void addEntry(const Entry& entry);
+
+    /**
+     * Replaces an entry in the translator.  If the @p existing entry is null,
+     * then this is equivalent to calling addEntry(@p replacement)
+     */
+    void replaceEntry(const Entry& existing , const Entry& replacement);
+
+    /**
+     * Removes an entry from the table.
+     */
+    void removeEntry(const Entry& entry);
+
+    /** Returns a list of all entries in the translator. */
+    QList<Entry> entries() const;
+
+private:
+
+    QMultiHash<int,Entry> _entries; // entries in this keyboard translation,
+                                                 // entries are indexed according to
+                                                 // their keycode
+    QString _name;
+    QString _description;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::States)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::Commands)
+
+/** 
+ * Parses the contents of a Keyboard Translator (.keytab) file and 
+ * returns the entries found in it.
+ *
+ * Usage example:
+ *
+ * @code
+ *  QFile source( "/path/to/keytab" );
+ *  source.open( QIODevice::ReadOnly );
+ *
+ *  KeyboardTranslator* translator = new KeyboardTranslator( "name-of-translator" );
+ *
+ *  KeyboardTranslatorReader reader(source);
+ *  while ( reader.hasNextEntry() )
+ *      translator->addEntry(reader.nextEntry());
+ *
+ *  source.close();
+ *
+ *  if ( !reader.parseError() )
+ *  {
+ *      // parsing succeeded, do something with the translator
+ *  } 
+ *  else
+ *  {
+ *      // parsing failed
+ *  }
+ * @endcode
+ */
+class KeyboardTranslatorReader
+{
+public:
+    /** Constructs a new reader which parses the given @p source */
+    KeyboardTranslatorReader( QIODevice* source );
+
+    /** 
+     * Returns the description text. 
+     * TODO: More documentation 
+     */
+    QString description() const;
+
+    /** Returns true if there is another entry in the source stream */
+    bool hasNextEntry();
+    /** Returns the next entry found in the source stream */
+    KeyboardTranslator::Entry nextEntry(); 
+
+    /** 
+     * Returns true if an error occurred whilst parsing the input or
+     * false if no error occurred.
+     */
+    bool parseError();
+
+    /**
+     * Parses a condition and result string for a translator entry
+     * and produces a keyboard translator entry.
+     *
+     * The condition and result strings are in the same format as in  
+     */
+    static KeyboardTranslator::Entry createEntry( const QString& condition ,
+                                                  const QString& result );
+private:
+    struct Token
+    {
+        enum Type
+        {
+            TitleKeyword,
+            TitleText,
+            KeyKeyword,
+            KeySequence,
+            Command,
+            OutputText
+        };
+        Type type;
+        QString text;
+    };
+    QList<Token> tokenize(const QString&);
+    void readNext();
+    bool decodeSequence(const QString& , 
+                                int& keyCode,
+                                Qt::KeyboardModifiers& modifiers,
+                                Qt::KeyboardModifiers& modifierMask,
+                                KeyboardTranslator::States& state,
+                                KeyboardTranslator::States& stateFlags);
+
+    static bool parseAsModifier(const QString& item , Qt::KeyboardModifier& modifier);
+    static bool parseAsStateFlag(const QString& item , KeyboardTranslator::State& state);
+    static bool parseAsKeyCode(const QString& item , int& keyCode);
+       static bool parseAsCommand(const QString& text , KeyboardTranslator::Command& command);
+
+    QIODevice* _source;
+    QString _description;
+    KeyboardTranslator::Entry _nextEntry;
+    bool _hasNext;
+};
+
+/** Writes a keyboard translation to disk. */
+class KeyboardTranslatorWriter
+{
+public:
+    /** 
+     * Constructs a new writer which saves data into @p destination.
+     * The caller is responsible for closing the device when writing is complete.
+     */
+    KeyboardTranslatorWriter(QIODevice* destination);
+    ~KeyboardTranslatorWriter();
+
+    /** 
+     * Writes the header for the keyboard translator. 
+     * @param description Description of the keyboard translator. 
+     */
+    void writeHeader( const QString& description );
+    /** Writes a translator entry. */
+    void writeEntry( const KeyboardTranslator::Entry& entry ); 
+
+private:
+    QIODevice* _destination;  
+    QTextStream* _writer;
+};
+
+/**
+ * Manages the keyboard translations available for use by terminal sessions,
+ * see KeyboardTranslator.
+ */
+class KONSOLEPRIVATE_EXPORT KeyboardTranslatorManager
+{
+public:
+    /** 
+     * Constructs a new KeyboardTranslatorManager and loads the list of
+     * available keyboard translations.
+     *
+     * The keyboard translations themselves are not loaded until they are
+     * first requested via a call to findTranslator()
+     */
+    KeyboardTranslatorManager();
+    ~KeyboardTranslatorManager();
+
+    /**
+     * Adds a new translator.  If a translator with the same name 
+     * already exists, it will be replaced by the new translator.
+     *
+     * TODO: More documentation.
+     */
+    void addTranslator(KeyboardTranslator* translator);
+
+    /**
+     * Deletes a translator.  Returns true on successful deletion or false otherwise.
+     *
+     * TODO: More documentation
+     */
+    bool deleteTranslator(const QString& name);
+
+    /** Returns the default translator for Konsole. */
+    const KeyboardTranslator* defaultTranslator();
+
+    /** 
+     * Returns the keyboard translator with the given name or 0 if no translator
+     * with that name exists.
+     *
+     * The first time that a translator with a particular name is requested,
+     * the on-disk .keyboard file is loaded and parsed.  
+     */
+    const KeyboardTranslator* findTranslator(const QString& name);
+    /**
+     * Returns a list of the names of available keyboard translators.
+     *
+     * The first time this is called, a search for available 
+     * translators is started.
+     */
+    QList<QString> allTranslators();
+
+    /** Returns the global KeyboardTranslatorManager instance. */
+   static KeyboardTranslatorManager* instance();
+
+private:
+    static const QByteArray defaultTranslatorText;
+    
+    void findTranslators(); // locate the available translators
+    KeyboardTranslator* loadTranslator(const QString& name); // loads the translator 
+                                                             // with the given name
+    KeyboardTranslator* loadTranslator(QIODevice* device,const QString& name);
+
+    bool saveTranslator(const KeyboardTranslator* translator);
+    QString findTranslatorPath(const QString& name);
+    
+    QHash<QString,KeyboardTranslator*> _translators; // maps translator-name -> KeyboardTranslator
+                                                     // instance
+    bool _haveLoadedAll;
+
+    static KeyboardTranslatorManager * theKeyboardTranslatorManager;
+};
+
+inline int KeyboardTranslator::Entry::keyCode() const { return _keyCode; }
+inline void KeyboardTranslator::Entry::setKeyCode(int keyCode) { _keyCode = keyCode; }
+
+inline void KeyboardTranslator::Entry::setModifiers( Qt::KeyboardModifiers modifier ) 
+{ 
+    _modifiers = modifier;
+}
+inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifiers() const { return _modifiers; }
+
+inline void  KeyboardTranslator::Entry::setModifierMask( Qt::KeyboardModifiers mask ) 
+{ 
+   _modifierMask = mask; 
+}
+inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifierMask() const { return _modifierMask; }
+
+inline bool KeyboardTranslator::Entry::isNull() const
+{
+    return ( *this == Entry() );
+}
+
+inline void KeyboardTranslator::Entry::setCommand( Command command )
+{ 
+    _command = command; 
+}
+inline KeyboardTranslator::Command KeyboardTranslator::Entry::command() const { return _command; }
+
+inline void KeyboardTranslator::Entry::setText( const QByteArray& text )
+{ 
+    _text = unescape(text);
+}
+inline int oneOrZero(int value)
+{
+    return value ? 1 : 0;
+}
+inline QByteArray KeyboardTranslator::Entry::text(bool expandWildCards,Qt::KeyboardModifiers modifiers) const 
+{
+    QByteArray expandedText = _text;
+    
+    if (expandWildCards)
+    {
+        int modifierValue = 1;
+        modifierValue += oneOrZero(modifiers & Qt::ShiftModifier);
+        modifierValue += oneOrZero(modifiers & Qt::AltModifier)     << 1;
+        modifierValue += oneOrZero(modifiers & Qt::ControlModifier) << 2;
+
+        for (int i=0;i<_text.length();i++) 
+        {
+            if (expandedText[i] == '*')
+                expandedText[i] = '0' + modifierValue;
+        }
+    }
+
+    return expandedText; 
+}
+
+inline void KeyboardTranslator::Entry::setState( States state )
+{ 
+    _state = state; 
+}
+inline KeyboardTranslator::States KeyboardTranslator::Entry::state() const { return _state; }
+
+inline void KeyboardTranslator::Entry::setStateMask( States stateMask )
+{ 
+    _stateMask = stateMask; 
+}
+inline KeyboardTranslator::States KeyboardTranslator::Entry::stateMask() const { return _stateMask; }
+
+
+Q_DECLARE_METATYPE(KeyboardTranslator::Entry)
+Q_DECLARE_METATYPE(const KeyboardTranslator*)
+
+#endif // KEYBOARDTRANSLATOR_H
+

=== added file 'src/LineFont.h'
--- src/LineFont.h	1970-01-01 00:00:00 +0000
+++ src/LineFont.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,21 @@
+// WARNING: Autogenerated by "fontembedder ./linefont.src".
+// You probably do not want to hand-edit this!
+
+static const quint32 LineChars[] = {
+    0x00007c00, 0x000fffe0, 0x00421084, 0x00e739ce, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00427000, 0x004e7380, 0x00e77800, 0x00ef7bc0,
+    0x00421c00, 0x00439ce0, 0x00e73c00, 0x00e7bde0, 0x00007084, 0x000e7384, 0x000079ce, 0x000f7bce,
+    0x00001c84, 0x00039ce4, 0x00003dce, 0x0007bdee, 0x00427084, 0x004e7384, 0x004279ce, 0x00e77884,
+    0x00e779ce, 0x004f7bce, 0x00ef7bc4, 0x00ef7bce, 0x00421c84, 0x00439ce4, 0x00423dce, 0x00e73c84,
+    0x00e73dce, 0x0047bdee, 0x00e7bde4, 0x00e7bdee, 0x00427c00, 0x0043fce0, 0x004e7f80, 0x004fffe0,
+    0x004fffe0, 0x00e7fde0, 0x006f7fc0, 0x00efffe0, 0x00007c84, 0x0003fce4, 0x000e7f84, 0x000fffe4,
+    0x00007dce, 0x0007fdee, 0x000f7fce, 0x000fffee, 0x00427c84, 0x0043fce4, 0x004e7f84, 0x004fffe4,
+    0x00427dce, 0x00e77c84, 0x00e77dce, 0x0047fdee, 0x004e7fce, 0x00e7fde4, 0x00ef7f84, 0x004fffee,
+    0x00efffe4, 0x00e7fdee, 0x00ef7fce, 0x00efffee, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+    0x000f83e0, 0x00a5294a, 0x004e1380, 0x00a57800, 0x00ad0bc0, 0x004390e0, 0x00a53c00, 0x00a5a1e0,
+    0x000e1384, 0x0000794a, 0x000f0b4a, 0x000390e4, 0x00003d4a, 0x0007a16a, 0x004e1384, 0x00a5694a,
+    0x00ad2b4a, 0x004390e4, 0x00a52d4a, 0x00a5a16a, 0x004f83e0, 0x00a57c00, 0x00ad83e0, 0x000f83e4,
+    0x00007d4a, 0x000f836a, 0x004f93e4, 0x00a57d4a, 0x00ad836a, 0x00000000, 0x00000000, 0x00000000,
+    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00001c00, 0x00001084, 0x00007000, 0x00421000,
+    0x00039ce0, 0x000039ce, 0x000e7380, 0x00e73800, 0x000e7f80, 0x00e73884, 0x0003fce0, 0x004239ce
+};

=== added file 'src/LineFont.src'
--- src/LineFont.src	1970-01-01 00:00:00 +0000
+++ src/LineFont.src	2017-09-09 05:25:54 +0000
@@ -0,0 +1,786 @@
+#2500: single horizontal line
+2500
+     
+     
+-----
+     
+     
+
+#2501: triple horizontal line
+2501
+     
+-----
+-----
+-----
+     
+
+#2502: single vertical line
+2502
+  |  
+  |  
+  |  
+  |  
+  |  
+
+#2503: triple vertical line
+2503
+ ||| 
+ ||| 
+ ||| 
+ ||| 
+ ||| 
+
+#2504-250B are dashed - not handled
+
+#250C: top-left corner (lines on bottom + right)
+250C
+     
+     
+  .--
+  |  
+  |  
+
+#250D: as above, but top line triple-width
+250D
+     
+  .--
+  .--
+  |--
+  |  
+
+#250E: now the vert line triple-width
+250E
+     
+     
+ ..--
+ ||| 
+ ||| 
+
+#250F: and now both lines triple-width
+250F
+     
+ .___
+ |.--
+ ||._
+ ||| 
+
+#2510: top-right corner
+2510
+     
+     
+--.  
+  |  
+  |  
+
+2511
+     
+==.  
+==.  
+==|  
+  | 
+
+2512
+     
+     
+==.. 
+ ||| 
+ ||| 
+
+2513
+     
+===. 
+==.| 
+=.|| 
+ ||| 
+
+#2514: bottom-left corner
+2514
+  |  
+  |  
+  .==
+     
+     
+
+2515
+  |  
+  |==
+  |==
+  ===
+     
+
+
+2516
+ ||| 
+ ||| 
+ |.==
+     
+     
+
+2517
+ ||| 
+ ||.=
+ |.==
+ .===
+     
+
+#2518: bottm-right corner
+2518
+  |  
+  |  
+==.  
+     
+     
+
+2519
+  |  
+==|  
+==|  
+===  
+     
+
+
+251A
+ ||| 
+ ||| 
+==== 
+     
+     
+
+251B
+ ||| 
+=.|| 
+==.| 
+===. 
+     
+
+#251C: Join of vertical line and one from the right
+251C
+  |  
+  |  
+  |==
+  |  
+  |  
+
+251D
+  |  
+  |==
+  |==
+  |==
+  |  
+
+251E
+ ||| 
+ ||| 
+ ||==
+  |  
+  |  
+
+251F
+  |  
+  |  
+ ||==
+ ||| 
+ ||| 
+
+
+2520
+ ||| 
+ ||| 
+ ||==
+ ||| 
+ ||| 
+
+2521
+ ||| 
+ |||=
+ ||==
+ .|==
+  |  
+
+2522
+  |  
+ .|==
+ ||==
+ |||=
+ ||| 
+
+2523
+ ||| 
+ ||.=
+ ||==
+ ||.=
+ ||| 
+
+#2524: Join of vertical line and one from the left
+2524
+  |  
+  |  
+==|  
+  |  
+  |  
+
+2525
+  |  
+==|  
+==|  
+==|  
+  |  
+
+2526
+ ||| 
+ ||| 
+==+| 
+  |  
+  |  
+
+2527
+  |  
+  |  
+==+| 
+ ||| 
+ ||| 
+
+2528
+ ||| 
+ ||| 
+==+| 
+ ||| 
+ ||| 
+
+2529
+ ||| 
+=+|| 
+==+| 
+===+ 
+  |  
+
+252A
+  |  
+=+|| 
+==+| 
+===+ 
+ ||| 
+
+252B
+ |||
+=+|| 
+==+| 
+=+|| 
+ |||
+
+#252C: horizontal line joined to from below
+252C
+     
+     
+=====
+  |  
+  |  
+
+252D
+     
+===  
+==|==
+==|  
+  |  
+
+252E
+     
+  ===
+==|==
+  |==
+  |  
+
+252F
+     
+==+==
+==|==
+==|==
+  |  
+
+2530
+     
+=====
+=====
+==|==
+  |  
+
+2531
+     
+===| 
+==||=
+=||| 
+ ||| 
+
+2532
+     
+ |===
+=||==
+ ||==
+ ||  
+
+2533
+     
+=====
+==|==
+=+|+=
+ ||| 
+
+#2534: bottom line, connected to from top
+2534
+  |
+  |
+=====
+     
+     
+
+2535
+  |
+==|
+=====
+===  
+    
+
+2536
+  |
+  |==
+=====
+  ===
+     
+
+2537
+  |
+==|==
+=====
+=====
+     
+
+2538
+ |||
+ |||
+=====
+     
+     
+
+2539
+ |||
+==||
+=====
+===| 
+    
+
+
+253A
+ |||
+ ||==
+=|===
+ |===
+     
+
+253B
+ |||
+==|==
+=====
+=====
+     
+
+#253C: vertical + horizontal lines intersecting
+253C
+  |  
+  |  
+=====
+  |  
+  |
+
+253D
+  |  
+==|  
+=====
+==|  
+  |
+
+253E
+  |  
+  |==
+=====
+  |==
+  |
+
+253F
+  |  
+==|==
+=====
+==|==
+  |
+
+2540
+ ||| 
+ ||| 
+=====
+  |  
+  |
+
+2541
+  |  
+  |  
+=====
+ ||| 
+ |||
+
+2542
+ ||| 
+ ||| 
+=====
+ ||| 
+ |||
+
+2543
+ ||| 
+=|||
+=====
+==|+ 
+  |
+
+2544
+ ||| 
+ ||==
+=====
+  |==
+  |
+
+2545
+  |
+==|+ 
+=====
+=|||
+ ||| 
+
+2546
+  |
+  |==
+=====
+ ||==
+ ||| 
+
+2547
+ ||| 
+=|||=
+=====
+=|||=
+  | 
+
+2548
+  |  
+=|||=
+=====
+=|||=
+ |||
+
+2549
+ ||| 
+=||| 
+=====
+=||| 
+ |||
+
+254A
+ ||| 
+ |||=
+=====
+ |||=
+ |||
+
+254B
+ ||| 
+=|||=
+=====
+=|||=
+ |||
+
+#254C-254F are dashed
+2550
+     
+_____
+     
+_____
+     
+
+2551
+ | | 
+ | |
+ | |
+ | |
+ | |
+
+2552
+     
+  |--
+  |
+  |--
+  |
+
+2553
+     
+     
+ ----
+ | | 
+ | | 
+
+2554
+     
+ +---
+ |
+ + +-
+ | |
+
+2555
+     
+--+
+  |  
+--+  
+  |  
+
+2556
+    
+    
+-+-+
+ | |
+ | |
+
+2557
+     
+---+ 
+   | 
+-+ |
+ | |
+
+2558
+  |
+  +--
+  |
+  +--
+
+2559
+ | | 
+ | | 
+ +-+-
+     
+     
+
+255A
+ | | 
+ | +-
+ |   
+ +---
+     
+
+255B
+  |  
+--+  
+  | 
+--+  
+     
+
+255C
+ | | 
+ | | 
+-+-+ 
+    
+
+255D
+ | | 
+-+ | 
+   |
+---+
+    
+
+255E
+  |
+  +--
+  |
+  +--
+  |
+
+255F
+ | |
+ | |
+ | +-
+ | |
+ | |
+
+2560
+ | |
+ | +-
+ | |
+ | +-
+ | |
+
+2561
+  |
+--+
+  |
+--+
+  |
+
+2562
+ | | 
+ | |
+-+ +
+ | |
+ | |
+
+2563
+ | |
+-+ |
+   |
+-+ |
+ | |
+
+2564
+     
+-----
+     
+--+--
+  |
+
+2565
+     
+     
+-+-+-
+ | | 
+ | |
+
+2566
+     
+-----
+     
+-+ +-
+ | |
+
+2567
+  |  
+--+--
+     
+-----
+     
+
+2568
+ | | 
+ | | 
+-+-+-
+     
+     
+
+2569
+ | | 
+-+ +-
+     
+-----
+     
+
+256A
+  |  
+--+--
+  |  
+--+--
+  |
+
+256B
+ | | 
+ | | 
+-+-+-
+ | | 
+ | | 
+
+256C
+ | | 
+-+ +-
+
+-+ +-
+ | | 
+
+#256F-2570 are curly,
+#2571-2573 are slashes and X
+
+2574
+     
+     
+___  
+     
+     
+
+2575
+  |  
+  |  
+  |  
+     
+    
+
+2576
+     
+     
+  ___
+     
+     
+
+2577
+     
+    
+  |  
+  |  
+  |  
+
+2578
+     
+___  
+___  
+___  
+     
+
+2579
+ ||| 
+ ||| 
+ ||| 
+     
+    
+
+257A
+     
+  ___
+  ___
+  ___
+     
+
+257B
+     
+    
+ ||| 
+ ||| 
+ ||| 
+
+257C
+     
+  ___
+_____
+  ___
+     
+
+257D
+  |  
+  |  
+ ||| 
+ ||| 
+ ||| 
+
+257E
+     
+___  
+_____
+___  
+     
+
+257F
+ ||| 
+ ||| 
+ ||| 
+  |  
+  |  

=== added file 'src/Pty.cpp'
--- src/Pty.cpp	1970-01-01 00:00:00 +0000
+++ src/Pty.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,310 @@
+/*
+ * This file is a part of QTerminal - http://gitorious.org/qterminal
+ *
+ * This file was un-linked from KDE and modified
+ * by Maxim Bourmistrov <maxim@xxxxxxxxxxxx>
+ *
+ */
+
+/*
+    This file is part of Konsole, an X terminal.
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+// Own
+#include "Pty.h"
+
+// System
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <termios.h>
+#include <signal.h>
+
+// Qt
+#include <QtCore/QStringList>
+
+#include "kpty.h"
+#include "kptydevice.h"
+
+
+void Pty::setWindowSize(int lines, int cols)
+{
+  _windowColumns = cols;
+  _windowLines = lines;
+
+  if (pty()->masterFd() >= 0)
+    pty()->setWinSize(lines, cols);
+}
+QSize Pty::windowSize() const
+{
+    return QSize(_windowColumns,_windowLines);
+}
+
+void Pty::setFlowControlEnabled(bool enable)
+{
+  _xonXoff = enable;
+
+  if (pty()->masterFd() >= 0)
+  {
+    struct ::termios ttmode;
+    pty()->tcGetAttr(&ttmode);
+    if (!enable)
+      ttmode.c_iflag &= ~(IXOFF | IXON);
+    else
+      ttmode.c_iflag |= (IXOFF | IXON);
+    if (!pty()->tcSetAttr(&ttmode))
+      qWarning() << "Unable to set terminal attributes.";
+  }
+}
+bool Pty::flowControlEnabled() const
+{
+    if (pty()->masterFd() >= 0)
+    {
+        struct ::termios ttmode;
+        pty()->tcGetAttr(&ttmode);
+        return ttmode.c_iflag & IXOFF &&
+               ttmode.c_iflag & IXON;
+    }  
+    qWarning() << "Unable to get flow control status, terminal not connected.";
+    return false;
+}
+
+void Pty::setUtf8Mode(bool enable)
+{
+#ifdef IUTF8 // XXX not a reasonable place to check it.
+  _utf8 = enable;
+
+  if (pty()->masterFd() >= 0)
+  {
+    struct ::termios ttmode;
+    pty()->tcGetAttr(&ttmode);
+    if (!enable)
+      ttmode.c_iflag &= ~IUTF8;
+    else
+      ttmode.c_iflag |= IUTF8;
+    if (!pty()->tcSetAttr(&ttmode))
+      qWarning() << "Unable to set terminal attributes.";
+  }
+#endif
+}
+
+void Pty::setErase(char erase)
+{
+  _eraseChar = erase;
+  
+  if (pty()->masterFd() >= 0)
+  {
+    struct ::termios ttmode;
+    pty()->tcGetAttr(&ttmode);
+    ttmode.c_cc[VERASE] = erase;
+    if (!pty()->tcSetAttr(&ttmode))
+      qWarning() << "Unable to set terminal attributes.";
+  }
+}
+
+char Pty::erase() const
+{
+    if (pty()->masterFd() >= 0)
+    {
+        struct ::termios ttyAttributes;
+        pty()->tcGetAttr(&ttyAttributes);
+        return ttyAttributes.c_cc[VERASE];
+    }
+
+    return _eraseChar;
+}
+
+void Pty::addEnvironmentVariables(const QStringList& environment)
+{
+    QListIterator<QString> iter(environment);
+    while (iter.hasNext())
+    {
+        QString pair = iter.next();
+
+        // split on the first '=' character
+        int pos = pair.indexOf('=');
+        
+        if ( pos >= 0 )
+        {
+            QString variable = pair.left(pos);
+            QString value = pair.mid(pos+1);
+
+            setEnv(variable,value);
+        }
+    }
+}
+
+int Pty::start(const QString& program, 
+               const QStringList& programArguments, 
+               const QStringList& environment, 
+               ulong winid, 
+               bool addToUtmp
+               //const QString& dbusService,
+               //const QString& dbusSession
+               )
+{
+  clearProgram();
+
+  // For historical reasons, the first argument in programArguments is the 
+  // name of the program to execute, so create a list consisting of all
+  // but the first argument to pass to setProgram()
+  Q_ASSERT(programArguments.count() >= 1);
+  setProgram(program.toLatin1(),programArguments.mid(1));
+
+  addEnvironmentVariables(environment);
+
+  setEnv("WINDOWID", QString::number(winid));
+
+  // unless the LANGUAGE environment variable has been set explicitly
+  // set it to a null string
+  // this fixes the problem where KCatalog sets the LANGUAGE environment
+  // variable during the application's startup to something which
+  // differs from LANG,LC_* etc. and causes programs run from
+  // the terminal to display messages in the wrong language
+  //
+  // this can happen if LANG contains a language which KDE
+  // does not have a translation for
+  //
+  // BR:149300
+  setEnv("LANGUAGE",QString(),false /* do not overwrite existing value if any */);
+
+  setUseUtmp(addToUtmp);
+
+  struct ::termios ttmode;
+  pty()->tcGetAttr(&ttmode);
+  if (!_xonXoff)
+    ttmode.c_iflag &= ~(IXOFF | IXON);
+  else
+    ttmode.c_iflag |= (IXOFF | IXON);
+#ifdef IUTF8 // XXX not a reasonable place to check it.
+  if (!_utf8)
+    ttmode.c_iflag &= ~IUTF8;
+  else
+    ttmode.c_iflag |= IUTF8;
+#endif
+
+  if (_eraseChar != 0)
+      ttmode.c_cc[VERASE] = _eraseChar;
+  
+  if (!pty()->tcSetAttr(&ttmode))
+    qWarning() << "Unable to set terminal attributes.";
+  
+  pty()->setWinSize(_windowLines, _windowColumns);
+
+  KProcess::start();
+
+  if (!waitForStarted())
+      return -1;
+
+  return 0;
+}
+
+void Pty::setWriteable(bool writeable)
+{
+  struct stat sbuf;
+  stat(pty()->ttyName(), &sbuf);
+  if (writeable)
+    chmod(pty()->ttyName(), sbuf.st_mode | S_IWGRP);
+  else
+    chmod(pty()->ttyName(), sbuf.st_mode & ~(S_IWGRP|S_IWOTH));
+}
+
+Pty::Pty(int masterFd, QObject* parent)
+    : KPtyProcess(masterFd,parent)
+{
+    init();
+}
+Pty::Pty(QObject* parent)
+    : KPtyProcess(parent)
+{
+    init();
+}
+void Pty::init()
+{
+  _windowColumns = 0;
+  _windowLines = 0;
+  _eraseChar = 0;
+  _xonXoff = true;
+  _utf8 =true;
+
+  connect(pty(), SIGNAL(readyRead()) , this , SLOT(dataReceived()));
+  setPtyChannels(KPtyProcess::AllChannels);
+}
+
+Pty::~Pty()
+{
+}
+
+void Pty::sendData(const char* data, int length)
+{
+  if (!length)
+      return;
+  
+  if (!pty()->write(data,length)) 
+  {
+    qWarning() << "Pty::doSendJobs - Could not send input data to terminal process.";
+    return;
+  }
+}
+
+void Pty::dataReceived() 
+{
+     QByteArray data = pty()->readAll();
+    emit receivedData(data.constData(),data.count());
+}
+
+void Pty::lockPty(bool lock)
+{
+    Q_UNUSED(lock);
+
+// TODO: Support for locking the Pty
+  //if (lock)
+    //suspend();
+  //else
+    //resume();
+}
+
+int Pty::foregroundProcessGroup() const
+{
+    int pid = tcgetpgrp(pty()->masterFd());
+
+    if ( pid != -1 )
+    {
+        return pid;
+    } 
+
+    return 0;
+}
+
+void Pty::setupChildProcess()
+{
+    KPtyProcess::setupChildProcess();
+    
+    // reset all signal handlers
+    // this ensures that terminal applications respond to 
+    // signals generated via key sequences such as Ctrl+C
+    // (which sends SIGINT)
+    struct sigaction action;
+    sigemptyset(&action.sa_mask);
+    action.sa_handler = SIG_DFL;
+    action.sa_flags = 0;
+    for (int signal=1;signal < NSIG; signal++)
+        sigaction(signal,&action,0L);
+}

=== added file 'src/Pty.h'
--- src/Pty.h	1970-01-01 00:00:00 +0000
+++ src/Pty.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,206 @@
+/*
+ * This file is a part of QTerminal - http://gitorious.org/qterminal
+ *
+ * This file was un-linked from KDE and modified
+ * by Maxim Bourmistrov <maxim@xxxxxxxxxxxx>
+ *
+ */
+
+/*
+    This file is part of Konsole, KDE's terminal emulator. 
+    
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+#ifndef PTY_H
+#define PTY_H
+
+// Qt
+#include <QtCore/QStringList>
+#include <QtCore/QVector>
+#include <QtCore/QList>
+#include <QtCore/QSize>
+
+// KDE
+#include "kptyprocess.h"
+
+
+/**
+ * The Pty class is used to start the terminal process, 
+ * send data to it, receive data from it and manipulate 
+ * various properties of the pseudo-teletype interface
+ * used to communicate with the process.
+ *
+ * To use this class, construct an instance and connect
+ * to the sendData slot and receivedData signal to
+ * send data to or receive data from the process.
+ *
+ * To start the terminal process, call the start() method
+ * with the program name and appropriate arguments. 
+ */
+class Pty: public KPtyProcess
+{
+Q_OBJECT
+
+  public:
+    
+    /** 
+     * Constructs a new Pty.
+     * 
+     * Connect to the sendData() slot and receivedData() signal to prepare
+     * for sending and receiving data from the terminal process.
+     *
+     * To start the terminal process, call the run() method with the 
+     * name of the program to start and appropriate arguments.
+     */
+    explicit Pty(QObject* parent = 0);
+
+    /** 
+     * Construct a process using an open pty master.
+     * See KPtyProcess::KPtyProcess()
+     */
+    explicit Pty(int ptyMasterFd, QObject* parent = 0);
+
+    ~Pty();
+
+    /**
+     * Starts the terminal process.  
+     *
+     * Returns 0 if the process was started successfully or non-zero
+     * otherwise.
+     *
+     * @param program Path to the program to start
+     * @param arguments Arguments to pass to the program being started
+     * @param environment A list of key=value pairs which will be added
+     * to the environment for the new process.  At the very least this
+     * should include an assignment for the TERM environment variable.
+     * @param winid Specifies the value of the WINDOWID environment variable
+     * in the process's environment.
+     * @param addToUtmp Specifies whether a utmp entry should be created for
+     * the pty used.  See K3Process::setUsePty() 
+     * @param dbusService Specifies the value of the KONSOLE_DBUS_SERVICE 
+     * environment variable in the process's environment.
+     * @param dbusSession Specifies the value of the KONSOLE_DBUS_SESSION
+     * environment variable in the process's environment. 
+     */
+    int start( const QString& program, 
+               const QStringList& arguments, 
+               const QStringList& environment, 
+               ulong winid, 
+               bool addToUtmp
+             );
+
+    /** TODO: Document me */
+    void setWriteable(bool writeable);
+
+    /** 
+     * Enables or disables Xon/Xoff flow control.  The flow control setting
+     * may be changed later by a terminal application, so flowControlEnabled()
+     * may not equal the value of @p on in the previous call to setFlowControlEnabled()
+     */
+    void setFlowControlEnabled(bool on);
+
+    /** Queries the terminal state and returns true if Xon/Xoff flow control is enabled. */
+    bool flowControlEnabled() const;
+
+    /** 
+     * Sets the size of the window (in lines and columns of characters) 
+     * used by this teletype.
+     */
+    void setWindowSize(int lines, int cols);
+    
+    /** Returns the size of the window used by this teletype.  See setWindowSize() */
+    QSize windowSize() const;
+
+    /** TODO Document me */
+    void setErase(char erase);
+
+    /** */
+    char erase() const;
+
+    /**
+     * Returns the process id of the teletype's current foreground
+     * process.  This is the process which is currently reading
+     * input sent to the terminal via. sendData()
+     *
+     * If there is a problem reading the foreground process group,
+     * 0 will be returned.
+     */
+    int foregroundProcessGroup() const;
+   
+  public slots:
+
+    /**
+     * Put the pty into UTF-8 mode on systems which support it.
+     */
+    void setUtf8Mode(bool on);
+
+    /**
+     * Suspend or resume processing of data from the standard 
+     * output of the terminal process.
+     *
+     * See K3Process::suspend() and K3Process::resume()
+     *
+     * @param lock If true, processing of output is suspended,
+     * otherwise processing is resumed.
+     */
+    void lockPty(bool lock);
+    
+    /** 
+     * Sends data to the process currently controlling the 
+     * teletype ( whose id is returned by foregroundProcessGroup() )
+     *
+     * @param buffer Pointer to the data to send.
+     * @param length Length of @p buffer.
+     */
+    void sendData(const char* buffer, int length);
+
+  signals:
+
+    /**
+     * Emitted when a new block of data is received from
+     * the teletype.
+     *
+     * @param buffer Pointer to the data received.
+     * @param length Length of @p buffer
+     */
+    void receivedData(const char* buffer, int length);
+   
+  protected:
+      void setupChildProcess();
+
+  private slots:
+    // called when data is received from the terminal process 
+    void dataReceived(); 
+    
+  private:
+      void init();
+
+    // takes a list of key=value pairs and adds them
+    // to the environment for the process
+    void addEnvironmentVariables(const QStringList& environment);
+
+    int  _windowColumns; 
+    int  _windowLines;
+    char _eraseChar;
+    bool _xonXoff;
+    bool _utf8;
+};
+
+#endif // PTY_H

=== added file 'src/Screen.cpp'
--- src/Screen.cpp	1970-01-01 00:00:00 +0000
+++ src/Screen.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,1360 @@
+/*
+   This file is part of Konsole, an X terminal.
+
+   Copyright 2007-2008 by Robert Knight <robert.knight@xxxxxxxxx>
+   Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+   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.
+   */
+
+// Own
+#include "Screen.h"
+
+// Standard
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+
+// Qt
+#include <QtCore/QTextStream>
+#include <QtCore/QDate>
+
+// KDE
+//#include <kdebug.h>
+
+// Konsole
+#include "konsole_wcwidth.h"
+#include "TerminalCharacterDecoder.h"
+
+
+
+//FIXME: this is emulation specific. Use false for xterm, true for ANSI.
+//FIXME: see if we can get this from terminfo.
+#define BS_CLEARS false
+
+//Macro to convert x,y position on screen to position within an image.
+//
+//Originally the image was stored as one large contiguous block of 
+//memory, so a position within the image could be represented as an
+//offset from the beginning of the block.  For efficiency reasons this
+//is no longer the case.  
+//Many internal parts of this class still use this representation for parameters and so on,
+//notably moveImage() and clearImage().
+//This macro converts from an X,Y position into an image offset.
+#ifndef loc
+#define loc(X,Y) ((Y)*columns+(X))
+#endif
+
+
+Character Screen::defaultChar = Character(' ',
+        CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR),
+        CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR),
+        DEFAULT_RENDITION);
+
+//#define REVERSE_WRAPPED_LINES  // for wrapped line debug
+
+Screen::Screen(int l, int c)
+    : lines(l),
+    columns(c),
+    screenLines(new ImageLine[lines+1] ),
+    _scrolledLines(0),
+    _droppedLines(0),
+    history(new HistoryScrollNone()),
+    cuX(0), cuY(0),
+    currentRendition(0),
+    _topMargin(0), _bottomMargin(0),
+    selBegin(0), selTopLeft(0), selBottomRight(0),
+    blockSelectionMode(false),
+    effectiveForeground(CharacterColor()), effectiveBackground(CharacterColor()), effectiveRendition(0),
+    lastPos(-1)
+{
+    lineProperties.resize(lines+1);
+    for (int i=0;i<lines+1;i++)
+        lineProperties[i]=LINE_DEFAULT;
+
+    initTabStops();
+    clearSelection();
+    reset();
+}
+
+/*! Destructor
+*/
+
+Screen::~Screen()
+{
+    delete[] screenLines;
+    delete history;
+}
+
+void Screen::cursorUp(int n)
+    //=CUU
+{
+    if (n == 0) n = 1; // Default
+    int stop = cuY < _topMargin ? 0 : _topMargin;
+    cuX = qMin(columns-1,cuX); // nowrap!
+    cuY = qMax(stop,cuY-n);
+}
+
+void Screen::cursorDown(int n)
+    //=CUD
+{
+    if (n == 0) n = 1; // Default
+    int stop = cuY > _bottomMargin ? lines-1 : _bottomMargin;
+    cuX = qMin(columns-1,cuX); // nowrap!
+    cuY = qMin(stop,cuY+n);
+}
+
+void Screen::cursorLeft(int n)
+    //=CUB
+{
+    if (n == 0) n = 1; // Default
+    cuX = qMin(columns-1,cuX); // nowrap!
+    cuX = qMax(0,cuX-n);
+}
+
+void Screen::cursorRight(int n)
+    //=CUF
+{
+    if (n == 0) n = 1; // Default
+    cuX = qMin(columns-1,cuX+n);
+}
+
+void Screen::setMargins(int top, int bot)
+    //=STBM
+{
+    if (top == 0) top = 1;      // Default
+    if (bot == 0) bot = lines;  // Default
+    top = top - 1;              // Adjust to internal lineno
+    bot = bot - 1;              // Adjust to internal lineno
+    if ( !( 0 <= top && top < bot && bot < lines ) )
+    { //Debug()<<" setRegion("<<top<<","<<bot<<") : bad range.";
+        return;                   // Default error action: ignore
+    }
+    _topMargin = top;
+    _bottomMargin = bot;
+    cuX = 0;
+    cuY = getMode(MODE_Origin) ? top : 0;
+
+}
+
+int Screen::topMargin() const
+{
+    return _topMargin;
+}
+int Screen::bottomMargin() const
+{
+    return _bottomMargin;
+}
+
+void Screen::index()
+    //=IND
+{
+    if (cuY == _bottomMargin)
+        scrollUp(1);
+    else if (cuY < lines-1)
+        cuY += 1;
+}
+
+void Screen::reverseIndex()
+    //=RI
+{
+    if (cuY == _topMargin)
+        scrollDown(_topMargin,1);
+    else if (cuY > 0)
+        cuY -= 1;
+}
+
+void Screen::nextLine()
+    //=NEL
+{
+    toStartOfLine(); index();
+}
+
+void Screen::eraseChars(int n)
+{
+    if (n == 0) n = 1; // Default
+    int p = qMax(0,qMin(cuX+n-1,columns-1));
+    clearImage(loc(cuX,cuY),loc(p,cuY),' ');
+}
+
+void Screen::deleteChars(int n)
+{
+    Q_ASSERT( n >= 0 );
+
+    // always delete at least one char
+    if (n == 0) 
+        n = 1; 
+
+    // if cursor is beyond the end of the line there is nothing to do
+    if ( cuX >= screenLines[cuY].count() )
+        return;
+
+    if ( cuX+n > screenLines[cuY].count() ) 
+        n = screenLines[cuY].count() - cuX;
+
+    Q_ASSERT( n >= 0 );
+    Q_ASSERT( cuX+n <= screenLines[cuY].count() );
+
+    screenLines[cuY].remove(cuX,n);
+}
+
+void Screen::insertChars(int n)
+{
+    if (n == 0) n = 1; // Default
+
+    if ( screenLines[cuY].size() < cuX )
+        screenLines[cuY].resize(cuX);
+
+    screenLines[cuY].insert(cuX,n,' ');
+
+    if ( screenLines[cuY].count() > columns )
+        screenLines[cuY].resize(columns);
+}
+
+void Screen::deleteLines(int n)
+{
+    if (n == 0) n = 1; // Default
+    scrollUp(cuY,n);
+}
+
+void Screen::insertLines(int n)
+{
+    if (n == 0) n = 1; // Default
+    scrollDown(cuY,n);
+}
+
+void Screen::setMode(int m)
+{
+    currentModes[m] = true;
+    switch(m)
+    {
+        case MODE_Origin : cuX = 0; cuY = _topMargin; break; //FIXME: home
+    }
+}
+
+void Screen::resetMode(int m)
+{
+    currentModes[m] = false;
+    switch(m)
+    {
+        case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
+    }
+}
+
+void Screen::saveMode(int m)
+{
+    savedModes[m] = currentModes[m];
+}
+
+void Screen::restoreMode(int m)
+{
+    currentModes[m] = savedModes[m];
+}
+
+bool Screen::getMode(int m) const
+{
+    return currentModes[m];
+}
+
+void Screen::saveCursor()
+{
+    savedState.cursorColumn = cuX;
+    savedState.cursorLine  = cuY;
+    savedState.rendition = currentRendition;
+    savedState.foreground = currentForeground;
+    savedState.background = currentBackground;
+}
+
+void Screen::restoreCursor()
+{
+    cuX     = qMin(savedState.cursorColumn,columns-1);
+    cuY     = qMin(savedState.cursorLine,lines-1);
+    currentRendition   = savedState.rendition; 
+    currentForeground   = savedState.foreground;
+    currentBackground   = savedState.background;
+    updateEffectiveRendition();
+}
+
+void Screen::resizeImage(int new_lines, int new_columns)
+{
+    if ((new_lines==lines) && (new_columns==columns)) return;
+
+    if (cuY > new_lines-1)
+    { // attempt to preserve focus and lines
+        _bottomMargin = lines-1; //FIXME: margin lost
+        for (int i = 0; i < cuY-(new_lines-1); i++)
+        {
+            addHistLine(); scrollUp(0,1);
+        }
+    }
+
+    // create new screen lines and copy from old to new
+
+    ImageLine* newScreenLines = new ImageLine[new_lines+1];
+    for (int i=0; i < qMin(lines-1,new_lines+1) ;i++)
+        newScreenLines[i]=screenLines[i];
+    for (int i=lines;(i > 0) && (i<new_lines+1);i++)
+        newScreenLines[i].resize( new_columns );
+
+    lineProperties.resize(new_lines+1);
+    for (int i=lines;(i > 0) && (i<new_lines+1);i++)
+        lineProperties[i] = LINE_DEFAULT;
+
+    clearSelection();
+
+    delete[] screenLines; 
+    screenLines = newScreenLines;
+
+    lines = new_lines;
+    columns = new_columns;
+    cuX = qMin(cuX,columns-1);
+    cuY = qMin(cuY,lines-1);
+
+    // FIXME: try to keep values, evtl.
+    _topMargin=0;
+    _bottomMargin=lines-1;
+    initTabStops();
+    clearSelection();
+}
+
+void Screen::setDefaultMargins()
+{
+    _topMargin = 0;
+    _bottomMargin = lines-1;
+}
+
+
+/*
+   Clarifying rendition here and in the display.
+
+   currently, the display's color table is
+   0       1       2 .. 9    10 .. 17
+   dft_fg, dft_bg, dim 0..7, intensive 0..7
+
+   currentForeground, currentBackground contain values 0..8;
+   - 0    = default color
+   - 1..8 = ansi specified color
+
+   re_fg, re_bg contain values 0..17
+   due to the TerminalDisplay's color table
+
+   rendition attributes are
+
+   attr           widget screen
+   -------------- ------ ------
+   RE_UNDERLINE     XX     XX    affects foreground only
+   RE_BLINK         XX     XX    affects foreground only
+   RE_BOLD          XX     XX    affects foreground only
+   RE_REVERSE       --     XX
+   RE_TRANSPARENT   XX     --    affects background only
+   RE_INTENSIVE     XX     --    affects foreground only
+
+   Note that RE_BOLD is used in both widget
+   and screen rendition. Since xterm/vt102
+   is to poor to distinguish between bold
+   (which is a font attribute) and intensive
+   (which is a color attribute), we translate
+   this and RE_BOLD in falls eventually appart
+   into RE_BOLD and RE_INTENSIVE.
+   */
+
+void Screen::reverseRendition(Character& p) const
+{ 
+    CharacterColor f = p.foregroundColor; 
+    CharacterColor b = p.backgroundColor;
+
+    p.foregroundColor = b; 
+    p.backgroundColor = f; //p->r &= ~RE_TRANSPARENT;
+}
+
+void Screen::updateEffectiveRendition()
+{
+    effectiveRendition = currentRendition;
+    if (currentRendition & RE_REVERSE)
+    {
+        effectiveForeground = currentBackground;
+        effectiveBackground = currentForeground;
+    }
+    else
+    {
+        effectiveForeground = currentForeground;
+        effectiveBackground = currentBackground;
+    }
+
+    if (currentRendition & RE_BOLD)
+        effectiveForeground.toggleIntensive();
+}
+
+void Screen::copyFromHistory(Character* dest, int startLine, int count) const
+{
+    Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= history->getLines() );
+
+    for (int line = startLine; line < startLine + count; line++) 
+    {
+        const int length = qMin(columns,history->getLineLen(line));
+        const int destLineOffset  = (line-startLine)*columns;
+
+        history->getCells(line,0,length,dest + destLineOffset);
+
+        for (int column = length; column < columns; column++) 
+            dest[destLineOffset+column] = defaultChar;
+
+        // invert selected text
+        if (selBegin !=-1)
+        {
+            for (int column = 0; column < columns; column++)
+            {
+                if (isSelected(column,line)) 
+                {
+                    reverseRendition(dest[destLineOffset + column]); 
+                }
+            }
+        }
+    }
+}
+
+void Screen::copyFromScreen(Character* dest , int startLine , int count) const
+{
+    Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= lines );
+
+    for (int line = startLine; line < (startLine+count) ; line++)
+    {
+        int srcLineStartIndex  = line*columns;
+        int destLineStartIndex = (line-startLine)*columns;
+
+        for (int column = 0; column < columns; column++)
+        { 
+            int srcIndex = srcLineStartIndex + column; 
+            int destIndex = destLineStartIndex + column;
+
+            dest[destIndex] = screenLines[srcIndex/columns].value(srcIndex%columns,defaultChar);
+
+            // invert selected text
+            if (selBegin != -1 && isSelected(column,line + history->getLines()))
+                reverseRendition(dest[destIndex]); 
+        }
+
+    }
+}
+
+void Screen::getImage( Character* dest, int size, int startLine, int endLine ) const
+{
+    Q_ASSERT( startLine >= 0 );
+    Q_ASSERT( endLine >= startLine && endLine < history->getLines() + lines );
+
+    const int mergedLines = endLine - startLine + 1;
+
+    Q_ASSERT( size >= mergedLines * columns ); 
+    Q_UNUSED( size );
+
+    const int linesInHistoryBuffer = qBound(0,history->getLines()-startLine,mergedLines);
+    const int linesInScreenBuffer = mergedLines - linesInHistoryBuffer;
+
+    // copy lines from history buffer
+    if (linesInHistoryBuffer > 0)
+        copyFromHistory(dest,startLine,linesInHistoryBuffer); 
+
+    // copy lines from screen buffer
+    if (linesInScreenBuffer > 0)
+        copyFromScreen(dest + linesInHistoryBuffer*columns,
+                startLine + linesInHistoryBuffer - history->getLines(),
+                linesInScreenBuffer);
+
+    // invert display when in screen mode
+    if (getMode(MODE_Screen))
+    {
+        for (int i = 0; i < mergedLines*columns; i++)
+            reverseRendition(dest[i]); // for reverse display
+    }
+
+    // mark the character at the current cursor position
+    int cursorIndex = loc(cuX, cuY + linesInHistoryBuffer);
+    if(getMode(MODE_Cursor) && cursorIndex < columns*mergedLines)
+        dest[cursorIndex].rendition |= RE_CURSOR;
+}
+
+QVector<LineProperty> Screen::getLineProperties( int startLine , int endLine ) const
+{
+    Q_ASSERT( startLine >= 0 ); 
+    Q_ASSERT( endLine >= startLine && endLine < history->getLines() + lines );
+
+    const int mergedLines = endLine-startLine+1;
+    const int linesInHistory = qBound(0,history->getLines()-startLine,mergedLines);
+    const int linesInScreen = mergedLines - linesInHistory;
+
+    QVector<LineProperty> result(mergedLines);
+    int index = 0;
+
+    // copy properties for lines in history
+    for (int line = startLine; line < startLine + linesInHistory; line++) 
+    {
+        //TODO Support for line properties other than wrapped lines
+        if (history->isWrappedLine(line))
+        {
+            result[index] = (LineProperty)(result[index] | LINE_WRAPPED);
+        }
+        index++;
+    }
+
+    // copy properties for lines in screen buffer
+    const int firstScreenLine = startLine + linesInHistory - history->getLines();
+    for (int line = firstScreenLine; line < firstScreenLine+linesInScreen; line++)
+    {
+        result[index]=lineProperties[line];
+        index++;
+    }
+
+    return result;
+}
+
+void Screen::reset(bool clearScreen)
+{
+    setMode(MODE_Wrap  ); saveMode(MODE_Wrap  );  // wrap at end of margin
+    resetMode(MODE_Origin); saveMode(MODE_Origin);  // position refere to [1,1]
+    resetMode(MODE_Insert); saveMode(MODE_Insert);  // overstroke
+    setMode(MODE_Cursor);                         // cursor visible
+    resetMode(MODE_Screen);                         // screen not inverse
+    resetMode(MODE_NewLine);
+
+    _topMargin=0;
+    _bottomMargin=lines-1;
+
+    setDefaultRendition();
+    saveCursor();
+
+    if ( clearScreen )
+        clear();
+}
+
+void Screen::clear()
+{
+    clearEntireScreen();
+    home();
+}
+
+void Screen::backspace()
+{
+    cuX = qMin(columns-1,cuX); // nowrap!
+    cuX = qMax(0,cuX-1);
+
+    if (screenLines[cuY].size() < cuX+1)
+        screenLines[cuY].resize(cuX+1);
+
+    if (BS_CLEARS) 
+        screenLines[cuY][cuX].character = ' ';
+}
+
+void Screen::tab(int n)
+{
+    // note that TAB is a format effector (does not write ' ');
+    if (n == 0) n = 1;
+    while((n > 0) && (cuX < columns-1))
+    {
+        cursorRight(1); 
+        while((cuX < columns-1) && !tabStops[cuX]) 
+            cursorRight(1);
+        n--;
+    }
+}
+
+void Screen::backtab(int n)
+{
+    // note that TAB is a format effector (does not write ' ');
+    if (n == 0) n = 1;
+    while((n > 0) && (cuX > 0))
+    {
+        cursorLeft(1); while((cuX > 0) && !tabStops[cuX]) cursorLeft(1);
+        n--;
+    }
+}
+
+void Screen::clearTabStops()
+{
+    for (int i = 0; i < columns; i++) tabStops[i] = false;
+}
+
+void Screen::changeTabStop(bool set)
+{
+    if (cuX >= columns) return;
+    tabStops[cuX] = set;
+}
+
+void Screen::initTabStops()
+{
+    tabStops.resize(columns);
+
+    // Arrg! The 1st tabstop has to be one longer than the other.
+    // i.e. the kids start counting from 0 instead of 1.
+    // Other programs might behave correctly. Be aware.
+    for (int i = 0; i < columns; i++) 
+        tabStops[i] = (i%8 == 0 && i != 0);
+}
+
+void Screen::newLine()
+{
+    if (getMode(MODE_NewLine)) 
+        toStartOfLine();
+    index();
+}
+
+void Screen::checkSelection(int from, int to)
+{
+    if (selBegin == -1) 
+        return;
+    int scr_TL = loc(0, history->getLines());
+    //Clear entire selection if it overlaps region [from, to]
+    if ( (selBottomRight >= (from+scr_TL)) && (selTopLeft <= (to+scr_TL)) )
+        clearSelection();
+}
+
+void Screen::displayCharacter(unsigned short c)
+{
+    // Note that VT100 does wrapping BEFORE putting the character.
+    // This has impact on the assumption of valid cursor positions.
+    // We indicate the fact that a newline has to be triggered by
+    // putting the cursor one right to the last column of the screen.
+
+    int w = konsole_wcwidth(c);
+    if (w <= 0)
+        return;
+
+    if (cuX+w > columns) {
+        if (getMode(MODE_Wrap)) {
+            lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | LINE_WRAPPED);
+            nextLine();
+        }
+        else
+            cuX = columns-w;
+    }
+
+    // ensure current line vector has enough elements
+    int size = screenLines[cuY].size();
+    if (size < cuX+w)
+    {
+        screenLines[cuY].resize(cuX+w);
+    }
+
+    if (getMode(MODE_Insert)) insertChars(w);
+
+    lastPos = loc(cuX,cuY);
+
+    // check if selection is still valid.
+    checkSelection(lastPos, lastPos);
+
+    Character& currentChar = screenLines[cuY][cuX];
+
+    currentChar.character = c;
+    currentChar.foregroundColor = effectiveForeground;
+    currentChar.backgroundColor = effectiveBackground;
+    currentChar.rendition = effectiveRendition;
+
+    int i = 0;
+    int newCursorX = cuX + w--;
+    while(w)
+    {
+        i++;
+
+        if ( screenLines[cuY].size() < cuX + i + 1 )
+            screenLines[cuY].resize(cuX+i+1);
+
+        Character& ch = screenLines[cuY][cuX + i];
+        ch.character = 0;
+        ch.foregroundColor = effectiveForeground;
+        ch.backgroundColor = effectiveBackground;
+        ch.rendition = effectiveRendition;
+
+        w--;
+    }
+    cuX = newCursorX;
+}
+
+void Screen::compose(const QString& /*compose*/)
+{
+    Q_ASSERT( 0 /*Not implemented yet*/ );
+
+    /*  if (lastPos == -1)
+        return;
+
+        QChar c(image[lastPos].character);
+        compose.prepend(c);
+    //compose.compose(); ### FIXME!
+    image[lastPos].character = compose[0].unicode();*/
+}
+
+int Screen::scrolledLines() const
+{
+    return _scrolledLines;
+}
+int Screen::droppedLines() const
+{
+    return _droppedLines;
+}
+void Screen::resetDroppedLines()
+{
+    _droppedLines = 0;
+}
+void Screen::resetScrolledLines()
+{
+    _scrolledLines = 0;
+}
+
+void Screen::scrollUp(int n)
+{
+    if (n == 0) n = 1; // Default
+    if (_topMargin == 0) addHistLine(); // history.history
+    scrollUp(_topMargin, n);
+}
+
+QRect Screen::lastScrolledRegion() const
+{
+    return _lastScrolledRegion;
+}
+
+void Screen::scrollUp(int from, int n)
+{
+    if (n <= 0 || from + n > _bottomMargin) return;
+
+    _scrolledLines -= n;
+    _lastScrolledRegion = QRect(0,_topMargin,columns-1,(_bottomMargin-_topMargin));
+
+    //FIXME: make sure `topMargin', `bottomMargin', `from', `n' is in bounds.
+    moveImage(loc(0,from),loc(0,from+n),loc(columns-1,_bottomMargin));
+    clearImage(loc(0,_bottomMargin-n+1),loc(columns-1,_bottomMargin),' ');
+}
+
+void Screen::scrollDown(int n)
+{
+    if (n == 0) n = 1; // Default
+    scrollDown(_topMargin, n);
+}
+
+void Screen::scrollDown(int from, int n)
+{
+    _scrolledLines += n;
+
+    //FIXME: make sure `topMargin', `bottomMargin', `from', `n' is in bounds.
+    if (n <= 0) 
+        return;
+    if (from > _bottomMargin) 
+        return;
+    if (from + n > _bottomMargin) 
+        n = _bottomMargin - from;
+    moveImage(loc(0,from+n),loc(0,from),loc(columns-1,_bottomMargin-n));
+    clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
+}
+
+void Screen::setCursorYX(int y, int x)
+{
+    setCursorY(y); setCursorX(x);
+}
+
+void Screen::setCursorX(int x)
+{
+    if (x == 0) x = 1; // Default
+    x -= 1; // Adjust
+    cuX = qMax(0,qMin(columns-1, x));
+}
+
+void Screen::setCursorY(int y)
+{
+    if (y == 0) y = 1; // Default
+    y -= 1; // Adjust
+    cuY = qMax(0,qMin(lines  -1, y + (getMode(MODE_Origin) ? _topMargin : 0) ));
+}
+
+void Screen::home()
+{
+    cuX = 0;
+    cuY = 0;
+}
+
+void Screen::toStartOfLine()
+{
+    cuX = 0;
+}
+
+int Screen::getCursorX() const
+{
+    return cuX;
+}
+
+int Screen::getCursorY() const
+{
+    return cuY;
+}
+
+void Screen::clearImage(int loca, int loce, char c)
+{ 
+    int scr_TL=loc(0,history->getLines());
+    //FIXME: check positions
+
+    //Clear entire selection if it overlaps region to be moved...
+    if ( (selBottomRight > (loca+scr_TL) )&&(selTopLeft < (loce+scr_TL)) )
+    {
+        clearSelection();
+    }
+
+    int topLine = loca/columns;
+    int bottomLine = loce/columns;
+
+    Character clearCh(c,currentForeground,currentBackground,DEFAULT_RENDITION);
+
+    //if the character being used to clear the area is the same as the
+    //default character, the affected lines can simply be shrunk.
+    bool isDefaultCh = (clearCh == Character());
+
+    for (int y=topLine;y<=bottomLine;y++)
+    {
+        lineProperties[y] = 0;
+
+        int endCol = ( y == bottomLine) ? loce%columns : columns-1;
+        int startCol = ( y == topLine ) ? loca%columns : 0;
+
+        QVector<Character>& line = screenLines[y];
+
+        if ( isDefaultCh && endCol == columns-1 )
+        {
+            line.resize(startCol);
+        }
+        else
+        {
+            if (line.size() < endCol + 1)
+                line.resize(endCol+1);
+
+            Character* data = line.data();
+            for (int i=startCol;i<=endCol;i++)
+                data[i]=clearCh;
+        }
+    }
+}
+
+void Screen::moveImage(int dest, int sourceBegin, int sourceEnd)
+{
+    Q_ASSERT( sourceBegin <= sourceEnd );
+
+    int lines=(sourceEnd-sourceBegin)/columns;
+
+    //move screen image and line properties:
+    //the source and destination areas of the image may overlap, 
+    //so it matters that we do the copy in the right order - 
+    //forwards if dest < sourceBegin or backwards otherwise.
+    //(search the web for 'memmove implementation' for details)
+    if (dest < sourceBegin)
+    {
+        for (int i=0;i<=lines;i++)
+        {
+            screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ];
+            lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i];
+        }
+    }
+    else
+    {
+        for (int i=lines;i>=0;i--)
+        {
+            screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ];
+            lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i];
+        }
+    }
+
+    if (lastPos != -1)
+    {
+        int diff = dest - sourceBegin; // Scroll by this amount
+        lastPos += diff;
+        if ((lastPos < 0) || (lastPos >= (lines*columns)))
+            lastPos = -1;
+    }
+
+    // Adjust selection to follow scroll.
+    if (selBegin != -1)
+    {
+        bool beginIsTL = (selBegin == selTopLeft);
+        int diff = dest - sourceBegin; // Scroll by this amount
+        int scr_TL=loc(0,history->getLines());
+        int srca = sourceBegin+scr_TL; // Translate index from screen to global
+        int srce = sourceEnd+scr_TL; // Translate index from screen to global
+        int desta = srca+diff;
+        int deste = srce+diff;
+
+        if ((selTopLeft >= srca) && (selTopLeft <= srce))
+            selTopLeft += diff;
+        else if ((selTopLeft >= desta) && (selTopLeft <= deste))
+            selBottomRight = -1; // Clear selection (see below)
+
+        if ((selBottomRight >= srca) && (selBottomRight <= srce))
+            selBottomRight += diff;
+        else if ((selBottomRight >= desta) && (selBottomRight <= deste))
+            selBottomRight = -1; // Clear selection (see below)
+
+        if (selBottomRight < 0)
+        {
+            clearSelection();
+        }
+        else
+        {
+            if (selTopLeft < 0)
+                selTopLeft = 0;
+        }
+
+        if (beginIsTL)
+            selBegin = selTopLeft;
+        else
+            selBegin = selBottomRight;
+    }
+}
+
+void Screen::clearToEndOfScreen()
+{
+    clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
+}
+
+void Screen::clearToBeginOfScreen()
+{
+    clearImage(loc(0,0),loc(cuX,cuY),' ');
+}
+
+void Screen::clearEntireScreen()
+{
+    // Add entire screen to history
+    for (int i = 0; i < (lines-1); i++)
+    {
+        addHistLine(); scrollUp(0,1);
+    }
+
+    clearImage(loc(0,0),loc(columns-1,lines-1),' ');
+}
+
+/*! fill screen with 'E'
+  This is to aid screen alignment
+  */
+
+void Screen::helpAlign()
+{
+    clearImage(loc(0,0),loc(columns-1,lines-1),'E');
+}
+
+void Screen::clearToEndOfLine()
+{
+    clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
+}
+
+void Screen::clearToBeginOfLine()
+{
+    clearImage(loc(0,cuY),loc(cuX,cuY),' ');
+}
+
+void Screen::clearEntireLine()
+{
+    clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
+}
+
+void Screen::setRendition(int re)
+{
+    currentRendition |= re;
+    updateEffectiveRendition();
+}
+
+void Screen::resetRendition(int re)
+{
+    currentRendition &= ~re;
+    updateEffectiveRendition();
+}
+
+void Screen::setDefaultRendition()
+{
+    setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR);
+    setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR);
+    currentRendition   = DEFAULT_RENDITION;
+    updateEffectiveRendition();
+}
+
+void Screen::setForeColor(int space, int color)
+{
+    currentForeground = CharacterColor(space, color);
+
+    if ( currentForeground.isValid() ) 
+        updateEffectiveRendition();
+    else 
+        setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR);
+}
+
+void Screen::setBackColor(int space, int color)
+{
+    currentBackground = CharacterColor(space, color);
+
+    if ( currentBackground.isValid() ) 
+        updateEffectiveRendition();
+    else
+        setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR);
+}
+
+void Screen::clearSelection() 
+{
+    selBottomRight = -1;
+    selTopLeft = -1;
+    selBegin = -1;
+}
+
+void Screen::getSelectionStart(int& column , int& line) const
+{
+    if ( selTopLeft != -1 )
+    {
+        column = selTopLeft % columns;
+        line = selTopLeft / columns; 
+    }
+    else
+    {
+        column = cuX + getHistLines();
+        line = cuY + getHistLines();
+    }
+}
+void Screen::getSelectionEnd(int& column , int& line) const
+{
+    if ( selBottomRight != -1 )
+    {
+        column = selBottomRight % columns;
+        line = selBottomRight / columns;
+    }
+    else
+    {
+        column = cuX + getHistLines();
+        line = cuY + getHistLines();
+    } 
+}
+void Screen::setSelectionStart(const int x, const int y, const bool mode)
+{
+    selBegin = loc(x,y); 
+    /* FIXME, HACK to correct for x too far to the right... */
+    if (x == columns) selBegin--;
+
+    selBottomRight = selBegin;
+    selTopLeft = selBegin;
+    blockSelectionMode = mode;
+}
+
+void Screen::setSelectionEnd( const int x, const int y)
+{
+    if (selBegin == -1) 
+        return;
+
+    int endPos =  loc(x,y); 
+
+    if (endPos < selBegin)
+    {
+        selTopLeft = endPos;
+        selBottomRight = selBegin;
+    }
+    else
+    {
+        /* FIXME, HACK to correct for x too far to the right... */
+        if (x == columns) 
+            endPos--;
+
+        selTopLeft = selBegin;
+        selBottomRight = endPos;
+    }
+
+    // Normalize the selection in column mode
+    if (blockSelectionMode)
+    {
+        int topRow = selTopLeft / columns;
+        int topColumn = selTopLeft % columns;
+        int bottomRow = selBottomRight / columns;
+        int bottomColumn = selBottomRight % columns;
+
+        selTopLeft = loc(qMin(topColumn,bottomColumn),topRow);
+        selBottomRight = loc(qMax(topColumn,bottomColumn),bottomRow);
+    }
+}
+
+bool Screen::isSelected( const int x,const int y) const
+{
+    bool columnInSelection = true;
+    if (blockSelectionMode)
+    {
+        columnInSelection = x >= (selTopLeft % columns) &&
+            x <= (selBottomRight % columns);
+    }
+
+    int pos = loc(x,y);
+    return pos >= selTopLeft && pos <= selBottomRight && columnInSelection;
+}
+
+QString Screen::selectedText(bool preserveLineBreaks) const
+{
+    QString result;
+    QTextStream stream(&result, QIODevice::ReadWrite);
+
+    PlainTextDecoder decoder;
+    decoder.begin(&stream);
+    writeSelectionToStream(&decoder , preserveLineBreaks);
+    decoder.end();
+
+    return result;
+}
+
+bool Screen::isSelectionValid() const
+{
+    return selTopLeft >= 0 && selBottomRight >= 0;
+}
+
+void Screen::writeSelectionToStream(TerminalCharacterDecoder* decoder , 
+        bool preserveLineBreaks) const
+{
+    if (!isSelectionValid())
+        return;
+    writeToStream(decoder,selTopLeft,selBottomRight,preserveLineBreaks);
+}
+
+void Screen::writeToStream(TerminalCharacterDecoder* decoder, 
+        int startIndex, int endIndex,
+        bool preserveLineBreaks) const
+{
+    int top = startIndex / columns;    
+    int left = startIndex % columns;
+
+    int bottom = endIndex / columns;
+    int right = endIndex % columns;
+
+    Q_ASSERT( top >= 0 && left >= 0 && bottom >= 0 && right >= 0 );
+
+    for (int y=top;y<=bottom;y++)
+    {
+        int start = 0;
+        if ( y == top || blockSelectionMode ) start = left;
+
+        int count = -1;
+        if ( y == bottom || blockSelectionMode ) count = right - start + 1;
+
+        const bool appendNewLine = ( y != bottom );
+        int copied = copyLineToStream( y,
+                start,
+                count,
+                decoder, 
+                appendNewLine,
+                preserveLineBreaks );
+
+        // if the selection goes beyond the end of the last line then
+        // append a new line character.
+        //
+        // this makes it possible to 'select' a trailing new line character after
+        // the text on a line.  
+        if ( y == bottom && 
+                copied < count    )
+        {
+            Character newLineChar('\n');
+            decoder->decodeLine(&newLineChar,1,0);
+        }
+    }    
+}
+
+int Screen::copyLineToStream(int line , 
+        int start, 
+        int count,
+        TerminalCharacterDecoder* decoder,
+        bool appendNewLine,
+        bool preserveLineBreaks) const
+{
+    //buffer to hold characters for decoding
+    //the buffer is static to avoid initialising every 
+    //element on each call to copyLineToStream
+    //(which is unnecessary since all elements will be overwritten anyway)
+    static const int MAX_CHARS = 1024;
+    static Character characterBuffer[MAX_CHARS];
+
+    assert( count < MAX_CHARS );
+
+    LineProperty currentLineProperties = 0;
+
+    //determine if the line is in the history buffer or the screen image
+    if (line < history->getLines())
+    {
+        const int lineLength = history->getLineLen(line);
+
+        // ensure that start position is before end of line
+        start = qMin(start,qMax(0,lineLength-1));
+
+        // retrieve line from history buffer.  It is assumed
+        // that the history buffer does not store trailing white space
+        // at the end of the line, so it does not need to be trimmed here 
+        if (count == -1)
+        {
+            count = lineLength-start;
+        }
+        else
+        {
+            count = qMin(start+count,lineLength)-start;
+        }
+
+        // safety checks
+        assert( start >= 0 );
+        assert( count >= 0 );    
+        assert( (start+count) <= history->getLineLen(line) );
+
+        history->getCells(line,start,count,characterBuffer);
+
+        if ( history->isWrappedLine(line) )
+            currentLineProperties |= LINE_WRAPPED;
+    }
+    else
+    {
+        if ( count == -1 )
+            count = columns - start;
+
+        assert( count >= 0 );
+
+        const int screenLine = line-history->getLines();
+
+        Character* data = screenLines[screenLine].data();
+        int length = screenLines[screenLine].count();
+
+        //retrieve line from screen image
+        for (int i=start;i < qMin(start+count,length);i++)
+        {
+            characterBuffer[i-start] = data[i];
+        }
+
+        // count cannot be any greater than length
+        count = qBound(0,count,length-start);
+
+        Q_ASSERT( screenLine < lineProperties.count() );
+        currentLineProperties |= lineProperties[screenLine]; 
+    }
+
+    // add new line character at end
+    const bool omitLineBreak = (currentLineProperties & LINE_WRAPPED) ||
+        !preserveLineBreaks;
+
+    if ( !omitLineBreak && appendNewLine && (count+1 < MAX_CHARS) )
+    {
+        characterBuffer[count] = '\n';
+        count++;
+    }
+
+    //decode line and write to text stream    
+    decoder->decodeLine( (Character*) characterBuffer , 
+            count, currentLineProperties );
+
+    return count;
+}
+
+void Screen::writeLinesToStream(TerminalCharacterDecoder* decoder, int fromLine, int toLine) const
+{
+    writeToStream(decoder,loc(0,fromLine),loc(columns-1,toLine));
+}
+
+void Screen::addHistLine()
+{
+    // add line to history buffer
+    // we have to take care about scrolling, too...
+
+    if (hasScroll())
+    {
+        int oldHistLines = history->getLines();
+
+        history->addCellsVector(screenLines[0]);
+        history->addLine( lineProperties[0] & LINE_WRAPPED );
+
+        int newHistLines = history->getLines();
+
+        bool beginIsTL = (selBegin == selTopLeft);
+
+        // If the history is full, increment the count
+        // of dropped lines
+        if ( newHistLines == oldHistLines )
+            _droppedLines++;
+
+        // Adjust selection for the new point of reference
+        if (newHistLines > oldHistLines)
+        {
+            if (selBegin != -1)
+            {
+                selTopLeft += columns;
+                selBottomRight += columns;
+            }
+        }
+
+        if (selBegin != -1)
+        {
+            // Scroll selection in history up
+            int top_BR = loc(0, 1+newHistLines);
+
+            if (selTopLeft < top_BR)
+                selTopLeft -= columns;
+
+            if (selBottomRight < top_BR)
+                selBottomRight -= columns;
+
+            if (selBottomRight < 0)
+                clearSelection();
+            else
+            {
+                if (selTopLeft < 0)
+                    selTopLeft = 0;
+            }
+
+            if (beginIsTL)
+                selBegin = selTopLeft;
+            else
+                selBegin = selBottomRight;
+        }
+    }
+
+}
+
+int Screen::getHistLines() const
+{
+    return history->getLines();
+}
+
+void Screen::setScroll(const HistoryType& t , bool copyPreviousScroll)
+{
+    clearSelection();
+
+    if ( copyPreviousScroll )
+        history = t.scroll(history);
+    else
+    {
+        HistoryScroll* oldScroll = history;
+        history = t.scroll(0);
+        delete oldScroll;
+    }
+}
+
+bool Screen::hasScroll() const
+{
+    return history->hasScroll();
+}
+
+const HistoryType& Screen::getScroll() const
+{
+    return history->getType();
+}
+
+void Screen::setLineProperty(LineProperty property , bool enable)
+{
+    if ( enable )
+        lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | property);
+    else
+        lineProperties[cuY] = (LineProperty)(lineProperties[cuY] & ~property);
+}
+void Screen::fillWithDefaultChar(Character* dest, int count)
+{
+    for (int i=0;i<count;i++)
+        dest[i] = defaultChar;
+}

=== added file 'src/Screen.h'
--- src/Screen.h	1970-01-01 00:00:00 +0000
+++ src/Screen.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,672 @@
+/*
+    This file is part of Konsole, KDE's terminal.
+
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+    Copyright 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    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.
+*/
+
+#ifndef SCREEN_H
+#define SCREEN_H
+
+// Qt
+#include <QtCore/QRect>
+#include <QtCore/QTextStream>
+#include <QtCore/QVarLengthArray>
+
+// Konsole
+#include "Character.h"
+#include "History.h"
+
+#define MODE_Origin    0
+#define MODE_Wrap      1
+#define MODE_Insert    2
+#define MODE_Screen    3
+#define MODE_Cursor    4
+#define MODE_NewLine   5
+#define MODES_SCREEN   6
+
+
+class TerminalCharacterDecoder;
+
+/**
+    \brief An image of characters with associated attributes.
+
+    The terminal emulation ( Emulation ) receives a serial stream of
+    characters from the program currently running in the terminal.
+    From this stream it creates an image of characters which is ultimately
+    rendered by the display widget ( TerminalDisplay ).  Some types of emulation
+    may have more than one screen image. 
+
+    getImage() is used to retrieve the currently visible image
+    which is then used by the display widget to draw the output from the
+    terminal. 
+
+    The number of lines of output history which are kept in addition to the current
+    screen image depends on the history scroll being used to store the output.  
+    The scroll is specified using setScroll()
+    The output history can be retrieved using writeToStream()
+
+    The screen image has a selection associated with it, specified using 
+    setSelectionStart() and setSelectionEnd().  The selected text can be retrieved
+    using selectedText().  When getImage() is used to retrieve the visible image,
+    characters which are part of the selection have their colours inverted.   
+*/
+class Screen
+{
+public:
+    /** Construct a new screen image of size @p lines by @p columns. */
+    Screen(int lines, int columns);
+    ~Screen();
+
+    // VT100/2 Operations 
+    // Cursor Movement
+    
+    /** 
+     * Move the cursor up by @p n lines.  The cursor will stop at the 
+     * top margin.
+     */
+    void cursorUp(int n);
+    /** 
+     * Move the cursor down by @p n lines.  The cursor will stop at the
+     * bottom margin.
+     */
+    void cursorDown(int n);
+    /** 
+     * Move the cursor to the left by @p n columns.
+     * The cursor will stop at the first column.
+     */
+    void cursorLeft(int n);
+    /** 
+     * Move the cursor to the right by @p n columns.
+     * The cursor will stop at the right-most column.
+     */
+    void cursorRight(int n);
+    /** Position the cursor on line @p y. */
+    void setCursorY(int y);
+    /** Position the cursor at column @p x. */
+    void setCursorX(int x);
+    /** Position the cursor at line @p y, column @p x. */
+    void setCursorYX(int y, int x);
+    /**
+     * Sets the margins for scrolling the screen.
+     *
+     * @param topLine The top line of the new scrolling margin. 
+     * @param bottomLine The bottom line of the new scrolling margin. 
+     */
+    void setMargins(int topLine , int bottomLine);
+    /** Returns the top line of the scrolling region. */ 
+    int topMargin() const;
+    /** Returns the bottom line of the scrolling region. */
+    int bottomMargin() const;
+
+    /** 
+     * Resets the scrolling margins back to the top and bottom lines
+     * of the screen.
+     */
+    void setDefaultMargins();
+    
+    /** 
+     * Moves the cursor down one line, if the MODE_NewLine mode 
+     * flag is enabled then the cursor is returned to the leftmost
+     * column first.
+     *
+     * Equivalent to NextLine() if the MODE_NewLine flag is set
+     * or index() otherwise. 
+     */
+    void newLine();
+    /**
+     * Moves the cursor down one line and positions it at the beginning
+     * of the line.  Equivalent to calling Return() followed by index()
+     */
+    void nextLine();
+
+    /** 
+     * Move the cursor down one line.  If the cursor is on the bottom
+     * line of the scrolling region (as returned by bottomMargin()) the
+     * scrolling region is scrolled up by one line instead.
+     */
+    void index();
+    /**
+     * Move the cursor up one line.  If the cursor is on the top line
+     * of the scrolling region (as returned by topMargin()) the scrolling
+     * region is scrolled down by one line instead.
+     */
+    void reverseIndex();
+    
+    /** 
+     * Scroll the scrolling region of the screen up by @p n lines. 
+     * The scrolling region is initially the whole screen, but can be changed 
+     * using setMargins()
+     */ 
+    void scrollUp(int n);
+    /**
+     * Scroll the scrolling region of the screen down by @p n lines.
+     * The scrolling region is initially the whole screen, but can be changed
+     * using setMargins()
+     */
+    void scrollDown(int n);
+    /** 
+     * Moves the cursor to the beginning of the current line. 
+     * Equivalent to setCursorX(0)
+     */
+    void toStartOfLine();
+    /** 
+     * Moves the cursor one column to the left and erases the character
+     * at the new cursor position.
+     */
+    void backspace();
+    /** Moves the cursor @p n tab-stops to the right. */
+    void tab(int n = 1);
+    /** Moves the cursor @p n tab-stops to the left. */
+    void backtab(int n);
+    
+    // Editing
+    
+    /** 
+     * Erase @p n characters beginning from the current cursor position. 
+     * This is equivalent to over-writing @p n characters starting with the current
+     * cursor position with spaces.
+     * If @p n is 0 then one character is erased. 
+     */
+    void eraseChars(int n);
+    /** 
+     * Delete @p n characters beginning from the current cursor position. 
+     * If @p n is 0 then one character is deleted. 
+     */
+    void deleteChars(int n);
+    /**
+     * Insert @p n blank characters beginning from the current cursor position.
+     * The position of the cursor is not altered.  
+     * If @p n is 0 then one character is inserted.
+     */
+    void insertChars(int n);
+    /** 
+     * Removes @p n lines beginning from the current cursor position.
+     * The position of the cursor is not altered.
+     * If @p n is 0 then one line is removed.
+     */
+    void deleteLines(int n);
+    /**
+     * Inserts @p lines beginning from the current cursor position.
+     * The position of the cursor is not altered.
+     * If @p n is 0 then one line is inserted.
+     */
+    void insertLines(int n);
+    /** Clears all the tab stops. */
+    void clearTabStops();
+    /**  Sets or removes a tab stop at the cursor's current column. */ 
+    void changeTabStop(bool set);
+   
+    /** Resets (clears) the specified screen @p mode. */
+    void resetMode(int mode);
+    /** Sets (enables) the specified screen @p mode. */
+    void setMode(int mode);
+    /** 
+     * Saves the state of the specified screen @p mode.  It can be restored
+     * using restoreMode()
+     */
+    void saveMode(int mode);
+    /** Restores the state of a screen @p mode saved by calling saveMode() */
+    void restoreMode(int mode);
+    /** Returns whether the specified screen @p mode is enabled or not .*/
+    bool getMode(int mode) const;
+   
+    /** 
+     * Saves the current position and appearance (text color and style) of the cursor. 
+     * It can be restored by calling restoreCursor() 
+     */ 
+    void saveCursor();
+    /** Restores the position and appearance of the cursor.  See saveCursor() */
+    void restoreCursor();
+   
+    /** Clear the whole screen, moving the current screen contents into the history first. */ 
+    void clearEntireScreen();
+    /** 
+     * Clear the area of the screen from the current cursor position to the end of 
+     * the screen.
+     */
+    void clearToEndOfScreen();
+    /**
+     * Clear the area of the screen from the current cursor position to the start
+     * of the screen.
+     */
+    void clearToBeginOfScreen();
+    /** Clears the whole of the line on which the cursor is currently positioned. */
+    void clearEntireLine();
+    /** Clears from the current cursor position to the end of the line. */
+    void clearToEndOfLine();
+    /** Clears from the current cursor position to the beginning of the line. */
+    void clearToBeginOfLine();
+    
+    /** Fills the entire screen with the letter 'E' */
+    void helpAlign();
+       
+    /** 
+     * Enables the given @p rendition flag.  Rendition flags control the appearance 
+     * of characters on the screen.
+     *
+     * @see Character::rendition
+     */  
+    void setRendition(int rendition);
+    /**
+     * Disables the given @p rendition flag.  Rendition flags control the appearance
+     * of characters on the screen.
+     *
+     * @see Character::rendition
+     */
+    void resetRendition(int rendition);
+    
+    /** 
+     * Sets the cursor's foreground color.
+     * @param space The color space used by the @p color argument
+     * @param color The new foreground color.  The meaning of this depends on
+     * the color @p space used.
+     *
+     * @see CharacterColor
+     */
+    void setForeColor(int space, int color);
+    /**
+     * Sets the cursor's background color.
+     * @param space The color space used by the @p color argumnet.
+     * @param color The new background color.  The meaning of this depends on
+     * the color @p space used.
+     *
+     * @see CharacterColor
+     */
+    void setBackColor(int space, int color);
+    /** 
+     * Resets the cursor's color back to the default and sets the 
+     * character's rendition flags back to the default settings.
+     */
+    void setDefaultRendition();
+    
+    /** Returns the column which the cursor is positioned at. */
+    int  getCursorX() const;
+    /** Returns the line which the cursor is positioned on. */
+    int  getCursorY() const;
+   
+    /** Clear the entire screen and move the cursor to the home position.
+     * Equivalent to calling clearEntireScreen() followed by home().
+     */
+    void clear();
+    /** 
+     * Sets the position of the cursor to the 'home' position at the top-left
+     * corner of the screen (0,0) 
+     */
+    void home();
+    /**
+     * Resets the state of the screen.  This resets the various screen modes
+     * back to their default states.  The cursor style and colors are reset
+     * (as if setDefaultRendition() had been called)
+     *
+     * <ul>
+     * <li>Line wrapping is enabled.</li>
+     * <li>Origin mode is disabled.</li>
+     * <li>Insert mode is disabled.</li>
+     * <li>Cursor mode is enabled.  TODO Document me</li>
+     * <li>Screen mode is disabled. TODO Document me</li>
+     * <li>New line mode is disabled.  TODO Document me</li>
+     * </ul>
+     *
+     * If @p clearScreen is true then the screen contents are erased entirely, 
+     * otherwise they are unaltered.
+     */
+    void reset(bool clearScreen = true);
+   
+    /** 
+     * Displays a new character at the current cursor position. 
+     * 
+     * If the cursor is currently positioned at the right-edge of the screen and
+     * line wrapping is enabled then the character is added at the start of a new 
+     * line below the current one.
+     *
+     * If the MODE_Insert screen mode is currently enabled then the character 
+     * is inserted at the current cursor position, otherwise it will replace the 
+     * character already at the current cursor position.  
+     */ 
+    void displayCharacter(unsigned short c);
+    
+    // Do composition with last shown character FIXME: Not implemented yet for KDE 4
+    void compose(const QString& compose);
+    
+    /** 
+     * Resizes the image to a new fixed size of @p new_lines by @p new_columns.  
+     * In the case that @p new_columns is smaller than the current number of columns,
+     * existing lines are not truncated.  This prevents characters from being lost
+     * if the terminal display is resized smaller and then larger again.
+     *
+     * The top and bottom margins are reset to the top and bottom of the new 
+     * screen size.  Tab stops are also reset and the current selection is
+     * cleared.
+     */
+    void resizeImage(int new_lines, int new_columns);
+    
+    /**
+     * Returns the current screen image.  
+     * The result is an array of Characters of size [getLines()][getColumns()] which
+     * must be freed by the caller after use.
+     *
+     * @param dest Buffer to copy the characters into
+     * @param size Size of @p dest in Characters
+     * @param startLine Index of first line to copy
+     * @param endLine Index of last line to copy
+     */
+    void getImage( Character* dest , int size , int startLine , int endLine ) const;
+
+    /** 
+     * Returns the additional attributes associated with lines in the image.
+     * The most important attribute is LINE_WRAPPED which specifies that the 
+     * line is wrapped,
+     * other attributes control the size of characters in the line.
+     */
+    QVector<LineProperty> getLineProperties( int startLine , int endLine ) const;
+    
+
+    /** Return the number of lines. */
+    int getLines() const   
+    { return lines; }
+    /** Return the number of columns. */
+    int getColumns() const 
+    { return columns; }
+    /** Return the number of lines in the history buffer. */
+    int getHistLines() const;
+    /** 
+     * Sets the type of storage used to keep lines in the history. 
+     * If @p copyPreviousScroll is true then the contents of the previous 
+     * history buffer are copied into the new scroll.
+     */
+    void setScroll(const HistoryType& , bool copyPreviousScroll = true);
+    /** Returns the type of storage used to keep lines in the history. */
+    const HistoryType& getScroll() const;
+    /** 
+     * Returns true if this screen keeps lines that are scrolled off the screen
+     * in a history buffer.
+     */
+    bool hasScroll() const;
+
+    /** 
+     * Sets the start of the selection.
+     *
+     * @param column The column index of the first character in the selection.
+     * @param line The line index of the first character in the selection.
+     * @param blockSelectionMode True if the selection is in column mode.
+     */
+    void setSelectionStart(const int column, const int line, const bool blockSelectionMode);
+    
+    /**
+     * Sets the end of the current selection.
+     *
+     * @param column The column index of the last character in the selection.
+     * @param line The line index of the last character in the selection. 
+     */ 
+    void setSelectionEnd(const int column, const int line);
+   
+    /**
+     * Retrieves the start of the selection or the cursor position if there
+     * is no selection.
+     */
+    void getSelectionStart(int& column , int& line) const;
+    
+    /**
+     * Retrieves the end of the selection or the cursor position if there
+     * is no selection.
+     */
+    void getSelectionEnd(int& column , int& line) const;
+
+    /** Clears the current selection */
+    void clearSelection();
+
+    /** 
+      *  Returns true if the character at (@p column, @p line) is part of the
+      *  current selection. 
+      */ 
+    bool isSelected(const int column,const int line) const;
+
+    /** 
+     * Convenience method.  Returns the currently selected text. 
+     * @param preserveLineBreaks Specifies whether new line characters should 
+     * be inserted into the returned text at the end of each terminal line.
+     */
+    QString selectedText(bool preserveLineBreaks) const;
+        
+    /**
+     * Copies part of the output to a stream.
+     *
+     * @param decoder A decoder which converts terminal characters into text
+     * @param fromLine The first line in the history to retrieve
+     * @param toLine The last line in the history to retrieve
+     */
+    void writeLinesToStream(TerminalCharacterDecoder* decoder, int fromLine, int toLine) const;
+
+    /**
+     * Copies the selected characters, set using @see setSelBeginXY and @see setSelExtentXY
+     * into a stream.
+     *
+     * @param decoder A decoder which converts terminal characters into text.  
+     * PlainTextDecoder is the most commonly used decoder which converts characters 
+     * into plain text with no formatting.
+     * @param preserveLineBreaks Specifies whether new line characters should 
+     * be inserted into the returned text at the end of each terminal line. 
+     */
+    void writeSelectionToStream(TerminalCharacterDecoder* decoder , bool
+                                preserveLineBreaks = true) const;
+
+    /**
+     * Checks if the text between from and to is inside the current
+     * selection. If this is the case, the selection is cleared. The
+     * from and to are coordinates in the current viewable window.
+     * The loc(x,y) macro can be used to generate these values from a
+     * column,line pair.
+     *
+     * @param from The start of the area to check.
+     * @param to The end of the area to check
+     */
+    void checkSelection(int from, int to);
+
+    /** 
+     * Sets or clears an attribute of the current line.
+     * 
+     * @param property The attribute to set or clear
+     * Possible properties are:
+     * LINE_WRAPPED:     Specifies that the line is wrapped.
+     * LINE_DOUBLEWIDTH: Specifies that the characters in the current line
+     *                   should be double the normal width.
+     * LINE_DOUBLEHEIGHT:Specifies that the characters in the current line 
+     *                   should be double the normal height.
+     *                   Double-height lines are formed of two lines containing the same characters,
+     *                   with both having the LINE_DOUBLEHEIGHT attribute.
+     *                   This allows other parts of the code to work on the
+     *                   assumption that all lines are the same height.
+     *
+     * @param enable true to apply the attribute to the current line or false to remove it
+     */
+    void setLineProperty(LineProperty property , bool enable);
+
+    /** 
+     * Returns the number of lines that the image has been scrolled up or down by,
+     * since the last call to resetScrolledLines().
+     *
+     * a positive return value indicates that the image has been scrolled up,
+     * a negative return value indicates that the image has been scrolled down. 
+     */
+    int scrolledLines() const;
+
+    /**
+     * Returns the region of the image which was last scrolled.
+     *
+     * This is the area of the image from the top margin to the 
+     * bottom margin when the last scroll occurred.
+     */
+    QRect lastScrolledRegion() const;
+
+    /** 
+     * Resets the count of the number of lines that the image has been scrolled up or down by,
+     * see scrolledLines()
+     */
+    void resetScrolledLines();
+
+    /**
+     * Returns the number of lines of output which have been
+     * dropped from the history since the last call
+     * to resetDroppedLines()
+     *
+     * If the history is not unlimited then it will drop
+     * the oldest lines of output if new lines are added when
+     * it is full.  
+     */
+    int droppedLines() const;
+
+    /**
+     * Resets the count of the number of lines dropped from
+     * the history.
+     */
+    void resetDroppedLines();
+
+    /** 
+      * Fills the buffer @p dest with @p count instances of the default (ie. blank)
+      * Character style.
+      */
+    static void fillWithDefaultChar(Character* dest, int count);
+
+private: 
+
+    //copies a line of text from the screen or history into a stream using a 
+    //specified character decoder.  Returns the number of lines actually copied,
+    //which may be less than 'count' if (start+count) is more than the number of characters on
+    //the line 
+    //
+    //line - the line number to copy, from 0 (the earliest line in the history) up to 
+    //         history->getLines() + lines - 1
+    //start - the first column on the line to copy
+    //count - the number of characters on the line to copy
+    //decoder - a decoder which converts terminal characters (an Character array) into text
+    //appendNewLine - if true a new line character (\n) is appended to the end of the line
+    int  copyLineToStream(int line, 
+                          int start, 
+                          int count, 
+                          TerminalCharacterDecoder* decoder,
+                          bool appendNewLine,
+                          bool preserveLineBreaks) const;
+    
+    //fills a section of the screen image with the character 'c'
+    //the parameters are specified as offsets from the start of the screen image.
+    //the loc(x,y) macro can be used to generate these values from a column,line pair.
+    void clearImage(int loca, int loce, char c);
+
+    //move screen image between 'sourceBegin' and 'sourceEnd' to 'dest'.
+    //the parameters are specified as offsets from the start of the screen image.
+    //the loc(x,y) macro can be used to generate these values from a column,line pair.
+    //
+    //NOTE: moveImage() can only move whole lines
+    void moveImage(int dest, int sourceBegin, int sourceEnd);
+    // scroll up 'i' lines in current region, clearing the bottom 'i' lines 
+    void scrollUp(int from, int i);
+    // scroll down 'i' lines in current region, clearing the top 'i' lines
+    void scrollDown(int from, int i);
+
+    void addHistLine();
+
+    void initTabStops();
+
+    void updateEffectiveRendition();
+    void reverseRendition(Character& p) const;
+
+    bool isSelectionValid() const;
+    // copies text from 'startIndex' to 'endIndex' to a stream
+    // startIndex and endIndex are positions generated using the loc(x,y) macro
+    void writeToStream(TerminalCharacterDecoder* decoder, int startIndex, 
+                       int endIndex, bool preserveLineBreaks = true) const;
+    // copies 'count' lines from the screen buffer into 'dest',
+    // starting from 'startLine', where 0 is the first line in the screen buffer
+    void copyFromScreen(Character* dest, int startLine, int count) const;
+    // copies 'count' lines from the history buffer into 'dest',
+    // starting from 'startLine', where 0 is the first line in the history
+    void copyFromHistory(Character* dest, int startLine, int count) const;
+
+
+    // screen image ----------------
+    int lines;
+    int columns;
+
+    typedef QVector<Character> ImageLine;      // [0..columns]
+    ImageLine*          screenLines;    // [lines]
+
+    int _scrolledLines;
+    QRect _lastScrolledRegion;
+
+    int _droppedLines;
+
+    QVarLengthArray<LineProperty,64> lineProperties;    
+    
+    // history buffer ---------------
+    HistoryScroll* history;
+    
+    // cursor location
+    int cuX;
+    int cuY;
+
+    // cursor color and rendition info
+    CharacterColor currentForeground;
+    CharacterColor currentBackground;
+    quint8 currentRendition; 
+
+    // margins ----------------
+    int _topMargin;
+    int _bottomMargin;
+
+    // states ----------------
+    int currentModes[MODES_SCREEN];
+    int savedModes[MODES_SCREEN];
+
+    // ----------------------------
+
+    QBitArray tabStops;
+
+    // selection -------------------
+    int selBegin; // The first location selected.
+    int selTopLeft;    // TopLeft Location.
+    int selBottomRight;    // Bottom Right Location.
+    bool blockSelectionMode;  // Column selection mode
+
+    // effective colors and rendition ------------
+    CharacterColor effectiveForeground; // These are derived from
+    CharacterColor effectiveBackground; // the cu_* variables above
+    quint8 effectiveRendition;          // to speed up operation
+
+    class SavedState  
+    {
+    public:
+        SavedState()
+        : cursorColumn(0),cursorLine(0),rendition(0) {}
+
+        int cursorColumn;
+        int cursorLine;
+        quint8 rendition;
+        CharacterColor foreground;
+        CharacterColor background;
+    };
+    SavedState savedState;
+        
+    // last position where we added a character
+    int lastPos;
+
+    static Character defaultChar;
+};
+
+
+#endif // SCREEN_H

=== added file 'src/ScreenWindow.cpp'
--- src/ScreenWindow.cpp	1970-01-01 00:00:00 +0000
+++ src/ScreenWindow.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,292 @@
+/*
+    Copyright (C) 2007 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+// Own
+#include "ScreenWindow.h"
+
+// Qt
+#include <QtDebug>
+
+// Konsole
+#include "Screen.h"
+
+ScreenWindow::ScreenWindow(QObject* parent)
+    : QObject(parent)
+    , _windowBuffer(0)
+    , _windowBufferSize(0)
+    , _bufferNeedsUpdate(true)
+    , _windowLines(1)
+    , _currentLine(0)
+    , _trackOutput(true)
+    , _scrollCount(0)
+{
+}
+ScreenWindow::~ScreenWindow()
+{
+    delete[] _windowBuffer;
+}
+void ScreenWindow::setScreen(Screen* screen)
+{
+    Q_ASSERT( screen );
+
+    _screen = screen;
+}
+
+Screen* ScreenWindow::screen() const
+{
+    return _screen;
+}
+
+Character* ScreenWindow::getImage()
+{
+    // reallocate internal buffer if the window size has changed
+    int size = windowLines() * windowColumns();
+    if (_windowBuffer == 0 || _windowBufferSize != size) 
+    {
+        delete[] _windowBuffer;
+        _windowBufferSize = size;
+        _windowBuffer = new Character[size];
+        _bufferNeedsUpdate = true;
+    }
+
+     if (!_bufferNeedsUpdate)
+        return _windowBuffer;
+ 
+    _screen->getImage(_windowBuffer,size,
+                      currentLine(),endWindowLine());
+
+    // this window may look beyond the end of the screen, in which 
+    // case there will be an unused area which needs to be filled
+    // with blank characters
+    fillUnusedArea();
+
+    _bufferNeedsUpdate = false;
+    return _windowBuffer;
+}
+
+void ScreenWindow::fillUnusedArea()
+{
+    int screenEndLine = _screen->getHistLines() + _screen->getLines() - 1;
+    int windowEndLine = currentLine() + windowLines() - 1;
+
+    int unusedLines = windowEndLine - screenEndLine;
+    int charsToFill = unusedLines * windowColumns();
+
+    Screen::fillWithDefaultChar(_windowBuffer + _windowBufferSize - charsToFill,charsToFill); 
+}
+
+// return the index of the line at the end of this window, or if this window 
+// goes beyond the end of the screen, the index of the line at the end
+// of the screen.
+//
+// when passing a line number to a Screen method, the line number should
+// never be more than endWindowLine()
+//
+int ScreenWindow::endWindowLine() const
+{
+    return qMin(currentLine() + windowLines() - 1,
+                lineCount() - 1);
+}
+QVector<LineProperty> ScreenWindow::getLineProperties()
+{
+    QVector<LineProperty> result = _screen->getLineProperties(currentLine(),endWindowLine());
+    
+    if (result.count() != windowLines())
+        result.resize(windowLines());
+
+    return result;
+}
+
+QString ScreenWindow::selectedText( bool preserveLineBreaks ) const
+{
+    return _screen->selectedText( preserveLineBreaks );
+}
+
+void ScreenWindow::getSelectionStart( int& column , int& line )
+{
+    _screen->getSelectionStart(column,line);
+    line -= currentLine();
+}
+void ScreenWindow::getSelectionEnd( int& column , int& line )
+{
+    _screen->getSelectionEnd(column,line);
+    line -= currentLine();
+}
+void ScreenWindow::setSelectionStart( int column , int line , bool columnMode )
+{
+    _screen->setSelectionStart( column , qMin(line + currentLine(),endWindowLine())  , columnMode);
+    
+    _bufferNeedsUpdate = true;
+    emit selectionChanged();
+}
+
+void ScreenWindow::setSelectionEnd( int column , int line )
+{
+    _screen->setSelectionEnd( column , qMin(line + currentLine(),endWindowLine()) );
+
+    _bufferNeedsUpdate = true;
+    emit selectionChanged();
+}
+
+bool ScreenWindow::isSelected( int column , int line )
+{
+    return _screen->isSelected( column , qMin(line + currentLine(),endWindowLine()) );
+}
+
+void ScreenWindow::clearSelection()
+{
+    _screen->clearSelection();
+
+    emit selectionChanged();
+}
+
+void ScreenWindow::setWindowLines(int lines)
+{
+    Q_ASSERT(lines > 0);
+    _windowLines = lines;
+}
+int ScreenWindow::windowLines() const
+{
+    return _windowLines;        
+}
+
+int ScreenWindow::windowColumns() const
+{
+    return _screen->getColumns();
+}
+
+int ScreenWindow::lineCount() const
+{
+    return _screen->getHistLines() + _screen->getLines();
+}
+
+int ScreenWindow::columnCount() const
+{
+    return _screen->getColumns();
+}
+
+QPoint ScreenWindow::cursorPosition() const
+{
+    QPoint position;
+    
+    position.setX( _screen->getCursorX() );
+    position.setY( _screen->getCursorY() );
+
+    return position; 
+}
+
+int ScreenWindow::currentLine() const
+{
+    return qBound(0,_currentLine,lineCount()-windowLines());
+}
+
+void ScreenWindow::scrollBy( RelativeScrollMode mode , int amount )
+{
+    if ( mode == ScrollLines )
+    {
+        scrollTo( currentLine() + amount );
+    }
+    else if ( mode == ScrollPages )
+    {
+        scrollTo( currentLine() + amount * ( windowLines() / 2 ) ); 
+    }
+}
+
+bool ScreenWindow::atEndOfOutput() const
+{
+    return currentLine() == (lineCount()-windowLines());
+}
+
+void ScreenWindow::scrollTo( int line )
+{
+    int maxCurrentLineNumber = lineCount() - windowLines();
+    line = qBound(0,line,maxCurrentLineNumber);
+
+    const int delta = line - _currentLine;
+    _currentLine = line;
+
+    // keep track of number of lines scrolled by,
+    // this can be reset by calling resetScrollCount()
+    _scrollCount += delta;
+
+    _bufferNeedsUpdate = true;
+
+    emit scrolled(_currentLine);
+}
+
+void ScreenWindow::setTrackOutput(bool trackOutput)
+{
+    _trackOutput = trackOutput;
+}
+
+bool ScreenWindow::trackOutput() const
+{
+    return _trackOutput;
+}
+
+int ScreenWindow::scrollCount() const
+{
+    return _scrollCount;
+}
+
+void ScreenWindow::resetScrollCount() 
+{
+    _scrollCount = 0;
+}
+
+QRect ScreenWindow::scrollRegion() const
+{
+    bool equalToScreenSize = windowLines() == _screen->getLines();
+
+    if ( atEndOfOutput() && equalToScreenSize )
+        return _screen->lastScrolledRegion();
+    else
+        return QRect(0,0,windowColumns(),windowLines());
+}
+
+void ScreenWindow::notifyOutputChanged()
+{
+    // move window to the bottom of the screen and update scroll count
+    // if this window is currently tracking the bottom of the screen
+    if ( _trackOutput )
+    { 
+        _scrollCount -= _screen->scrolledLines();
+        _currentLine = qMax(0,_screen->getHistLines() - (windowLines()-_screen->getLines()));
+    }
+    else
+    {
+        // if the history is not unlimited then it may 
+        // have run out of space and dropped the oldest
+        // lines of output - in this case the screen
+        // window's current line number will need to 
+        // be adjusted - otherwise the output will scroll
+        _currentLine = qMax(0,_currentLine - 
+                              _screen->droppedLines());
+
+        // ensure that the screen window's current position does
+        // not go beyond the bottom of the screen
+        _currentLine = qMin( _currentLine , _screen->getHistLines() );
+    }
+
+    _bufferNeedsUpdate = true;
+
+    emit outputChanged(); 
+}
+
+//#include "ScreenWindow.moc"

=== added file 'src/ScreenWindow.h'
--- src/ScreenWindow.h	1970-01-01 00:00:00 +0000
+++ src/ScreenWindow.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,257 @@
+/*
+    Copyright 2007-2008 by Robert Knight <robertknight@xxxxxxxxx>
+
+    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.
+*/
+
+#ifndef SCREENWINDOW_H
+#define SCREENWINDOW_H
+
+// Qt
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+#include <QtCore/QRect>
+
+// Konsole
+#include "Character.h"
+
+
+class Screen;
+
+/**
+ * Provides a window onto a section of a terminal screen.  A terminal widget can then render
+ * the contents of the window and use the window to change the terminal screen's selection 
+ * in response to mouse or keyboard input.
+ *
+ * A new ScreenWindow for a terminal session can be created by calling Emulation::createWindow()
+ *
+ * Use the scrollTo() method to scroll the window up and down on the screen.
+ * Use the getImage() method to retrieve the character image which is currently visible in the window.
+ *
+ * setTrackOutput() controls whether the window moves to the bottom of the associated screen when new
+ * lines are added to it.
+ *
+ * Whenever the output from the underlying screen is changed, the notifyOutputChanged() slot should
+ * be called.  This in turn will update the window's position and emit the outputChanged() signal
+ * if necessary.
+ */
+class ScreenWindow : public QObject
+{
+Q_OBJECT
+
+public:
+    /** 
+     * Constructs a new screen window with the given parent.
+     * A screen must be specified by calling setScreen() before calling getImage() or getLineProperties().
+     *
+     * You should not call this constructor directly, instead use the Emulation::createWindow() method
+     * to create a window on the emulation which you wish to view.  This allows the emulation
+     * to notify the window when the associated screen has changed and synchronize selection updates
+     * between all views on a session.
+     */
+    ScreenWindow(QObject* parent = 0);
+    virtual ~ScreenWindow();
+
+    /** Sets the screen which this window looks onto */
+    void setScreen(Screen* screen);
+    /** Returns the screen which this window looks onto */
+    Screen* screen() const;
+
+    /** 
+     * Returns the image of characters which are currently visible through this window
+     * onto the screen.
+     *
+     * The returned buffer is managed by the ScreenWindow instance and does not need to be
+     * deleted by the caller.
+     */
+    Character* getImage();
+
+    /**
+     * Returns the line attributes associated with the lines of characters which
+     * are currently visible through this window
+     */
+    QVector<LineProperty> getLineProperties();
+
+    /**
+     * Returns the number of lines which the region of the window
+     * specified by scrollRegion() has been scrolled by since the last call 
+     * to resetScrollCount().  scrollRegion() is in most cases the 
+     * whole window, but will be a smaller area in, for example, applications
+     * which provide split-screen facilities.
+     *
+     * This is not guaranteed to be accurate, but allows views to optimize
+     * rendering by reducing the amount of costly text rendering that
+     * needs to be done when the output is scrolled. 
+     */
+    int scrollCount() const;
+
+    /**
+     * Resets the count of scrolled lines returned by scrollCount()
+     */
+    void resetScrollCount();
+
+    /**
+     * Returns the area of the window which was last scrolled, this is 
+     * usually the whole window area.
+     *
+     * Like scrollCount(), this is not guaranteed to be accurate,
+     * but allows views to optimize rendering.
+     */
+    QRect scrollRegion() const;
+
+    /** 
+     * Sets the start of the selection to the given @p line and @p column within 
+     * the window.
+     */
+    void setSelectionStart( int column , int line , bool columnMode );
+    /**
+     * Sets the end of the selection to the given @p line and @p column within
+     * the window.
+     */
+    void setSelectionEnd( int column , int line ); 
+    /**
+     * Retrieves the start of the selection within the window.
+     */
+    void getSelectionStart( int& column , int& line );
+    /**
+     * Retrieves the end of the selection within the window.
+     */
+    void getSelectionEnd( int& column , int& line );
+    /**
+     * Returns true if the character at @p line , @p column is part of the selection.
+     */
+    bool isSelected( int column , int line );
+    /** 
+     * Clears the current selection
+     */
+    void clearSelection();
+
+    /** Sets the number of lines in the window */
+    void setWindowLines(int lines);
+    /** Returns the number of lines in the window */
+    int windowLines() const;
+    /** Returns the number of columns in the window */
+    int windowColumns() const;
+    
+    /** Returns the total number of lines in the screen */
+    int lineCount() const;
+    /** Returns the total number of columns in the screen */
+    int columnCount() const;
+
+    /** Returns the index of the line which is currently at the top of this window */
+    int currentLine() const;
+
+    /** 
+     * Returns the position of the cursor 
+     * within the window.
+     */
+    QPoint cursorPosition() const;
+
+    /** 
+     * Convenience method. Returns true if the window is currently at the bottom
+     * of the screen.
+     */
+    bool atEndOfOutput() const;
+
+    /** Scrolls the window so that @p line is at the top of the window */
+    void scrollTo( int line );
+
+    /** Describes the units which scrollBy() moves the window by. */
+    enum RelativeScrollMode
+    {
+        /** Scroll the window down by a given number of lines. */
+        ScrollLines,
+        /** 
+         * Scroll the window down by a given number of pages, where
+         * one page is windowLines() lines
+         */
+        ScrollPages
+    };
+
+    /** 
+     * Scrolls the window relative to its current position on the screen.
+     *
+     * @param mode Specifies whether @p amount refers to the number of lines or the number
+     * of pages to scroll.    
+     * @param amount The number of lines or pages ( depending on @p mode ) to scroll by.  If
+     * this number is positive, the view is scrolled down.  If this number is negative, the view
+     * is scrolled up.
+     */
+    void scrollBy( RelativeScrollMode mode , int amount );
+
+    /** 
+     * Specifies whether the window should automatically move to the bottom
+     * of the screen when new output is added.
+     *
+     * If this is set to true, the window will be moved to the bottom of the associated screen ( see 
+     * screen() ) when the notifyOutputChanged() method is called.
+     */
+    void setTrackOutput(bool trackOutput);
+    /** 
+     * Returns whether the window automatically moves to the bottom of the screen as
+     * new output is added.  See setTrackOutput()
+     */
+    bool trackOutput() const;
+
+    /**
+     * Returns the text which is currently selected.
+     *
+     * @param preserveLineBreaks See Screen::selectedText()
+     */
+    QString selectedText( bool preserveLineBreaks ) const;
+
+public slots:
+    /** 
+     * Notifies the window that the contents of the associated terminal screen have changed.
+     * This moves the window to the bottom of the screen if trackOutput() is true and causes
+     * the outputChanged() signal to be emitted.
+     */
+    void notifyOutputChanged();
+
+signals:
+    /**
+     * Emitted when the contents of the associated terminal screen (see screen()) changes. 
+     */
+    void outputChanged();
+
+    /**
+     * Emitted when the screen window is scrolled to a different position.
+     * 
+     * @param line The line which is now at the top of the window.
+     */
+    void scrolled(int line);
+
+    /** Emitted when the selection is changed. */
+    void selectionChanged();
+
+private:
+    int endWindowLine() const;
+    void fillUnusedArea();
+
+    Screen* _screen; // see setScreen() , screen()
+    Character* _windowBuffer;
+    int _windowBufferSize;
+    bool _bufferNeedsUpdate;
+
+    int  _windowLines;
+    int  _currentLine; // see scrollTo() , currentLine()
+    bool _trackOutput; // see setTrackOutput() , trackOutput() 
+    int  _scrollCount; // count of lines which the window has been scrolled by since
+                       // the last call to resetScrollCount()
+};
+
+
+#endif // SCREENWINDOW_H

=== added file 'src/Session.cpp'
--- src/Session.cpp	1970-01-01 00:00:00 +0000
+++ src/Session.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,1064 @@
+/*
+    This file is part of Konsole
+
+    Copyright (C) 2006-2007 by Robert Knight <robertknight@xxxxxxxxx>
+    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    Rewritten for QT4     by e_k      <e_k at users.sourceforge.net>, Copyright (C) 2008
+    Rewritten for QT5/QML by Dmitry Zagnoyko   <hiroshidi@xxxxxxxxx>, Copyright (C) 2013
+
+    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.
+*/
+
+// Own
+#include "Session.h"
+
+// Standard
+#include <assert.h>
+#include <stdlib.h>
+
+// Qt
+#include <QGuiApplication>
+#include <QtGui/QWindow>
+
+#include <QtCore/QByteRef>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+#include <QtCore/QFile>
+#include <QtCore>
+
+#include "Pty.h" // REUSE THIS
+//#include "kptyprocess.h"
+#include "TerminalDisplay.h"
+#include "ShellCommand.h" // REUSE THIS
+#include "Vt102Emulation.h" // REUSE THIS
+
+
+int Session::lastSessionId = 0;
+
+Session::Session() :
+        _shellProcess(0)
+        , _emulation(0)
+        , _monitorActivity(false)
+        , _monitorSilence(false)
+        , _notifiedActivity(false)
+        , _autoClose(true)
+        , _wantedClose(false)
+        , _silenceSeconds(10)
+        , _addToUtmp(false)  // disabled by default because of a bug encountered on certain systems
+        // which caused Konsole to hang when closing a tab and then opening a new
+        // one.  A 'QProcess destroyed while still running' warning was being
+        // printed to the terminal.  Likely a problem in KPty::logout()
+        // or KPty::login() which uses a QProcess to start /usr/bin/utempter
+        , _flowControl(true)
+        , _fullScripting(false)
+        , _sessionId(0)
+//   , _zmodemBusy(false)
+//   , _zmodemProc(0)
+//   , _zmodemProgress(0)
+        , _hasDarkBackground(false)
+{
+    //prepare DBus communication
+//    new SessionAdaptor(this);
+    _sessionId = ++lastSessionId;
+//    QDBusConnection::sessionBus().registerObject(QLatin1String("/Sessions/")+QString::number(_sessionId), this);
+
+    //create teletype for I/O with shell process
+    _shellProcess = new Pty();
+
+    //create emulation backend
+    _emulation = new Vt102Emulation();
+
+    connect( _emulation, SIGNAL( titleChanged( int, const QString & ) ),
+             this, SLOT( setUserTitle( int, const QString & ) ) );
+    connect( _emulation, SIGNAL( stateSet(int) ),
+             this, SLOT( activityStateSet(int) ) );
+//    connect( _emulation, SIGNAL( zmodemDetected() ), this ,
+//            SLOT( fireZModemDetected() ) );
+    connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ),
+             this, SIGNAL( changeTabTextColorRequest( int ) ) );
+    connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString &)),
+             this, SIGNAL( profileChangeCommandReceived(const QString &)) );
+    // TODO
+    // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this ,
+    //        SLOT(onEmulationSizeChange(int,int)) );
+
+    //connect teletype to emulation backend
+    _shellProcess->setUtf8Mode(_emulation->utf8());
+
+    connect( _shellProcess,SIGNAL(receivedData(const char *,int)),this,
+             SLOT(onReceiveBlock(const char *,int)) );
+    connect( _emulation,SIGNAL(sendData(const char *,int)),_shellProcess,
+             SLOT(sendData(const char *,int)) );
+    connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) );
+    connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) );
+
+    connect( _shellProcess,SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(done(int)) );
+    // not in kprocess anymore connect( _shellProcess,SIGNAL(done(int)), this, SLOT(done(int)) );
+
+    //setup timer for monitoring session activity
+    _monitorTimer = new QTimer(this);
+    _monitorTimer->setSingleShot(true);
+    connect(_monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone()));
+}
+
+WId Session::windowId() const
+{
+    // Returns a window ID for this session which is used
+    // to set the WINDOWID environment variable in the shell
+    // process.
+    //
+    // Sessions can have multiple views or no views, which means
+    // that a single ID is not always going to be accurate.
+    //
+    // If there are no views, the window ID is just 0.  If
+    // there are multiple views, then the window ID for the
+    // top-level window which contains the first view is
+    // returned
+
+    if ( _views.count() == 0 ) {
+        return 0;
+    } else {
+//        QQuickItem * window = _views.first();
+
+//        Q_ASSERT( window );
+
+//        while ( window->parentWidget() != 0 ) {
+//            window = window->parentWidget();
+//        }
+
+        return QGuiApplication::focusWindow()->winId();
+    }
+}
+
+void Session::setDarkBackground(bool darkBackground)
+{
+    _hasDarkBackground = darkBackground;
+}
+bool Session::hasDarkBackground() const
+{
+    return _hasDarkBackground;
+}
+bool Session::isRunning() const
+{
+    return _shellProcess->state() == QProcess::Running;
+}
+
+void Session::setCodec(QTextCodec * codec)
+{
+    emulation()->setCodec(codec);
+}
+
+void Session::setProgram(const QString & program)
+{
+    _program = ShellCommand::expand(program);
+}
+void Session::setInitialWorkingDirectory(const QString & dir)
+{
+    _initialWorkingDir = ShellCommand::expand(dir);
+}
+void Session::setArguments(const QStringList & arguments)
+{
+    _arguments = ShellCommand::expand(arguments);
+}
+
+QList<KTerminalDisplay *> Session::views() const
+{
+    return _views;
+}
+
+void Session::addView(KTerminalDisplay * widget)
+{
+    Q_ASSERT( !_views.contains(widget) );
+
+    _views.append(widget);
+
+    if ( _emulation != 0 ) {
+        // connect emulation - view signals and slots
+        connect( widget , SIGNAL(keyPressedSignal(QKeyEvent *)) , _emulation ,
+                 SLOT(sendKeyEvent(QKeyEvent *)) );
+//        connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation ,
+//                 SLOT(sendMouseEvent(int,int,int,int)) );
+//        connect( widget , SIGNAL(sendStringToEmu(const char *)) , _emulation ,
+//                 SLOT(sendString(const char *)) );
+
+        // allow emulation to notify view when the foreground process
+        // indicates whether or not it is interested in mouse signals
+//        connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget ,
+//                 SLOT(setUsesMouse(bool)) );
+
+        //widget->setUsesMouse( _emulation->programUsesMouse() );
+
+        widget->setScreenWindow(_emulation->createWindow());
+    }
+
+    //connect view signals and slots
+    QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this,
+                      SLOT(onViewSizeChange(int,int)));
+
+    QObject::connect( widget ,SIGNAL(destroyed(QObject *)) , this ,
+                      SLOT(viewDestroyed(QObject *)) );
+//slot for close
+    //QObject::connect(this, SIGNAL(finished()), widget, SLOT(close()));
+
+}
+
+void Session::viewDestroyed(QObject * view)
+{
+    KTerminalDisplay * display = (KTerminalDisplay *)view;
+
+    Q_ASSERT( _views.contains(display) );
+
+    removeView(display);
+}
+
+void Session::removeView(KTerminalDisplay * widget)
+{
+    _views.removeAll(widget);
+
+    disconnect(widget,0,this,0);
+
+    if ( _emulation != 0 ) {
+        // disconnect
+        //  - key presses signals from widget
+        //  - mouse activity signals from widget
+        //  - string sending signals from widget
+        //
+        //  ... and any other signals connected in addView()
+        disconnect( widget, 0, _emulation, 0);
+
+        // disconnect state change signals emitted by emulation
+        disconnect( _emulation , 0 , widget , 0);
+    }
+
+    // close the session automatically when the last view is removed
+    if ( _views.count() == 0 ) {
+        close();
+    }
+}
+
+void Session::run()
+{
+    //check that everything is in place to run the session
+//    if (_program.isEmpty()) {
+//        qDebug() << "Session::run() - program to run not set.";
+//    }
+//    else {
+//        qDebug() << "Session::run() - program:" << _program;
+//    }
+
+//    if (_arguments.isEmpty()) {
+//        qDebug() << "Session::run() - no command line arguments specified.";
+//    }
+//    else {
+//        qDebug() << "Session::run() - arguments:" << _arguments;
+//    }
+
+    // Upon a KPty error, there is no description on what that error was...
+    // Check to see if the given program is executable.
+
+
+    /* ok iam not exactly sure where _program comes from - however it was set to /bin/bash on my system
+     * Thats bad for BSD as its /usr/local/bin/bash there - its also bad for arch as its /usr/bin/bash there too!
+     * So i added a check to see if /bin/bash exists - if no then we use $SHELL - if that does not exist either, we fall back to /bin/sh
+     * As far as i know /bin/sh exists on every unix system.. You could also just put some ifdef __FREEBSD__ here but i think these 2 filechecks are worth
+     * their computing time on any system - especially with the problem on arch linux beeing there too.
+     */
+    QString exec = QFile::encodeName(_program);
+    // if 'exec' is not specified, fall back to default shell.  if that
+    // is not set then fall back to /bin/sh
+
+    // here we expect full path. If there is no fullpath let's expect it's
+    // a custom shell (eg. python, etc.) available in the PATH.
+    if (exec.startsWith("/"))
+    {
+        QFile excheck(exec);
+        if ( exec.isEmpty() || !excheck.exists() ) {
+            exec = getenv("SHELL");
+        }
+        excheck.setFileName(exec);
+
+        if ( exec.isEmpty() || !excheck.exists() ) {
+            exec = "/bin/sh";
+        }
+    }
+
+    // _arguments sometimes contain ("") so isEmpty()
+    // or count() does not work as expected...
+    QString argsTmp(_arguments.join(" ").trimmed());
+    QStringList arguments;
+    arguments << exec;
+    if (argsTmp.length())
+        arguments << _arguments;
+
+    QString cwd = QDir::currentPath();
+    if (!_initialWorkingDir.isEmpty()) {
+        _shellProcess->setWorkingDirectory(_initialWorkingDir);
+    } else {
+        _shellProcess->setWorkingDirectory(cwd);
+    }
+
+    _shellProcess->setFlowControlEnabled(_flowControl);
+    _shellProcess->setErase(_emulation->eraseChar());
+
+    // this is not strictly accurate use of the COLORFGBG variable.  This does not
+    // tell the terminal exactly which colors are being used, but instead approximates
+    // the color scheme as "black on white" or "white on black" depending on whether
+    // the background color is deemed dark or not
+    QString backgroundColorHint = _hasDarkBackground ? "COLORFGBG=15;0" : "COLORFGBG=0;15";
+
+    /* if we do all the checking if this shell exists then we use it ;)
+     * Dont know about the arguments though.. maybe youll need some more checking im not sure
+     * However this works on Arch and FreeBSD now.
+     */
+    int result = _shellProcess->start(exec,
+                                      arguments,
+                                      _environment << backgroundColorHint,
+                                      windowId(),
+                                      _addToUtmp);
+
+    if (result < 0) {
+        qDebug() << "CRASHED! result: " << result;
+        return;
+    }
+
+    _shellProcess->setWriteable(false);  // We are reachable via kwrited.
+    //qDebug() << "started!";
+    emit started();
+}
+
+void Session::setUserTitle( int what, const QString & caption )
+{
+    //set to true if anything is actually changed (eg. old _nameTitle != new _nameTitle )
+    bool modified = false;
+
+    // (btw: what=0 changes _userTitle and icon, what=1 only icon, what=2 only _nameTitle
+    if ((what == 0) || (what == 2)) {
+        if ( _userTitle != caption ) {
+            _userTitle = caption;
+            modified = true;
+        }
+    }
+
+    if ((what == 0) || (what == 1)) {
+        if ( _iconText != caption ) {
+            _iconText = caption;
+            modified = true;
+        }
+    }
+
+    if (what == 11) {
+        QString colorString = caption.section(';',0,0);
+        qDebug() << __FILE__ << __LINE__ << ": setting background colour to " << colorString;
+        QColor backColor = QColor(colorString);
+        if (backColor.isValid()) { // change color via \033]11;Color\007
+            if (backColor != _modifiedBackground) {
+                _modifiedBackground = backColor;
+
+                // bail out here until the code to connect the terminal display
+                // to the changeBackgroundColor() signal has been written
+                // and tested - just so we don't forget to do this.
+                Q_ASSERT( 0 );
+
+                emit changeBackgroundColorRequest(backColor);
+            }
+        }
+    }
+
+    if (what == 30) {
+        if ( _nameTitle != caption ) {
+            setTitle(Session::NameRole,caption);
+            return;
+        }
+    }
+
+    if (what == 31) {
+        QString cwd=caption;
+        cwd=cwd.replace( QRegExp("^~"), QDir::homePath() );
+        emit openUrlRequest(cwd);
+    }
+
+    // change icon via \033]32;Icon\007
+    if (what == 32) {
+        if ( _iconName != caption ) {
+            _iconName = caption;
+
+            modified = true;
+        }
+    }
+
+    if (what == 50) {
+        emit profileChangeCommandReceived(caption);
+        return;
+    }
+
+    if ( modified ) {
+        emit titleChanged();
+    }
+}
+
+QString Session::userTitle() const
+{
+    return _userTitle;
+}
+void Session::setTabTitleFormat(TabTitleContext context , const QString & format)
+{
+    if ( context == LocalTabTitle ) {
+        _localTabTitleFormat = format;
+    } else if ( context == RemoteTabTitle ) {
+        _remoteTabTitleFormat = format;
+    }
+}
+QString Session::tabTitleFormat(TabTitleContext context) const
+{
+    if ( context == LocalTabTitle ) {
+        return _localTabTitleFormat;
+    } else if ( context == RemoteTabTitle ) {
+        return _remoteTabTitleFormat;
+    }
+
+    return QString();
+}
+
+void Session::monitorTimerDone()
+{
+    //FIXME: The idea here is that the notification popup will appear to tell the user than output from
+    //the terminal has stopped and the popup will disappear when the user activates the session.
+    //
+    //This breaks with the addition of multiple views of a session.  The popup should disappear
+    //when any of the views of the session becomes active
+
+
+    //FIXME: Make message text for this notification and the activity notification more descriptive.
+    if (_monitorSilence) {
+//    KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(),
+//                    QApplication::activeWindow(),
+//                    KNotification::CloseWhenWidgetActivated);
+        emit stateChanged(NOTIFYSILENCE);
+    } else {
+        emit stateChanged(NOTIFYNORMAL);
+    }
+
+    _notifiedActivity=false;
+}
+
+void Session::activityStateSet(int state)
+{
+    if (state==NOTIFYBELL) {
+        QString s;
+        s.sprintf("Bell in session '%s'",_nameTitle.toLatin1().data());
+
+        emit bellRequest( s );
+    } else if (state==NOTIFYACTIVITY) {
+        if (_monitorSilence) {
+            _monitorTimer->start(_silenceSeconds*1000);
+        }
+
+        if ( _monitorActivity ) {
+            //FIXME:  See comments in Session::monitorTimerDone()
+            if (!_notifiedActivity) {
+//        KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(),
+//                        QApplication::activeWindow(),
+//        KNotification::CloseWhenWidgetActivated);
+                _notifiedActivity=true;
+            }
+        }
+    }
+
+    if ( state==NOTIFYACTIVITY && !_monitorActivity ) {
+        state = NOTIFYNORMAL;
+    }
+    if ( state==NOTIFYSILENCE && !_monitorSilence ) {
+        state = NOTIFYNORMAL;
+    }
+
+    emit stateChanged(state);
+}
+
+void Session::onViewSizeChange(int /*height*/, int /*width*/)
+{
+    updateTerminalSize();
+}
+void Session::onEmulationSizeChange(int lines , int columns)
+{
+    setSize( QSize(lines,columns) );
+}
+
+void Session::updateTerminalSize()
+{
+    QListIterator<KTerminalDisplay *> viewIter(_views);
+
+    int minLines = -1;
+    int minColumns = -1;
+
+    // minimum number of lines and columns that views require for
+    // their size to be taken into consideration ( to avoid problems
+    // with new view widgets which haven't yet been set to their correct size )
+    const int VIEW_LINES_THRESHOLD = 2;
+    const int VIEW_COLUMNS_THRESHOLD = 2;
+
+    //select largest number of lines and columns that will fit in all visible views
+    while ( viewIter.hasNext() ) {
+        KTerminalDisplay * view = viewIter.next();
+        if ( view->lines() >= VIEW_LINES_THRESHOLD &&
+                view->columns() >= VIEW_COLUMNS_THRESHOLD ) {
+            minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() );
+            minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() );
+        }
+    }
+
+    // backend emulation must have a _terminal of at least 1 column x 1 line in size
+    if ( minLines > 0 && minColumns > 0 ) {
+        _emulation->setImageSize( minLines , minColumns );
+        _shellProcess->setWindowSize( minLines , minColumns );
+    }
+}
+
+void Session::refresh()
+{
+    // attempt to get the shell process to redraw the display
+    //
+    // this requires the program running in the shell
+    // to cooperate by sending an update in response to
+    // a window size change
+    //
+    // the window size is changed twice, first made slightly larger and then
+    // resized back to its normal size so that there is actually a change
+    // in the window size (some shells do nothing if the
+    // new and old sizes are the same)
+    //
+    // if there is a more 'correct' way to do this, please
+    // send an email with method or patches to konsole-devel@xxxxxxx
+
+    const QSize existingSize = _shellProcess->windowSize();
+    _shellProcess->setWindowSize(existingSize.height(),existingSize.width()+1);
+    _shellProcess->setWindowSize(existingSize.height(),existingSize.width());
+}
+
+bool Session::sendSignal(int signal)
+{
+    int result = ::kill(_shellProcess->pid(),signal);
+
+     if ( result == 0 )
+     {
+         _shellProcess->waitForFinished();
+         return true;
+     }
+     else
+         return false;
+}
+
+void Session::close()
+{
+    _autoClose = true;
+    _wantedClose = true;
+    if (!_shellProcess->isRunning() || !sendSignal(SIGHUP)) {
+        // Forced close.
+        QTimer::singleShot(1, this, SIGNAL(finished()));
+    }
+}
+
+void Session::sendText(const QString &text) const
+{
+    _emulation->sendText(text);
+}
+
+void Session::sendKey(QKeyEvent *key)
+{
+    _emulation->sendKeyEvent(key);
+}
+
+Session::~Session()
+{
+    delete _emulation;
+    delete _shellProcess;
+//  delete _zmodemProc;
+}
+
+void Session::setProfileKey(const QString & key)
+{
+    _profileKey = key;
+    emit profileChanged(key);
+}
+QString Session::profileKey() const
+{
+    return _profileKey;
+}
+
+void Session::done(int exitStatus)
+{
+    if (!_autoClose) {
+        _userTitle = ("This session is done. Finished");
+        emit titleChanged();
+        return;
+    }
+
+    QString message;
+    if (!_wantedClose || exitStatus != 0) {
+
+        if (_shellProcess->exitStatus() == QProcess::NormalExit) {
+            message.sprintf("Session '%s' exited with status %d.",
+                          _nameTitle.toLatin1().data(), exitStatus);
+        } else {
+            message.sprintf("Session '%s' crashed.",
+                          _nameTitle.toLatin1().data());
+        }
+    }
+
+    if ( !_wantedClose && _shellProcess->exitStatus() != QProcess::NormalExit )
+        message.sprintf("Session '%s' exited unexpectedly.",
+                        _nameTitle.toLatin1().data());
+    else
+        emit finished();
+
+}
+
+Emulation * Session::emulation() const
+{
+    return _emulation;
+}
+
+QString Session::keyBindings() const
+{
+    return _emulation->keyBindings();
+}
+
+QStringList Session::environment() const
+{
+    return _environment;
+}
+
+void Session::setEnvironment(const QStringList & environment)
+{
+    _environment = environment;
+}
+
+int Session::sessionId() const
+{
+    return _sessionId;
+}
+
+void Session::setKeyBindings(const QString & id)
+{
+    _emulation->setKeyBindings(id);
+}
+
+void Session::setTitle(TitleRole role , const QString & newTitle)
+{
+    if ( title(role) != newTitle ) {
+        if ( role == NameRole ) {
+            _nameTitle = newTitle;
+        } else if ( role == DisplayedTitleRole ) {
+            _displayTitle = newTitle;
+        }
+
+        emit titleChanged();
+    }
+}
+
+QString Session::title(TitleRole role) const
+{
+    if ( role == NameRole ) {
+        return _nameTitle;
+    } else if ( role == DisplayedTitleRole ) {
+        return _displayTitle;
+    } else {
+        return QString();
+    }
+}
+
+void Session::setIconName(const QString & iconName)
+{
+    if ( iconName != _iconName ) {
+        _iconName = iconName;
+        emit titleChanged();
+    }
+}
+
+void Session::setIconText(const QString & iconText)
+{
+    _iconText = iconText;
+    //kDebug(1211)<<"Session setIconText " <<  _iconText;
+}
+
+QString Session::iconName() const
+{
+    return _iconName;
+}
+
+QString Session::iconText() const
+{
+    return _iconText;
+}
+
+void Session::setHistoryType(const HistoryType & hType)
+{
+    _emulation->setHistory(hType);
+}
+
+const HistoryType & Session::historyType() const
+{
+    return _emulation->history();
+}
+
+void Session::clearHistory()
+{
+    _emulation->clearHistory();
+}
+
+QStringList Session::arguments() const
+{
+    return _arguments;
+}
+
+QString Session::program() const
+{
+    return _program;
+}
+
+// unused currently
+bool Session::isMonitorActivity() const
+{
+    return _monitorActivity;
+}
+// unused currently
+bool Session::isMonitorSilence()  const
+{
+    return _monitorSilence;
+}
+
+void Session::setMonitorActivity(bool _monitor)
+{
+    _monitorActivity=_monitor;
+    _notifiedActivity=false;
+
+    activityStateSet(NOTIFYNORMAL);
+}
+
+void Session::setMonitorSilence(bool _monitor)
+{
+    if (_monitorSilence==_monitor) {
+        return;
+    }
+
+    _monitorSilence=_monitor;
+    if (_monitorSilence) {
+        _monitorTimer->start(_silenceSeconds*1000);
+    } else {
+        _monitorTimer->stop();
+    }
+
+    activityStateSet(NOTIFYNORMAL);
+}
+
+void Session::setMonitorSilenceSeconds(int seconds)
+{
+    _silenceSeconds=seconds;
+    if (_monitorSilence) {
+        _monitorTimer->start(_silenceSeconds*1000);
+    }
+}
+
+void Session::setAddToUtmp(bool set)
+{
+    _addToUtmp = set;
+}
+
+void Session::setFlowControlEnabled(bool enabled)
+{
+    if (_flowControl == enabled) {
+        return;
+    }
+
+    _flowControl = enabled;
+
+    if (_shellProcess) {
+        _shellProcess->setFlowControlEnabled(_flowControl);
+    }
+
+    emit flowControlEnabledChanged(enabled);
+}
+bool Session::flowControlEnabled() const
+{
+    return _flowControl;
+}
+//void Session::fireZModemDetected()
+//{
+//  if (!_zmodemBusy)
+//  {
+//    QTimer::singleShot(10, this, SIGNAL(zmodemDetected()));
+//    _zmodemBusy = true;
+//  }
+//}
+
+//void Session::cancelZModem()
+//{
+//  _shellProcess->sendData("\030\030\030\030", 4); // Abort
+//  _zmodemBusy = false;
+//}
+
+//void Session::startZModem(const QString &zmodem, const QString &dir, const QStringList &list)
+//{
+//  _zmodemBusy = true;
+//  _zmodemProc = new KProcess();
+//  _zmodemProc->setOutputChannelMode( KProcess::SeparateChannels );
+//
+//  *_zmodemProc << zmodem << "-v" << list;
+//
+//  if (!dir.isEmpty())
+//     _zmodemProc->setWorkingDirectory(dir);
+//
+//  _zmodemProc->start();
+//
+//  connect(_zmodemProc,SIGNAL (readyReadStandardOutput()),
+//          this, SLOT(zmodemReadAndSendBlock()));
+//  connect(_zmodemProc,SIGNAL (readyReadStandardError()),
+//          this, SLOT(zmodemReadStatus()));
+//  connect(_zmodemProc,SIGNAL (finished(int,QProcess::ExitStatus)),
+//          this, SLOT(zmodemFinished()));
+//
+//  disconnect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(onReceiveBlock(const char*,int)) );
+//  connect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(zmodemRcvBlock(const char*,int)) );
+//
+//  _zmodemProgress = new ZModemDialog(QApplication::activeWindow(), false,
+//                                    i18n("ZModem Progress"));
+//
+//  connect(_zmodemProgress, SIGNAL(user1Clicked()),
+//          this, SLOT(zmodemDone()));
+//
+//  _zmodemProgress->show();
+//}
+
+/*void Session::zmodemReadAndSendBlock()
+{
+  _zmodemProc->setReadChannel( QProcess::StandardOutput );
+  QByteArray data = _zmodemProc->readAll();
+
+  if ( data.count() == 0 )
+      return;
+
+  _shellProcess->sendData(data.constData(),data.count());
+}
+*/
+/*
+void Session::zmodemReadStatus()
+{
+  _zmodemProc->setReadChannel( QProcess::StandardError );
+  QByteArray msg = _zmodemProc->readAll();
+  while(!msg.isEmpty())
+  {
+     int i = msg.indexOf('\015');
+     int j = msg.indexOf('\012');
+     QByteArray txt;
+     if ((i != -1) && ((j == -1) || (i < j)))
+     {
+       msg = msg.mid(i+1);
+     }
+     else if (j != -1)
+     {
+       txt = msg.left(j);
+       msg = msg.mid(j+1);
+     }
+     else
+     {
+       txt = msg;
+       msg.truncate(0);
+     }
+     if (!txt.isEmpty())
+       _zmodemProgress->addProgressText(QString::fromLocal8Bit(txt));
+  }
+}
+*/
+/*
+void Session::zmodemRcvBlock(const char *data, int len)
+{
+  QByteArray ba( data, len );
+
+  _zmodemProc->write( ba );
+}
+*/
+/*
+void Session::zmodemFinished()
+{
+  if (_zmodemProc)
+  {
+    delete _zmodemProc;
+    _zmodemProc = 0;
+    _zmodemBusy = false;
+
+    disconnect( _shellProcess,SIGNAL(block_in(const char*,int)), this ,SLOT(zmodemRcvBlock(const char*,int)) );
+    connect( _shellProcess,SIGNAL(block_in(const char*,int)), this, SLOT(onReceiveBlock(const char*,int)) );
+
+    _shellProcess->sendData("\030\030\030\030", 4); // Abort
+    _shellProcess->sendData("\001\013\n", 3); // Try to get prompt back
+    _zmodemProgress->transferDone();
+  }
+}
+*/
+void Session::onReceiveBlock( const char * buf, int len )
+{
+    _emulation->receiveData( buf, len );
+    emit receivedData( QString::fromLatin1( buf, len ) );
+}
+
+QSize Session::size()
+{
+    return _emulation->imageSize();
+}
+
+void Session::setSize(const QSize & size)
+{
+    if ((size.width() <= 1) || (size.height() <= 1)) {
+        return;
+    }
+
+    emit resizeRequest(size);
+}
+int Session::foregroundProcessId() const
+{
+    return _shellProcess->foregroundProcessGroup();
+}
+int Session::processId() const
+{
+    return _shellProcess->pid();
+}
+
+SessionGroup::SessionGroup()
+        : _masterMode(0)
+{
+}
+SessionGroup::~SessionGroup()
+{
+    // disconnect all
+    connectAll(false);
+}
+int SessionGroup::masterMode() const
+{
+    return _masterMode;
+}
+QList<Session *> SessionGroup::sessions() const
+{
+    return _sessions.keys();
+}
+bool SessionGroup::masterStatus(Session * session) const
+{
+    return _sessions[session];
+}
+
+void SessionGroup::addSession(Session * session)
+{
+    _sessions.insert(session,false);
+
+    QListIterator<Session *> masterIter(masters());
+
+    while ( masterIter.hasNext() ) {
+        connectPair(masterIter.next(),session);
+    }
+}
+void SessionGroup::removeSession(Session * session)
+{
+    setMasterStatus(session,false);
+
+    QListIterator<Session *> masterIter(masters());
+
+    while ( masterIter.hasNext() ) {
+        disconnectPair(masterIter.next(),session);
+    }
+
+    _sessions.remove(session);
+}
+void SessionGroup::setMasterMode(int mode)
+{
+    _masterMode = mode;
+
+    connectAll(false);
+    connectAll(true);
+}
+QList<Session *> SessionGroup::masters() const
+{
+    return _sessions.keys(true);
+}
+void SessionGroup::connectAll(bool connect)
+{
+    QListIterator<Session *> masterIter(masters());
+
+    while ( masterIter.hasNext() ) {
+        Session * master = masterIter.next();
+
+        QListIterator<Session *> otherIter(_sessions.keys());
+        while ( otherIter.hasNext() ) {
+            Session * other = otherIter.next();
+
+            if ( other != master ) {
+                if ( connect ) {
+                    connectPair(master,other);
+                } else {
+                    disconnectPair(master,other);
+                }
+            }
+        }
+    }
+}
+void SessionGroup::setMasterStatus(Session * session, bool master)
+{
+    bool wasMaster = _sessions[session];
+    _sessions[session] = master;
+
+    if ((!wasMaster && !master)
+            || (wasMaster && master)) {
+        return;
+    }
+
+    QListIterator<Session *> iter(_sessions.keys());
+    while (iter.hasNext()) {
+        Session * other = iter.next();
+
+        if (other != session) {
+            if (master) {
+                connectPair(session, other);
+            } else {
+                disconnectPair(session, other);
+            }
+        }
+    }
+}
+
+void SessionGroup::connectPair(Session * master , Session * other)
+{
+//    qDebug() << k_funcinfo;
+
+    if ( _masterMode & CopyInputToAll ) {
+        qDebug() << "Connection session " << master->nameTitle() << "to" << other->nameTitle();
+
+        connect( master->emulation() , SIGNAL(sendData(const char *,int)) , other->emulation() ,
+                 SLOT(sendString(const char *,int)) );
+    }
+}
+void SessionGroup::disconnectPair(Session * master , Session * other)
+{
+//    qDebug() << k_funcinfo;
+
+    if ( _masterMode & CopyInputToAll ) {
+        qDebug() << "Disconnecting session " << master->nameTitle() << "from" << other->nameTitle();
+
+        disconnect( master->emulation() , SIGNAL(sendData(const char *,int)) , other->emulation() ,
+                    SLOT(sendString(const char *,int)) );
+    }
+}
+
+//#include "moc_Session.cpp"

=== added file 'src/Session.h'
--- src/Session.h	1970-01-01 00:00:00 +0000
+++ src/Session.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,626 @@
+/*
+    This file is part of Konsole, an X terminal.
+
+    Copyright (C) 2007 by Robert Knight <robertknight@xxxxxxxxx>
+    Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@xxxxxxxxxx>
+
+    Rewritten for QT4     by e_k      <e_k at users.sourceforge.net>, Copyright (C) 2008
+    Rewritten for QT5/QML by Dmitry Zagnoyko   <hiroshidi@xxxxxxxxx>, Copyright (C) 2013
+
+    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.
+*/
+
+#ifndef SESSION_H
+#define SESSION_H
+
+
+#include <QStringList>
+
+#include <QtCore/QTimer>
+#include <QtGui/QWindow>
+
+#include "History.h"
+
+class KProcess;
+
+
+class Emulation;
+class Pty;
+class KTerminalDisplay;
+//class ZModemDialog;
+
+/**
+ * Represents a terminal session consisting of a pseudo-teletype and a terminal emulation.
+ * The pseudo-teletype (or PTY) handles I/O between the terminal process and Konsole.
+ * The terminal emulation ( Emulation and subclasses ) processes the output stream from the
+ * PTY and produces a character image which is then shown on views connected to the session.
+ *
+ * Each Session can be connected to one or more views by using the addView() method.
+ * The attached views can then display output from the program running in the terminal
+ * or send input to the program in the terminal in the form of keypresses and mouse
+ * activity.
+ */
+class Session : public QObject {
+    Q_OBJECT
+
+public:
+    Q_PROPERTY(QString name READ nameTitle)
+    Q_PROPERTY(int processId READ processId)
+    Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings)
+    Q_PROPERTY(QSize size READ size WRITE setSize)
+
+    /**
+     * Constructs a new session.
+     *
+     * To start the terminal process, call the run() method,
+     * after specifying the program and arguments
+     * using setProgram() and setArguments()
+     *
+     * If no program or arguments are specified explicitly, the Session
+     * falls back to using the program specified in the SHELL environment
+     * variable.
+     */
+    Session();
+    ~Session();
+
+    /**
+     * Returns true if the session is currently running.  This will be true
+     * after run() has been called successfully.
+     */
+    bool isRunning() const;
+
+    /**
+     * Sets the profile associated with this session.
+     *
+     * @param profileKey A key which can be used to obtain the current
+     * profile settings from the SessionManager
+     */
+    void setProfileKey(const QString & profileKey);
+    /**
+     * Returns the profile key associated with this session.
+     * This can be passed to the SessionManager to obtain the current
+     * profile settings.
+     */
+    QString profileKey() const;
+
+    /**
+     * Adds a new view for this session.
+     *
+     * The viewing widget will display the output from the terminal and
+     * input from the viewing widget (key presses, mouse activity etc.)
+     * will be sent to the terminal.
+     *
+     * Views can be removed using removeView().  The session is automatically
+     * closed when the last view is removed.
+     */
+    void addView(KTerminalDisplay * widget);
+    /**
+     * Removes a view from this session.  When the last view is removed,
+     * the session will be closed automatically.
+     *
+     * @p widget will no longer display output from or send input
+     * to the terminal
+     */
+    void removeView(KTerminalDisplay * widget);
+
+    /**
+     * Returns the views connected to this session
+     */
+    QList<KTerminalDisplay *> views() const;
+
+    /**
+     * Returns the terminal emulation instance being used to encode / decode
+     * characters to / from the process.
+     */
+    Emulation * emulation() const;
+
+    /**
+     * Returns the environment of this session as a list of strings like
+     * VARIABLE=VALUE
+     */
+    QStringList environment() const;
+    /**
+     * Sets the environment for this session.
+     * @p environment should be a list of strings like
+     * VARIABLE=VALUE
+     */
+    void setEnvironment(const QStringList & environment);
+
+    /** Returns the unique ID for this session. */
+    int sessionId() const;
+
+    /**
+     * Return the session title set by the user (ie. the program running
+     * in the terminal), or an empty string if the user has not set a custom title
+     */
+    QString userTitle() const;
+
+    /**
+     * This enum describes the contexts for which separate
+     * tab title formats may be specified.
+     */
+    enum TabTitleContext {
+        /** Default tab title format */
+        LocalTabTitle,
+        /**
+         * Tab title format used session currently contains
+         * a connection to a remote computer (via SSH)
+         */
+        RemoteTabTitle
+    };
+    /**
+     * Sets the format used by this session for tab titles.
+     *
+     * @param context The context whoose format should be set.
+     * @param format The tab title format.  This may be a mixture
+     * of plain text and dynamic elements denoted by a '%' character
+     * followed by a letter.  (eg. %d for directory).  The dynamic
+     * elements available depend on the @p context
+     */
+    void setTabTitleFormat(TabTitleContext context , const QString & format);
+    /** Returns the format used by this session for tab titles. */
+    QString tabTitleFormat(TabTitleContext context) const;
+
+
+    /** Returns the arguments passed to the shell process when run() is called. */
+    QStringList arguments() const;
+    /** Returns the program name of the shell process started when run() is called. */
+    QString program() const;
+
+    /**
+     * Sets the command line arguments which the session's program will be passed when
+     * run() is called.
+     */
+    void setArguments(const QStringList & arguments);
+    /** Sets the program to be executed when run() is called. */
+    void setProgram(const QString & program);
+
+    /** Returns the session's current working directory. */
+    QString initialWorkingDirectory() {
+        return _initialWorkingDir;
+    }
+
+    /**
+     * Sets the initial working directory for the session when it is run
+     * This has no effect once the session has been started.
+     */
+    void setInitialWorkingDirectory( const QString & dir );
+
+    /**
+     * Sets the type of history store used by this session.
+     * Lines of output produced by the terminal are added
+     * to the history store.  The type of history store
+     * used affects the number of lines which can be
+     * remembered before they are lost and the storage
+     * (in memory, on-disk etc.) used.
+     */
+    void setHistoryType(const HistoryType & type);
+    /**
+     * Returns the type of history store used by this session.
+     */
+    const HistoryType & historyType() const;
+    /**
+     * Clears the history store used by this session.
+     */
+    void clearHistory();
+
+    /**
+     * Enables monitoring for activity in the session.
+     * This will cause notifySessionState() to be emitted
+     * with the NOTIFYACTIVITY state flag when output is
+     * received from the terminal.
+     */
+    void setMonitorActivity(bool);
+    /** Returns true if monitoring for activity is enabled. */
+    bool isMonitorActivity() const;
+
+    /**
+     * Enables monitoring for silence in the session.
+     * This will cause notifySessionState() to be emitted
+     * with the NOTIFYSILENCE state flag when output is not
+     * received from the terminal for a certain period of
+     * time, specified with setMonitorSilenceSeconds()
+     */
+    void setMonitorSilence(bool);
+    /**
+     * Returns true if monitoring for inactivity (silence)
+     * in the session is enabled.
+     */
+    bool isMonitorSilence()  const;
+    /** See setMonitorSilence() */
+    void setMonitorSilenceSeconds(int seconds);
+
+    /**
+     * Sets the key bindings used by this session.  The bindings
+     * specify how input key sequences are translated into
+     * the character stream which is sent to the terminal.
+     *
+     * @param id The name of the key bindings to use.  The
+     * names of available key bindings can be determined using the
+     * KeyboardTranslatorManager class.
+     */
+    void setKeyBindings(const QString & id);
+    /** Returns the name of the key bindings used by this session. */
+    QString keyBindings() const;
+
+    /**
+     * This enum describes the available title roles.
+     */
+    enum TitleRole {
+        /** The name of the session. */
+        NameRole,
+        /** The title of the session which is displayed in tabs etc. */
+        DisplayedTitleRole
+    };
+
+    /** Sets the session's title for the specified @p role to @p title. */
+    void setTitle(TitleRole role , const QString & title);
+    /** Returns the session's title for the specified @p role. */
+    QString title(TitleRole role) const;
+    /** Convenience method used to read the name property.  Returns title(Session::NameRole). */
+    QString nameTitle() const {
+        return title(Session::NameRole);
+    }
+
+    /** Sets the name of the icon associated with this session. */
+    void setIconName(const QString & iconName);
+    /** Returns the name of the icon associated with this session. */
+    QString iconName() const;
+
+    /** Sets the text of the icon associated with this session. */
+    void setIconText(const QString & iconText);
+    /** Returns the text of the icon associated with this session. */
+    QString iconText() const;
+
+    /** Specifies whether a utmp entry should be created for the pty used by this session. */
+    void setAddToUtmp(bool);
+
+    /** Sends the specified @p signal to the terminal process. */
+    bool sendSignal(int signal);
+
+    /**
+     * Specifies whether to close the session automatically when the terminal
+     * process terminates.
+     */
+    void setAutoClose(bool b) {
+        _autoClose = b;
+    }
+
+    /**
+     * Sets whether flow control is enabled for this terminal
+     * session.
+     */
+    void setFlowControlEnabled(bool enabled);
+
+    /** Returns whether flow control is enabled for this terminal session. */
+    bool flowControlEnabled() const;
+
+    /**
+     * Sends @p text to the current foreground terminal program.
+     */
+    void sendText(const QString &text) const;
+
+    /**
+     * Sends @p QKeyEvent to the current foreground terminal program.
+     */
+    void sendKey(QKeyEvent *key);
+
+    /**
+     * Returns the process id of the terminal process.
+     * This is the id used by the system API to refer to the process.
+     */
+    int processId() const;
+
+    /**
+     * Returns the process id of the terminal's foreground process.
+     * This is initially the same as processId() but can change
+     * as the user starts other programs inside the terminal.
+     */
+    int foregroundProcessId() const;
+
+    /** Returns the terminal session's window size in lines and columns. */
+    QSize size();
+    /**
+     * Emits a request to resize the session to accommodate
+     * the specified window size.
+     *
+     * @param size The size in lines and columns to request.
+     */
+    void setSize(const QSize & size);
+
+    /** Sets the text codec used by this session's terminal emulation. */
+    void setCodec(QTextCodec * codec);
+
+    /**
+     * Sets whether the session has a dark background or not.  The session
+     * uses this information to set the COLORFGBG variable in the process's
+     * environment, which allows the programs running in the terminal to determine
+     * whether the background is light or dark and use appropriate colors by default.
+     *
+     * This has no effect once the session is running.
+     */
+    void setDarkBackground(bool darkBackground);
+    /**
+     * Returns true if the session has a dark background.
+     * See setDarkBackground()
+     */
+    bool hasDarkBackground() const;
+
+    /**
+     * Attempts to get the shell program to redraw the current display area.
+     * This can be used after clearing the screen, for example, to get the
+     * shell to redraw the prompt line.
+     */
+    void refresh();
+
+//  void startZModem(const QString &rz, const QString &dir, const QStringList &list);
+//  void cancelZModem();
+//  bool isZModemBusy() { return _zmodemBusy; }
+
+public slots:
+
+    /**
+     * Starts the terminal session.
+     *
+     * This creates the terminal process and connects the teletype to it.
+     */
+    void run();
+
+    /**
+     * Closes the terminal session.  This sends a hangup signal
+     * (SIGHUP) to the terminal process and causes the done(Session*)
+     * signal to be emitted.
+     */
+    void close();
+
+    /**
+     * Changes the session title or other customizable aspects of the terminal
+     * emulation display. For a list of what may be changed see the
+     * Emulation::titleChanged() signal.
+     */
+    void setUserTitle( int, const QString & caption );
+
+signals:
+
+    /** Emitted when the terminal process starts. */
+    void started();
+
+    /**
+     * Emitted when the terminal process exits.
+     */
+    void finished();
+
+    /**
+     * Emitted when output is received from the terminal process.
+     */
+    void receivedData( const QString & text );
+
+    /** Emitted when the session's title has changed. */
+    void titleChanged();
+
+    /** Emitted when the session's profile has changed. */
+    void profileChanged(const QString & profile);
+
+    /**
+     * Emitted when the activity state of this session changes.
+     *
+     * @param state The new state of the session.  This may be one
+     * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY
+     */
+    void stateChanged(int state);
+
+    /** Emitted when a bell event occurs in the session. */
+    void bellRequest( const QString & message );
+
+    /**
+     * Requests that the color the text for any tabs associated with
+     * this session should be changed;
+     *
+     * TODO: Document what the parameter does
+     */
+    void changeTabTextColorRequest(int);
+
+    /**
+     * Requests that the background color of views on this session
+     * should be changed.
+     */
+    void changeBackgroundColorRequest(const QColor &);
+
+    /** TODO: Document me. */
+    void openUrlRequest(const QString & url);
+
+    /** TODO: Document me. */
+//  void zmodemDetected();
+
+    /**
+     * Emitted when the terminal process requests a change
+     * in the size of the terminal window.
+     *
+     * @param size The requested window size in terms of lines and columns.
+     */
+    void resizeRequest(const QSize & size);
+
+    /**
+     * Emitted when a profile change command is received from the terminal.
+     *
+     * @param text The text of the command.  This is a string of the form
+     * "PropertyName=Value;PropertyName=Value ..."
+     */
+    void profileChangeCommandReceived(const QString & text);
+
+    /**
+     * Emitted when the flow control state changes.
+     *
+     * @param enabled True if flow control is enabled or false otherwise.
+     */
+    void flowControlEnabledChanged(bool enabled);
+
+private slots:
+    void done(int);
+
+//  void fireZModemDetected();
+
+    void onReceiveBlock( const char * buffer, int len );
+    void monitorTimerDone();
+
+    void onViewSizeChange(int height, int width);
+    void onEmulationSizeChange(int lines , int columns);
+
+    void activityStateSet(int);
+
+    //automatically detach views from sessions when view is destroyed
+    void viewDestroyed(QObject * view);
+
+//  void zmodemReadStatus();
+//  void zmodemReadAndSendBlock();
+//  void zmodemRcvBlock(const char *data, int len);
+//  void zmodemFinished();
+
+private:
+
+    void updateTerminalSize();
+    WId windowId() const;
+
+    int            _uniqueIdentifier;
+
+    Pty     *_shellProcess;
+    Emulation  *  _emulation;
+
+    QList<KTerminalDisplay *> _views;
+
+    bool           _monitorActivity;
+    bool           _monitorSilence;
+    bool           _notifiedActivity;
+    bool           _masterMode;
+    bool           _autoClose;
+    bool           _wantedClose;
+    QTimer    *    _monitorTimer;
+
+    int            _silenceSeconds;
+
+    QString        _nameTitle;
+    QString        _displayTitle;
+    QString        _userTitle;
+
+    QString        _localTabTitleFormat;
+    QString        _remoteTabTitleFormat;
+
+    QString        _iconName;
+    QString        _iconText; // as set by: echo -en '\033]1;IconText\007
+    bool           _addToUtmp;
+    bool           _flowControl;
+    bool           _fullScripting;
+
+    QString        _program;
+    QStringList    _arguments;
+
+    QStringList    _environment;
+    int            _sessionId;
+
+    QString        _initialWorkingDir;
+
+    // ZModem
+//  bool           _zmodemBusy;
+//  KProcess*      _zmodemProc;
+//  ZModemDialog*  _zmodemProgress;
+
+    // Color/Font Changes by ESC Sequences
+
+    QColor         _modifiedBackground; // as set by: echo -en '\033]11;Color\007
+
+    QString        _profileKey;
+
+    bool _hasDarkBackground;
+
+    static int lastSessionId;
+
+};
+
+/**
+ * Provides a group of sessions which is divided into master and slave sessions.
+ * Activity in master sessions can be propagated to all sessions within the group.
+ * The type of activity which is propagated and method of propagation is controlled
+ * by the masterMode() flags.
+ */
+class SessionGroup : public QObject {
+    Q_OBJECT
+
+public:
+    /** Constructs an empty session group. */
+    SessionGroup();
+    /** Destroys the session group and removes all connections between master and slave sessions. */
+    ~SessionGroup();
+
+    /** Adds a session to the group. */
+    void addSession( Session * session );
+    /** Removes a session from the group. */
+    void removeSession( Session * session );
+
+    /** Returns the list of sessions currently in the group. */
+    QList<Session *> sessions() const;
+
+    /**
+     * Sets whether a particular session is a master within the group.
+     * Changes or activity in the group's master sessions may be propagated
+     * to all the sessions in the group, depending on the current masterMode()
+     *
+     * @param session The session whoose master status should be changed.
+     * @param master True to make this session a master or false otherwise
+     */
+    void setMasterStatus( Session * session , bool master );
+    /** Returns the master status of a session.  See setMasterStatus() */
+    bool masterStatus( Session * session ) const;
+
+    /**
+     * This enum describes the options for propagating certain activity or
+     * changes in the group's master sessions to all sessions in the group.
+     */
+    enum MasterMode {
+        /**
+         * Any input key presses in the master sessions are sent to all
+         * sessions in the group.
+         */
+        CopyInputToAll = 1
+    };
+
+    /**
+     * Specifies which activity in the group's master sessions is propagated
+     * to all sessions in the group.
+     *
+     * @param mode A bitwise OR of MasterMode flags.
+     */
+    void setMasterMode( int mode );
+    /**
+     * Returns a bitwise OR of the active MasterMode flags for this group.
+     * See setMasterMode()
+     */
+    int masterMode() const;
+
+private:
+    void connectPair(Session * master , Session * other);
+    void disconnectPair(Session * master , Session * other);
+    void connectAll(bool connect);
+    QList<Session *> masters() const;
+
+    // maps sessions to their master status
+    QHash<Session *,bool> _sessions;
+
+    int _masterMode;
+};
+
+
+
+#endif

=== added file 'src/ShellCommand.cpp'
--- src/ShellCommand.cpp	1970-01-01 00:00:00 +0000
+++ src/ShellCommand.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,167 @@
+/*
+    Copyright (C) 2007 by Robert Knight <robertknight@xxxxxxxxx>
+
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    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.
+*/
+
+// Own
+#include "ShellCommand.h"
+
+//some versions of gcc(4.3) require explicit include
+#include <cstdlib>
+
+
+// expands environment variables in 'text'
+// function copied from kdelibs/kio/kio/kurlcompletion.cpp
+static bool expandEnv(QString & text);
+
+ShellCommand::ShellCommand(const QString & fullCommand)
+{
+    bool inQuotes = false;
+
+    QString builder;
+
+    for ( int i = 0 ; i < fullCommand.count() ; i++ ) {
+        QChar ch = fullCommand[i];
+
+        const bool isLastChar = ( i == fullCommand.count() - 1 );
+        const bool isQuote = ( ch == '\'' || ch == '\"' );
+
+        if ( !isLastChar && isQuote ) {
+            inQuotes = !inQuotes;
+        } else {
+            if ( (!ch.isSpace() || inQuotes) && !isQuote ) {
+                builder.append(ch);
+            }
+
+            if ( (ch.isSpace() && !inQuotes) || ( i == fullCommand.count()-1 ) ) {
+                _arguments << builder;
+                builder.clear();
+            }
+        }
+    }
+}
+ShellCommand::ShellCommand(const QString & command , const QStringList & arguments)
+{
+    _arguments = arguments;
+
+    if ( !_arguments.isEmpty() ) {
+        _arguments[0] == command;
+    }
+}
+QString ShellCommand::fullCommand() const
+{
+    return _arguments.join(QChar(' '));
+}
+QString ShellCommand::command() const
+{
+    if ( !_arguments.isEmpty() ) {
+        return _arguments[0];
+    } else {
+        return QString();
+    }
+}
+QStringList ShellCommand::arguments() const
+{
+    return _arguments;
+}
+bool ShellCommand::isRootCommand() const
+{
+    Q_ASSERT(0); // not implemented yet
+    return false;
+}
+bool ShellCommand::isAvailable() const
+{
+    Q_ASSERT(0); // not implemented yet
+    return false;
+}
+QStringList ShellCommand::expand(const QStringList & items)
+{
+    QStringList result;
+
+    foreach( QString item , items )
+    result << expand(item);
+
+    return result;
+}
+QString ShellCommand::expand(const QString & text)
+{
+    QString result = text;
+    expandEnv(result);
+    return result;
+}
+
+/*
+ * expandEnv
+ *
+ * Expand environment variables in text. Escaped '$' characters are ignored.
+ * Return true if any variables were expanded
+ */
+static bool expandEnv( QString & text )
+{
+    // Find all environment variables beginning with '$'
+    //
+    int pos = 0;
+
+    bool expanded = false;
+
+    while ( (pos = text.indexOf(QLatin1Char('$'), pos)) != -1 ) {
+
+        // Skip escaped '$'
+        //
+        if ( pos > 0 && text.at(pos-1) == QLatin1Char('\\') ) {
+            pos++;
+        }
+        // Variable found => expand
+        //
+        else {
+            // Find the end of the variable = next '/' or ' '
+            //
+            int pos2 = text.indexOf( QLatin1Char(' '), pos+1 );
+            int pos_tmp = text.indexOf( QLatin1Char('/'), pos+1 );
+
+            if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) ) {
+                pos2 = pos_tmp;
+            }
+
+            if ( pos2 == -1 ) {
+                pos2 = text.length();
+            }
+
+            // Replace if the variable is terminated by '/' or ' '
+            // and defined
+            //
+            if ( pos2 >= 0 ) {
+                int len = pos2 - pos;
+                QString key = text.mid( pos+1, len-1);
+                QString value =
+                    QString::fromLocal8Bit( ::getenv(key.toLocal8Bit()) );
+
+                if ( !value.isEmpty() ) {
+                    expanded = true;
+                    text.replace( pos, len, value );
+                    pos = pos + value.length();
+                } else {
+                    pos = pos2;
+                }
+            }
+        }
+    }
+
+    return expanded;
+}

=== added file 'src/ShellCommand.h'
--- src/ShellCommand.h	1970-01-01 00:00:00 +0000
+++ src/ShellCommand.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,90 @@
+/*
+    Copyright (C) 2007 by Robert Knight <robertknight@xxxxxxxxx>
+
+    Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
+
+    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.
+*/
+
+#ifndef SHELLCOMMAND_H
+#define SHELLCOMMAND_H
+
+// Qt
+#include <QtCore/QStringList>
+
+
+/**
+ * A class to parse and extract information about shell commands.
+ *
+ * ShellCommand can be used to:
+ *
+ * <ul>
+ *      <li>Take a command-line (eg "/bin/sh -c /path/to/my/script") and split it
+ *          into its component parts (eg. the command "/bin/sh" and the arguments
+ *          "-c","/path/to/my/script")
+ *      </li>
+ *      <li>Take a command and a list of arguments and combine them to
+ *          form a complete command line.
+ *      </li>
+ *      <li>Determine whether the binary specified by a command exists in the
+ *          user's PATH.
+ *      </li>
+ *      <li>Determine whether a command-line specifies the execution of
+ *          another command as the root user using su/sudo etc.
+ *      </li>
+ * </ul>
+ */
+class ShellCommand {
+public:
+    /**
+     * Constructs a ShellCommand from a command line.
+     *
+     * @param fullCommand The command line to parse.
+     */
+    ShellCommand(const QString & fullCommand);
+    /**
+     * Constructs a ShellCommand with the specified @p command and @p arguments.
+     */
+    ShellCommand(const QString & command , const QStringList & arguments);
+
+    /** Returns the command. */
+    QString command() const;
+    /** Returns the arguments. */
+    QStringList arguments() const;
+
+    /**
+     * Returns the full command line.
+     */
+    QString fullCommand() const;
+
+    /** Returns true if this is a root command. */
+    bool isRootCommand() const;
+    /** Returns true if the program specified by @p command() exists. */
+    bool isAvailable() const;
+
+    /** Expands environment variables in @p text .*/
+    static QString expand(const QString & text);
+
+    /** Expands environment variables in each string in @p list. */
+    static QStringList expand(const QStringList & items);
+
+private:
+    QStringList _arguments;
+};
+
+
+#endif // SHELLCOMMAND_H
+

=== added file 'src/TerminalCharacterDecoder.cpp'
--- src/TerminalCharacterDecoder.cpp	1970-01-01 00:00:00 +0000
+++ src/TerminalCharacterDecoder.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,251 @@
+/*
+    This file is part of Konsole, an X terminal.
+    
+    Copyright 2006-2008 by Robert Knight <robertknight@xxxxxxxxx>
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser 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.
+*/
+
+// Own
+#include "TerminalCharacterDecoder.h"
+
+// Qt
+#include <QtCore/QTextStream>
+
+// KDE
+//#include <kdebug.h>
+
+// Konsole
+#include "konsole_wcwidth.h"
+
+
+PlainTextDecoder::PlainTextDecoder()
+ : _output(0)
+ , _includeTrailingWhitespace(true)
+ , _recordLinePositions(false)
+{
+
+}
+void PlainTextDecoder::setTrailingWhitespace(bool enable)
+{
+    _includeTrailingWhitespace = enable;
+}
+bool PlainTextDecoder::trailingWhitespace() const
+{
+    return _includeTrailingWhitespace;
+}
+void PlainTextDecoder::begin(QTextStream* output)
+{
+   _output = output;
+   if (!_linePositions.isEmpty())
+       _linePositions.clear();
+}
+void PlainTextDecoder::end()
+{
+    _output = 0;
+}
+
+void PlainTextDecoder::setRecordLinePositions(bool record)
+{
+    _recordLinePositions = record;
+}
+QList<int> PlainTextDecoder::linePositions() const
+{
+    return _linePositions;
+}
+void PlainTextDecoder::decodeLine(const Character* const characters, int count, LineProperty /*properties*/
+                             )
+{
+    Q_ASSERT( _output );
+
+    if (_recordLinePositions && _output->string())
+    {
+        int pos = _output->string()->count();
+        _linePositions << pos;
+    }
+
+    //TODO should we ignore or respect the LINE_WRAPPED line property?
+
+    //note:  we build up a QString and send it to the text stream rather writing into the text
+    //stream a character at a time because it is more efficient.
+    //(since QTextStream always deals with QStrings internally anyway)
+    QString plainText;
+    plainText.reserve(count);
+   
+    int outputCount = count;
+
+    // if inclusion of trailing whitespace is disabled then find the end of the
+    // line
+    if ( !_includeTrailingWhitespace )
+    {
+        for (int i = count-1 ; i >= 0 ; i--)
+        {
+            if ( characters[i].character != ' '  )
+                break;
+            else
+                outputCount--;
+        }
+    }
+    
+    for (int i=0;i<outputCount;)
+    {
+        plainText.append( QChar(characters[i].character) );
+        i += qMax(1,konsole_wcwidth(characters[i].character));
+    }
+    *_output << plainText;
+}
+
+HTMLDecoder::HTMLDecoder() :
+        _output(0)
+    ,_colorTable(base_color_table)
+       ,_innerSpanOpen(false)
+       ,_lastRendition(DEFAULT_RENDITION)
+{
+    
+}
+
+void HTMLDecoder::begin(QTextStream* output)
+{
+    _output = output;
+
+    QString text;
+
+    //open monospace span
+    openSpan(text,"font-family:monospace");
+
+    *output << text;
+}
+
+void HTMLDecoder::end()
+{
+    Q_ASSERT( _output );
+
+    QString text;
+
+    closeSpan(text);
+
+    *_output << text;
+
+    _output = 0;
+
+}
+
+//TODO: Support for LineProperty (mainly double width , double height)
+void HTMLDecoder::decodeLine(const Character* const characters, int count, LineProperty /*properties*/
+                            )
+{
+    Q_ASSERT( _output );
+
+    QString text;
+
+    int spaceCount = 0;
+        
+    for (int i=0;i<count;i++)
+    {
+        QChar ch(characters[i].character);
+
+        //check if appearance of character is different from previous char
+        if ( characters[i].rendition != _lastRendition  ||
+             characters[i].foregroundColor != _lastForeColor  ||
+             characters[i].backgroundColor != _lastBackColor )
+        {
+            if ( _innerSpanOpen )
+                    closeSpan(text);
+
+            _lastRendition = characters[i].rendition;
+            _lastForeColor = characters[i].foregroundColor;
+            _lastBackColor = characters[i].backgroundColor;
+            
+            //build up style string
+            QString style;
+
+            bool useBold;
+            ColorEntry::FontWeight weight = characters[i].fontWeight(_colorTable);
+            if (weight == ColorEntry::UseCurrentFormat)
+                useBold = _lastRendition & RE_BOLD;
+            else
+                useBold = weight == ColorEntry::Bold;
+            
+            if (useBold)
+                style.append("font-weight:bold;");
+
+            if ( _lastRendition & RE_UNDERLINE )
+                    style.append("font-decoration:underline;");
+        
+            //colours - a colour table must have been defined first
+            if ( _colorTable )    
+            {
+                style.append( QString("color:%1;").arg(_lastForeColor.color(_colorTable).name() ) );
+
+                if (!characters[i].isTransparent(_colorTable))
+                {
+                    style.append( QString("background-color:%1;").arg(_lastBackColor.color(_colorTable).name() ) );
+                }
+            }
+        
+            //open the span with the current style    
+            openSpan(text,style);
+            _innerSpanOpen = true;
+        }
+
+        //handle whitespace
+        if (ch.isSpace())
+            spaceCount++;
+        else
+            spaceCount = 0;
+        
+
+        //output current character
+        if (spaceCount < 2)
+        {
+            //escape HTML tag characters and just display others as they are
+            if ( ch == '<' )
+                text.append("&lt;");
+            else if (ch == '>')
+                    text.append("&gt;");
+            else    
+                    text.append(ch);
+        }
+        else
+        {
+            text.append("&nbsp;"); //HTML truncates multiple spaces, so use a space marker instead
+        }
+        
+    }
+
+    //close any remaining open inner spans
+    if ( _innerSpanOpen )
+        closeSpan(text);
+
+    //start new line
+    text.append("<br>");
+    
+    *_output << text;
+}
+void HTMLDecoder::openSpan(QString& text , const QString& style)
+{
+    text.append( QString("<span style=\"%1\">").arg(style) );
+}
+
+void HTMLDecoder::closeSpan(QString& text)
+{
+    text.append("</span>");
+}
+
+void HTMLDecoder::setColorTable(const ColorEntry* table)
+{
+    _colorTable = table;
+}

=== added file 'src/TerminalCharacterDecoder.h'
--- src/TerminalCharacterDecoder.h	1970-01-01 00:00:00 +0000
+++ src/TerminalCharacterDecoder.h	2017-09-09 05:25:54 +0000
@@ -0,0 +1,148 @@
+/*
+    This file is part of Konsole, an X terminal.
+    
+    Copyright 2006-2008 by Robert Knight <robertknight@xxxxxxxxx>
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser 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.
+*/
+
+#ifndef TERMINAL_CHARACTER_DECODER_H
+#define TERMINAL_CHARACTER_DECODER_H
+
+#include "Character.h"
+
+#include <QList>
+
+class QTextStream;
+
+
+
+/**
+ * Base class for terminal character decoders
+ *
+ * The decoder converts lines of terminal characters which consist of a unicode character, foreground
+ * and background colours and other appearance-related properties into text strings.
+ *
+ * Derived classes may produce either plain text with no other colour or appearance information, or
+ * they may produce text which incorporates these additional properties. 
+ */
+class TerminalCharacterDecoder
+{
+public:
+    virtual ~TerminalCharacterDecoder() {}
+
+    /** Begin decoding characters.  The resulting text is appended to @p output. */
+    virtual void begin(QTextStream* output) = 0;
+    /** End decoding. */
+    virtual void end() = 0;
+
+    /**
+     * Converts a line of terminal characters with associated properties into a text string
+     * and writes the string into an output QTextStream.
+     *
+     * @param characters An array of characters of length @p count.
+     * @param count The number of characters
+     * @param properties Additional properties which affect all characters in the line
+     */
+    virtual void decodeLine(const Character* const characters, 
+                            int count,
+                            LineProperty properties) = 0; 
+};
+
+/**
+ * A terminal character decoder which produces plain text, ignoring colours and other appearance-related
+ * properties of the original characters.
+ */
+class PlainTextDecoder : public TerminalCharacterDecoder
+{
+public:
+    PlainTextDecoder(); 
+
+    /** 
+     * Set whether trailing whitespace at the end of lines should be included 
+     * in the output.
+     * Defaults to true.
+     */
+    void setTrailingWhitespace(bool enable);
+    /**
+     * Returns whether trailing whitespace at the end of lines is included
+     * in the output.
+     */
+    bool trailingWhitespace() const;
+    /** 
+     * Returns of character positions in the output stream
+     * at which new lines where added.  Returns an empty if setTrackLinePositions() is false or if 
+     * the output device is not a string.
+     */
+    QList<int> linePositions() const;
+    /** Enables recording of character positions at which new lines are added.  See linePositions() */
+    void setRecordLinePositions(bool record);
+
+    virtual void begin(QTextStream* output);
+    virtual void end();
+
+    virtual void decodeLine(const Character* const characters,
+                            int count,
+                            LineProperty properties);    
+
+    
+private:
+    QTextStream* _output;
+    bool _includeTrailingWhitespace;
+
+    bool _recordLinePositions;
+    QList<int> _linePositions;
+};
+
+/**
+ * A terminal character decoder which produces pretty HTML markup
+ */
+class HTMLDecoder : public TerminalCharacterDecoder
+{
+public:
+    /** 
+     * Constructs an HTML decoder using a default black-on-white color scheme.
+     */
+    HTMLDecoder();
+
+    /**
+     * Sets the colour table which the decoder uses to produce the HTML colour codes in its
+     * output
+     */
+    void setColorTable( const ColorEntry* table );
+        
+    virtual void decodeLine(const Character* const characters,
+                            int count,
+                            LineProperty properties);
+
+    virtual void begin(QTextStream* output);
+    virtual void end();
+
+private:
+    void openSpan(QString& text , const QString& style);
+    void closeSpan(QString& text);
+
+    QTextStream* _output;
+    const ColorEntry* _colorTable;
+    bool _innerSpanOpen; 
+    quint8 _lastRendition;
+    CharacterColor _lastForeColor;
+    CharacterColor _lastBackColor;
+
+};
+
+
+#endif

=== added file 'src/TerminalDisplay.cpp'
--- src/TerminalDisplay.cpp	1970-01-01 00:00:00 +0000
+++ src/TerminalDisplay.cpp	2017-09-09 05:25:54 +0000
@@ -0,0 +1,2168 @@
+/*
+    This file is part of KTerminal, QML plugin of the Konsole,
+    which is a terminal emulator from KDE.
+
+    Copyright 2006-2008 by Robert Knight   <robertknight@xxxxxxxxx>
+    Copyright 1997,1998 by Lars Doelle     <lars.doelle@xxxxxxxxxx>
+
+    Rewritten for QT5/QML by Dmitry Zagnoyko   <hiroshidi@xxxxxxxxx>, Copyright (C) 2013
+
+    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.
+*/
+
+// Own
+#include "TerminalDisplay.h"
+
+// Qt
+#include <QtQuick/QtQuick>
+
+#include <QGuiApplication>
+#include <QStyleHints>
+#include <QInputMethod>
+
+#include <QtGui/QPainter>
+#include <QtGui/QPixmap>
+#include <QtGui/QClipboard>
+#include <QtGui/QKeyEvent>
+
+#include <QtCore/QEvent>
+#include <QtCore/QTime>
+#include <QtCore/QFile>
+#include <QtCore/QTimer>
+
+#include <QtDebug>
+#include <QUrl>
+
+// Konsole
+//#include <config-apps.h>
+#include "Filter.h"
+#include "konsole_wcwidth.h"
+#include "ScreenWindow.h"
+#include "ColorScheme.h"
+#include "ColorTables.h"
+#include "TerminalCharacterDecoder.h"
+
+
+#ifndef loc
+#define loc(X,Y) ((Y)*_columns+(X))
+#endif
+
+#define REPCHAR   "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+                  "abcdefgjijklmnopqrstuvwxyz" \
+                  "0123456789./+@"
+
+const ColorEntry base_color_table[TABLE_COLORS] =
+// The following are almost IBM standard color codes, with some slight
+// gamma correction for the dim colors to compensate for bright X screens.
+// It contains the 8 ansiterm/xterm colors in 2 intensities.
+{
+  // Fixme: could add faint colors here, also.
+  // normal
+  ColorEntry(QColor(0x00,0x00,0x00), 0), ColorEntry( QColor(0xB2,0xB2,0xB2), 1), // Dfore, Dback
+  ColorEntry(QColor(0x00,0x00,0x00), 0), ColorEntry( QColor(0xB2,0x18,0x18), 0), // Black, Red
+  ColorEntry(QColor(0x18,0xB2,0x18), 0), ColorEntry( QColor(0xB2,0x68,0x18), 0), // Green, Yellow
+  ColorEntry(QColor(0x18,0x18,0xB2), 0), ColorEntry( QColor(0xB2,0x18,0xB2), 0), // Blue, Magenta
+  ColorEntry(QColor(0x18,0xB2,0xB2), 0), ColorEntry( QColor(0xB2,0xB2,0xB2), 0), // Cyan, White
+  // intensiv
+  ColorEntry(QColor(0x00,0x00,0x00), 0), ColorEntry( QColor(0xFF,0xFF,0xFF), 1),
+  ColorEntry(QColor(0x68,0x68,0x68), 0), ColorEntry( QColor(0xFF,0x54,0x54), 0),
+  ColorEntry(QColor(0x54,0xFF,0x54), 0), ColorEntry( QColor(0xFF,0xFF,0x54), 0),
+  ColorEntry(QColor(0x54,0x54,0xFF), 0), ColorEntry( QColor(0xFF,0x54,0xFF), 0),
+  ColorEntry(QColor(0x54,0xFF,0xFF), 0), ColorEntry( QColor(0xFF,0xFF,0xFF), 0)
+};
+
+// scroll increment used when dragging selection at top/bottom of window.
+
+// static
+bool KTerminalDisplay::_antialiasText = true;
+bool KTerminalDisplay::HAVE_TRANSPARENCY = true;
+
+// we use this to force QPainter to display text in LTR mode
+// more information can be found in: http://unicode.org/reports/tr9/
+const QChar LTR_OVERRIDE_CHAR( 0x202D );
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                Colors                                     */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
+
+   Code        0       1       2       3       4       5       6       7
+   ----------- ------- ------- ------- ------- ------- ------- ------- -------
+   ANSI  (bgr) Black   Red     Green   Yellow  Blue    Magenta Cyan    White
+   IBMPC (rgb) Black   Blue    Green   Cyan    Red     Magenta Yellow  White
+*/
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+///                                   BEGIN
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                         Constructor / Destructor                          */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+KTerminalDisplay::KTerminalDisplay(QQuickItem *parent) :
+    QQuickPaintedItem(parent)
+  ,_screenWindow(0)
+  ,_allowBell(true)
+  ,_fontHeight(1)
+  ,_fontWidth(1)
+  ,_fontAscent(1)
+  ,_boldIntense(true)
+  ,_lines(1)
+  ,_columns(1)
+  ,_usedLines(1)
+  ,_usedColumns(1)
+  ,_contentHeight(1)
+  ,_contentWidth(1)
+  ,_image(0)
+  ,_randomSeed(0)
+  ,_resizing(false)
+  ,_bidiEnabled(false)
+  ,_actSel(0)
+  ,_wordSelectionMode(false)
+  ,_lineSelectionMode(false)
+  ,_preserveLineBreaks(false)
+  ,_columnSelectionMode(false)
+  ,_wordCharacters(":@-./_~")
+  ,_bellMode(NotifyBell) //def: SystemBeepBell)
+  ,_blinking(false)
+  ,_hasBlinker(false)
+  ,_cursorBlinking(false)
+  ,_hasBlinkingCursor(false)
+  ,_allowBlinkingText(true)
+  ,_isFixedSize(false)
+  ,_resizeTimer(0)
+  ,_flowControlWarningEnabled(false)
+  ,_lineSpacing(0)
+  ,_colorsInverted(false)
+  ,_cursorShape(BlockCursor)
+  ,m_session(0)
+  ,m_focusOnClick(true)
+  ,m_showVKBonClick(true)
+  ,m_parent(parent)
+{
+    _blendColor  = qRgba(0,0,0,0xff);
+    m_widgetRect = QRectF(0,0,1,1);
+
+    m_palette = qApp->palette();
+
+    m_font = QFont("Monospace",16);
+
+#ifdef Q_WS_UBUNTU
+#if QT_VERSION >= 0x040700
+    m_font.setStyleStrategy(QFont::ForceIntegerMetrics);
+#else
+#warning "Correct handling of the QFont metrics requited Qt>=4.7"
+#endif
+#endif
+
+    // The offsets are not yet calculated.
+    // Do not calculate these too often to be more smoothly when resizing
+    // konsole in opaque mode.
+    _topMargin = DEFAULT_TOP_MARGIN;
+    _leftMargin = DEFAULT_LEFT_MARGIN;
+
+    // setup timers for blinking cursor and text
+    _blinkTimer   = new QTimer(this);
+    connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent()));
+    _blinkCursorTimer   = new QTimer(this);
+    connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent()));
+
+    //KCursor::setAutoHideCursor( this, true );
+
+    setColorTable(base_color_table);
+
+    new AutoScrollHandler(this);
+
+    setAcceptedMouseButtons(Qt::LeftButton);
+    setFlags(ItemHasContents | ItemAcceptsInputMethod);
+    //installEventFilter(this);
+
+    m_font.setStyleHint(QFont::TypeWriter);
+
+    setVTFont(m_font);
+}
+
+KTerminalDisplay::~KTerminalDisplay()
+{
+    disconnect(_blinkTimer);
+    disconnect(_blinkCursorTimer);
+
+    delete[] _image;
+}
+
+void KTerminalDisplay::setSession(KSession * session)
+{
+    if (m_session != session) {
+        m_session = session;
+
+        connect(this, SIGNAL(copyAvailable(bool)),
+                m_session, SLOT(selectionChanged(bool)));
+        connect(this, SIGNAL(termGetFocus()),
+                m_session, SIGNAL(termGetFocus()));
+        connect(this, SIGNAL(termLostFocus()),
+                m_session, SIGNAL(termLostFocus()));
+        connect(this, SIGNAL(keyPressedSignal(QKeyEvent *)),
+                m_session, SIGNAL(termKeyPressed(QKeyEvent *)));
+
+        m_session->addView(this);
+
+        //m_session->changeDir(QDir::currentPath());
+
+        setRandomSeed(m_session->getRandomSeed());
+
+        emit changedSession(session);
+    }
+}
+
+
+ScreenWindow* KTerminalDisplay::screenWindow() const
+{
+    return _screenWindow;
+}
+
+void KTerminalDisplay::forcedFocus()
+{
+
+    bool focused = hasActiveFocus();
+
+    if (!focused) {
+        forceActiveFocus();
+        focused = hasActiveFocus();
+    }
+
+}
+
+void KTerminalDisplay::setScreenWindow(ScreenWindow* window)
+{
+    // disconnect existing screen window if any
+    if ( _screenWindow )
+    {
+        disconnect( _screenWindow , 0 , this , 0 );
+    }
+
+    _screenWindow = window;
+
+    if ( window )
+    {
+
+// TODO: Determine if this is an issue.
+//#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?"
+        connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) );
+        connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) );
+        window->setWindowLines(_lines);
+    }
+}
+
+const ColorEntry* KTerminalDisplay::colorTable() const
+{
+  return _colorTable;
+}
+void KTerminalDisplay::setBackgroundColor(const QColor& color)
+{
+    _colorTable[DEFAULT_BACK_COLOR].color = color;
+//    QPalette p = m_palette;
+//    p.setColor( backgroundRole(), color );
+//    setPalette( p );
+
+    update();
+}
+void KTerminalDisplay::setForegroundColor(const QColor& color)
+{
+    _colorTable[DEFAULT_FORE_COLOR].color = color;
+
+    update();
+}
+void KTerminalDisplay::setColorTable(const ColorEntry table[])
+{
+  for (int i = 0; i < TABLE_COLORS; i++)
+      _colorTable[i] = table[i];
+
+  setBackgroundColor(_colorTable[DEFAULT_BACK_COLOR].color);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                   Font                                    */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+/*
+   The VT100 has 32 special graphical characters. The usual vt100 extended
+   xterm fonts have these at 0x00..0x1f.
+
+   QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
+   come in here as proper unicode characters.
+
+   We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
+   from unicode to 0x00..0x1f. The remaining translation is then left to the
+   QCodec.
+*/
+
+static inline bool isLineChar(quint16 c) { return ((c & 0xFF80) == 0x2500);}
+static inline bool isLineCharString(const QString& string)
+{
+        return (string.length() > 0) && (isLineChar(string.at(0).unicode()));
+}
+
+
+// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
+
+unsigned short vt100_graphics[32] =
+{ // 0/8     1/9    2/10    3/11    4/12    5/13    6/14    7/15
+  0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
+  0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
+  0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
+  0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
+};
+
+void KTerminalDisplay::fontChange(const QFont&)
+{
+  QFontMetrics fm(m_font);
+  _fontHeight = fm.height() + _lineSpacing;
+
+  // waba TerminalDisplay 1.123:
+  // "Base character width on widest ASCII character. This prevents too wide
+  //  characters in the presence of double wide (e.g. Japanese) characters."
+  // Get the width from representative normal width characters
+  _fontWidth = (double)fm.width(REPCHAR)/(double)strlen(REPCHAR);
+
+  _fixedFont = true;
+
+  int fw = fm.width(REPCHAR[0]);
+  for(unsigned int i=1; i< strlen(REPCHAR); i++)
+  {
+    if (fw != fm.width(REPCHAR[i]))
+    {
+      _fixedFont = false;
+      break;
+    }
+  }
+
+  if (_fontWidth < 1)
+    _fontWidth=1;
+
+  _fontAscent = fm.ascent();
+
+  emit changedFontMetricSignal( _fontHeight, _fontWidth );
+  propagateSize();
+  update();
+}
+
+void KTerminalDisplay::setVTFont(const QFont& f)
+{
+  QFont font = f;
+
+#if defined(Q_WS_MAC) || defined(Q_WS_UBUNTU)
+#if QT_VERSION >= 0x040700
+    font.setStyleStrategy(QFont::ForceIntegerMetrics);
+#else
+#warning "Correct handling of the QFont metrics requited Qt>=4.7"
+#endif
+#endif
+
+  QFontMetrics metrics(font);
+
+  if ( !QFontInfo(font).fixedPitch() )
+  {
+      qDebug() << "Using an unsupported variable-width font in the terminal.  This may produce display errors.";
+  }
+
+  if ( metrics.height() < height() && metrics.maxWidth() < width() )
+  {
+    // hint that text should be drawn without anti-aliasing.
+    // depending on the user's font configuration, this may not be respected
+    if (!_antialiasText)
+        font.setStyleStrategy( QFont::NoAntialias );
+
+    // experimental optimization.  Konsole assumes that the terminal is using a
+    // mono-spaced font, in which case kerning information should have an effect.
+    // Disabling kerning saves some computation when rendering text.
+    font.setKerning(false);
+
+    //QWidget::setFont(font);
+    m_font = font;
+    fontChange(font);
+  }
+}
+
+void KTerminalDisplay::setColorScheme(const QString &name)
+{
+    const ColorScheme *cs;
+    // avoid legacy (int) solution
+    if (!availableColorSchemes().contains(name))
+        cs = ColorSchemeManager::instance()->defaultColorScheme();
+    else
+        cs = ColorSchemeManager::instance()->findColorScheme(name);
+
+    if (! cs)
+    {
+#ifndef QT_NO_DEBUG
+        qDebug() << "Cannot load color scheme: " << name;
+#endif
+        return;
+    }
+
+    ColorEntry table[TABLE_COLORS];
+    cs->getColorTable(table);
+    setColorTable(table);
+    m_scheme = name;
+}
+
+QStringList KTerminalDisplay::availableColorSchemes()
+{
+    QStringList ret;
+    foreach (const ColorScheme* cs, ColorSchemeManager::instance()->allColorSchemes())
+        ret.append(cs->name());
+    return ret;
+}
+
+void KTerminalDisplay::click(qreal x, qreal y)
+{
+    QMouseEvent me(QEvent::MouseButtonPress, QPointF(x,y), Qt::RightButton, Qt::RightButton, Qt::NoModifier);
+    mousePressEvent(&me);
+}
+
+void KTerminalDisplay::setAutoFocus(bool au)
+{
+    m_focusOnClick = au;
+    emit changedAutoFocus(au);
+}
+
+void KTerminalDisplay::setAutoVKB(bool au)
+{
+    m_showVKBonClick = au;
+    emit changedAutoVKB(au);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                             Display Operations                            */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+/**
+ A table for emulating the simple (single width) unicode drawing chars.
+ It represents the 250x - 257x glyphs. If it's zero, we can't use it.
+ if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered
+ 0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit.
+
+ Then, the pixels basically have the following interpretation:
+ _|||_
+ -...-
+ -...-
+ -...-
+ _|||_
+
+where _ = none
+      | = vertical line.
+      - = horizontal line.
+ */
+
+
+enum LineEncode
+{
+    TopL  = (1<<1),
+    TopC  = (1<<2),
+    TopR  = (1<<3),
+
+    LeftT = (1<<5),
+    Int11 = (1<<6),
+    Int12 = (1<<7),
+    Int13 = (1<<8),
+    RightT = (1<<9),
+
+    LeftC = (1<<10),
+    Int21 = (1<<11),
+    Int22 = (1<<12),
+    Int23 = (1<<13),
+    RightC = (1<<14),
+
+    LeftB = (1<<15),
+    Int31 = (1<<16),
+    Int32 = (1<<17),
+    Int33 = (1<<18),
+    RightB = (1<<19),
+
+    BotL  = (1<<21),
+    BotC  = (1<<22),
+    BotR  = (1<<23)
+};
+
+#include "LineFont.h"
+
+static void drawLineChar(QPainter* paint, qreal x, qreal y, qreal w, qreal h, uchar code)
+{
+    //Calculate cell midpoints, end points.
+    qreal cx = x + w/2;
+    qreal cy = y + h/2;
+    qreal ex = x + w - 1;
+    qreal ey = y + h - 1;
+
+    quint32 toDraw = LineChars[code];
+
+    //Top _lines:
+    if (toDraw & TopL)
+        paint->drawLine(cx-1, y, cx-1, cy-2);
+    if (toDraw & TopC)
+        paint->drawLine(cx, y, cx, cy-2);
+    if (toDraw & TopR)
+        paint->drawLine(cx+1, y, cx+1, cy-2);
+
+    //Bot _lines:
+    if (toDraw & BotL)
+        paint->drawLine(cx-1, cy+2, cx-1, ey);
+    if (toDraw & BotC)
+        paint->drawLine(cx, cy+2, cx, ey);
+    if (toDraw & BotR)
+        paint->drawLine(cx+1, cy+2, cx+1, ey);
+
+    //Left _lines:
+    if (toDraw & LeftT)
+        paint->drawLine(x, cy-1, cx-2, cy-1);
+    if (toDraw & LeftC)
+        paint->drawLine(x, cy, cx-2, cy);
+    if (toDraw & LeftB)
+        paint->drawLine(x, cy+1, cx-2, cy+1);
+
+    //Right _lines:
+    if (toDraw & RightT)
+        paint->drawLine(cx+2, cy-1, ex, cy-1);
+    if (toDraw & RightC)
+        paint->drawLine(cx+2, cy, ex, cy);
+    if (toDraw & RightB)
+        paint->drawLine(cx+2, cy+1, ex, cy+1);
+
+    //Intersection points.
+    if (toDraw & Int11)
+        paint->drawPoint(cx-1, cy-1);
+    if (toDraw & Int12)
+        paint->drawPoint(cx, cy-1);
+    if (toDraw & Int13)
+        paint->drawPoint(cx+1, cy-1);
+
+    if (toDraw & Int21)
+        paint->drawPoint(cx-1, cy);
+    if (toDraw & Int22)
+        paint->drawPoint(cx, cy);
+    if (toDraw & Int23)
+        paint->drawPoint(cx+1, cy);
+
+    if (toDraw & Int31)
+        paint->drawPoint(cx-1, cy+1);
+    if (toDraw & Int32)
+        paint->drawPoint(cx, cy+1);
+    if (toDraw & Int33)
+        paint->drawPoint(cx+1, cy+1);
+
+}
+
+void KTerminalDisplay::setKeyboardCursorShape(KeyboardCursorShape shape)
+{
+    _cursorShape = shape;
+}
+
+KTerminalDisplay::KeyboardCursorShape KTerminalDisplay::keyboardCursorShape() const
+{
+    return _cursorShape;
+}
+
+void KTerminalDisplay::setKeyboardCursorColor(bool useForegroundColor, const QColor& color)
+{
+    if (useForegroundColor)
+        _cursorColor = QColor(); // an invalid color means that
+                                 // the foreground color of the
+                                 // current character should
+                                 // be used
+
+    else
+        _cursorColor = color;
+}
+
+QColor KTerminalDisplay::keyboardCursorColor() const
+{
+    return _cursorColor;
+}
+
+void KTerminalDisplay::ShowVKB(bool show)
+{
+    bool focused = hasActiveFocus();
+
+    if (focused && show && !qGuiApp->inputMethod()->isVisible()) {
+        updateInputMethod(Qt::ImEnabled);
+        qGuiApp->inputMethod()->show();
+    }
+
+    if (focused && !show && qGuiApp->inputMethod()->isVisible()) {
+        updateInputMethod(Qt::ImEnabled);
+        qGuiApp->inputMethod()->hide();
+    }
+}
+
+void KTerminalDisplay::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; }
+uint KTerminalDisplay::randomSeed() const { return _randomSeed; }
+
+#if 0
+/*!
+    Set XIM Position
+*/
+void TerminalDisplay::setCursorPos(const int curx, const int cury)
+{
+    int xpos, ypos;
+    ypos = _topMargin + _fontHeight*(cury-1) + _fontAscent;
+    xpos = _leftMargin + _fontWidth*curx;
+    //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ???
+    // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos);
+    _cursorLine = cury;
+    _cursorCol = curx;
+}
+#endif
+
+// scrolls the image by 'lines', down if lines > 0 or up otherwise.
+//
+// the terminal emulation keeps track of the scrolling of the character
+// image as it receives input, and when the view is updated, it calls scrollImage()
+// with the final scroll amount.  this improves performance because scrolling the
+// display is much cheaper than re-rendering all the text for the
+// part of the image which has moved up or down.
+// Instead only new lines have to be drawn
+void KTerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion)
+{
+    // constrain the region to the display
+    // the bottom of the region is capped to the number of lines in the display's
+    // internal image - 2, so that the height of 'region' is strictly less
+    // than the height of the internal image.
+    QRect region = screenWindowRegion;
+    region.setBottom( qMin(region.bottom(),this->_lines-2) );
+
+    // return if there is nothing to do
+    if (    lines == 0
+         || _image == 0
+         || !region.isValid()
+         || (region.top() + abs(lines)) >= region.bottom()
+         || this->_lines <= region.height() ) return;
+
+
+    void* firstCharPos = &_image[ region.top() * this->_columns ];
+    void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ];
+
+    int top = _topMargin + (region.top() * _fontHeight);
+    Q_UNUSED(top) //BAD IDEA!
+    int linesToMove = region.height() - abs(lines);
+    int bytesToMove = linesToMove *
+                      this->_columns *
+                      sizeof(Character);
+
+    Q_ASSERT( linesToMove > 0 );
+    Q_ASSERT( bytesToMove > 0 );
+
+    //scroll internal image
+    if ( lines > 0 )
+    {
+        // check that the memory areas that we are going to move are valid
+        Q_ASSERT( (char*)lastCharPos + bytesToMove <
+                  (char*)(_image + (this->_lines * this->_columns)) );
+
+        Q_ASSERT( (lines*this->_columns) < _imageSize );
+
+        //scroll internal image down
+        memmove( firstCharPos , lastCharPos , bytesToMove );
+    }
+    else
+    {
+        // check that the memory areas that we are going to move are valid
+        Q_ASSERT( (char*)firstCharPos + bytesToMove <
+                  (char*)(_image + (this->_lines * this->_columns)) );
+
+        //scroll internal image up
+        memmove( lastCharPos , firstCharPos , bytesToMove );
+    }
+
+    // Q_ASSERT(scrollRect.isValid() && !scrollRect.isEmpty());
+
+    //scroll the display vertically to match internal _image
+    // scroll( 0 , _fontHeight * (-lines) , scrollRect );
+}
+
+void KTerminalDisplay::updateImage()
+{
+  if ( !_screenWindow )
+      return;
+
+  // optimization - scroll the existing image where possible and
+  // avoid expensive text drawing for parts of the image that
+  // can simply be moved up or down
+  scrollImage( _screenWindow->scrollCount() ,
+               _screenWindow->scrollRegion() );
+  _screenWindow->resetScrollCount();
+
+  if (!_image) {
+     // Create _image.
+     // The emitted changedContentSizeSignal also leads to getImage being recreated, so do this first.
+     updateImageSize();
+  }
+
+  Character* const newimg = _screenWindow->getImage();
+  int lines   = _screenWindow->windowLines();
+  int columns = _screenWindow->windowColumns();
+
+  Q_ASSERT( this->_usedLines <= this->_lines );
+  Q_ASSERT( this->_usedColumns <= this->_columns );
+
+  int y,x,len;
+
+  _hasBlinker = false;
+
+  CharacterColor cf;       // undefined
+  CharacterColor _clipboard;       // undefined
+  int cr  = -1;   // undefined
+
+  const int linesToUpdate   = qMin(this->_lines,  qMax(0,lines  ));
+  const int columnsToUpdate = qMin(this->_columns,qMax(0,columns));
+
+  QChar *disstrU = new QChar[columnsToUpdate];
+  char *dirtyMask = new char[columnsToUpdate+2];
+  QRegion dirtyRegion;
+
+  // debugging variable, this records the number of lines that are found to
+  // be 'dirty' ( ie. have changed from the old _image to the new _image ) and
+  // which therefore need to be repainted
+  int dirtyLineCount = 0;
+
+  for (y = 0; y < linesToUpdate; ++y)
+  {
+    const Character*       currentLine = &_image[y*this->_columns];
+    const Character* const newLine = &newimg[y*columns];
+
+    bool updateLine = false;
+
+    // The dirty mask indicates which characters need repainting. We also
+    // mark surrounding neighbours dirty, in case the character exceeds
+    // its cell boundaries
+    memset(dirtyMask, 0, columnsToUpdate+2);
+
+    for( x = 0 ; x < columnsToUpdate ; ++x)
+    {
+        if ( newLine[x] != currentLine[x] )
+        {
+            dirtyMask[x] = true;
+        }
+    }
+
+    if (!_resizing) // not while _resizing, we're expecting a paintEvent
+    for (x = 0; x < columnsToUpdate; ++x)
+    {
+      _hasBlinker |= (newLine[x].rendition & RE_BLINK);
+
+      // Start drawing if this character or the next one differs.
+      // We also take the next one into account to handle the situation
+      // where characters exceed their cell width.
+      if (dirtyMask[x])
+      {
+        quint16 c = newLine[x+0].character;
+        if ( !c )
+            continue;
+        int p = 0;
+        disstrU[p++] = c; //fontMap(c);
+        bool lineDraw = isLineChar(c);
+        bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0);
+        cr = newLine[x].rendition;
+        _clipboard = newLine[x].backgroundColor;
+        if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor;
+        int lln = columnsToUpdate - x;
+        for (len = 1; len < lln; ++len)
+        {
+            const Character& ch = newLine[x+len];
+
+            if (!ch.character)
+                continue; // Skip trailing part of multi-col chars.
+
+            bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0);
+
+            if (  ch.foregroundColor != cf ||
+                  ch.backgroundColor != _clipboard ||
+                  ch.rendition != cr ||
+                  !dirtyMask[x+len] ||
+                  isLineChar(c) != lineDraw ||
+                  nextIsDoubleWidth != doubleWidth )
+            break;
+
+          disstrU[p++] = c; //fontMap(c);
+        }
+
+        QString unistr(disstrU, p);
+
+        bool saveFixedFont = _fixedFont;
+        if (lineDraw)
+           _fixedFont = false;
+        if (doubleWidth)
+           _fixedFont = false;
+
+        updateLine = true;
+
+        _fixedFont = saveFixedFont;
+        x += len - 1;
+      }
+
+    }
+
+    //both the top and bottom halves of double height _lines must always be redrawn
+    //although both top and bottom halves contain the same characters, only
+    //the top one is actually
+    //drawn.
+    if (_lineProperties.count() > y)
+        updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);
+
+    // if the characters on the line are different in the old and the new _image
+    // then this line must be repainted.
+    if (updateLine)
+    {
+        dirtyLineCount++;
+
+        // add the area occupied by this line to the region which needs to be
+        // repainted
+        QRect dirtyRect = QRect( qRound(_leftMargin),
+                                 qRound(_topMargin + _fontHeight*y) ,
+                                 qRound(_fontWidth * columnsToUpdate) ,
+                                 _fontHeight );
+
+        dirtyRegion |= dirtyRect;
+    }
+
+    // replace the line of characters in the old _image with the
+    // current line of the new _image
+    memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character));
+  }
+
+  // if the new _image is smaller than the previous _image, then ensure that the area
+  // outside the new _image is cleared
+  if ( linesToUpdate < _usedLines )
+  {
+    dirtyRegion |= QRect( qRound(_leftMargin),
+                          qRound(_topMargin + _fontHeight*linesToUpdate) ,
+                          qRound(_fontWidth * this->_columns) ,
+                          _fontHeight * (_usedLines-linesToUpdate) );
+  }
+  _usedLines = linesToUpdate;
+
+  if ( columnsToUpdate < _usedColumns )
+  {
+    dirtyRegion |= QRect( qRound(_leftMargin + columnsToUpdate*_fontWidth) ,
+                          qRound(_topMargin),
+                          qRound(_fontWidth * (_usedColumns-columnsToUpdate)) ,
+                          _fontHeight * this->_lines );
+  }
+  _usedColumns = columnsToUpdate;
+
+  dirtyRegion |= geometryRound(_inputMethodData.previousPreeditRect);
+
+  // update the parts of the display which have changed
+  // update(dirtyRegion.boundingRect());
+
+  // update whole widget
+  update();
+
+  if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( TEXT_BLINK_DELAY );
+  if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; }
+  delete[] dirtyMask;
+  delete[] disstrU;
+
+}
+
+void KTerminalDisplay::setBlinkingCursor(bool blink)
+{
+  _hasBlinkingCursor=blink;
+
+  if (blink && !_blinkCursorTimer->isActive())
+      _blinkCursorTimer->start(100); // WARN! HARDCODE
+
+  if (!blink && _blinkCursorTimer->isActive())
+  {
+    _blinkCursorTimer->stop();
+    if (_cursorBlinking)
+      blinkCursorEvent();
+    else
+      _cursorBlinking = false;
+  }
+}
+
+void KTerminalDisplay::setBlinkingTextEnabled(bool blink)
+{
+    _allowBlinkingText = blink;
+
+    if (blink && !_blinkTimer->isActive())
+        _blinkTimer->start(qApp->styleHints()->cursorFlashTime() / 2);
+
+    if (!blink && _blinkTimer->isActive())
+    {
+        _blinkTimer->stop();
+        _blinking = false;
+    }
+}
+
+void KTerminalDisplay::focusOutEvent(QFocusEvent*)
+{
+    emit termLostFocus();
+    // trigger a repaint of the cursor so that it is both visible (in case
+    // it was hidden during blinking)
+    // and drawn in a focused out state
+    _cursorBlinking = false;
+    updateCursor();
+
+    _blinkCursorTimer->stop();
+    if (_blinking)
+        blinkEvent();
+
+    _blinkTimer->stop();
+
+    //parent->activeFocus = false;
+    emit activeFocusChanged(true);
+}
+
+void KTerminalDisplay::focusInEvent(QFocusEvent*)
+{
+    emit termGetFocus();
+    if (_hasBlinkingCursor)
+    {
+        _blinkCursorTimer->start();
+    }
+    updateCursor();
+
+    if (_hasBlinker)
+        _blinkTimer->start();
+}
+
+QPoint KTerminalDisplay::cursorPosition() const
+{
+    if (_screenWindow)
+        return _screenWindow->cursorPosition();
+    else
+        return QPoint(0,0);
+}
+
+void KTerminalDisplay::blinkEvent()
+{
+  if (!_allowBlinkingText) return;
+
+  _blinking = !_blinking;
+
+  //TODO:  Optimize to only repaint the areas of the widget
+  // where there is blinking text
+  // rather than repainting the whole widget.
+  update();
+}
+
+void KTerminalDisplay::updateCursor()
+{
+  QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) );
+  update(cursorRect);
+}
+
+void KTerminalDisplay::blinkCursorEvent()
+{
+  _cursorBlinking = !_cursorBlinking;
+  updateCursor();
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                  Resizing                                 */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+void KTerminalDisplay::propagateSize()
+{
+  if (_image) {
+     updateImageSize();
+  }
+}
+
+void KTerminalDisplay::updateImageSize()
+{
+  Character* oldimg = _image;
+  int oldlin = _lines;
+  int oldcol = _columns;
+
+  makeImage();
+
+  // copy the old image to reduce flicker
+  int lines =   qMin(oldlin,_lines);
+  int columns = qMin(oldcol,_columns);
+
+  if (oldimg)
+  {
+    for (int line = 0; line < lines; line++)
+    {
+      memcpy((void*)&_image[_columns*line],
+             (void*)&oldimg[oldcol*line],columns*sizeof(Character));
+    }
+    delete[] oldimg;
+  }
+
+  if (_screenWindow)
+      _screenWindow->setWindowLines(_lines);
+
+  _resizing = (oldlin!=_lines) || (oldcol!=_columns);
+
+  if ( _resizing )
+  {
+    emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent
+  }
+
+  _resizing = false;
+}
+
+void KTerminalDisplay::scrollToEnd()
+{
+  //_screenWindow->scrollTo( _scrollBar->value() + 1 );
+  _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() );
+}
+
+void KTerminalDisplay::extendSelection( const QPoint& position )
+{
+  QPoint pos = position;
+
+  if ( !_screenWindow )
+      return;
+
+  //if ( !contentsRect().contains(ev->pos()) ) return;
+
+  // we're in the process of moving the mouse with the left button pressed
+  // the mouse cursor will kept caught within the bounds of the text in
+  // this widget.
+
+  int linesBeyondWidget = 0;
+
+  QRect textBounds( _leftMargin,
+                    _topMargin,
+                   _usedColumns*_fontWidth-1,
+                   _usedLines*_fontHeight-1);
+
+  // Adjust position within text area bounds.
+  QPoint oldpos = pos;
+
+  pos.setX( qBound(textBounds.left(),pos.x(),textBounds.right()) );
+  pos.setY( qBound(textBounds.top(),pos.y(),textBounds.bottom()) );
+
+  if ( oldpos.y() > textBounds.bottom() )
+  {
+      linesBeyondWidget = (oldpos.y()-textBounds.bottom()) / _fontHeight;
+  }
+  if ( oldpos.y() < textBounds.top() )
+  {
+      linesBeyondWidget = (textBounds.top()-oldpos.y()) / _fontHeight;
+  }
+
+  int charColumn = 0;
+  int charLine = 0;
+  getCharacterPosition(pos,charLine,charColumn);
+
+  QPoint here = QPoint(charColumn,charLine); //QPoint((pos.x()-tLx-_leftMargin+(_fontWidth/2))/_fontWidth,(pos.y()-tLy-_topMargin)/_fontHeight);
+  QPoint ohere;
+  QPoint _iPntSelCorr = _iPntSel;
+  _iPntSelCorr.ry() -= 0; //_scrollBar->value();
+  QPoint _pntSelCorr = _pntSel;
+  _pntSelCorr.ry() -= 0; //_scrollBar->value();
+  bool swapping = false;
+
+  if ( _wordSelectionMode )
+  {
+    // Extend to word boundaries
+    int i;
+    QChar selClass;
+
+    bool left_not_right = ( here.y() < _iPntSelCorr.y() ||
+       ( here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x() ) );
+    bool old_left_not_right = ( _pntSelCorr.y() < _iPntSelCorr.y() ||
+       ( _pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x() ) );
+    swapping = left_not_right != old_left_not_right;
+
+    // Find left (left_not_right ? from here : from start)
+    QPoint left = left_not_right ? here : _iPntSelCorr;
+    i = loc(left.x(),left.y());
+    if (i>=0 && i<=_imageSize) {
+      selClass = charClass(_image[i].character);
+      while ( ((left.x()>0) || (left.y()>0 && (_lineProperties[left.y()-1] & LINE_WRAPPED) ))
+                      && charClass(_image[i-1].character) == selClass )
+      { i--; if (left.x()>0) left.rx()--; else {left.rx()=_usedColumns-1; left.ry()--;} }
+    }
+
+    // Find left (left_not_right ? from start : from here)
+    QPoint right = left_not_right ? _iPntSelCorr : here;
+    i = loc(right.x(),right.y());
+    if (i>=0 && i<=_imageSize) {
+      selClass = charClass(_image[i].character);
+      while( ((right.x()<_usedColumns-1) || (right.y()<_usedLines-1 && (_lineProperties[right.y()] & LINE_WRAPPED) ))
+                      && charClass(_image[i+1].character) == selClass )
+      { i++; if (right.x()<_usedColumns-1) right.rx()++; else {right.rx()=0; right.ry()++; } }
+    }
+
+    // Pick which is start (ohere) and which is extension (here)
+    if ( left_not_right )
+    {
+      here = left; ohere = right;
+    }
+    else
+    {
+      here = right; ohere = left;
+    }
+    ohere.rx()++;
+  }
+
+  if ( _lineSelectionMode )
+  {
+    // Extend to complete line
+    bool above_not_below = ( here.y() < _iPntSelCorr.y() );
+
+    QPoint above = above_not_below ? here : _iPntSelCorr;
+    QPoint below = above_not_below ? _iPntSelCorr : here;
+
+    while (above.y()>0 && (_lineProperties[above.y()-1] & LINE_WRAPPED) )
+      above.ry()--;
+    while (below.y()<_usedLines-1 && (_lineProperties[below.y()] & LINE_WRAPPED) )
+      below.ry()++;
+
+    above.setX(0);
+    below.setX(_usedColumns-1);
+
+    // Pick which is start (ohere) and which is extension (here)
+    if ( above_not_below )
+    {
+      here = above; ohere = below;
+    }
+    else
+    {
+      here = below; ohere = above;
+    }
+
+    QPoint newSelBegin = QPoint( ohere.x(), ohere.y() );
+    swapping = !(_tripleSelBegin==newSelBegin);
+    _tripleSelBegin = newSelBegin;
+
+    ohere.rx()++;
+  }
+
+  int offset = 0;
+  if ( !_wordSelectionMode && !_lineSelectionMode )
+  {
+    int i;
+    QChar selClass;
+
+    bool left_not_right = ( here.y() < _iPntSelCorr.y() ||
+       ( here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x() ) );
+    bool old_left_not_right = ( _pntSelCorr.y() < _iPntSelCorr.y() ||
+       ( _pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x() ) );
+    swapping = left_not_right != old_left_not_right;
+
+    // Find left (left_not_right ? from here : from start)
+    QPoint left = left_not_right ? here : _iPntSelCorr;
+
+    // Find left (left_not_right ? from start : from here)
+    QPoint right = left_not_right ? _iPntSelCorr : here;
+    if ( right.x() > 0 && !_columnSelectionMode )
+    {
+      i = loc(right.x(),right.y());
+      if (i>=0 && i<=_imageSize) {
+        selClass = charClass(_image[i-1].character);
+       /* if (selClass == ' ')
+        {
+          while ( right.x() < _usedColumns-1 && charClass(_image[i+1].character) == selClass && (right.y()<_usedLines-1) &&
+                          !(_lineProperties[right.y()] & LINE_WRAPPED))
+          { i++; right.rx()++; }
+          if (right.x() < _usedColumns-1)
+            right = left_not_right ? _iPntSelCorr : here;
+          else
+            right.rx()++;  // will be balanced later because of offset=-1;
+        }*/
+      }
+    }
+
+    // Pick which is start (ohere) and which is extension (here)
+    if ( left_not_right )
+    {
+      here = left; ohere = right; offset = 0;
+    }
+    else
+    {
+      here = right; ohere = left; offset = -1;
+    }
+  }
+
+  //if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) return; // not moved
+
+  if (here == ohere) return; // It's not left, it's not right.
+
+  if ( _actSel < 2 || swapping )
+  {
+    if ( _columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode )
+    {
+        _screenWindow->setSelectionStart( ohere.x() , ohere.y() , true );
+    }
+    else
+    {
+        _screenWindow->setSelectionStart( ohere.x()-1-offset , ohere.y() , false );
+    }
+
+  }
+
+  _actSel = 2; // within selection
+  _pntSel = here;
+  _pntSel.ry() += 0; //_scrollBar->value();
+
+  if ( _columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode )
+  {
+     _screenWindow->setSelectionEnd( here.x() , here.y() );
+  }
+  else
+  {
+     _screenWindow->setSelectionEnd( here.x()+offset , here.y() );
+  }
+
+    Q_UNUSED(linesBeyondWidget)
+
+}
+
+void KTerminalDisplay::updateLineProperties()
+{
+    if ( !_screenWindow )
+        return;
+
+    _lineProperties = _screenWindow->getLineProperties();
+}
+
+QChar KTerminalDisplay::charClass(QChar qch) const
+{
+    if ( qch.isSpace() ) return ' ';
+
+    if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) )
+    return 'a';
+
+    return qch;
+}
+
+void KTerminalDisplay::setWordCharacters(const QString& wc)
+{
+    _wordCharacters = wc;
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                               Clipboard                                   */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+#undef KeyPress
+
+void KTerminalDisplay::emitSelection(bool useXselection,bool appendReturn)
+{
+  if ( !_screenWindow )
+      return;
+
+  // Paste Clipboard by simulating keypress events
+  QString text = QGuiApplication::clipboard()->text(useXselection ? QClipboard::Selection :
+                                                                 QClipboard::Clipboard);
+  if(appendReturn)
+    text.append("\r");
+  if ( ! text.isEmpty() )
+  {
+    text.replace('\n', '\r');
+    QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text);
+    emit keyPressedSignal(&e); // expose as a big fat keypress event
+
+    _screenWindow->clearSelection();
+  }
+}
+
+void KTerminalDisplay::setSelection(const QString& t)
+{
+  QGuiApplication::clipboard()->setText(t, QClipboard::Selection);
+}
+
+void KTerminalDisplay::copyClipboard()
+{
+  if ( !_screenWindow )
+      return;
+
+  QString text = _screenWindow->selectedText(_preserveLineBreaks);
+  if (!text.isEmpty())
+    QGuiApplication::clipboard()->setText(text);
+}
+
+void KTerminalDisplay::pasteClipboard()
+{
+  emitSelection(false,false);
+}
+
+void KTerminalDisplay::pasteSelection()
+{
+  emitSelection(true,false);
+}
+
+/* ------------------------------------------------------------------------- */
+/*                                                                           */
+/*                                Keyboard                                   */
+/*                                                                           */
+/* ------------------------------------------------------------------------- */
+
+void KTerminalDisplay::setFlowControlWarningEnabled( bool enable )
+{
+    _flowControlWarningEnabled = enable;
+
+    // if the dialog is currently visible and the flow control warning has
+    // been disabled then hide the dialog
+//    if (!enable)
+//        outputSuspended(false);
+}
+
+void KTerminalDisplay::inputMethodEvent( QInputMethodEvent* event )
+{
+    QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString());
+    emit keyPressedSignal(&keyEvent);
+
+    _inputMethodData.preeditString = event->preeditString();
+    QRect updRect = geometryRound(preeditRect() | _inputMethodData.previousPreeditRect);
+    update(updRect);
+
+    event->accept();
+}
+
+void KTerminalDisplay::inputMethodQuery(QInputMethodQueryEvent *event)
+{
+    event->setValue(Qt::ImEnabled, true);
+    event->accept();
+}
+
+QVariant KTerminalDisplay::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+    const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0);
+    switch ( query )
+    {
+        case Qt::ImEnabled:
+            return (bool)(flags() & ItemAcceptsInputMethod);
+            break;
+        case Qt::ImMicroFocus:
+            return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1));
+            break;
+        case Qt::ImFont:
+            return m_font;
+            break;
+        case Qt::ImCursorPosition:
+            // return the cursor position within the current line
+            return cursorPos.x();
+            break;
+        case Qt::ImSurroundingText:
+            {
+                // return the text from the current line
+                QString lineText;
+                QTextStream stream(&lineText);
+                PlainTextDecoder decoder;
+                decoder.begin(&stream);
+                decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]);
+                decoder.end();
+                return lineText;
+            }
+            break;
+        case Qt::ImCurrentSelection:
+            return QString();
+            break;
+        default:
+            break;
+    }
+
+    return QVariant();
+}
+
+bool KTerminalDisplay::handleShortcutOverrideEvent(QKeyEvent* keyEvent)
+{
+    int modifiers = keyEvent->modifiers();
+
+    //  When a possible shortcut combination is pressed,
+    //  emit the overrideShortcutCheck() signal to allow the host
+    //  to decide whether the terminal should override it or not.
+    if (modifiers != Qt::NoModifier)
+    {
+        int modifierCount = 0;
+        unsigned int currentModifier = Qt::ShiftModifier;
+
+        while (currentModifier <= Qt::KeypadModifier)
+        {
+            if (modifiers & currentModifier)
+                modifierCount++;
+            currentModifier <<= 1;
+        }
+        if (modifierCount < 2)
+        {
+            bool override = false;
+            emit overrideShortcutCheck(keyEvent,override);
+            if (override)
+            {
+                keyEvent->accept();
+                return true;
+            }
+        }
+    }
+
+    // Override any of the following shortcuts because
+    // they are needed by the terminal
+    int keyCode = keyEvent->key() | modifiers;
+    switch ( keyCode )
+    {
+      // list is taken from the QLineEdit::event() code
+      case Qt::Key_Tab:
+      case Qt::Key_Delete:
+      case Qt::Key_Home:
+      case Qt::Key_End:
+      case Qt::Key_Backspace:
+      case Qt::Key_Left:
+      case Qt::Key_Right:
+        keyEvent->accept();
+        return true;
+    }
+    return false;
+}
+
+bool KTerminalDisplay::event(QEvent* event)
+{
+  switch (event->type())
+  {
+    case QEvent::ShortcutOverride:
+        handleShortcutOverrideEvent((QKeyEvent*)event);
+        break;
+    case QEvent::PaletteChange:
+    case QEvent::ApplicationPaletteChange:
+        break;
+    case QEvent::InputMethod:
+        inputMethodEvent(static_cast<QInputMethodEvent *>(event));
+        break;
+    case QEvent::InputMethodQuery:
+        inputMethodQuery(static_cast<QInputMethodQueryEvent *>(event));
+        break;
+    default:
+        break;
+  }
+  return QQuickPaintedItem::event(event);
+}
+
+void KTerminalDisplay::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+    if (newGeometry != oldGeometry) {
+        m_widgetRect = newGeometry;
+        propagateSize();
+        update();
+    }
+
+    QQuickPaintedItem::geometryChanged(newGeometry,oldGeometry);
+}
+
+QRect KTerminalDisplay::geometryRound(const QRectF &r) const
+{
+    QRect rect;
+
+    rect.setTop(qRound(r.top()));
+    rect.setBottom(qRound(r.bottom()));
+    rect.setLeft(qRound(r.left()));
+    rect.setRight(qRound(r.right()));
+
+    return rect;
+}
+
+void KTerminalDisplay::mousePressEvent(QMouseEvent *ev)
+{
+    if (m_focusOnClick) forcedFocus();
+    if (m_showVKBonClick) ShowVKB(true);
+
+    emit clicked();
+    QQuickPaintedItem::mouseMoveEvent(ev);
+}
+
+void KTerminalDisplay::setBellMode(int mode)
+{
+  _bellMode=mode;
+}
+
+void KTerminalDisplay::enableBell()
+{
+    _allowBell = true;
+}
+
+void KTerminalDisplay::bell(const QString& message)
+{
+  Q_UNUSED(message)
+
+  if (_bellMode==NoBell) return;
+
+  //limit the rate at which bells can occur
+  //...mainly for sound effects where rapid bells in sequence
+  //produce a horrible noise
+  if ( _allowBell )
+  {
+    _allowBell = false;
+    QTimer::singleShot(500,this,SLOT(enableBell()));
+
+    if (_bellMode==SystemBeepBell)
+    {
+        // NO BEEP !
+        //QGuiApplication::beep();
+        int a = 0;
+        Q_UNUSED(a)
+    }
+    else if (_bellMode==NotifyBel