@@ -46,10 +46,6 @@ public protocol TerminalViewDelegate {
46
46
* wiring this up to a pseudo-terminal.
47
47
*/
48
48
public class TerminalView : NSView , TerminalDelegate , NSTextInputClient , NSUserInterfaceValidations {
49
- public func selectionChanged( source: Terminal ) {
50
- abort ( )
51
- }
52
-
53
49
public func setTerminalIconTitle( source: Terminal , title: String ) {
54
50
//
55
51
}
@@ -137,6 +133,8 @@ public class TerminalView: NSView, TerminalDelegate, NSTextInputClient, NSUserIn
137
133
print ( " Scroller .decrementLine clicked " )
138
134
case . incrementLine:
139
135
print ( " Scroller .incrementLine clicked " )
136
+ default :
137
+ print ( " Scroller: New value introduced " )
140
138
}
141
139
}
142
140
@@ -940,6 +938,7 @@ public class TerminalView: NSView, TerminalDelegate, NSTextInputClient, NSUserIn
940
938
}
941
939
942
940
public func validateUserInterfaceItem( _ item: NSValidatedUserInterfaceItem ) -> Bool {
941
+ //print ("Validating selector: \(item.action)")
943
942
switch item. action {
944
943
case #selector( performTextFinderAction ( _: ) ) :
945
944
if let fa = NSTextFinder . Action ( rawValue: item. tag) {
@@ -955,28 +954,95 @@ public class TerminalView: NSView, TerminalDelegate, NSTextInputClient, NSUserIn
955
954
}
956
955
}
957
956
return false
958
- // case #selector(paste: ):
959
- // return true
957
+ case #selector( paste ( _ : ) ) :
958
+ return true
960
959
case #selector( selectAll ( _: ) ) :
961
960
return true
962
- // case #selector(copy: ):
963
- // return true
961
+ case #selector( copy ( _ : ) ) :
962
+ return selection . active
964
963
default :
965
964
print ( " Validating User Interface Item: \( item) " )
966
965
return false
967
966
}
968
967
}
969
968
969
+ public func selectionChanged( source: Terminal ) {
970
+ selectionView. update ( )
971
+ }
972
+
970
973
func cut ( sender: Any ? ) { }
971
- func copy ( sender: Any ? ) { }
972
- func paste ( sender: Any ? ) { }
973
- public override func selectAll( _ sender: Any ? ) { }
974
- func undo ( sender: Any ) { }
975
- func redo ( sender: Any ) { }
974
+
975
+ @objc
976
+ public func paste( _ sender: Any )
977
+ {
978
+ let clipboard = NSPasteboard . general
979
+ let text = clipboard. string ( forType: . string)
980
+ insertText ( text ?? " " , replacementRange: NSRange ( location: 0 , length: 0 ) )
981
+ }
982
+
983
+ @objc
984
+ public func copy( _ sender: Any )
985
+ {
986
+ // find the selected range of text in the buffer and put in the clipboard
987
+ let str = selection. getSelectedText ( )
988
+
989
+ let clipboard = NSPasteboard . general
990
+ clipboard. clearContents ( )
991
+ clipboard. setString ( str, forType: . string)
992
+ }
993
+
994
+ public override func selectAll( _ sender: Any ? )
995
+ {
996
+ selection. selectAll ( )
997
+ }
998
+
999
+ //func undo (sender: Any) {}
1000
+ //func redo (sender: Any) {}
976
1001
func zoomIn ( sender: Any ) { }
977
1002
func zoomOut ( sender: Any ) { }
978
1003
func zoomReset ( sender: Any ) { }
1004
+
1005
+ // Returns the vt100 mouseflags
1006
+ func encodeMouseEvent ( with event: NSEvent , down: Bool ) -> Int
1007
+ {
1008
+ let flags = event. modifierFlags
1009
+
1010
+ return terminal. encodeButton ( button: event. buttonNumber, release: false , shift: flags. contains ( . shift) , meta: flags. contains ( . option) , control: flags. contains ( . control) )
1011
+ }
1012
+
1013
+ func calculateMouseHit ( with event: NSEvent , down: Bool ) -> ( col: Int , row: Int )
1014
+ {
1015
+ let point = convert ( event. locationInWindow, from: nil )
1016
+ let col = Int ( point. x / cellWidth)
1017
+ let row = Int ( ( frame. height- point. y) / cellHeight)
1018
+ return ( col, row)
1019
+ }
1020
+
1021
+ func sharedMouseEvent ( with event: NSEvent , down: Bool )
1022
+ {
1023
+ let ( col, row) = calculateMouseHit ( with: event, down: down)
1024
+ let buttonFlags = encodeMouseEvent ( with: event, down: down)
1025
+ terminal. sendEvent ( buttonFlags: buttonFlags, x: col, y: row)
1026
+ }
979
1027
1028
+ public override func mouseDown( with event: NSEvent ) {
1029
+ if terminal. mouseEvents {
1030
+ sharedMouseEvent ( with: event, down: true )
1031
+ return
1032
+ }
1033
+ // TODO: autoscrolltimer setup
1034
+ }
1035
+
1036
+ public override func mouseUp( with event: NSEvent ) {
1037
+ // todo disable autoscrolltimer
1038
+ if terminal. mouseEvents {
1039
+ if terminal. mouseSendsRelease {
1040
+ sharedMouseEvent ( with: event, down: false )
1041
+ }
1042
+ return
1043
+ }
1044
+
1045
+ }
980
1046
}
981
1047
982
1048
@@ -1031,7 +1097,7 @@ class SelectionView: NSView {
1031
1097
rowHeight = terminalView. cellHeight
1032
1098
colWidth = terminalView. cellWidth
1033
1099
rowDelta = terminalView. cellDelta
1034
- selectionColor = NSColor . red
1100
+ selectionColor = NSColor ( calibratedRed : 0.4 , green : 0.2 , blue : 0.9 , alpha : 0.8 )
1035
1101
1036
1102
super. init ( frame: frame)
1037
1103
wantsLayer = true
@@ -1051,7 +1117,74 @@ class SelectionView: NSView {
1051
1117
1052
1118
func notifyScrolled ( )
1053
1119
{
1120
+ update ( )
1121
+ }
1122
+
1123
+ func update ( )
1124
+ {
1125
+ updateMask ( )
1126
+ }
1127
+
1128
+ func updateMask ( )
1129
+ {
1130
+ // remove the prior mask
1131
+ maskLayer. path = nil
1132
+
1133
+ maskLayer. frame = bounds
1134
+ let path = CGMutablePath ( )
1135
+ let terminal = terminalView. terminal!
1136
+ let screenRowStart = selection. start. row - terminal. buffer. yDisp;
1137
+ let screenRowEnd = selection. end. row - terminal. buffer. yDisp;
1138
+
1139
+ // mask the row that contains the start position
1140
+ // snap to either the first or last column depending on
1141
+ // where the end position is in relation to the start
1142
+ var col = selection. end. col
1143
+ if screenRowEnd > screenRowStart {
1144
+ col = terminal. cols
1145
+ }
1146
+ if screenRowEnd < screenRowStart {
1147
+ col = 0
1148
+ }
1149
+
1150
+ maskPartialRow ( path: path, row: screenRowStart, colStart: selection. start. col, colEnd: col)
1151
+
1152
+ if screenRowStart == screenRowEnd {
1153
+ // we're done, only one row to mask
1154
+ maskLayer. path = path
1155
+ return
1156
+ }
1157
+
1158
+ // now mask the row with the end position
1159
+ col = selection. start. col
1160
+ if screenRowEnd > screenRowStart {
1161
+ col = 0
1162
+ if ( screenRowEnd < screenRowStart) {
1163
+ col = terminal. cols
1164
+ }
1165
+ }
1166
+ maskPartialRow ( path: path, row: screenRowEnd, colStart: col, colEnd: selection. end. col)
1167
+
1168
+ // now mask any full rows in between
1169
+ let fullRowCount = screenRowEnd - screenRowStart
1170
+ if fullRowCount > 1 {
1171
+ // Mask full rows up to the last row
1172
+ maskFullRows ( path: path, rowStart: screenRowStart + 1 , rowCount: fullRowCount- 1 )
1173
+ } else if fullRowCount < - 1 {
1174
+ // Mask full rows up to the last row
1175
+ maskFullRows ( path: path, rowStart: screenRowStart - 0 , rowCount: fullRowCount+ 1 )
1176
+ }
1054
1177
1178
+ maskLayer. path = path
1179
+ }
1180
+
1181
+ func maskFullRows ( path: CGMutablePath , rowStart: Int , rowCount: Int )
1182
+ {
1183
+ let cursorYOffset : CGFloat = 2
1184
+ let startY = frame. height - ( CGFloat ( rowStart + rowCount) * rowHeight - rowDelta - cursorYOffset)
1185
+ let pathRect = CGRect ( x: 0 , y: startY, width: frame. width, height: rowHeight * CGFloat ( rowCount) )
1186
+
1187
+ path. addRect ( pathRect)
1055
1188
}
1056
1189
1057
1190
func maskPartialRow ( path: CGMutablePath , row: Int , colStart: Int , colEnd: Int )
@@ -1067,32 +1200,15 @@ class SelectionView: NSView {
1067
1200
if colStart == colEnd {
1068
1201
// basically the same as the cursor
1069
1202
pathRect = CGRect ( x: startX - cursorXPadding, y: startY, width: colWidth + ( 2 * cursorXPadding) , height: rowHeight)
1070
- path. addRect ( pathRect)
1071
- return
1072
- }
1073
-
1074
- if ( colStart < colEnd) {
1203
+ } else if ( colStart < colEnd) {
1075
1204
// start before the beginning of the start column and end just before the start of the next column
1076
- pathRect = CGRect (
1077
- x: startX - cursorXPadding,
1078
- y: startY,
1079
- width: ( CGFloat ( colEnd - colStart) * colWidth) + ( 2 * cursorXPadding) ,
1080
- height: rowHeight) ;
1081
-
1082
- path. addRect ( pathRect)
1083
- return ;
1205
+ pathRect = CGRect ( x: startX - cursorXPadding, y: startY, width: ( CGFloat ( colEnd - colStart) * colWidth) + ( 2 * cursorXPadding) , height: rowHeight) ;
1206
+ } else {
1207
+ // start before the beginning of the _end_ column and end just before the start of the _start_ column
1208
+ // note this creates a rect with negative width
1209
+ pathRect = CGRect ( x: startX + cursorXPadding, y: startY, width: ( CGFloat ( colEnd - colStart) * colWidth) - ( 2 * cursorXPadding) , height: rowHeight)
1084
1210
}
1085
-
1086
- // start before the beginning of the _end_ column and end just before the start of the _start_ column
1087
- // note this creates a rect with negative width
1088
- pathRect = CGRect (
1089
- x: startX + cursorXPadding,
1090
- y: startY,
1091
- width: ( CGFloat ( colEnd - colStart) * colWidth) - ( 2 * cursorXPadding) ,
1092
- height: rowHeight)
1093
-
1094
- path. addRect ( pathRect)
1211
+ path. addRect ( pathRect)
1095
1212
}
1096
-
1097
1213
}
1098
1214
#endif
0 commit comments